[
  {
    "path": ".clang-format",
    "content": "---\nBasedOnStyle: Google\nStatementMacros:\n  - INITIALIZER\nAlignConsecutiveMacros: true\nAlignConsecutiveDeclarations: false\nAlwaysBreakBeforeMultilineStrings: false\nAllowShortFunctionsOnASingleLine: false\nKeepEmptyLinesAtTheStartOfBlocks: true\nConstructorInitializerAllOnOneLineOrOnePerLine: true\n---\nLanguage: Cpp\nAllowShortFunctionsOnASingleLine: false\n---\nLanguage: Proto\n...\n"
  },
  {
    "path": ".gitattributes",
    "content": "# -*- conf -*-\n*.xz binary\n*.com binary\n*.elf binary\n/configure text eol=lf\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [jart]\n"
  },
  {
    "path": ".github/workflows/cygwin.yml",
    "content": "name: Build with Cygwin\n\non:\n  push:\n    branches:\n      - \"master\"\n      - \"flake\"\n      - \"ga\"\n  pull_request:\n    branches:\n      - \"master\"\n\n  # run workflow manually from the Actions tab\n  workflow_dispatch:\n\njobs:\n  build:\n    runs-on: windows-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - name: Install cached Cygwin\n        id: cache\n        uses: actions/cache@v3\n        with:\n          path: C:\\tools\\cygwin\n          key: 'cygwin'\n\n      - name: Install Cygwin\n        if: steps.cache.outputs.cache-hit != 'true'\n        uses: egor-tensin/setup-cygwin@v4.0.1\n        with:\n          packages: gcc-core make chere\n\n      - name: make matrix\n        run: |\n          cd \"$GITHUB_WORKSPACE\"\n          ./configure\n          cat config.log\n          make -j$(nproc) check o//test/blink\n        shell: C:\\tools\\cygwin\\bin\\bash.exe --login --norc -eo pipefail -o igncr '{0}'\n\n      - name: Test with VFS enabled\n        run: |\n          cd \"$GITHUB_WORKSPACE\"\n          ./configure --enable-vfs\n          cat config.log\n          export BLINK_PREFIX=\"o\"\n          make -j$(nproc) check o//test/blink\n        shell: C:\\tools\\cygwin\\bin\\bash.exe --login --norc -eo pipefail -o igncr '{0}'\n"
  },
  {
    "path": ".gitignore",
    "content": "# -*- conf -*-\n*.gz\n*.xz\n*.elf\n*.so\n*.so.1\nblink.log\n/o\n/core*\n/TAGS\n/HTAGS\n/config.h\n/config.mk\n/config.log\n/*.dump\n/gmon.out\n/perf.data\n/perf.data.old\n/third_party/cosmo/**/*.com\n/third_party/cosmo/**/*.dbg\n"
  },
  {
    "path": "LICENSE",
    "content": "ISC License\n\nCopyright 2022 Justine Alexandra Roberts Tunney\n\nPermission to use, copy, modify, and/or distribute this software for\nany purpose with or without fee is hereby granted, provided that the\nabove copyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL\nWARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE\nAUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\nDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\nPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\nTORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nSHELL = /bin/sh\nMAKEFLAGS += --no-builtin-rules\nARCHITECTURES = x86_64 x86_64-gcc49 i486 aarch64 arm mips s390x mipsel mips64 mips64el powerpc powerpc64le\n\n.SUFFIXES:\n.DELETE_ON_ERROR:\n.FEATURES: output-sync\n.PHONY: o all clean check check2 test tags format install\n\nifeq ($(MAKE_VERSION), 3.81)\n$(error please \"brew install make\" and use the \"gmake\" command)\nendif\nifneq ($(shell echo -e \"4.0\\n$(MAKE_VERSION)\" | sort -ct. -k1,1n -k2,2n 2>/dev/null && echo YES), YES)\n$(error please use GNU Make 4.0 or newer)\nendif\n\nifeq ($(wildcard config.h),)\n  $(error ./configure needs to be run, use ./configure --help for help)\nendif\ninclude config.mk\nCONFIG_COMMAND ?= ./configure\nifneq ($(CONFIG_HOSTNAME), $(shell hostname))\n  undefine CC\n  undefine AR\n  undefine TMPDIR\n  undefine CFLAGS\n  undefine LDFLAGS\n  undefine UOPFLAGS\n  undefine CPPFLAGS\n  undefine TARGET_ARCH\n  $(shell $(CONFIG_COMMAND))\n  $(error please run $(MAKE) again)\nendif\n\nifneq ($(m),)\nifeq ($(MODE),)\nMODE := $(m)\nendif\nendif\n\nifneq ($(HOST_SYSTEM), Linux)\nVM = o/$(MODE)/blink/blink\nendif\nifneq ($(HOST_ARCH), x86_64)\nVM = o/$(MODE)/blink/blink\nendif\n\no:\to/ok\no/ok:\to/$(MODE)/blink\n\ttouch $@\n\t@echo \"\"\n\t@echo \"Your Blink Virtual Machine successfully compiled:\"\n\t@echo \"\"\n\t@echo \"  o/$(MODE)/blink/blink\"\n\t@echo \"  o/$(MODE)/blink/blinkenlights\"\n\t@echo \"\"\n\t@echo \"You may also want to run:\"\n\t@echo \"\"\n\t@echo \"  make check\"\n\t@echo \"  doas make install\"\n\t@echo \"\"\n\ntest:\to/$(MODE)/blink\t\t\t\t\\\n\to/$(MODE)/test\n\nformat:\n\tclang-format -i -style=file blink/*.c blink/*.h\n\ncheck:\ttest\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo\t\t\\\n\to/$(MODE)/third_party/libc-test\t\t\\\n\to/$(MODE)/test/metal\t\t\t\\\n\to/$(MODE)/test/metalrom\n\ncheck2:\to/$(MODE)/test/sse\t\t\t\\\n\to/$(MODE)/test/lib\t\t\t\\\n\to/$(MODE)/test/sys\t\t\t\\\n\to/$(MODE)/test/func\t\t\t\\\n\to/$(MODE)/test/asm\t\t\t\\\n\to/$(MODE)/third_party/ltp\t\t\\\n\to/$(MODE)/test/asm/emulates\t\t\\\n\to/$(MODE)/test/func/emulates\n\nemulates:\t\t\t\t\t\\\n\to/$(MODE)/test/asm\t\t\t\\\n\to/$(MODE)/test/flat\t\t\t\\\n\to/$(MODE)/third_party/ltp/medium\t\\\n\to/$(MODE)/third_party/cosmo/emulates\n\ntags: TAGS HTAGS\n\ninclude build/config.mk\ninclude build/rules.mk\ninclude third_party/libz/zlib.mk\ninclude blink/blink.mk\ninclude test/test.mk\ninclude test/asm/asm.mk\ninclude test/func/func.mk\ninclude test/flat/flat.mk\ninclude test/blink/test.mk\ninclude test/metal/metal.mk\ninclude test/metalrom/metalrom.mk\ninclude tool/config/config.mk\ninclude third_party/gcc/gcc.mk\ninclude third_party/ltp/ltp.mk\ninclude third_party/musl/musl.mk\ninclude third_party/qemu/qemu.mk\ninclude third_party/cosmo/cosmo.mk\ninclude third_party/libc-test/libc-test.mk\n\nBUILD_TOOLCHAIN := -DBUILD_TOOLCHAIN=\"\\\"$(shell $(CC) --version | head -n1 | sed s/\\ / /g)\\\"\"\nBUILD_TIMESTAMP := -DBUILD_TIMESTAMP=\"\\\"$(shell LC_ALL=C TZ=UTC date +\"%a %b %e %T %Z %Y\" | sed s/\\ / /g)\\\"\"\nBLINK_COMMITS := -DBLINK_COMMITS=\"\\\"$(shell git rev-list HEAD --count 2>/dev/null)\\\"\"\nBLINK_GITSHA := -DBLINK_GITSHA=\"\\\"$(shell git rev-parse --verify HEAD 2>/dev/null)\\\"\"\n\nCONFIG_CPPFLAGS =\t\t\t\\\n\t$(CONFIG_ARGUMENTS)\t\t\\\n\t$(BUILD_TOOLCHAIN)\t\t\\\n\t$(BUILD_TIMESTAMP)\t\t\\\n\t$(BLINK_COMMITS)\t\t\\\n\t$(BLINK_UNAME_V)\t\t\\\n\t$(BLINK_GITSHA)\t\t\t\\\n\t-DBUILD_MODE=\"\\\"$(MODE)\\\"\"\n\nOBJS\t = $(foreach x,$(PKGS),$($(x)_OBJS))\nSRCS\t:= $(foreach x,$(PKGS),$($(x)_SRCS))\nHDRS\t:= $(foreach x,$(PKGS),$($(x)_HDRS))\nINCS\t = $(foreach x,$(PKGS),$($(x)_INCS))\nBINS\t = $(foreach x,$(PKGS),$($(x)_BINS))\nTESTS\t = $(foreach x,$(PKGS),$($(x)_TESTS))\nCHECKS\t = $(foreach x,$(PKGS),$($(x)_CHECKS))\n\no/$(MODE)/.x:\n\t@mkdir -p $(@D)\n\t@touch $@\n\no/tool/sha256sum: tool/sha256sum.c\n\t@mkdir -p $(@D)\n\t$(CC) -w -O2 -o $@ $<\n\no/$(MODE)/tool/sha256sum.o: tool/sha256sum.c\n\t@mkdir -p $(@D)\n\tclang++ -Wall -Wextra -Werror -pedantic -O2 -xc++ -c -o $@ $<\n\tg++ -Wall -Wextra -Werror -pedantic -O2 -xc++ -c -o $@ $<\n\tclang -Wall -Wextra -Werror -pedantic -O2 -c -o $@ $<\n\tgcc -Wall -Wextra -Werror -pedantic -O2 -c -o $@ $<\n\no/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(SRCS) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))\n\t$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))\no/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(HDRS) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))\n\t$(file >$@) $(foreach x,blink/types.h $(HDRS) $(INCS),$(file >>$@,$(x)))\n\nMAKEFILES =\t\t\t\t\\\n\tMakefile\t\t\t\\\n\tbuild/config.mk\t\t\t\\\n\tbuild/rules.mk\t\t\t\\\n\tblink/blink.mk\t\t\t\\\n\tthird_party/libz/zlib.mk\n\n$(OBJS): $(MAKEFILES)\n\nDEPENDS =\t\t\t\t\\\n\to/$(MODE)/depend.host\t\t\\\n\to/$(MODE)/depend.i486\t\t\\\n\to/$(MODE)/depend.m68k\t\t\\\n\to/$(MODE)/depend.x86_64\t\t\\\n\to/$(MODE)/depend.x86_64-gcc49\t\\\n\to/$(MODE)/depend.arm\t\t\\\n\to/$(MODE)/depend.aarch64\t\\\n\to/$(MODE)/depend.riscv64\t\\\n\to/$(MODE)/depend.mips\t\t\\\n\to/$(MODE)/depend.mipsel\t\t\\\n\to/$(MODE)/depend.mips64\t\t\\\n\to/$(MODE)/depend.mips64el\t\\\n\to/$(MODE)/depend.s390x\t\t\\\n\to/$(MODE)/depend.microblaze\t\\\n\to/$(MODE)/depend.powerpc\t\\\n\to/$(MODE)/depend.powerpc64le\n\no/$(MODE)/depend: $(DEPENDS)\n\tcat $^ >$@\no/$(MODE)/depend.host: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.i486: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/i486/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.m68k: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/m68k/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.x86_64: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/x86_64/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.x86_64-gcc49: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/x86_64-gcc49/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.arm: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/arm/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.aarch64: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/aarch64/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.riscv64: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/riscv64/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.mips: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/mips/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.mipsel: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/mipsel/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.mips64: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/mips64/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.mips64el: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/mips64el/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.s390x: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/s390x/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.microblaze: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/microblaze/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.powerpc: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/powerpc/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\no/$(MODE)/depend.powerpc64le: o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt\n\t$(VM) build/bootstrap/mkdeps.com -o $@ -r o/$(MODE)/powerpc64le/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt 2>/dev/null\n\nTAGS:\to/$(MODE)/srcs.txt $(SRCS)\n\t$(RM) $@\n\t$(TAGS) $(TAGSFLAGS) -L $< -o $@\n\nHTAGS:\to/$(MODE)/hdrs.txt $(HDRS)\n\t$(RM) $@\n\tbuild/htags -L $< -o $@\n\n$(OBJS): config.h\n\nconfig.h: configure\n\t$(CONFIG_COMMAND)\n\ninstall:\n\tmkdir -p $(PREFIX)/bin\n\tinstall -m 0755 o//blink/blink $(PREFIX)/bin/blink\n\tinstall -m 0755 o//blink/blinkenlights $(PREFIX)/bin/blinkenlights\n\tmkdir -p $(PREFIX)/share/man/man1\n\tinstall -m 0644 blink/blink.1 $(PREFIX)/share/man/man1/blink.1\n\tinstall -m 0644 blink/blinkenlights.1 $(PREFIX)/share/man/man1/blinkenlights.1\n\nclean:\n\trm -f $(OBJS) o/$(MODE)/blink/blink o/$(MODE)/blink/blinkenlights o/$(MODE)/blink/blink.a o/$(MODE)/third_party/libz/zlib.a\n\ndistclean:\n\trm -rf o\n\trm -f config.h TAGS HTAGS *.dump gmon.out perf.data perf.data.old\n\trm -f $(find third_party -name \\*.elf)\n\trm -f $(find third_party -name \\*.com)\n\trm -f $(find third_party -name \\*.dbg)\n\trm -f $(find third_party -name \\*.so.1)\n\trm -f $(find third_party -name \\*.so)\n\trm -f $(find third_party -name \\*.gz)\n\trm -f $(find third_party -name \\*.xz)\n\n$(SRCS):\n$(HDRS):\n$(INCS):\n.DEFAULT:\n\t@echo >&2\n\t@echo NOTE: deleting o/$(MODE)/depend because of an unspecified prerequisite: $@ >&2\n\t@echo >&2\n\trm -f o/$(MODE)/depend $(DEPENDS)\n\n-include o/$(MODE)/depend\n"
  },
  {
    "path": "README.md",
    "content": "![Screenshot of Blink running GCC 9.4.0](blink/blink-gcc.png)\n\n# Blinkenlights\n\nThis project contains two programs:\n\n`blink` is a virtual machine that runs x86-64-linux programs on\ndifferent operating systems and hardware architectures. It's designed to\ndo the same thing as the `qemu-x86_64` command, except that\n\n1. Blink is 221kb in size (115kb with optional features disabled),\n   whereas qemu-x86_64 is a 4mb binary.\n\n2. Blink will run your Linux binaries on any POSIX system, whereas\n   qemu-x86_64 only supports Linux.\n\n3. Blink goes 2x faster than qemu-x86_64 on some benchmarks, such as SSE\n   integer / floating point math. Blink is also much faster at running\n   ephemeral programs such as compilers.\n\n[`blinkenlights`](https://justine.lol/blinkenlights) is a terminal user\ninterface that may be used for debugging x86_64-linux or i8086 programs\nacross platforms. Unlike GDB, Blinkenlights focuses on visualizing\nprogram execution. It uses UNICODE IBM Code Page 437 characters to\ndisplay binary memory panels, which change as you step through your\nprogram's assembly code. These memory panels may be scrolled and zoomed\nusing your mouse wheel. Blinkenlights also permits reverse debugging,\nwhere scroll wheeling over the assembly display allows the rewinding of\nexecution history.\n\n## Getting Started\n\nWe regularly test that Blink is able run x86-64-linux binaries on the\nfollowing platforms:\n\n- Linux (x86, ARM, RISC-V, MIPS, PowerPC, s390x)\n- macOS (x86, ARM)\n- FreeBSD\n- OpenBSD\n- Cygwin\n\nBlink depends on the following libraries:\n\n- libc (POSIX.1-2017 with XSI extensions)\n\nBlink can be compiled on UNIX systems that have:\n\n- A C11 compiler with atomics (e.g. GCC 4.9.4+)\n- Modern GNU Make (i.e. not the one that comes with XCode)\n\nThe instructions for compiling Blink are as follows:\n\n```sh\n./configure\nmake -j4\ndoas make install  # note: doas is modern sudo\nblink -v\nman blink\n```\n\nHere's how you can run a simple hello world program with Blink:\n\n```sh\nblink third_party/cosmo/tinyhello.elf\n```\n\nBlink has a debugger TUI, which works with UTF-8 ANSI terminals. The\nmost important keystrokes in this interface are `?` for help, `s` for\nstep, `c` for continue, and scroll wheel for reverse debugging.\n\n```sh\nblinkenlights third_party/cosmo/tinyhello.elf\n```\n\n### Alternative Builds\n\nFor maximum tinyness, use `MODE=tiny`, since it makes Blink's binary\nfootprint 50% smaller. The Blink executable should be on the order of\n200kb in size. Performance isn't impacted. Please note that all\nassertions will be removed, as well as all logging. Use this mode if\nyou're confident that Blink is bug-free for your use case.\n\n```sh\nmake MODE=tiny\nstrip o/tiny/blink/blink\nls -hal o/tiny/blink/blink\n```\n\nSome distros configure their compilers to add a lot of security bloat,\nwhich might add 60kb or more to the above binary size. You can work\naround that by using one of Blink's toolchains. This should produce\nconsistently the smallest possible executable size.\n\n```sh\nmake MODE=tiny o/tiny/x86_64/blink/blink\no/third_party/gcc/x86_64/bin/x86_64-linux-musl-strip o/tiny/x86_64/blink/blink\nls -hal o/tiny/x86_64/blink/blink\n```\n\nIf you want to make Blink *even tinier* (more on the order of 120kb\nrather than 200kb) than you can tune the `./configure` script to disable\noptional features such as jit, threads, sockets, x87, bcd, xsi, etc.\n\n```sh\n./configure --disable-all --posix\nmake MODE=tiny o/tiny/x86_64/blink/blink\no/third_party/gcc/x86_64/bin/x86_64-linux-musl-strip o/tiny/x86_64/blink/blink\nls -hal o/tiny/x86_64/blink/blink\n```\n\nThe traditional `MODE=rel` or `MODE=opt` modes are available. Use this\nmode if you're on a non-JIT architecture (since this won't improve\nperformance on AMD64 and ARM64) and you're confident that Blink is\nbug-free for your use case, and would rather have Blink not create a\n`blink.log` or print `SIGSEGV` delivery warnings to standard error,\nsince many apps implement their own crash reporting.\n\n```sh\nmake MODE=rel\no/rel/blink/blink -h\n```\n\nYou can hunt down bugs in Blink using the following build modes:\n\n- `MODE=asan` helps find memory safety bugs\n- `MODE=tsan` helps find threading related bugs\n- `MODE=ubsan` to find violations of the C standard\n- `MODE=msan` helps find uninitialized memory errors\n\nYou can check Blink's compliance with the POSIX standard using the\nfollowing configuration flags:\n\n```sh\n./configure --posix  # only use c11 with posix xopen standard\n```\n\nIf you want to run a full `chroot`'d Linux distro and require correct\nhandling of absolute symlinks, displaying of certain values in `/proc`,\nand so on, and you don't mind paying a small price in terms of size\nand performance, you can enable the emulated VFS feature by using\nthe following configuration:\n\n```sh\n./configure --enable-vfs\n```\n\n### Testing\n\nBlink is tested primarily using precompiled binaries downloaded\nautomatically. Blink has more than 700 test programs total. You can\ncheck how well Blink works on your local platform by running:\n\n```sh\nmake check\n```\n\nTo check that Blink works on 11 different hardware `$(ARCHITECTURES)`\n(see [Makefile](Makefile)), you can run the following command, which\nwill download statically-compiled builds of GCC and Qemu. Since our\ntoolchain binaries are intended for x86-64 Linux, Blink will bootstrap\nitself locally first, so that it's possible to run these tests on other\noperating systems and architectures.\n\n```sh\nmake check2\nmake emulates\n```\n\n### Production Worthiness\n\nBlink passes 194 test suites from the Cosmopolitan Libc project (see\n[third_party/cosmo](third_party/cosmo)). Blink passes 350 test suites\nfrom the [Linux Test Project](https://github.com/linux-test-project/ltp)\n(see [third_party/ltp](third_party/ltp)). Blink passes 108 of [Musl\nLibc's unit test suite](https://github.com/jart/libc-test) (see\n[third_party/libc-test](third_party/libc-test)). The tests we haven't\nincluded are because either (1) it wanted x87 long double to have 80-bit\nprecision, or (2) it used Linux APIs we can't or won't support, e.g.\nSystem V message queues. Blink runs the precompiled Linux test binaries\nabove on other operating systems too, e.g. Apple M1, FreeBSD, Cygwin.\n\n## Reference\n\nThe Blinkenlights project provides two programs which may be launched on\nthe command line.\n\n### `blink` Flags\n\nThe headless Blinkenlights virtual machine command (named `blink` by\nconvention) accepts command line arguments per the specification:\n\n```\nblink [FLAG...] PROGRAM [ARG...]\n```\n\nWhere `PROGRAM` is an x86_64-linux binary that may be specified as:\n\n1. An absolute path to an executable file, which will be run as-is\n2. A relative path containing slashes, which will be run as-is\n3. A path name without slashes, which will be `$PATH` searched\n\nThe following `FLAG` arguments are provided:\n\n- `-h` shows help on command usage\n\n- `-v` shows version and build configuration details\n\n- `-e` means log to standard error (fd 2) in addition to the log file.\n  If logging to *only* standard error is desired, then `-eL/dev/null`\n  may be used.\n\n- `-j` disables Just-In-Time (JIT) compilation, which will make Blink go\n  ~10x slower.\n\n- `-m` disables the linear memory optimization. This makes Blink memory\n  safe, but comes at the cost of going ~4x slower. On some platforms\n  this can help avoid the possibility of an mmap() crisis.\n\n- `-0` allows `argv[0]` to be specified on the command line. Under\n  normal circumstances, `blink cmd arg1` is equivalent to `execve(\"cmd\",\n  {\"cmd\", \"arg1\"})` since that's how most programs are launched. However\n  if you need the full power of execve() process spawning, you can say\n  `blink -0 cmd arg0 arg1` which is equivalent to `execve(\"cmd\",\n  {\"arg0\", \"arg1\"})`.\n\n- `-L PATH` specifies the log path. The default log path is `blink.log`\n  in the current directory at startup. This log file won't be created\n  until something is actually logged. If logging to a file isn't\n  desired, then `-L /dev/null` may be used. See also the `-e` flag for\n  logging to standard error.\n\n- `-s` enables system call logging. This will emit to the log file the\n  names of system calls each time a SYSCALL instruction in executed,\n  along with its arguments and result. System calls are logged once\n  they've completed. If this option is specified twice, then system\n  calls which are likely to block (e.g. poll) will be logged at entry\n  too. If this option is specified thrice, then all cancellation points\n  will be logged upon entry. System call logging isn't available in\n  `MODE=rel` and `MODE=tiny` builds, in which case this flag is ignored.\n\n- `-Z` will cause internal statistics to be printed to standard error on\n  exit. Stats aren't available in `MODE=rel` and `MODE=tiny` builds, and\n  this flag is ignored.\n\n- `-C path` will cause blink to launch the program in a chroot'd\n  environment. This flag is both equivalent to and overrides the\n  `BLINK_OVERLAYS` environment variable. Note: This flag works\n  especially well if you use `./configure --enable-vfs`.\n\n### `blinkenlights` Flags\n\nThe Blinkenlights ANSI TUI interface command (named `blinkenlights` by\nconvention) accepts its command line arguments in accordance with the\nfollowing specification:\n\n```\nblinkenlights [FLAG...] PROGRAM [ARG...]\n```\n\nWhere `PROGRAM` is an x86_64-linux binary that may be specified as:\n\n1. An absolute path to an executable file, which will be run as-is\n2. A relative path containing slashes, which will be run as-is\n3. A path name without slashes, which will be `$PATH` searched\n\nThe following `FLAG` arguments are provided:\n\n- `-h` shows help on command usage\n\n- `-v` shows version and build configuration details\n\n- `-r` puts your virtual machine in real mode. This may be used to run\n  16-bit i8086 programs, such as SectorLISP. It's also used for booting\n  programs from Blinkenlights's simulated BIOS.\n\n- `-b ADDR` pushes a breakpoint, which may be specified as a raw\n  hexadecimal address, or a symbolic name that's defined by your ELF\n  binary (or its associated `.dbg` file). When pressing `c` (continue)\n  or `C` (continue harder) in the TUI, Blink will immediately stop upon\n  reaching an instruction that's listed as a breakpoint, after which a\n  modal dialog is displayed. The modal dialog may be cleared by `ENTER`\n  after which the TUI resumes its normal state.\n\n- `-w ADDR` pushes a watchpoint, which may be specified as a raw\n  hexadecimal address, or a symbolic name that's defined by your ELF\n  binary (or its associated `.dbg` file). When pressing `c` (continue)\n  or `C` (continue harder) in the TUI, Blink will immediately stop upon\n  reaching an instruction that either (a) has a ModR/M encoding that\n  references an address that's listed as a watchpoint, or (b) manages to\n  mutate the memory stored at a watchpoint address by some other means.\n  When Blinkenlights is stopped at a watchpoint, a modal dialog will be\n  displayed which may be cleared by pressing `ENTER`, after which the\n  TUI resumes its normal state.\n\n- `-j` enables Just-In-Time (JIT) compilation. This will make\n  Blinkenlights go significantly faster, at the cost of taking away the\n  ability to step through each instruction. The TUI will visualize JIT\n  path formation in the assembly display; see the JIT Path Glyphs\n  section below to learn more. Please note this flag has the opposite\n  meaning as it does in the `blink` command.\n\n- `-m` enables the linear memory optimization. This makes blinkenlights\n  capable of faster emulation, at the cost of losing some statistics. It\n  no longer becomes possible to display which percentage of a memory map\n  has been activated. Blinkenlights will also remove the commit /\n  reserve / free page statistics from the status panel on the bottom\n  right of the display. Please note this flag has the opposite meaning\n  as it does in the `blink` command.\n\n- `-t` may be used to disable Blinkenlights TUI mode. This makes the\n  program behave similarly to the `blink` command, however not as good.\n  We're currently using this flag for unit testing real mode programs,\n  which are encouraged to use the `SYSCALL` instruction to report their\n  exit status.\n\n- `-L PATH` specifies the log path. The default log path is\n  `$TMPDIR/blink.log` or `/tmp/blink.log` if `$TMPDIR` isn't defined.\n\n- `-C path` will cause blink to launch the program in a chroot'd\n  environment. This flag is both equivalent to and overrides the\n  `BLINK_OVERLAYS` environment variable.\n\n- `-s` enables system call logging. This will emit to the log file the\n  names of system calls each time a SYSCALL instruction in executed,\n  along with its arguments and result. System calls are logged once\n  they've completed. If this option is specified twice, then system\n  calls which are likely to block (e.g. poll) will be logged at entry\n  too. If this option is specified thrice, then all cancellation points\n  will be logged upon entry. System call logging isn't available in\n  `MODE=rel` and `MODE=tiny` builds, in which case this flag is ignored.\n\n- `-Z` will cause internal statistics to be printed to standard error on\n  exit. Each line will display a monitoring metric. Most metrics will\n  either be integer counters or floating point running averages. Most\n  but not all integer counters are monotonic. In the interest of not\n  negatively impacting Blink's performance, statistics are computed on a\n  best effort basis which currently isn't guaranteed to be atomic in a\n  multi-threaded environment. Stats aren't available in `MODE=rel` and\n  `MODE=tiny` builds, and this flag is ignored.\n\n- `-z` [repeatable] may be specified to zoom the memory panels, so they\n  display a larger amount of memory in a smaller space. By default, one\n  terminal cell corresponds to a single byte of memory. When memory has\n  been zoomed the magic kernel is used (similar to Lanczos) to decimate\n  the number of bytes by half, for each `-z` that's specified. Normally\n  this would be accomplished by using `CTRL+MOUSEWHEEL` where the mouse\n  cursor is hovered over the panel that should be zoomed. However, many\n  terminal emulators (especially on Windows), do not support this xterm\n  feature and as such, this flag is provided as an alternative.\n\n- `-V` [repeatable] increases verbosity\n\n- `-R` disables reactive error mode\n\n- `-H` disables syntax highlighting\n\n- `-N` enables natural scrolling\n\n### Recommended Environments\n\nBlinkenlights' TUI requires a UTF-8 VT100 / XTERM style terminal to use.\nWe recommend the following terminals, ordered by preference:\n\n- [KiTTY](https://sw.kovidgoyal.net/kitty/) (Linux)\n- [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) (Windows)\n- Gnome Terminal (Linux)\n- Terminal.app (macOS)\n- CMD.EXE (Windows 10+)\n- PowerShell (Windows 10+)\n- Xterm (Linux)\n\nThe following fonts are recommended, ordered by preference:\n\n- [PragmataPro Regular Mono](https://fsd.it/shop/fonts/pragmatapro/) (€59)\n- Bitstream Vera Sans Mono (a.k.a. DejaVu Sans Mono)\n- Consolas\n- Menlo\n\n#### JIT Path Glyphs\n\nWhen the Blinkenlights TUI is run with JITing enabled (using the `-j`\nflag) the assembly dump display will display a glyph next to the address\nof each instruction, to indicate the status of JIT path formation. Those\nglyphs are defined as follows:\n\n- ` ` or space indicates no JIT path is associated with an address\n\n- `S` means that a JIT path is currently being constructed which\n  starts at this address. By continuing to press `s` (step) in the TUI\n  interface, the JIT path will grow longer until it is eventually\n  completed, and the `S` glyph is replaced by `*`.\n\n- `*` (asterisk) means that a JIT path has been installed to the\n  adjacent address. When `s` (step) is pressed at such addresses\n  within the TUI display, stepping takes on a different meaning.\n  Rather than stepping a single instruction, it will step the entire\n  length of the JIT path. The next assembly line that'll be\n  highlighted will be the instruction after where the path ends.\n\n### Environment Variables\n\nThe following environment variables are recognized by both the `blink`\nand `blinkenlights` commands:\n\n- `BLINK_LOG_FILENAME` may be specified to supply a log path to be used\n  in cases where the `-L PATH` flag isn't specified. This value should\n  be an absolute path. If logging to standard error is desired, use the\n  `blink -e` flag.\n\n- `BLINK_OVERLAYS` specifies one or more directories to use as the root\n  filesystem. Similar to `$PATH` this is a colon delimited list of\n  pathnames. If relative paths are specified, they'll be resolved to an\n  absolute path at startup time. Overlays only apply to IO system calls\n  that specify an absolute path. The empty string overlay means use the\n  normal `/` root filesystem. The default value is `:o`, which means if\n  the absolute path `/$f` is opened, then first check if `/$f` exists,\n  and if it doesn't, then check if `o/$f` exists, in which case open\n  that instead. Blink uses this convention to open shared object tests.\n  It favors the system version if it exists, but also downloads\n  `ld-musl-x86_64.so.1` to `o/lib/ld-musl-x86_64.so.1` so the dynamic\n  linker can transparently find it on platforms like Apple, that don't\n  let users put files in the root folder. On the other hand, it's\n  possible to say `BLINK_OVERLAYS=o:` so that `o/...` takes precedence\n  over `/...` (noting again that empty string means root). If a single\n  overlay is specified that isn't empty string, then it'll effectively\n  act as a restricted chroot environment.\n\n## Compiling and Running Programs under Blink\n\nBlink can be picky about which Linux binaries it'll execute. It may also\nbe the case that your Linux binary will only run under Blink on Linux,\nbut report errors if run under Blink on another platform, e.g. macOS. In\nour experience, how successfully a program can run under Blink depends\nalmost entirely on (1) how it was compiled, and (2) which C library it\nuses. This section will provide guidance on which tools will work best.\n\nFirst, some background. Blink's coverage of the x86_64 instruction set\nis comprehensive. However the Linux system call ABI is much larger and\ntherefore not possible to fully support, unless Blink emulated a Linux\nkernel image too. Blink has sought to support the subset of Linux ABIs\nthat are either (1) standardized by POSIX.1-2017 or (2) too popular to\n*not* support. As an example, `AF_INET`, `AF_UNIX`, and `AF_INET6` are\nsupported, but Blink will return `EINVAL` if a program requests any of\nthe dozens of other ones, e.g. `AF_BLUETOOTH`. Such errors are usually\nlogged to `/tmp/blink.log`, to make it easy to file a feature request.\nIn other cases ABIs aren't supported simply because they're Linux-only\nand difficult to polyfill on other POSIX platforms. For example, Blink\nwill polyfill `open(O_TMPFILE)` on non-Linux platforms so it works the\nsame way, but other Linux-specific ABIs like `membarrier()` we haven't\nhad the time to figure out yet. Since app developers usually don't use\nnon-portable APIs, it's usually the platform C library that's at fault\nfor calling them. Many Linux system calls, could be rightfully thought\nof as an implementation detail of Glibc.\n\nBlink's prime directive is to support binaries built with Cosmopolitan\nLibc. Actually Portable Executables make up the bulk of Blink's unit\ntest suite. Anything created by Cosmopolitan is almost certainly going\nto work very well. Since Cosmopolitan is closely related to Musl Libc,\nprograms compiled using Musl also tend to work very well. For example,\nAlpine Linux is a Musl Libc based distro, so their prebuilt dynamic\nbinaries tend to all work well, and it's also a great platform to use\nfor compiling other software from source that's intended for Blink.\n\nSo the recommended approach is either:\n\n1. Build your app using Cosmopolitan Libc, otherwise\n2. Build your app using GNU Autotools on Alpine Linux\n3. Build your app using Buildroot\n\nFor Cosmopolitan, please read [Getting Started with Cosmopolitan\nLibc](https://jeskin.net/blog/getting-started-with-cosmopolitan-libc/)\nfor information on how to get started. Cosmopolitan comes with a lot of\nthird party software included that you can try with Blink right away,\ne.g. SQLite, Python, QuickJS, and Antirez's Kilo editor.\n\n```\ngit clone https://github.com/jart/cosmopolitan/\ncd cosmopolitan\n\nmake -j8 o//third_party/python/python.com\nblinkenlights -jm o//third_party/python/python.com\n\nmake -j8 o//third_party/quickjs/qjs.com\nblinkenlights -jm o//third_party/quickjs/qjs.com\n\nmake -j8 o//third_party/sqlite3/sqlite3.com\nblinkenlights -jm o//third_party/sqlite3/sqlite3.com\n\nmake -j8 o//examples/kilo.com\nblinkenlights -jm o//examples/kilo.com\n```\n\nBlink is great for making single-file autonomous binaries like the above\neasily copyable across platforms. If you're more interested in building\nsystems instead, then [Buildroot](https://buildroot.org/) is one way to\ncreate a Linux userspace that'll run under Blink. All you have to do is\nset the `$BLINK_OVERLAYS` environment variable to the buildroot target\nfolder, which will ask Blink to create a chroot'd environment.\n\n```\ncd ~/buildroot\nexport CC=\"gcc -Wl,-z,common-page-size=65536,-z,max-page-size=65536\"\nmake menuconfig\nmake\ncp -R output/target ~/blinkroot\ndoas mount -t devtmpfs none ~/blinkroot/dev\ndoas mount -t sysfs none ~/blinkroot/sys\ndoas mount -t proc none ~/blinkroot/proc\ncd ~/blink\nmake -j8\nexport BLINK_OVERLAYS=$HOME/blinkroot\nblink sh\nuname -a\nLinux hostname 4.5 blink-1.0 x86_64 GNU/Linux\n```\n\nIf you want to build an Autotools project like Emacs, the best way to do\nthat is to spin up an Alpine Linux container and use\n[jart/blink-isystem](https://github.com/jart/blink-isystem) as your\nsystem header subset. blink-isystem is basically just the Musl Linux\nheaders with all the problematic APIs commented out. That way autoconf\nwon't think the APIs Blink doesn't have are available, and will instead\nconfigure Emacs to use portable alternatives. Setting this up is simple:\n\n```\n./configure CFLAGS=\"-isystem $HOME/blink-isystem\" \\\n            CXXFLAGS=\"-isystem $HOME/blink-isystem\" \\\n            LDFLAGS=\"-static -Wl,-z,common-page-size=65536,-z,max-page-size=65536\"\nmake -j\n```\n\nAnother big issue is the host system page size may cause problems on\nnon-Linux platforms like Apple M1 (16kb) and Cygwin (64kb). On such\nplatforms, you may encounter an error like this:\n\n```\np_vaddr p_offset skew unequal w.r.t. host page size\n```\n\nThe simplest way to solve that is by disabling the linear memory\noptimization (using the `blink -m` flag) but that'll slow down\nperformance. Another option is to try recompiling your executable so\nthat its ELF program headers will work on systems with a larger page\nsize. You can do that using these GCC flags:\n\n```\ngcc -static -Wl,-z,common-page-size=65536,-z,max-page-size=65536 ...\n```\n\nHowever that's just step one. The program also needs to be using APIs\nlike `sysconf(_SC_PAGESIZE)` which will return the true host page size,\nrather than naively assuming it's 4096 bytes. Your C library gets this\ninformation from Blink via `getauxval(AT_PAGESZ)`.\n\nIf you're using the Blinkenlights debugger TUI, then another important\nset of flags to use are the following:\n\n- `-fno-omit-frame-pointer`\n- `-mno-omit-leaf-frame-pointer`\n\nBy default, GCC and Clang use the `%rbp` backtrace pointer as a general\npurpose register, and as such, Blinkenlights won't be able to display a\nframes panel visualizing your call stack. Using those flags solves that.\nHowever it's tricky sometimes to correctly specify them in a complex\nbuild environment, where other optimization flags might subsequently\nturn them back off again.\n\nThe trick we recommend using for compiling your programs, is to create a\nshell script that wraps your compiler command, and then use the script\nin your `$CC` environment variable. The script should look something\nlike the following:\n\n```sh\n#!/bin/sh\nset /usr/bin/gcc \"$@\" -g \\\n    -fno-omit-frame-pointer \\\n    -fno-optimize-sibling-calls \\\n    -mno-omit-leaf-frame-pointer \\\n    -Wl,-z,norelro \\\n    -Wl,-z,noseparate-code \\\n    -Wl,-z,max-page-size=65536 \\\n    -Wl,-z,common-page-size=65536\nprintf '%s\\n' \"$*\" >>/tmp/gcc.log\nexec \"$@\"\n```\n\nThose flags will go a long way towards helping your Linux binaries be\n(1) capable of running under Blink on all of its supported operating\nsystems and microprocessor architectures, and (2) trading away some of\nthe modern security blankets in the interest of making the assembly\npanel more readable, and less likely to be picky about memory.\n\nIf you're a Cosmopolitan Libc user, then Cosmopolitan already provides\nsuch a script, which is the `cosmocc` and `cosmoc++` toolchain. Please\nnote that Cosmopolitan Libc uses a 64kb page size so it isn't impacted\nby many of these issues that Glibc and Musl users may experience.\n\n- [cosmopolitan/tool/scripts/cosmocc](https://github.com/jart/cosmopolitan/blob/master/tool/scripts/cosmocc)\n- [cosmopolitan/tool/scripts/cosmoc++](https://github.com/jart/cosmopolitan/blob/master/tool/scripts/cosmoc%2B%2B)\n\nIf you're not a C / C++ developer, and you prefer to use high-level\nlanguages instead, then one program you might consider emulating is\nActually Portable Python, which is an APE build of the CPython v3.6\ninterpreter. It can be built from source, and then used as follows:\n\n```\ngit clone https://github.com/jart/cosmopolitan/\ncd cosmopolitan\nmake -j8 o//third_party/python/python.com\nblinkenlights -jm o//third_party/python/python.com\n```\n\nThe `-jm` flags are helpful here, since they ask the Blinkenlights TUI\nto enable JIT and the linear memory optimization. It's helpful to have\nthose flags because Python is a very complicated and compute intensive\nprogram, that would otherwise move too slowly under the Blinkenlights\nvizualization. You may also want to press the `CTRL-T` (TURBO) key a few\ntimes, to make Python emulate in the TUI even faster.\n\n## Technical Details\n\nblink is an x86-64 interpreter for POSIX platforms that's written in\nANSI C11 that's compatible with C++ compilers. Instruction decoding is\ndone using our trimmed-down version of Intel's disassembler Xed.\n\nThe prime directive of this project is to act as a virtual machine for\nuserspace binaries compiled by Cosmopolitan Libc. However we've also had\nsuccess virtualizing programs compiled with Glibc and Musl Libc, such as\nGCC and Qemu. Blink supports 500+ instructions and 150+ Linux syscalls,\nincluding fork() and clone(). Linux system calls may only be used by\nlong mode programs via the `SYSCALL` instruction, as it is written in\nthe System V ABI.\n\n### Instruction Sets\n\nThe following hardware ISAs are supported by Blink.\n\n- i8086\n- i386\n- X87\n- SSE2\n- x86_64\n- SSE3\n- SSSE3\n- CLMUL\n- POPCNT\n- ADX\n- BMI2\n- RDRND\n- RDSEED\n- RDTSCP\n\nPrograms may use `CPUID` to confirm the presence or absence of optional\ninstruction sets. Please note that Blink does not follow the same\nmonotonic progress as Intel's hardware. For example, BMI2 is supported;\nthis is an AVX2-encoded (VEX) instruction set, which Blink is able to\ndecode, even though the AVX2 ISA isn't supported. Therefore it's\nimportant to not glob ISAs into \"levels\" (as Windows software tends to\ndo) where it's assumed that BMI2 support implies AVX2 support; because\nwith Blink that currently isn't the case.\n\nOn the other hand, Blink does share Windows' x87 behavior w.r.t. double\n(rather than long double) precision. It's not possible to use 80-bit\nfloating point precision with Blink, because Blink simply passes along\nfloating point operations to the host architecture, and very few\narchitectures support `long double` precision. You can still use x87\nwith 80-bit words. Blink will just store 64-bit floating point values\ninside them, and that's a legal configuration according to the x87 FPU\ncontrol word. If possible, it's recommended that `long double` simply be\navoided. If 64-bit floating point [is good enough for the rocket\nscientists at\nNASA](https://www.jpl.nasa.gov/edu/news/2016/3/16/how-many-decimals-of-pi-do-we-really-need/)\nthen it should be good enough for everybody. There are some peculiar\ndifferences in behavior with `double` across architectures (which Blink\ncurrently does nothing to address) but they tend to be comparatively\nminor, e.g. an op returning `NAN` instead of `-NAN`.\n\nBlink has reasonably comprehensive coverage of the baseline ISAs,\nincluding even support for BCD operations (even in long mode!). But there\nare some truly fringe instructions Blink hasn't implemented, such as\n`BOUND` and `ENTER`. Most of the unsupported instructions, are usually\nring-0 system instructions, since Blink is primarily a user-mode VM, and\ntherefore only has limited support for bare metal operating system\nsoftware (which we'll discuss more in-depth in a later section).\n\nBlink advertises itself as `Linux 4.5` in the `uname()` system call and\n`uname -v` will report `blink-1.0`. Programs may detect they're running\nin Blink by issuing a `CPUID` instruction where `EAX` is set to the leaf\nnumber:\n\n- Leaf `0x0` (or `0x80000000`) reports `GenuineIntel` in\n  `EBX ‖ EDX ‖ ECX`\n\n- Leaf `0x1` reports that Blink is a hypervisor in bit `31` of `ECX`\n\n- Leaf `0x40000000` reports `GenuineBlink` as the hypervisor name in\n  `EBX ‖ ECX ‖ EDX`\n\n- Leaf `0x40031337` reports the underlying operating system name in\n  `EBX ‖ ECX ‖ EDX` with zero filling for strings shorter than 12:\n\n  - `Linux` for Linux\n  - `XNU` for macOS\n  - `FreeBSD` for FreeBSD\n  - `NetBSD` for NetBSD\n  - `OpenBSD` for OpenBSD\n  - `Linux` for Linux\n  - `Cygwin` for Windows under Cygwin\n  - `Windows` for Windows under Cosmopolitan\n  - `Unknown` if compiled on unrecognized platform\n\n- Leaf `0x40031338` reports the underlying hardware architecture name\n  in `EBX ‖ ECX ‖ EDX` with zero filling for strings shorter than 12:\n\n  - `x86_64` for x86_64\n  - `i386` for i386\n  - `aarch64` for aarch64\n  - `arm` for arm32\n  - `ppc64` for powerpc64\n  - `ppc64le` for powerpc64le\n  - `ppc` for powerpc\n  - `s390x` for s390x\n  - `riscv64` for riscv64\n  - `riscv32` for riscv32\n  - `Unknown` if compiled on unrecognized platform\n\n- Leaf `0x80000001` tells if Blink's JIT is enabled in bit `31` in `ECX`\n\n### JIT\n\nBlink uses just-in-time compilation, which is supported on x86_64 and\naarch64. Blink takes the appropriate steps to work around restrictions\nrelating to JIT, on platforms like Apple and OpenBSD. We generate JIT\ncode using a printf-style domain-specific language. The JIT works by\ngenerating functions at runtime which call the micro-op functions the\ncompiler created. To make micro-operations go faster, Blink determines\nthe byte length of the compiled function at runtime by scanning for a\nRET instruction. Blink will then copy the compiled function into the\nfunction that the JIT is generating. This works in most cases, however\nsome tools can cause problems. For example, OpenBSD RetGuard inserts\nstatic memory relocations into every compiled function, which Blink's\nJIT currently doesn't understand; so we need to use compiler flags to\ndisable that type of magic. In the event other such magic slips through,\nBlink has a runtime check which will catch obvious problems, and then\ngracefully fall back to using a CALL instruction. Since no JIT can be\nfully perfect on all platforms, the `blink -j` flag may be passed to\ndisable Blink's JIT. Please note that disabling JIT makes Blink go 10x\nslower. With the `blinkenlights` command, the `-j` flag takes on the\nopposite meaning, where it instead *enables* JIT. This can be useful for\ntroubleshooting the JIT, because the TUI display has a feature that lets\nJIT path formation be visualized. Blink currently only enables the JIT\nfor programs running in long mode (64-bit) but we may support JITing\n16-bit programs in the future.\n\n### Virtualization\n\nBlink virtualizes memory using the same PML4T approach as the hardware\nitself, where memory lookups are indirected through a four-level radix\ntree. Since performing four separate page table lookups on every memory\naccess can be slow, Blink checks a translation lookaside buffer, which\ncontains the sixteen most recently used page table entries. The PML4T\nallows all memory lookups in Blink to be \"safe\" but it still doesn't\noffer the best possible performance. Therefore, on systems with a huge\naddress space (i.e. petabytes of virtual memory) Blink relies on itself\nbeing loaded to a random location, and then identity maps guest memory\nusing a simple linear translation. For example, if the guest virtual\naddress is `0x400000` then the host address might be\n`0x400000+0x088800000000`. This means that each time a memory operation\nis executed, only a simple addition needs to be performed. This goes\nextremely fast, however it may present issues for programs that use\n`MAP_FIXED`. Some systems, such as modern Raspberry Pi, actually have a\nlarger address space than x86-64, which lets Blink offer the guest the\ncomplete address space. However on some platforms, like 32-bit ones,\nonly a limited number of identity mappings are possible. There's also\ncompiler tools like TSAN which lay claim to much of the fixed address\nspace. Blink's solution is designed to meet the needs of Cosmopolitan\nLibc, while working around Apple's restriction on 32-bit addresses, and\nstill remain fully compatible with ASAN's restrictions. In the event\nthat this translation scheme doesn't work on your system, the `blink -m`\nflag may be passed to disable the linear translation optimization, and\ninstead use only the memory safe full virtualization approach of the\nPML4T and TLB.\n\n#### Lockless Hashing\n\nBlink stores generated functions by virtual address in a multithreaded\nlockless hash table. The hottest operation in the codebase is reading\nfrom this hash table, using a function called `GetJitHook`. Since it'd\nslow Blink down by more than 33% if a mutex were used here, Blink will\nsynchronize reads optimistically using only carefully ordered load\ninstructions, three of which have acquire semantics. This hash table\nstarts off at a reasonable size and grows gradually with the memory\nrequirements. This design is the primary reason Blink usually uses 40%\nless peak resident memory than Qemu.\n\n#### Acyclic Codegen\n\nEven though JIT paths will always end at branching instructions, Blink\nwill generate code so that paths tail call into each other, in order to\navoid dropping back into the main interpreter loop. The average length\nof a JIT path is about ~5 opcodes. Connecting paths causes the average\npath length to be ~13 opcodes.\n\nSince Blink only checks for asynchronous signal delivery and shutdown\nevents from the main interpreter loop, Blink maintains a bidirectional\nmap of edges between generated functions, so that path connections which\nwould result in cycles are never introduced.\n\nAn exception is made for tight conditional branches, i.e. jumps whose\ntaken path jump backwards to the start of the JIT path. Such branches\nare allowed to be self-referencing so that whole loops of non-system\noperations may be run in purely native code.\n\n#### Reliable Memory\n\nBlink has a 22mb global static variable that's set aside for JIT code.\nThis limit was chosen because that's roughly the maximum displacement\npermitted on Arm64 architecture. Having that memory near the program\nimage helps make Blink simpler, since generated functions call normal\nfunctions, without needing relocations or procedure linkage tables.\n\nWhen Blink runs out of JIT memory, it simply clears all JIT hooks and\nlets the whole code generation process start again. Blink is very fast\nat generating code, and it wouldn't make sense during an OOM panic to\narbitrarily choose a subset of pages to reset, since resetting pages\nrequires tracing their dependencies and resetting those too. Starting\nover is much better. It's so much better in fact, that even if Blink\nonly reserved less than a megabyte of memory for JIT, then the slowdown\nthat'd be incurred running 40mb binaries like GCC CC1 would only be 3x.\n\nBlink triggers the OOM panic when only 10% of its JIT memory remains.\nThat's because in multi-threaded programs, there's no way to guarantee\nnothing is still executing on the retired code blocks. Blink solves this\nby letting retired blocks cool off at the back of a freelist queue, so\nthe acyclicity invariant has abundant time to ensure threads drop out.\n\n### Self-Modifying Code\n\nMany CPU architectures require esoteric rituals for flushing CPU caches\nwhen code modifies itself. That's not the case with x86 architecture,\nwhich takes care of this chore automatically. Blink is able to offer the\nsame promises here as Intel and AMD, by abstracting fast and automatic\ninvalidation of caches for programs using self-modifying code (SMC).\n\nWhen Blink's JIT isn't enabled, self-modifying code always causes\ninstruction caches to be invalidated immediately, at least within the\nsame thread. That's because Blink compares the raw instruction bytes\nwith what's in the instruction cache before fetching its decoded value.\n\nWhen JITing is enabled, Blink will automatically invalidate JIT memory\nassociated with code that's been modified. This happens on a 4096-byte\npage granularity. When a function like mprotect() is called that causes\nmemory pages to transition from a non-executable to executable state,\nthe impacted pages will be invalidated by the JIT. The JIT maintains a\nhash table where the key is the virtual address at which a generated\nfunction begins (which we call a \"path\") and the value is a function\npointer to the generated code. When Blink is generating paths, it is\ncareful to ensure that all the guest instructions which are added to a\npath, only exist within the confines of a single 4096-byte page. Thus\nwhen a page needs to be invalidated, Blink simply deletes any hook for\neach address within the page.\n\nWhen RWX memory is used, Blink can't rely on mprotect() to communicate\nthe intent of the guest program. What Blink will do instead is protect\nany RWX guest memory, so that it's registered as read-only in the host\noperating system. This way, whenever the guest writes to RWX memory, a\nSIGSEGV signal will be delivered to Blink, which then re-enables write\npermissions on the impacted RWX page, flips a bit to the thread in the\nSMC state and then permits execution to resume for at least one opcode\nbefore the interpreter loop notices the SMC state, invalidates the JIT\nand re-enables the memory protection. This means that:\n\n1. Memory ops in general aren't slowed down by Blink's SMC support\n2. RWX memory can be written-to with some overhead\n3. RWX memory can be read-from with zero overhead\n4. Changes take effect when a JIT path ends\n\nIntel's sixteen thousand page manual lays out the following guidelines\nfor conformant self-modifying code:\n\n> To write self-modifying code and ensure that it is compliant with\n> current and future versions of the IA-32 architectures, use one of\n> the following coding options:\n>\n> (* OPTION 1 *)  \n> Store modified code (as data) into code segment;  \n> Jump to new code or an intermediate location;  \n> Execute new code;\n>\n> (* OPTION 2 *)  \n> Store modified code (as data) into code segment;  \n> Execute a serializing instruction; (* For example, CPUID instruction *)  \n> Execute new code;\n>\n> ──Quoth Intel Manual V.3, §8.1.3\n\nBlink implements this behavior because branching instructions cause JIT\npaths to end, paths only jump into one another selectively , and lastly\nserializing instructions are never added to paths in the first place.\n\nIntel's rules allow Blink some leeway to make writing to RWX memory go\nfast, without causing any signal storms, or incurring too much system\ncall overhead. As an example, consider the internal statistics printed\nby the [`smc2_test.c`](test/func/smc2_test.c) program:\n\n```\nmake -j8 o//blink/blink o//test/func/smc2_test.elf\no//blink/blink -Z o//test/func/smc2_test.elf\n[...]\nicache_resets                    = 1\njit_blocks                       = 1\njit_hooks_installed              = 132\njit_hooks_deleted                = 19\njit_page_resets                  = 21\nsmc_checks                       = 22\nsmc_flushes                      = 22\nsmc_enqueued                     = 22\nsmc_segfaults                    = 22\n[...]\n```\n\nThe above program performs 300+ independent write operations to RWX\nmemory. However we can see very few of them resulted in segfaults, since\nmost of those ops happened in the SlowMemCpy() function which uses a\ntight conditional branch loop rather than a proper jump. This let the\nprogram get more accomplished, before dropping out of JIT code back into\nthe main interpreter loop, which is where Blink checks the SMC state in\norder to flush the caches reapply any missing write protection.\n\n## Pseudoteletypewriter\n\nBlink has an xterm-compatible ANSI pseudoteletypewriter display\nimplementation which allows Blink's TUI interface to host other TUI\nprograms, within an embedded terminal display. For example, it's\npossible to use Antirez's Kilo text editor inside Blink's TUI. For the\ncomplete list of ANSI sequences which are supported, please refer to\n[blink/pty.c](blink/pty.c).\n\nIn real mode, Blink's PTY can be configured via `INT $0x16` to convert\nCGA memory stored at address `0xb0000` into UNICODE block characters,\nthereby making retro video gaming in the terminal possible.\n\n## Real Mode\n\nBlink supports 16-bit BIOS programs, such as SectorLISP. To boot real\nmode programs in Blink, the `blinkenlights -r` flag may be passed, which\nputs the virtual machine in i8086 mode. Currently only a limited set of\nBIOS APIs are available. For example, Blink supports IBM PC Serial UART,\nCGA, and MDA. We hope to expand our real mode support in the near\nfuture, in order to run operating systems like ELKS.\n\nBlink supports troubleshooting operating system bootloaders. Blink was\ndesigned for Cosmopolitan Libc, which embeds an operating system in each\nbinary it compiles. Blink has helped us debug our bare metal support,\nsince Blink is capable of running in the 16-bit, 32-bit, and 64-bit\nmodes a bootloader requires at various stages. In order to do that, we\nneeded to implement some ring0 hardware instructions. Blink has enough\nto support Cosmopolitan, but it'll take much more time to get Blink to a\npoint where it can boot something like Windows.\n\n## Executable Formats\n\nBlink supports several different executable formats. You can run:\n\n- x86-64-linux ELF executables (both static and dynamic).\n\n- Actually Portable Executables, which have either the `MZqFpD` or\n  `jartsr` magic.\n\n- Flat executables, which must end with the file extension `.bin`. In\n  this case, you can make executables as small as 10 bytes in size,\n  since they're treated as raw x86-64 code. Blink always loads flat\n  executables to the address `0x400000` and automatically appends 16mb\n  of BSS memory.\n\n- Real mode executables, which are loaded to the address `0x7c00`. These\n  programs must be run using the `blinkenlights` command with the `-r`\n  flag.\n\n## Filesystems\n\nWhen Blink is built with the VFS feature enabled (`--enable-vfs`),\nit comes with three default filesystems:\n- `hostfs`: A filesystem that mirrors a certain directory on the\nhost's filesystem. Files on `hostfs` mounts have everything\nread from and written directly to the corresponding host directory,\nwith the exception of `st_dev` and `st_ino` fields. `st_dev` is\nmanaged by Blink's VFS subsystem, while `st_ino` is calculated using\na hash function based on the host's `st_dev` and `st_ino` value.\n- `proc`: A filesystem that emulates Linux's `/proc` using information\navailable to Blink.\n- `devfs`: A filesystem that emulates Linux's `/dev`. Currently, this\nis only a wrapper for `hostfs`.\n\nWhen Blink is launched, these default mount points are added:\n- `/` of type `hostfs` pointing to the corresponding host directory.\nThis is determined by querying `$BLINK_PREFIX` and the `-C` parameter\nin order and falls back to `/` if neither are available.\n- `/proc` of type `proc`.\n- `/dev` of type `devfs`.\n- `/SytemRoot` of type `hostfs` pointing to the host's root `/`.\n\nIt is possbile for programs to add additional mount points by using\nthe `mount` syscall (for `hostfs` mounts, pass the path to the\ndirectory on the _host_ as the `source` argument), but see the quirks\nbelow.\n\n## Quirks\n\nHere's the current list of Blink's known quirks and tradeoffs.\n\n### Flags\n\nFlag dependencies may not carry across function call boundaries under\nlong mode. This is because when Blink's JIT is speculating whether or\nnot it's necessary for an arithmetic instruction to compute flags, it\nconsiders `RET` and `CALL` terminal ops that break the chain. As such\n64-bit code shouldn't do things we did in the DOS days, such as using\ncarry flag as a return value to indicate error. This should work fine\nwhen `STC` is used to set the carry flag, but if the code computes it\ncleverly using instructions like `SUB`, then EFLAGS might not change.\n\nAs a special case, if a `RET` instruction sports a `REP` prefix, then\nBlink can return flags across the `RET`.\n\n### Faults\n\nBlink may not report the precise program counter where a fault occurred\nin `ucontext_t::uc_mcontext::rip` when signalling a segmentation fault.\nThis is currently only possible when `PUSH` or `POP` access bad memory.\nThat's because Blink's JIT tries to avoid updating `Machine::ip` on ops\nit considers \"pure\" such as those that only access registers, which for\nreasons of performance is defined to include pushing and popping.\n\n### Threads\n\nBlink doesn't have a working implementation of `set_robust_list()` yet,\nwhich means robust mutexes might not get unlocked if a process crashes.\n\n### Coherency\n\nPOSIX.1 provides almost no guarantees of coherency, synchronization, and\ndurability when it comes to `MAP_SHARED` mappings and recommends that\nmsync() be explicitly used to synchronize memory with file contents. The\nLinux Kernel implements shared memory so well, that this is rarely\nnecessary. However some platforms like OpenBSD lack write coherency.\nThis means if you change a shared writable memory map and then call\npread() on the associated file region, you might get stale data. Blink\nisn't able to polyfill incoherent platforms to be as coherent as Linux,\ntherefore apps that run in Blink should assume the POSIX rules apply.\n\n### Signal Handling\n\nBlink uses `SIGSYS` to deliver signals internally. This signal is\nprecious to Blink. It's currently not possible for guest applications to\ncapture it from external processes.\n\n### Memory Protection\n\nBlink offers guest programs a 48-bit virtual address space with a\n4096-byte page size. When programs are run on (1) host systems that have\na larger page (e.g. Apple M1, Cygwin), and (2) the linear memory\noptimization is enabled (i.e. you're *not* using `blink -m`) then Blink\nmay need to relax memory protections in cases where the memory intervals\ndefined by the guest aren't aligned to the host system page size. This\nmeans that, on system with a larger than 4096 byte page size:\n\n1. Misaligned read-only pages could become writable\n2. JIT hooks might not invalidate automatically on misaligned RWX pages\n\nIt's recommended, when calling functions like mmap() and mprotect(),\nthat both `addr` and `addr + size` be aliged to the host page size.\nBlink reports that value to the guest program in `getauxval(AT_PAGESZ)`,\nwhich should be obtainable via the POSIX API `sysconf(_SC_PAGESIZE)` if\nthe C library is implemented correctly. Please note that when Blink is\nrunning in full virtualization mode (i.e. `blink -m`) this concern no\nlonger applies. That's because Blink will allocate a full system page\nfor every 4096 byte page that's mapped from a file.\n\n### Process Management\n\nFor builds with the VFS feature enabled (--enable-vfs), while a `procfs`\nmount is available at `/proc`, it is limited to information available\nin a single process. Only `/proc/self` and the corresponding PID folder\nis available. This means programs can get the expected values at\n`/proc/self/exe` and similar files, but process management tools like\n`ps` will not work.\n\nOn Linux, some `procfs` symlinks possess a hardlink-like ability of\nbeing dereferenceable even after the target has been `unlink`ed.\nBlink's implementation currently does not support this use case.\n\n### Mounts\n\nFor builds with the VFS feature enabled (`--enable-vfs`), Blink does not\nshare mount information with other emulated processes. As a result,\ncommands like this may seem to work (by return a 0 status code):\n\n```sh\nmount -t hostfs /some/path/on/host folder\n```\n\nBut subsequent calls to `ls folder` on the same shell still does not\ndisplay the expected contents. This is because the `mount` command\ncould only modify the mount table kept by itself (and propagated to\nchildren through `fork`), but not the one used by its parent shell.\nIn other words, Blink behaves as if `CLONE_NEWNS` is added to every\n`clone` call, separating the mount namespace of the child from its\nparent.\n\nSome might view this behavior as a feature, but it diverges from\nclassic system behavior; a mechanism for handling shared process\nstate is being considered in\n[#92](https://github.com/jart/blink/issues/92).\n"
  },
  {
    "path": "blink/abort.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdlib.h>\n\n#include \"blink/assert.h\"\n#include \"blink/macros.h\"\n#include \"blink/stats.h\"\n#include \"blink/util.h\"\n\nstatic struct AbortHooks {\n  int n;\n  aborthook_f *p[4];\n} g_aborthooks;\n\nvoid AtAbort(aborthook_f *hook) {\n  unassert(g_aborthooks.n < ARRAYLEN(g_aborthooks.p));\n  g_aborthooks.p[g_aborthooks.n++] = hook;\n}\n\nvoid Abort(void) {\n  int i;\n#ifndef NDEBUG\n  if (FLAG_statistics) {\n    PrintStats();\n  }\n#endif\n  for (i = g_aborthooks.n; i--;) {\n    g_aborthooks.p[i]();\n  }\n  abort();\n}\n"
  },
  {
    "path": "blink/address.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n#include \"blink/x86.h\"\n\ni64 GetPc(struct Machine *m) {\n  return m->cs.base + GetIp(m);\n}\n\ni64 GetIp(struct Machine *m) {\n  return MaskAddress(m->mode.omode, m->ip);\n}\n\nu64 MaskAddress(u32 mode, u64 x) {\n  if (mode != XED_MODE_LONG) {\n    if (mode == XED_MODE_REAL) {\n      x &= 0xffff;\n    } else {\n      x &= 0xffffffff;\n    }\n  }\n  return x;\n}\n\ni64 AddSegment(P, u64 i, u64 s) {\n  if (!Sego(rde)) {\n    return i + s;\n  } else {\n    return i + m->seg[Sego(rde) - 1].base;\n  }\n}\n\nu64 AddressOb(P) {\n  return AddSegment(A, disp, m->ds.base);\n}\n\nu64 GetSegmentBase(P, unsigned s) {\n  if (s < 6) {\n    return m->seg[s].base;\n  } else {\n    OpUdImpl(m);\n  }\n}\n\ni64 DataSegment(P, u64 i) {\n  return AddSegment(A, i, m->ds.base);\n}\n\ni64 AddressSi(P) {\n  switch (Eamode(rde)) {\n    case XED_MODE_LONG:\n      return DataSegment(A, Get64(m->si));\n    case XED_MODE_REAL:\n      return DataSegment(A, Get16(m->si));\n    case XED_MODE_LEGACY:\n      return DataSegment(A, Get32(m->si));\n    default:\n      __builtin_unreachable();\n  }\n}\n\nu64 AddressDi(P) {\n  u64 i = m->es.base;\n  switch (Eamode(rde)) {\n    case XED_MODE_LONG:\n      return i + Get64(m->di);\n    case XED_MODE_REAL:\n      return i + Get16(m->di);\n    case XED_MODE_LEGACY:\n      return i + Get32(m->di);\n    default:\n      __builtin_unreachable();\n  }\n}\n"
  },
  {
    "path": "blink/alu.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/alu.h\"\n\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n\nconst aluop_f kAlu[12][4] = {\n    {Add8, Add16, Add32, Add64},  //\n    {Or8, Or16, Or32, Or64},      //\n    {Adc8, Adc16, Adc32, Adc64},  //\n    {Sbb8, Sbb16, Sbb32, Sbb64},  //\n    {And8, And16, And32, And64},  //\n    {Sub8, Sub16, Sub32, Sub64},  //\n    {Xor8, Xor16, Xor32, Xor64},  //\n    {Sub8, Sub16, Sub32, Sub64},  //\n    {Not8, Not16, Not32, Not64},  //\n    {Neg8, Neg16, Neg32, Neg64},  //\n    {Inc8, Inc16, Inc32, Inc64},  //\n    {Dec8, Dec16, Dec32, Dec64},  //\n};\n\nconst aluop_f kBsu[8][4] = {\n    {Rol8, Rol16, Rol32, Rol64},  //\n    {Ror8, Ror16, Ror32, Ror64},  //\n    {Rcl8, Rcl16, Rcl32, Rcl64},  //\n    {Rcr8, Rcr16, Rcr32, Rcr64},  //\n    {Shl8, Shl16, Shl32, Shl64},  //\n    {Shr8, Shr16, Shr32, Shr64},  //\n    {Shl8, Shl16, Shl32, Shl64},  //\n    {Sar8, Sar16, Sar32, Sar64},  //\n};\n\nstatic i64 AluFlags(struct Machine *m, u64 x, u32 af, u32 of, u32 cf, u32 sf) {\n  m->flags &= ~(CF | ZF | SF | OF | AF | 0xFF000000u);\n  m->flags |= sf << FLAGS_SF | cf << FLAGS_CF | !x << FLAGS_ZF |\n              of << FLAGS_OF | af << FLAGS_AF | (x & 0xFF) << 24;\n  return x;\n}\n\nstatic i64 AluFlags8(struct Machine *m, u8 z, u32 af, u32 of, u32 cf) {\n  return AluFlags(m, z, af, of, cf, z >> 7);\n}\n\ni64 Xor8(struct Machine *m, u64 x, u64 y) {\n  return AluFlags8(m, x ^ y, 0, 0, 0);\n}\n\ni64 Or8(struct Machine *m, u64 x, u64 y) {\n  return AluFlags8(m, x | y, 0, 0, 0);\n}\n\ni64 And8(struct Machine *m, u64 x, u64 y) {\n  return AluFlags8(m, x & y, 0, 0, 0);\n}\n\ni64 Sub8(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u8 x, y, z;\n  x = x64;\n  y = y64;\n  z = x - y;\n  cf = x < z;\n  af = (x & 15) < (z & 15);\n  of = ((x ^ y) & (z ^ x)) >> 7;\n  return AluFlags8(m, z, af, of, cf);\n}\n\ni64 Add8(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u8 x, y, z;\n  x = x64;\n  y = y64;\n  z = x + y;\n  cf = z < y;\n  af = (z & 15) < (y & 15);\n  of = ((z ^ x) & (z ^ y)) >> 7;\n  return AluFlags8(m, z, af, of, cf);\n}\n\nstatic i64 AluFlags32(struct Machine *m, u32 z, u32 af, u32 of, u32 cf) {\n  return AluFlags(m, z, af, of, cf, z >> 31);\n}\n\ni64 Xor32(struct Machine *m, u64 x, u64 y) {\n  return AluFlags32(m, x ^ y, 0, 0, 0);\n}\n\ni64 Or32(struct Machine *m, u64 x, u64 y) {\n  return AluFlags32(m, x | y, 0, 0, 0);\n}\n\ni64 And32(struct Machine *m, u64 x, u64 y) {\n  return AluFlags32(m, x & y, 0, 0, 0);\n}\n\ni64 Sub32(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u32 x, y, z;\n  x = x64;\n  y = y64;\n  z = x - y;\n  cf = x < z;\n  af = (x & 15) < (z & 15);\n  of = ((x ^ y) & (z ^ x)) >> 31;\n  return AluFlags32(m, z, af, of, cf);\n}\n\ni64 Add32(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u32 x, y, z;\n  x = x64;\n  y = y64;\n  z = x + y;\n  cf = z < y;\n  af = (z & 15) < (y & 15);\n  of = ((z ^ x) & (z ^ y)) >> 31;\n  return AluFlags32(m, z, af, of, cf);\n}\n\nstatic i64 AluFlags64(struct Machine *m, u64 z, u32 af, u32 of, u32 cf) {\n  return AluFlags(m, z, af, of, cf, z >> 63);\n}\n\ni64 Xor64(struct Machine *m, u64 x, u64 y) {\n  return AluFlags64(m, x ^ y, 0, 0, 0);\n}\n\ni64 Or64(struct Machine *m, u64 x, u64 y) {\n  return AluFlags64(m, x | y, 0, 0, 0);\n}\n\ni64 And64(struct Machine *m, u64 x, u64 y) {\n  return AluFlags64(m, x & y, 0, 0, 0);\n}\n\ni64 Sub64(struct Machine *m, u64 x, u64 y) {\n  u64 z;\n  bool cf, of, af;\n  z = x - y;\n  cf = x < z;\n  af = (x & 15) < (z & 15);\n  of = ((x ^ y) & (z ^ x)) >> 63;\n  return AluFlags64(m, z, af, of, cf);\n}\n\ni64 Add64(struct Machine *m, u64 x, u64 y) {\n  u64 z;\n  bool cf, of, af;\n  z = x + y;\n  cf = z < y;\n  af = (z & 15) < (y & 15);\n  of = ((z ^ x) & (z ^ y)) >> 63;\n  return AluFlags64(m, z, af, of, cf);\n}\n\ni64 Adc8(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u8 x, y, z, t;\n  x = x64;\n  y = y64;\n  t = x + !!(m->flags & CF);\n  z = t + y;\n  cf = (t < x) | (z < y);\n  of = ((z ^ x) & (z ^ y)) >> 7;\n  af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15));\n  return AluFlags8(m, z, af, of, cf);\n}\n\ni64 Adc32(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u32 x, y, z, t;\n  x = x64;\n  y = y64;\n  t = x + !!(m->flags & CF);\n  z = t + y;\n  cf = (t < x) | (z < y);\n  of = ((z ^ x) & (z ^ y)) >> 31;\n  af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15));\n  return AluFlags32(m, z, af, of, cf);\n}\n\ni64 Adc64(struct Machine *m, u64 x, u64 y) {\n  u64 z, t;\n  bool cf, of, af;\n  t = x + !!(m->flags & CF);\n  z = t + y;\n  cf = (t < x) | (z < y);\n  of = ((z ^ x) & (z ^ y)) >> 63;\n  af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15));\n  return AluFlags64(m, z, af, of, cf);\n}\n\ni64 Sbb8(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u8 x, y, z, t;\n  x = x64;\n  y = y64;\n  t = x - !!(m->flags & CF);\n  z = t - y;\n  cf = (x < t) | (t < z);\n  of = ((z ^ x) & (x ^ y)) >> 7;\n  af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15));\n  return AluFlags8(m, z, af, of, cf);\n}\n\ni64 Sbb32(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u32 x, y, z, t;\n  x = x64;\n  y = y64;\n  t = x - !!(m->flags & CF);\n  z = t - y;\n  cf = (x < t) | (t < z);\n  of = ((z ^ x) & (x ^ y)) >> 31;\n  af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15));\n  return AluFlags32(m, z, af, of, cf);\n}\n\ni64 Sbb64(struct Machine *m, u64 x, u64 y) {\n  u64 z, t;\n  bool cf, of, af;\n  t = x - !!(m->flags & CF);\n  z = t - y;\n  cf = (x < t) | (t < z);\n  of = ((z ^ x) & (x ^ y)) >> 63;\n  af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15));\n  return AluFlags64(m, z, af, of, cf);\n}\n\ni64 Neg8(struct Machine *m, u64 x64, u64 y) {\n  u8 x;\n  bool cf, of, af;\n  x = x64;\n  af = cf = !!x;\n  of = x == 0x80;\n  x = ~x + 1;\n  return AluFlags8(m, x, af, of, cf);\n}\n\ni64 Neg32(struct Machine *m, u64 x64, u64 y) {\n  u32 x;\n  bool cf, of, af;\n  x = x64;\n  af = cf = !!x;\n  of = x == 0x80000000;\n  x = ~x + 1;\n  return AluFlags32(m, x, af, of, cf);\n}\n\ni64 Neg64(struct Machine *m, u64 x64, u64 y) {\n  u64 x;\n  bool cf, of, af;\n  x = x64;\n  af = cf = !!x;\n  of = x == 0x8000000000000000;\n  x = ~x + 1;\n  return AluFlags64(m, x, af, of, cf);\n}\n\nstatic i64 BumpFlags(struct Machine *m, u64 x, u32 af, u32 of, u32 sf) {\n  return AluFlags(m, x, af, of, !!(m->flags & CF), sf);\n}\n\ni64 Dec32(struct Machine *m, u64 x64, u64 y) {\n  u32 x, z, of, sf, af;\n  x = x64;\n  z = x - 1;\n  sf = z >> 31;\n  af = (x & 15) < (z & 15);\n  of = ((z ^ x) & (x ^ 1)) >> 31;\n  return BumpFlags(m, z, af, of, sf);\n}\n\ni64 Inc32(struct Machine *m, u64 x64, u64 y) {\n  u32 x, z, of, sf, af;\n  x = x64;\n  z = x + 1;\n  sf = z >> 31;\n  af = (z & 15) < (y & 15);\n  of = ((z ^ x) & (z ^ 1)) >> 31;\n  return BumpFlags(m, z, af, of, sf);\n}\n\ni64 Inc64(struct Machine *m, u64 x, u64 y) {\n  u64 z;\n  u32 of, sf, af;\n  z = x + 1;\n  sf = z >> 63;\n  af = (z & 15) < (y & 15);\n  of = ((z ^ x) & (z ^ 1)) >> 63;\n  return BumpFlags(m, z, af, of, sf);\n}\n\ni64 Dec64(struct Machine *m, u64 x, u64 y) {\n  u64 z;\n  u32 of, sf, af;\n  z = x - 1;\n  sf = z >> 63;\n  af = (x & 15) < (z & 15);\n  of = ((z ^ x) & (x ^ 1)) >> 63;\n  return BumpFlags(m, z, af, of, sf);\n}\n\ni64 Inc8(struct Machine *m, u64 x64, u64 y) {\n  u8 x, z;\n  u32 of, sf, af;\n  x = x64;\n  z = x + 1;\n  sf = z >> 7;\n  af = (z & 15) < (y & 15);\n  of = ((z ^ x) & (z ^ 1)) >> 7;\n  return BumpFlags(m, z, af, of, sf);\n}\n\ni64 Dec8(struct Machine *m, u64 x64, u64 y) {\n  u8 x, z;\n  u32 of, sf, af;\n  x = x64;\n  z = x - 1;\n  sf = z >> 7;\n  af = (x & 15) < (z & 15);\n  of = ((z ^ x) & (x ^ 1)) >> 7;\n  return BumpFlags(m, z, af, of, sf);\n}\n\ni64 Shr8(struct Machine *m, u64 x64, u64 y) {\n  u32 x, cf;\n  x = x64 & 0xff;\n  if ((y &= 31)) {\n    cf = (x >> (y - 1)) & 1;\n    x >>= y;\n    return AluFlags8(m, x, 0, ((x << 1) ^ x) >> 7, cf);\n  } else {\n    return x;\n  }\n}\n\ni64 Shr32(struct Machine *m, u64 x64, u64 y) {\n  u32 cf, x = x64;\n  if ((y &= 31)) {\n    cf = (x >> (y - 1)) & 1;\n    x >>= y;\n    return AluFlags32(m, x, 0, ((x << 1) ^ x) >> 31, cf);\n  } else {\n    return x;\n  }\n}\n\ni64 Shr64(struct Machine *m, u64 x, u64 y) {\n  u32 cf;\n  if ((y &= 63)) {\n    cf = (x >> (y - 1)) & 1;\n    x >>= y;\n    return AluFlags64(m, x, 0, ((x << 1) ^ x) >> 63, cf);\n  } else {\n    return x;\n  }\n}\n\ni64 Shl8(struct Machine *m, u64 x64, u64 y) {\n  u32 x, cf;\n  x = x64 & 0xff;\n  if ((y &= 31)) {\n    cf = (x >> ((8 - y) & 31)) & 1;\n    x = (x << y) & 0xff;\n    return AluFlags8(m, x, 0, (x >> 7) ^ cf, cf);\n  } else {\n    return x;\n  }\n}\n\ni64 Shl32(struct Machine *m, u64 x64, u64 y) {\n  u32 cf, x = x64;\n  if ((y &= 31)) {\n    cf = (x >> (32 - y)) & 1;\n    x <<= y;\n    return AluFlags32(m, x, 0, (x >> 31) ^ cf, cf);\n  } else {\n    return x;\n  }\n}\n\ni64 Shl64(struct Machine *m, u64 x, u64 y) {\n  u32 cf;\n  if ((y &= 63)) {\n    cf = (x >> (64 - y)) & 1;\n    x <<= y;\n    return AluFlags64(m, x, 0, (x >> 63) ^ cf, cf);\n  } else {\n    return x;\n  }\n}\n\ni64 Sar8(struct Machine *m, u64 x64, u64 y) {\n  u32 x, cf;\n  x = x64 & 0xff;\n  if ((y &= 31)) {\n    cf = ((i32)(i8)x >> (y - 1)) & 1;\n    x = ((i32)(i8)x >> y) & 0xff;\n    return AluFlags8(m, x, 0, 0, cf);\n  } else {\n    return x;\n  }\n}\n\ni64 Sar32(struct Machine *m, u64 x64, u64 y) {\n  u32 cf, x = x64;\n  if ((y &= 31)) {\n    cf = ((i32)x >> (y - 1)) & 1;\n    x = (i32)x >> y;\n    return AluFlags32(m, x, 0, 0, cf);\n  } else {\n    return x;\n  }\n}\n\ni64 Sar64(struct Machine *m, u64 x, u64 y) {\n  u32 cf;\n  if ((y &= 63)) {\n    cf = ((i64)x >> (y - 1)) & 1;\n    x = (i64)x >> y;\n    return AluFlags64(m, x, 0, 0, cf);\n  } else {\n    return x;\n  }\n}\n\nstatic i64 RotateFlags(struct Machine *m, u64 x, u32 cf, u32 of) {\n  m->flags &= ~(CF | OF);\n  m->flags |= cf << FLAGS_CF | of << FLAGS_OF;\n  return x;\n}\n\ni64 Rol32(struct Machine *m, u64 x64, u64 y) {\n  u32 x = x64;\n  if ((y &= 31)) {\n    x = x << y | x >> (32 - y);\n    return RotateFlags(m, x, x & 1, ((x >> 31) ^ x) & 1);\n  } else {\n    return x;\n  }\n}\n\ni64 Rol64(struct Machine *m, u64 x, u64 y) {\n  if ((y &= 63)) {\n    x = x << y | x >> (64 - y);\n    return RotateFlags(m, x, x & 1, ((x >> 63) ^ x) & 1);\n  } else {\n    return x;\n  }\n}\n\ni64 Ror32(struct Machine *m, u64 x64, u64 y) {\n  u32 x = x64;\n  if ((y &= 31)) {\n    x = x >> y | x << (32 - y);\n    return RotateFlags(m, x, x >> 31, ((x >> 31) ^ (x >> 30)) & 1);\n  } else {\n    return x;\n  }\n}\n\ni64 Ror64(struct Machine *m, u64 x, u64 y) {\n  if ((y &= 63)) {\n    x = x >> y | x << (64 - y);\n    return RotateFlags(m, x, x >> 63, ((x >> 63) ^ (x >> 62)) & 1);\n  } else {\n    return x;\n  }\n}\n\ni64 Rol8(struct Machine *m, u64 x64, u64 y) {\n  u8 x = x64;\n  if (y & 31) {\n    if ((y &= 7)) x = x << y | x >> (8 - y);\n    return RotateFlags(m, x, x & 1, ((x >> 7) ^ x) & 1);\n  } else {\n    return x;\n  }\n}\n\ni64 Ror8(struct Machine *m, u64 x64, u64 y) {\n  u8 x = x64;\n  if (y & 31) {\n    if ((y &= 7)) x = x >> y | x << (8 - y);\n    return RotateFlags(m, x, x >> 7, ((x >> 7) ^ (x >> 6)) & 1);\n  } else {\n    return x;\n  }\n}\n\nstatic i64 Rcr(struct Machine *m, u64 x, u64 y, u64 xm, u64 k) {\n  u64 cf;\n  u32 ct;\n  x &= xm;\n  if (y) {\n    cf = !!(m->flags & CF);\n    ct = (x >> (y - 1)) & 1;\n    if (y == 1) {\n      x = (x >> 1 | cf << (k - 1)) & xm;\n    } else {\n      x = (x >> y | cf << (k - y) | x << (k + 1 - y)) & xm;\n    }\n    return RotateFlags(m, x, ct, (((x << 1) ^ x) >> (k - 1)) & 1);\n  } else {\n    return x;\n  }\n}\n\ni64 Rcr8(struct Machine *m, u64 x, u64 y) {\n  return Rcr(m, x, ((unsigned)y & 31) % 9, 0xff, 8);\n}\n\ni64 Rcr16(struct Machine *m, u64 x, u64 y) {\n  return Rcr(m, x, ((unsigned)y & 31) % 17, 0xffff, 16);\n}\n\ni64 Rcr32(struct Machine *m, u64 x, u64 y) {\n  return Rcr(m, x, y & 31, 0xffffffff, 32);\n}\n\ni64 Rcr64(struct Machine *m, u64 x, u64 y) {\n  return Rcr(m, x, y & 63, 0xffffffffffffffff, 64);\n}\n\nstatic i64 Rcl(struct Machine *m, u64 x, u64 y, u64 xm, u64 k) {\n  u64 cf;\n  u32 ct;\n  x &= xm;\n  if (y) {\n    cf = !!(m->flags & CF);\n    ct = (x >> (k - y)) & 1;\n    if (y == 1) {\n      x = (x << 1 | cf) & xm;\n    } else {\n      x = (x << y | cf << (y - 1) | x >> (k + 1 - y)) & xm;\n    }\n    return RotateFlags(m, x, ct, ct ^ ((x >> (k - 1)) & 1));\n  } else {\n    return x;\n  }\n}\n\ni64 Rcl8(struct Machine *m, u64 x, u64 y) {\n  return Rcl(m, x, ((unsigned)y & 31) % 9, 0xff, 8);\n}\n\ni64 Rcl16(struct Machine *m, u64 x, u64 y) {\n  return Rcl(m, x, ((unsigned)y & 31) % 17, 0xffff, 16);\n}\n\ni64 Rcl32(struct Machine *m, u64 x, u64 y) {\n  return Rcl(m, x, y & 31, 0xffffffff, 32);\n}\n\ni64 Rcl64(struct Machine *m, u64 x, u64 y) {\n  return Rcl(m, x, y & 63, 0xffffffffffffffff, 64);\n}\n\nu64 BsuDoubleShift(struct Machine *m, int w, u64 x, u64 y, u8 b, bool isright) {\n  bool cf, of;\n  u64 s, k, M, z;\n  k = 8;\n  k <<= w;\n  s = 1;\n  s <<= k - 1;\n  M = s | (s - 1);\n  b &= w == 3 ? 63 : 31;\n  x &= M;\n  if (b) {\n    if (isright) {\n      z = x >> b | y << (k - b);\n      cf = (x >> (b - 1)) & 1;\n      of = b == 1 && (z & s) != (x & s);\n    } else {\n      z = x << b | y >> (k - b);\n      cf = (x >> (k - b)) & 1;\n      of = b == 1 && (z & s) != (x & s);\n    }\n    x = z;\n    x &= M;\n    return AluFlags(m, x, 0, of, cf, !!(x & s));\n  } else {\n    return x;\n  }\n}\n\nstatic i64 AluFlags16(struct Machine *m, u16 z, u32 af, u32 of, u32 cf) {\n  return AluFlags(m, z, af, of, cf, z >> 15);\n}\n\ni64 Xor16(struct Machine *m, u64 x, u64 y) {\n  return AluFlags16(m, x ^ y, 0, 0, 0);\n}\n\ni64 Or16(struct Machine *m, u64 x, u64 y) {\n  return AluFlags16(m, x | y, 0, 0, 0);\n}\n\ni64 And16(struct Machine *m, u64 x, u64 y) {\n  return AluFlags16(m, x & y, 0, 0, 0);\n}\n\ni64 Sub16(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u16 x, y, z;\n  x = x64;\n  y = y64;\n  z = x - y;\n  cf = x < z;\n  af = (x & 15) < (z & 15);\n  of = ((x ^ y) & (z ^ x)) >> 15;\n  return AluFlags16(m, z, af, of, cf);\n}\n\ni64 Add16(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u16 x, y, z;\n  x = x64;\n  y = y64;\n  z = x + y;\n  cf = z < y;\n  af = (z & 15) < (y & 15);\n  of = ((z ^ x) & (z ^ y)) >> 15;\n  return AluFlags16(m, z, af, of, cf);\n}\n\ni64 Adc16(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u16 x, y, z, t;\n  x = x64;\n  y = y64;\n  t = x + !!(m->flags & CF);\n  z = t + y;\n  cf = (t < x) | (z < y);\n  of = ((z ^ x) & (z ^ y)) >> 15;\n  af = ((t & 15) < (x & 15)) | ((z & 15) < (y & 15));\n  return AluFlags16(m, z, af, of, cf);\n}\n\ni64 Sbb16(struct Machine *m, u64 x64, u64 y64) {\n  bool cf, of, af;\n  u16 x, y, z, t;\n  x = x64;\n  y = y64;\n  t = x - !!(m->flags & CF);\n  z = t - y;\n  cf = (x < t) | (t < z);\n  of = ((z ^ x) & (x ^ y)) >> 15;\n  af = ((x & 15) < (t & 15)) | ((t & 15) < (z & 15));\n  return AluFlags16(m, z, af, of, cf);\n}\n\ni64 Neg16(struct Machine *m, u64 x64, u64 y) {\n  u16 x;\n  bool cf, of, af;\n  x = x64;\n  af = cf = !!x;\n  of = x == 0x8000;\n  x = ~x + 1;\n  return AluFlags16(m, x, af, of, cf);\n}\n\ni64 Inc16(struct Machine *m, u64 x64, u64 y) {\n  u16 x, z;\n  u32 of, sf, af;\n  x = x64;\n  z = x + 1;\n  sf = z >> 15;\n  af = (z & 15) < (y & 15);\n  of = ((z ^ x) & (z ^ 1)) >> 15;\n  return BumpFlags(m, z, af, of, sf);\n}\n\ni64 Dec16(struct Machine *m, u64 x64, u64 y) {\n  u16 x, z;\n  u32 of, sf, af;\n  x = x64;\n  z = x - 1;\n  sf = z >> 15;\n  af = (x & 15) < (z & 15);\n  of = ((z ^ x) & (x ^ 1)) >> 15;\n  return BumpFlags(m, z, af, of, sf);\n}\n\ni64 Shr16(struct Machine *m, u64 x64, u64 y) {\n  u32 x, cf;\n  x = x64 & 0xffff;\n  if ((y &= 31)) {\n    cf = (x >> (y - 1)) & 1;\n    x >>= y;\n    return AluFlags16(m, x, 0, ((x << 1) ^ x) >> 15, cf);\n  } else {\n    return x;\n  }\n}\n\ni64 Shl16(struct Machine *m, u64 x64, u64 y) {\n  u32 x, cf;\n  x = x64 & 0xffff;\n  if ((y &= 31)) {\n    cf = (x >> ((16 - y) & 31)) & 1;\n    x = (x << y) & 0xffff;\n    return AluFlags16(m, x, 0, (x >> 15) ^ cf, cf);\n  } else {\n    return x;\n  }\n}\n\ni64 Sar16(struct Machine *m, u64 x64, u64 y) {\n  u32 x, cf;\n  x = x64 & 0xffff;\n  if ((y &= 31)) {\n    cf = ((i32)(i16)x >> (y - 1)) & 1;\n    x = ((i32)(i16)x >> y) & 0xffff;\n    return AluFlags16(m, x, 0, 0, cf);\n  } else {\n    return x;\n  }\n}\n\ni64 Rol16(struct Machine *m, u64 x64, u64 y) {\n  u16 x = x64;\n  if (y & 31) {\n    if ((y &= 15)) x = x << y | x >> (16 - y);\n    return RotateFlags(m, x, x & 1, ((x >> 15) ^ x) & 1);\n  } else {\n    return x;\n  }\n}\n\ni64 Ror16(struct Machine *m, u64 x64, u64 y) {\n  u16 x = x64;\n  if (y & 31) {\n    if ((y &= 15)) x = x >> y | x << (16 - y);\n    return RotateFlags(m, x, x >> 15, ((x >> 15) ^ (x >> 14)) & 1);\n  } else {\n    return x;\n  }\n}\n"
  },
  {
    "path": "blink/alu.h",
    "content": "#ifndef BLINK_ALU_H_\n#define BLINK_ALU_H_\n#include <stdbool.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/intrin.h\"\n#include \"blink/machine.h\"\n#include \"blink/types.h\"\n\n#define ALU_ADD 0\n#define ALU_OR  1\n#define ALU_ADC 2\n#define ALU_SBB 3\n#define ALU_AND 4\n#define ALU_SUB 5\n#define ALU_XOR 6\n#define ALU_CMP 7\n#define ALU_NOT 8\n#define ALU_NEG 9\n#define ALU_INC 10\n#define ALU_DEC 11\n\n#define BSU_ROL 0\n#define BSU_ROR 1\n#define BSU_RCL 2\n#define BSU_RCR 3\n#define BSU_SHL 4\n#define BSU_SHR 5\n#define BSU_SAL 6\n#define BSU_SAR 7\n\n#define ALU_INT8  0\n#define ALU_INT16 1\n#define ALU_INT32 2\n#define ALU_INT64 3\n\ntypedef i64 (*aluop_f)(struct Machine *, u64, u64);\n\nextern const aluop_f kAlu[12][4];\nextern const aluop_f kBsu[8][4];\nextern const aluop_f kJustAlu[8];\nextern const aluop_f kJustBsu[8];\nextern const aluop_f kFastDec[4];\nextern const aluop_f kJustBsu32[8];\nextern const aluop_f kAluFast[8][4];\nextern const aluop_f kJustBsuCl32[8];\nextern const aluop_f kJustBsuCl64[8];\n\ni64 JustDec(u64);\ni64 JustNeg(u64);\ni64 JustAdd(struct Machine *, u64, u64);\ni64 JustOr(struct Machine *, u64, u64);\ni64 JustAdc(struct Machine *, u64, u64);\ni64 JustSbb(struct Machine *, u64, u64);\ni64 JustAnd(struct Machine *, u64, u64);\ni64 JustSub(struct Machine *, u64, u64);\ni64 JustXor(struct Machine *, u64, u64);\n\ni64 Xor8(struct Machine *, u64, u64);\ni64 Xor16(struct Machine *, u64, u64);\ni64 Xor32(struct Machine *, u64, u64);\ni64 Xor64(struct Machine *, u64, u64);\ni64 Or8(struct Machine *, u64, u64);\ni64 Or16(struct Machine *, u64, u64);\ni64 Or32(struct Machine *, u64, u64);\ni64 Or64(struct Machine *, u64, u64);\ni64 And8(struct Machine *, u64, u64);\ni64 And16(struct Machine *, u64, u64);\ni64 And32(struct Machine *, u64, u64);\ni64 And64(struct Machine *, u64, u64);\ni64 Sub8(struct Machine *, u64, u64);\ni64 Sbb8(struct Machine *, u64, u64);\ni64 Sub16(struct Machine *, u64, u64);\ni64 Sbb16(struct Machine *, u64, u64);\ni64 Sub32(struct Machine *, u64, u64);\ni64 Sbb32(struct Machine *, u64, u64);\ni64 Sub64(struct Machine *, u64, u64);\ni64 Sbb64(struct Machine *, u64, u64);\ni64 Add8(struct Machine *, u64, u64);\ni64 Adc8(struct Machine *, u64, u64);\ni64 Add16(struct Machine *, u64, u64);\ni64 Adc16(struct Machine *, u64, u64);\ni64 Add32(struct Machine *, u64, u64);\ni64 Adc32(struct Machine *, u64, u64);\ni64 Add64(struct Machine *, u64, u64);\ni64 Adc64(struct Machine *, u64, u64);\ni64 Not8(struct Machine *, u64, u64);\ni64 Not16(struct Machine *, u64, u64);\ni64 Not32(struct Machine *, u64, u64);\ni64 Not64(struct Machine *, u64, u64);\ni64 Neg8(struct Machine *, u64, u64);\ni64 Neg16(struct Machine *, u64, u64);\ni64 Neg32(struct Machine *, u64, u64);\ni64 Neg64(struct Machine *, u64, u64);\ni64 Inc8(struct Machine *, u64, u64);\ni64 Inc16(struct Machine *, u64, u64);\ni64 Inc32(struct Machine *, u64, u64);\ni64 Inc64(struct Machine *, u64, u64);\ni64 Dec8(struct Machine *, u64, u64);\ni64 Dec16(struct Machine *, u64, u64);\ni64 Dec32(struct Machine *, u64, u64);\ni64 Dec64(struct Machine *, u64, u64);\n\ni64 Shr8(struct Machine *, u64, u64);\ni64 Shr16(struct Machine *, u64, u64);\ni64 Shr32(struct Machine *, u64, u64);\ni64 Shr64(struct Machine *, u64, u64);\ni64 Shl8(struct Machine *, u64, u64);\ni64 Shl16(struct Machine *, u64, u64);\ni64 Shl32(struct Machine *, u64, u64);\ni64 Shl64(struct Machine *, u64, u64);\ni64 Sar8(struct Machine *, u64, u64);\ni64 Sar16(struct Machine *, u64, u64);\ni64 Sar32(struct Machine *, u64, u64);\ni64 Sar64(struct Machine *, u64, u64);\ni64 Rol8(struct Machine *, u64, u64);\ni64 Rol16(struct Machine *, u64, u64);\ni64 Rol32(struct Machine *, u64, u64);\ni64 Rol64(struct Machine *, u64, u64);\ni64 Ror8(struct Machine *, u64, u64);\ni64 Ror16(struct Machine *, u64, u64);\ni64 Ror32(struct Machine *, u64, u64);\ni64 Ror64(struct Machine *, u64, u64);\ni64 Rcr8(struct Machine *, u64, u64);\ni64 Rcr16(struct Machine *, u64, u64);\ni64 Rcr32(struct Machine *, u64, u64);\ni64 Rcr64(struct Machine *, u64, u64);\ni64 Rcl8(struct Machine *, u64, u64);\ni64 Rcl16(struct Machine *, u64, u64);\ni64 Rcl32(struct Machine *, u64, u64);\ni64 Rcl64(struct Machine *, u64, u64);\n\nu64 BsuDoubleShift(struct Machine *, int, u64, u64, u8, bool);\n\ni64 Adcx32(u64, u64, struct Machine *);\ni64 Adcx64(u64, u64, struct Machine *);\ni64 Adox32(u64, u64, struct Machine *);\ni64 Adox64(u64, u64, struct Machine *);\n\n#ifndef HAVE_JIT\n#define kAluFast kAlu\n#endif\n\n// the combinations of needed flags for which we can use kAluFast[];\n// the no-flags case (0) which uses kJustAlu[] is handled separately\n#if defined(HAVE_JIT) && X86_INTRINSICS\n#define CASE_ALU_FAST         \\\n  case CF:                    \\\n  case ZF:                    \\\n  case CF | ZF:               \\\n  case SF:                    \\\n  case SF | CF:               \\\n  case SF | ZF:               \\\n  case SF | CF | ZF:          \\\n  case AF:                    \\\n  case AF | CF:               \\\n  case AF | ZF:               \\\n  case AF | CF | ZF:          \\\n  case SF | AF:               \\\n  case SF | AF | CF:          \\\n  case SF | AF | ZF:          \\\n  case SF | AF | CF | ZF:     \\\n  case OF:                    \\\n  case OF | CF:               \\\n  case OF | ZF:               \\\n  case OF | CF | ZF:          \\\n  case OF | SF:               \\\n  case OF | SF | CF:          \\\n  case OF | SF | ZF:          \\\n  case OF | SF | CF | ZF:     \\\n  case OF | AF:               \\\n  case OF | AF | CF:          \\\n  case OF | AF | ZF:          \\\n  case OF | AF | CF | ZF:     \\\n  case OF | SF | AF:          \\\n  case OF | SF | AF | CF:     \\\n  case OF | SF | AF | ZF:     \\\n  case OF | SF | AF | CF | ZF\n#else\n#define CASE_ALU_FAST         \\\n  case CF:                    \\\n  case ZF:                    \\\n  case CF | ZF\n#endif\n\n#endif /* BLINK_ALU_H_ */\n"
  },
  {
    "path": "blink/alu1.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <limits.h>\n\n#include \"blink/alu.h\"\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n#include \"blink/stats.h\"\n#include \"blink/swap.h\"\n#include \"blink/thread.h\"\n\nstatic void AluEb(P, aluop_f op) {\n  u8 x, z, *p = GetModrmRegisterBytePointerWrite1(A);\n  if (Lock(rde)) {\n    x = atomic_load_explicit((_Atomic(u8) *)p, memory_order_acquire);\n    do {\n      z = Little8(op(m, Little8(x), 0));\n    } while (!atomic_compare_exchange_weak_explicit(\n        (_Atomic(u8) *)p, &x, z, memory_order_release, memory_order_relaxed));\n  } else {\n    Store8(p, op(m, Load8(p), 0));\n  }\n}\n\nvoid OpNotEb(P) {\n  AluEb(A, Not8);\n}\n\nvoid OpNegEb(P) {\n  AluEb(A, Neg8);\n}\n\nvoid Op0fe(P) {\n  switch (ModrmReg(rde)) {\n    case 0:\n      AluEb(A, Inc8);\n      break;\n    case 1:\n      AluEb(A, Dec8);\n      break;\n    default:\n      OpUdImpl(m);\n  }\n}\n\nstatic void AluEvqp(P, const aluop_f ops[4]) {\n  u8 *p;\n  aluop_f f;\n  f = ops[WordLog2(rde)];\n  if (Rexw(rde)) {\n    p = GetModrmRegisterWordPointerWrite8(A);\n#if CAN_64BIT\n    if (Lock(rde) && !((uintptr_t)p & 7)) {\n      u64 x, z;\n      x = atomic_load_explicit((_Atomic(u64) *)p, memory_order_acquire);\n      do {\n        z = Little64(f(m, Little64(x), 0));\n      } while (!atomic_compare_exchange_weak_explicit((_Atomic(u64) *)p, &x, z,\n                                                      memory_order_release,\n                                                      memory_order_relaxed));\n      return;\n    }\n#endif\n    if (!Lock(rde)) {\n      Store64(p, f(m, Load64(p), 0));\n    } else {\n      LockBus(p);\n      Store64Unlocked(p, f(m, Load64Unlocked(p), 0));\n      UnlockBus(p);\n    }\n  } else if (!Osz(rde)) {\n    u32 x, z;\n    p = GetModrmRegisterWordPointerWrite4(A);\n    if (Lock(rde) && !((uintptr_t)p & 3)) {\n      x = atomic_load_explicit((_Atomic(u32) *)p, memory_order_acquire);\n      do {\n        z = Little32(f(m, Little32(x), 0));\n      } while (!atomic_compare_exchange_weak_explicit((_Atomic(u32) *)p, &x, z,\n                                                      memory_order_release,\n                                                      memory_order_relaxed));\n    } else {\n      if (Lock(rde)) LockBus(p);\n      Store32(p, f(m, Load32(p), 0));\n      if (Lock(rde)) UnlockBus(p);\n    }\n    if (IsModrmRegister(rde)) {\n      Put32(p + 4, 0);\n    }\n  } else {\n    p = GetModrmRegisterWordPointerWrite2(A);\n    if (Lock(rde) && !((uintptr_t)p & 1)) {\n      u16 x, z;\n      x = atomic_load_explicit((_Atomic(u16) *)p, memory_order_acquire);\n      do {\n        z = Little16(f(m, Little16(x), 0));\n      } while (!atomic_compare_exchange_weak_explicit((_Atomic(u16) *)p, &x, z,\n                                                      memory_order_release,\n                                                      memory_order_relaxed));\n    } else {\n      if (Lock(rde)) LockBus(p);\n      Store16(p, f(m, Load16(p), 0));\n      if (Lock(rde)) UnlockBus(p);\n    }\n  }\n}\n\nvoid OpNotEvqp(P) {\n  AluEvqp(A, kAlu[ALU_NOT]);\n  if (IsMakingPath(m) && !Lock(rde)) {\n    Jitter(A,\n           \"B\"      // res0 = GetRegOrMem(RexbRm)\n           \"r0a1=\"  // arg1 = res0\n           \"q\"      // arg0 = machine\n           \"m\"      // call function\n           \"r0D\",   // PutRegOrMem(RexbRm, res0)\n           kAlu[ALU_NOT][WordLog2(rde)]);\n  }\n}\n\nvoid OpNegEvqp(P) {\n  AluEvqp(A, kAlu[ALU_NEG]);\n  if (IsMakingPath(m) && !Lock(rde)) {\n    if (!GetNeededFlags(m, m->ip, CF | ZF | SF | OF | AF | PF)) {\n      Jitter(A,\n             \"B\"     // res0 = GetRegOrMem(RexbRm)\n             \"t\"     // arg0 = res0\n             \"m\"     // call micro-op\n             \"r0D\",  // PutRegOrMem(RexbRm, res0)\n             JustNeg);\n    } else {\n      Jitter(A,\n             \"B\"      // res0 = GetRegOrMem(RexbRm)\n             \"r0a1=\"  // arg1 = res0\n             \"q\"      // arg0 = machine\n             \"c\"      // call function\n             \"r0D\",   // PutRegOrMem(RexbRm, res0)\n             kAlu[ALU_NEG][WordLog2(rde)]);\n    }\n  }\n}\n\nvoid OpIncEvqp(P) {\n  AluEvqp(A, kAlu[ALU_INC]);\n  if (IsMakingPath(m) && !Lock(rde)) {\n    Jitter(A,\n           \"B\"      // res0 = GetRegOrMem(RexbRm)\n           \"r0a1=\"  // arg1 = res0\n           \"q\"      // arg0 = machine\n           \"c\"      // call function\n           \"r0D\",   // PutRegOrMem(RexbRm, res0)\n           kAlu[ALU_INC][WordLog2(rde)]);\n  }\n}\n\nvoid OpDecEvqp(P) {\n  AluEvqp(A, kAlu[ALU_DEC]);\n  if (IsMakingPath(m) && !Lock(rde)) {\n    STATISTIC(++alu_ops);\n    switch (GetNeededFlags(m, m->ip, ZF | SF | OF | AF | PF)) {\n      case 0:\n        STATISTIC(++alu_unflagged);\n        Jitter(A,\n               \"B\"     // res0 = GetRegOrMem(RexbRm)\n               \"t\"     // arg0 = res0\n               \"m\"     // call micro-op\n               \"r0D\",  // PutRegOrMem(RexbRm, res0)\n               JustDec);\n        break;\n      case ZF:\n        STATISTIC(++alu_simplified);\n        Jitter(A,\n               \"B\"      // res0 = GetRegOrMem(RexbRm)\n               \"s0a1=\"  // arg1 = machine\n               \"t\"      // arg0 = res0\n               \"m\"      // call micro-op\n               \"r0D\",   // PutRegOrMem(RexbRm, res0)\n               kFastDec[WordLog2(rde)]);\n        break;\n      default:\n        Jitter(A,\n               \"B\"      // res0 = GetRegOrMem(RexbRm)\n               \"r0a1=\"  // arg1 = res0\n               \"q\"      // arg0 = machine\n               \"c\"      // call function\n               \"r0D\",   // PutRegOrMem(RexbRm, res0)\n               kAlu[ALU_DEC][WordLog2(rde)]);\n        break;\n    }\n  }\n}\n"
  },
  {
    "path": "blink/alu2.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <limits.h>\n\n#include \"blink/alu.h\"\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n#include \"blink/stats.h\"\n#include \"blink/swap.h\"\n#include \"blink/thread.h\"\n\nvoid LoadAluArgs(P) {\n  if (IsMakingPath(m)) {\n    if (IsModrmRegister(rde) && RexrReg(rde) == RexbRm(rde)) {\n      Jitter(A, \"A\"        // res0 = GetReg(RexrReg)\n                \"r0a2=\"    // arg2 = res0\n                \"r0a1=\");  // arg1 = res0\n    } else {\n      Jitter(A, \"B\"        // res0 = GetRegOrMem(RexbRm)\n                \"r0s1=\"    // sav1 = res0\n                \"A\"        // res0 = GetReg(RexrReg)\n                \"r0a2=\"    // arg2 = res0\n                \"s1a1=\");  // arg1 = sav1\n    }\n  }\n}\n\nvoid LoadAluFlipArgs(P) {\n  if (IsMakingPath(m)) {\n    if (IsModrmRegister(rde) && RexrReg(rde) == RexbRm(rde)) {\n      Jitter(A, \"A\"        // res0 = GetReg(RexrReg)\n                \"r0a2=\"    // arg2 = res0\n                \"r0a1=\");  // arg1 = res0\n    } else {\n      Jitter(A, \"B\"        // res0 = GetRegOrMem(RexbRm)\n                \"r0s1=\"    // sav1 = res0\n                \"A\"        // res0 = GetReg(RexrReg)\n                \"s1a2=\"    // arg2 = sav1\n                \"r0a1=\");  // arg1 = res0\n    }\n  }\n}\n\nvoid OpAlub(P) {\n  u8 x, y, z, *p, *q;\n  aluop_f f;\n  f = kAlu[(Opcode(rde) & 070) >> 3][0];\n  p = GetModrmRegisterBytePointerWrite1(A);\n  q = ByteRexrReg(m, rde);\n  if (Lock(rde)) {\n    x = atomic_load_explicit((_Atomic(u8) *)p, memory_order_acquire);\n    y = atomic_load_explicit((_Atomic(u8) *)q, memory_order_relaxed);\n    y = Little8(y);\n    do {\n      z = Little8(f(m, Little8(x), y));\n    } while (!atomic_compare_exchange_weak_explicit(\n        (_Atomic(u8) *)p, &x, z, memory_order_release, memory_order_relaxed));\n  } else {\n    x = Load8(p);\n    y = Get8(q);\n    z = f(m, x, y);\n    Store8(p, z);\n  }\n}\n\nvoid OpAluw(P) {\n  u8 *p, *q;\n  aluop_f f;\n  int t, flags;\n  q = RegRexrReg(m, rde);\n  t = (Opcode(rde) & 070) >> 3;\n  f = kAlu[t][RegLog2(rde)];\n  if (Rexw(rde)) {\n    p = GetModrmRegisterWordPointerWrite8(A);\n#if CAN_64BIT\n    if (Lock(rde) && !((uintptr_t)p & 7)) {\n      u64 x, y, z;\n      x = atomic_load_explicit((_Atomic(u64) *)p, memory_order_acquire);\n      y = atomic_load_explicit((_Atomic(u64) *)q, memory_order_relaxed);\n      y = Little64(y);\n      do {\n        z = Little64(f(m, Little64(x), y));\n      } while (!atomic_compare_exchange_weak_explicit((_Atomic(u64) *)p, &x, z,\n                                                      memory_order_release,\n                                                      memory_order_relaxed));\n      return;\n    }\n#endif\n    u64 x, y, z;\n    /* The integrity of a bus lock is not affected by the alignment of\n       the memory field. ──Intel V.3 §8.1.2.2 */\n    if (Lock(rde)) {\n      LockBus(p);\n      x = Load64Unlocked(p);\n      y = Get64(q);\n      z = f(m, x, y);\n      Store64Unlocked(p, z);\n      UnlockBus(p);\n    } else {\n      x = Load64(p);\n      y = Get64(q);\n      z = f(m, x, y);\n      Store64(p, z);\n    }\n  } else if (!Osz(rde)) {\n    u32 x, y, z;\n    p = GetModrmRegisterWordPointerWrite4(A);\n    if (IsModrmRegister(rde)) {\n      Put32(p + 4, 0);\n    }\n    if (Lock(rde) && !((uintptr_t)p & 3)) {\n      x = atomic_load_explicit((_Atomic(u32) *)p, memory_order_acquire);\n      y = atomic_load_explicit((_Atomic(u32) *)q, memory_order_relaxed);\n      y = Little32(y);\n      do {\n        z = Little32(f(m, Little32(x), y));\n      } while (!atomic_compare_exchange_weak_explicit((_Atomic(u32) *)p, &x, z,\n                                                      memory_order_release,\n                                                      memory_order_relaxed));\n    } else {\n      if (Lock(rde)) LockBus(p);\n      x = Load32(p);\n      y = Get32(q);\n      z = f(m, x, y);\n      Store32(p, z);\n      if (Lock(rde)) UnlockBus(p);\n    }\n  } else {\n    u16 x, y, z;\n    p = GetModrmRegisterWordPointerWrite2(A);\n    if (Lock(rde) && !((uintptr_t)p & 1)) {\n      x = atomic_load_explicit((_Atomic(u16) *)p, memory_order_acquire);\n      y = atomic_load_explicit((_Atomic(u16) *)q, memory_order_relaxed);\n      y = Little16(y);\n      do {\n        z = Little16(f(m, Little16(x), y));\n      } while (!atomic_compare_exchange_weak_explicit((_Atomic(u16) *)p, &x, z,\n                                                      memory_order_release,\n                                                      memory_order_relaxed));\n    } else {\n      if (Lock(rde)) LockBus(p);\n      x = Load16(p);\n      y = Get16(q);\n      z = f(m, x, y);\n      Store16(p, z);\n      if (Lock(rde)) UnlockBus(p);\n    }\n  }\n  if (IsMakingPath(m) && !Lock(rde)) {\n    STATISTIC(++alu_ops);\n    flags = GetNeededFlags(m, m->ip, CF | ZF | SF | OF | AF | PF);\n    if (t == ALU_XOR &&          //\n        RegLog2(rde) >= 2 &&     //\n        IsModrmRegister(rde) &&  //\n        RexrReg(rde) == RexbRm(rde)) {\n      if (flags) {\n        Jitter(A,\n               \"a1i\"  // arg1 = register index\n               \"m\",   // call micro-op\n               RexrReg(rde), ZeroRegFlags);\n      } else {\n        Jitter(A,\n               \"s0a1=\"  // arg1 = machine\n               \"a0i\"    // arg0 = zero\n               \"m\",     // call micro-op\n               (u64)0, kPutReg64[RexrReg(rde)]);\n      }\n    } else {\n      LoadAluArgs(A);\n      switch (flags) {\n        case 0:\n          STATISTIC(++alu_unflagged);\n          if (GetFlagDeps(rde)) Jitter(A, \"q\");  // arg0 = machine\n          Jitter(A,\n                 \"m\"     // call micro-op\n                 \"r0D\",  // PutRegOrMem(RexbRm, res0)\n                 kJustAlu[t]);\n          break;\n        CASE_ALU_FAST:\n          STATISTIC(++alu_simplified);\n          Jitter(A,\n                 \"q\"     // arg0 = machine\n                 \"m\"     // call micro-op\n                 \"r0D\",  // PutRegOrMem(RexbRm, res0)\n                 kAluFast[t][RegLog2(rde)]);\n          break;\n        default:\n          Jitter(A,\n                 \"q\"     // arg0 = machine\n                 \"c\"     // call function\n                 \"r0D\",  // PutRegOrMem(RexbRm, res0)\n                 f);\n          break;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "blink/alui.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/alu.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/flags.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n#include \"blink/stats.h\"\n\nstatic void AluiRo(P, const aluop_f ops[4], const aluop_f fast[4]) {\n  ops[RegLog2(rde)](m, ReadRegisterOrMemoryBW(rde, GetModrmReadBW(A)), uimm0);\n  if (IsMakingPath(m)) {\n    STATISTIC(++alu_ops);\n    switch (GetNeededFlags(m, m->ip, CF | ZF | SF | OF | AF | PF)) {\n      case 0:\n      CASE_ALU_FAST:\n        STATISTIC(++alu_simplified);\n        Jitter(A,\n               \"B\"      // res0 = GetRegOrMem(RexbRm)\n               \"a2i\"    // arg2 = uimm0\n               \"r0a1=\"  // arg1 = res0\n               \"q\"      // arg0 = sav0 (machine)\n               \"m\",     // call micro-op\n               uimm0, fast[RegLog2(rde)]);\n        break;\n      default:\n        Jitter(A,\n               \"B\"      // res0 = GetRegOrMem(RexbRm)\n               \"a2i\"    // arg2 = uimm0\n               \"r0a1=\"  // arg1 = res0\n               \"q\"      // arg0 = sav0 (machine)\n               \"c\",     // call function\n               uimm0, ops[RegLog2(rde)]);\n        break;\n    }\n  }\n}\n\nstatic void AluiUnlocked(P, u8 *p, aluop_f op) {\n  WriteRegisterOrMemoryBW(rde, p, op(m, ReadRegisterOrMemoryBW(rde, p), uimm0));\n  if (IsMakingPath(m)) {\n    STATISTIC(++alu_ops);\n    Jitter(A,\n           \"B\"      // res0 = GetRegOrMem(RexbRm)\n           \"r0a1=\"  // arg1 = res0\n           \"a2i\",   // arg2 = uimm0\n           uimm0);\n    switch (GetNeededFlags(m, m->ip, CF | ZF | SF | OF | AF | PF)) {\n      case 0:\n        STATISTIC(++alu_unflagged);\n        if (GetFlagDeps(rde)) {\n          Jitter(A, \"q\");  // arg0 = sav0 (machine)\n        }\n        Jitter(A,\n               \"m\"     // call micro-op\n               \"r0D\",  // PutRegOrMem(RexbRm, res0)\n               kJustAlu[ModrmReg(rde)]);\n        break;\n      CASE_ALU_FAST:\n        STATISTIC(++alu_simplified);\n        Jitter(A,\n               \"q\"     // arg0 = sav0 (machine)\n               \"m\"     // call micro-op\n               \"r0D\",  // PutRegOrMem(RexbRm, res0)\n               kAluFast[ModrmReg(rde)][RegLog2(rde)]);\n        break;\n      default:\n        Jitter(A,\n               \"q\"     // arg0 = sav0 (machine)\n               \"c\"     // call function\n               \"r0D\",  // PutRegOrMem(RexbRm, res0)\n               op);\n        break;\n    }\n  }\n}\n\nstatic void AluiLocked(P, u8 *p, aluop_f op) {\n  switch (RegLog2(rde)) {\n    case 3:\n#if CAN_64BIT\n      if (!((uintptr_t)p & 7)) {\n        u64 x, z;\n        x = atomic_load_explicit((_Atomic(u64) *)p, memory_order_acquire);\n        do {\n          z = Little64(op(m, Little64(x), uimm0));\n        } while (!atomic_compare_exchange_weak_explicit((_Atomic(u64) *)p, &x,\n                                                        z, memory_order_release,\n                                                        memory_order_relaxed));\n        return;\n      }\n#endif\n      LockBus(p);\n      Store64Unlocked(p, op(m, Load64Unlocked(p), uimm0));\n      UnlockBus(p);\n      break;\n    case 2:\n      if (!((uintptr_t)p & 3)) {\n        u32 x, z;\n        x = atomic_load_explicit((_Atomic(u32) *)p, memory_order_acquire);\n        do {\n          z = Little32(op(m, Little32(x), uimm0));\n        } while (!atomic_compare_exchange_weak_explicit((_Atomic(u32) *)p, &x,\n                                                        z, memory_order_release,\n                                                        memory_order_relaxed));\n        return;\n      }\n      LockBus(p);\n      Store32(p, op(m, Load32(p), uimm0));\n      UnlockBus(p);\n      break;\n    case 1:\n      if (!((uintptr_t)p & 1)) {\n        u16 x, z;\n        x = atomic_load_explicit((_Atomic(u16) *)p, memory_order_acquire);\n        do {\n          z = Little16(op(m, Little16(x), uimm0));\n        } while (!atomic_compare_exchange_weak_explicit((_Atomic(u16) *)p, &x,\n                                                        z, memory_order_release,\n                                                        memory_order_relaxed));\n        return;\n      }\n      LockBus(p);\n      Store16(p, op(m, Load16(p), uimm0));\n      UnlockBus(p);\n      break;\n    case 0: {\n      u8 x, z;\n      x = atomic_load_explicit((_Atomic(u8) *)p, memory_order_acquire);\n      do {\n        z = Little8(op(m, Little8(x), uimm0));\n      } while (!atomic_compare_exchange_weak_explicit(\n          (_Atomic(u8) *)p, &x, z, memory_order_release, memory_order_relaxed));\n      break;\n    }\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic void Alui(P) {\n  u8 *p;\n  aluop_f op;\n  p = GetModrmWriteBW(A);\n  op = kAlu[ModrmReg(rde)][RegLog2(rde)];\n  if (Lock(rde) && !IsModrmRegister(rde)) {\n    AluiLocked(A, p, op);\n  } else {\n    AluiUnlocked(A, p, op);\n  }\n}\n\nvoid OpAlui(P) {\n  if (ModrmReg(rde) == ALU_CMP) {\n    if (IsMakingPath(m) && FuseBranchCmp(A, true)) {\n      kAlu[ALU_SUB][RegLog2(rde)](\n          m, ReadRegisterOrMemoryBW(rde, GetModrmReadBW(A)), uimm0);\n    } else {\n      AluiRo(A, kAlu[ALU_SUB], kAluFast[ALU_SUB]);\n    }\n  } else {\n    Alui(A);\n  }\n}\n\nvoid OpTest(P) {\n  AluiRo(A, kAlu[ALU_AND], kAluFast[ALU_AND]);\n}\n"
  },
  {
    "path": "blink/ancillary.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/ancillary.h\"\n\n#include <fcntl.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/socket.h>\n#include <sys/un.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/errno.h\"\n#include \"blink/fds.h\"\n#include \"blink/linux.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n\n#ifndef DISABLE_SOCKETS\n#ifndef DISABLE_ANCILLARY\n\n#ifndef CMSG_LEN\nstatic socklen_t CMSG_LEN(size_t len) {\n  return (CMSG_DATA((struct cmsghdr *)0) - (unsigned char *)0) + len;\n}\n#endif\n\n#ifndef CMSG_SPACE\nstatic socklen_t CMSG_SPACE(size_t len) {\n  struct msghdr msg;\n  struct cmsghdr cmsg;\n  msg.msg_control = &cmsg;\n  msg.msg_controllen = -1;\n  cmsg.cmsg_len = CMSG_LEN(len);\n  return (char *)CMSG_NXTHDR(&msg, &cmsg) - (char *)&cmsg;\n}\n#endif\n\n/**\n * @fileoverview Ancillary Socket Data Marshalling\n *\n * This module marshals `msg_control` for sendmsg() and recvmsg(), which\n * is used by UNIX domain sockets to perform tricks such as sharing file\n * descriptors between processes and X11 server authentication.\n */\n\nstatic int AppendCmsg(struct Machine *m, struct msghdr *msg, int level,\n                      int type, const void *data, size_t size) {\n  struct cmsghdr *cmsg;\n  if (!msg->msg_control &&\n      !(msg->msg_control = AddToFreeList(m, calloc(1, kMaxAncillary)))) {\n    return -1;\n  }\n  if (msg->msg_controllen + CMSG_SPACE(size) > kMaxAncillary) {\n    LOGF(\"kMaxAncillary exceeded\");\n    return enomem();\n  }\n  cmsg = (struct cmsghdr *)((u8 *)msg->msg_control + msg->msg_controllen);\n  cmsg->cmsg_len = CMSG_LEN(size);\n  cmsg->cmsg_level = level;\n  cmsg->cmsg_type = type;\n  memcpy(CMSG_DATA(cmsg), data, size);\n  msg->msg_controllen += CMSG_SPACE(size);\n  return 0;\n}\n\n#ifdef HAVE_SCM_CREDENTIALS\nstatic int SendScmCredentials(struct Machine *m, struct msghdr *msg,\n                              const struct ucred_linux *payload,\n                              size_t elements) {\n  struct ucred ucred;\n  if (elements != 1) return einval();\n  ucred.pid = Read32(payload->pid);\n  ucred.uid = Read32(payload->uid);\n  ucred.gid = Read32(payload->gid);\n  SYS_LOGF(\"SendScmCredentials(pid=%d, uid=%d, gid=%d)\", ucred.pid, ucred.uid,\n           ucred.gid);\n  return AppendCmsg(m, msg, SOL_SOCKET, SCM_CREDENTIALS, &ucred, sizeof(ucred));\n}\n#endif\n\n#ifdef SCM_RIGHTS\nstatic int SendScmRights(struct Machine *m, struct msghdr *msg,\n                         const u8 *payload, size_t elements) {\n  size_t i;\n  int fd[SCM_MAX_FD_LINUX];\n  if (elements > SCM_MAX_FD_LINUX) {\n    LOGF(\"too many scm_rights fds\");\n    return einval();\n  }\n  for (i = 0; i < elements; ++i) {\n    fd[i] = Read32(payload + i * 4);\n    SYS_LOGF(\"SendScmRights(fd=%d)\", fd[i]);\n  }\n  return AppendCmsg(m, msg, SOL_SOCKET, SCM_RIGHTS, &fd, i * sizeof(int));\n}\n#endif\n\nstatic ssize_t GetAncillaryElementLength(const struct cmsghdr_linux *gcmsg) {\n  switch (Read32(gcmsg->level)) {\n    case SOL_SOCKET_LINUX:\n      switch (Read32(gcmsg->type)) {\n#ifdef SCM_RIGHTS\n        case SCM_RIGHTS_LINUX:\n          return 4;\n#endif\n#ifdef HAVE_SCM_CREDENTIALS\n#ifndef DISABLE_NONPOSIX\n        case SCM_CREDENTIALS_LINUX:\n          return sizeof(struct ucred_linux);\n#endif\n#endif\n        default:\n          break;\n      }\n    default:\n      break;\n  }\n  LOGF(\"%s ancillary level=%d type=%d\", \"unsupported\", Read32(gcmsg->level),\n       Read32(gcmsg->type));\n  return einval();\n}\n\nint SendAncillary(struct Machine *m, struct msghdr *msg,\n                  const struct msghdr_linux *gm) {\n  ssize_t rc;\n  u32 len, need;\n  void *payload;\n  size_t avail, i, space, elements;\n  const struct cmsghdr_linux *gcmsg;\n  for (i = 0; (avail = Read64(gm->controllen) - i); i += space) {\n    if (sizeof(*gcmsg) > avail) {\n      LOGF(\"ancillary corrupted\");\n      return einval();\n    }\n    if (!(gcmsg = (const struct cmsghdr_linux *)SchlepR(\n              m, Read64(gm->control) + i, sizeof(*gcmsg)))) {\n      return -1;\n    }\n    len = Read32(gcmsg->len);\n    if (len > ROUNDUP(sizeof(*gcmsg), 8)) {\n      len -= ROUNDUP(sizeof(*gcmsg), 8);\n    } else {\n      len = 0;\n    }\n    need = ROUNDUP(sizeof(*gcmsg), 8) + len;\n    space = ROUNDUP(sizeof(*gcmsg), 8) + ROUNDUP(len, 8);\n    if (space > avail) space = avail;\n    if (need > avail) {\n    ThisCorruption:\n      LOGF(\"ancillary corrupted len=%u level=%u type=%u avail=%zu need=%u\", len,\n           Read32(gcmsg->level), Read32(gcmsg->type), avail, (unsigned)need);\n      return einval();\n    }\n    if ((rc = GetAncillaryElementLength(gcmsg)) == -1) {\n      return -1;\n    }\n    if (len) {\n      if (!(payload =\n                SchlepR(m, Read64(gm->control) + i + ROUNDUP(sizeof(*gcmsg), 8),\n                        ROUNDUP(len, 8)))) {\n        return -1;\n      }\n      if ((need = rc) && need <= len) {\n        elements = len / need;\n        if (len % need != 0) {\n          goto ThisCorruption;\n        }\n      } else {\n        goto ThisCorruption;\n      }\n    } else {\n      payload = 0;\n      elements = 0;\n    }\n    switch (Read32(gcmsg->level)) {\n      case SOL_SOCKET_LINUX:\n        switch (Read32(gcmsg->type)) {\n#ifdef SCM_RIGHTS\n          case SCM_RIGHTS_LINUX:\n            if (SendScmRights(m, msg, (const u8 *)payload, elements) == -1)\n              return -1;\n            break;\n#endif\n#ifdef HAVE_SCM_CREDENTIALS\n#ifndef DISABLE_NONPOSIX\n          case SCM_CREDENTIALS_LINUX:\n            if (SendScmCredentials(m, msg, (const struct ucred_linux *)payload,\n                                   elements) == -1)\n              return -1;\n            break;\n#endif\n#endif\n          default:\n            unassert(!\"inconsistent ancillary type\");\n            __builtin_unreachable();\n        }\n        break;\n      default:\n        unassert(!\"inconsistent ancillary level\");\n        __builtin_unreachable();\n    }\n  }\n  return 0;\n}\n\nstatic i64 CopyCmsg(struct Machine *m, struct msghdr_linux *gm, int level,\n                    int type, void *data, size_t len, u64 i) {\n  i64 control;\n  size_t hdrspace;\n  struct cmsghdr_linux gcmsg;\n  hdrspace = ROUNDUP(sizeof(gcmsg), 8);\n  Write64(gcmsg.len, hdrspace + len);\n  Write32(gcmsg.level, level);\n  Write32(gcmsg.type, type);\n  control = Read64(gm->control);\n  unassert(CopyToUserWrite(m, control + i, &gcmsg, sizeof(gcmsg)) != -1);\n  unassert(CopyToUserWrite(m, control + i + hdrspace, data, len) != -1);\n  return hdrspace + ROUNDUP(len, 8);\n}\n\nstatic void TrackScmRightsFd(struct Machine *m, int fildes, int flags) {\n  int oflags;\n  SYS_LOGF(\"ReceiveScmRights(fd=%d)\", fildes);\n  unassert((oflags = VfsFcntl(fildes, F_GETFL, 0)) != -1);\n  InheritFd(AddFd(\n      &m->system->fds, fildes,\n      oflags | O_RDWR | (flags & MSG_CMSG_CLOEXEC_LINUX ? O_CLOEXEC : 0)));\n#ifndef MSG_CMSG_CLOEXEC\n  if (flags & MSG_CMSG_CLOEXEC_LINUX) {\n    unassert(!VfsFcntl(fildes, F_SETFD, FD_CLOEXEC));\n  }\n#endif\n}\n\n#ifdef SCM_RIGHTS\nstatic i64 ReceiveScmRights(struct Machine *m, struct msghdr_linux *gm,\n                            struct cmsghdr *cmsg, u64 offset, int flags) {\n  const int *p, *e;\n  size_t space, avail;\n  size_t i, received, relayable;\n  u8 fd[SCM_MAX_FD_LINUX][4];\n  // determine how many file descriptors we received from the host\n  p = (const int *)CMSG_DATA(cmsg);\n  e = (const int *)((const u8 *)cmsg + cmsg->cmsg_len);\n  received = e - p;\n  unassert(received > 0);\n  avail = Read64(gm->controllen) - offset;\n  space = ROUNDUP(sizeof(struct cmsghdr_linux), 8);\n  // determine how many file descriptors we can relay to the guest\n  if (space + 4 < avail) {\n    relayable = MIN(MIN(received, (avail - space) / 4), SCM_MAX_FD_LINUX);\n    if (relayable != received) {\n      LOGF(\"truncated %zd scm_rights fds\", received - relayable);\n      Write32(gm->flags, Read32(gm->flags) | MSG_CTRUNC_LINUX);\n    }\n    // serialize fds\n    for (i = 0; i < relayable; ++i) {\n      Write32(fd[i], p[i]);\n      TrackScmRightsFd(m, p[i], flags);\n    }\n    // close excess fds\n    for (i = relayable; i < received; ++i) {\n      close(p[i]);\n    }\n    return CopyCmsg(m, gm, SOL_SOCKET_LINUX, SCM_RIGHTS_LINUX, fd,\n                    relayable * 4, offset);\n  } else {\n    // truncate the control message because there wasn't enough\n    // room in the guest's memory for a single file descriptor.\n    for (i = 0; i < received; ++i) {\n      close(p[i]);\n    }\n    return 0;\n  }\n}\n#endif\n\n#ifdef HAVE_SCM_CREDENTIALS\nstatic i64 ReceiveScmCredentials(struct Machine *m, struct msghdr_linux *gm,\n                                 struct cmsghdr *cmsg, u64 offset) {\n  struct ucred_linux gucred;\n  const struct ucred *ucred;\n  ucred = (const struct ucred *)CMSG_DATA(cmsg);\n  SYS_LOGF(\"ReceiveScmCredentials(pid=%d, uid=%d, gid=%d)\", ucred->pid,\n           ucred->uid, ucred->gid);\n  if (offset + ROUNDUP(sizeof(struct cmsghdr_linux), 8) +\n          ROUNDUP(sizeof(gucred), 8) <=\n      Read64(gm->controllen)) {\n    Write32(gucred.pid, ucred->pid);\n    Write32(gucred.uid, ucred->uid);\n    Write32(gucred.gid, ucred->gid);\n    return CopyCmsg(m, gm, SOL_SOCKET_LINUX, SCM_CREDENTIALS_LINUX, &gucred,\n                    sizeof(gucred), offset);\n  } else {\n    return 0;\n  }\n}\n#endif\n\nstatic i64 ReceiveControlMessage(struct Machine *m, struct msghdr_linux *gm,\n                                 struct cmsghdr *cmsg, u64 offset, int flags) {\n  if (cmsg->cmsg_level == SOL_SOCKET) {\n#ifdef SCM_RIGHTS\n    if (cmsg->cmsg_type == SCM_RIGHTS) {\n      return ReceiveScmRights(m, gm, cmsg, offset, flags);\n    }\n#endif\n#ifdef HAVE_SCM_CREDENTIALS\n#ifndef DISABLE_NONPOSIX\n    if (cmsg->cmsg_type == SCM_CREDENTIALS) {\n      return ReceiveScmCredentials(m, gm, cmsg, offset);\n    }\n#endif\n#endif\n  }\n  LOGF(\"%s ancillary level=%d type=%d\", \"unsupported\", cmsg->cmsg_level,\n       cmsg->cmsg_type);\n  return enotsup();\n}\n\nint ReceiveAncillary(struct Machine *m, struct msghdr_linux *gm,\n                     struct msghdr *msg, int flags) {\n  ssize_t rc;\n  u64 offset = 0;\n  struct cmsghdr *cmsg;\n  if ((cmsg = CMSG_FIRSTHDR(msg))) {\n    do {\n      switch ((rc = ReceiveControlMessage(m, gm, cmsg, offset, flags))) {\n        case -1:\n          return -1;\n        case 0:\n          LOGF(\"%s ancillary level=%d type=%d\", \"truncated\", cmsg->cmsg_level,\n               cmsg->cmsg_type);\n          Write32(gm->flags, Read32(gm->flags) | MSG_CTRUNC_LINUX);\n          offset = Read64(gm->controllen);\n          break;\n        default:\n          offset += rc;\n          break;\n      }\n    } while ((cmsg = CMSG_NXTHDR(msg, cmsg)));\n  }\n  Write64(gm->controllen, offset);\n  return 0;\n}\n\n#endif /* DISABLE_ANCILLARY */\n#endif /* DISABLE_SOCKETS */\n"
  },
  {
    "path": "blink/ancillary.h",
    "content": "#ifndef COSMOPOLITAN_BLINK_ANCILLARY_H_\n#define COSMOPOLITAN_BLINK_ANCILLARY_H_\n#include <sys/socket.h>\n\n#include \"blink/machine.h\"\n\nint SendAncillary(struct Machine *, struct msghdr *,\n                  const struct msghdr_linux *);\nint ReceiveAncillary(struct Machine *, struct msghdr_linux *, struct msghdr *,\n                     int);\n\n#endif /* COSMOPOLITAN_BLINK_ANCILLARY_H_ */\n"
  },
  {
    "path": "blink/argv.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/endian.h\"\n#include \"blink/flag.h\"\n#include \"blink/linux.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/map.h\"\n#include \"blink/syscall.h\"\n#include \"blink/util.h\"\n\n#define STACKALIGN 16\n\n#define PUSH_AUXV(k, v) \\\n  --naux;               \\\n  *--p = v;             \\\n  *--p = k\n\nstatic size_t GetArgListLen(char **p) {\n  size_t n;\n  for (n = 0; *p; ++p) ++n;\n  return n;\n}\n\nstatic i64 PushBuffer(struct Machine *m, void *s, size_t n) {\n  i64 sp = Get64(m->sp) - n;\n  Put64(m->sp, sp);\n  unassert(!CopyToUser(m, sp, s, n));\n  return sp;\n}\n\nstatic i64 PushString(struct Machine *m, char *s) {\n  if (s) {\n    return PushBuffer(m, s, strlen(s) + 1);\n  } else {\n    return 0;\n  }\n}\n\nstatic long GetGuestPageSize(struct Machine *m) {\n  if (HasLinearMapping()) {\n    return FLAG_pagesize;\n  } else {\n    return 4096;\n  }\n}\n\nvoid LoadArgv(struct Machine *m, char *execfn, char *prog, char **args,\n              char **vars, u8 rng[16]) {\n  u8 *bytes;\n  struct Elf *elf;\n  i64 sp, dx, *p, *bloc;\n  size_t i, narg, nenv, naux, nall;\n  elf = &m->system->elf;\n  naux = 10;\n  if (elf->at_entry) {\n    naux += 4;\n    if (elf->at_base != -1) {\n      naux += 1;\n    }\n  }\n  nenv = GetArgListLen(vars);\n  narg = GetArgListLen(args);\n  nall = 1 + narg + 1 + nenv + 1 + naux * 2;\n  bloc = (i64 *)malloc(sizeof(i64) * nall);\n  p = bloc + nall;\n  dx = PushString(m, prog);\n  PUSH_AUXV(0, 0);\n  PUSH_AUXV(AT_UID_LINUX, getuid());\n  PUSH_AUXV(AT_EUID_LINUX, geteuid());\n  PUSH_AUXV(AT_GID_LINUX, getgid());\n  PUSH_AUXV(AT_EGID_LINUX, getegid());\n  PUSH_AUXV(AT_SECURE_LINUX, IsProcessTainted());\n  PUSH_AUXV(AT_PAGESZ_LINUX, GetGuestPageSize(m));\n  PUSH_AUXV(AT_CLKTCK_LINUX, sysconf(_SC_CLK_TCK));\n  PUSH_AUXV(AT_RANDOM_LINUX, PushBuffer(m, rng, 16));\n  PUSH_AUXV(AT_EXECFN_LINUX, PushString(m, execfn));\n  if (elf->at_entry) {\n    PUSH_AUXV(AT_PHDR_LINUX, elf->at_phdr);\n    PUSH_AUXV(AT_PHENT_LINUX, elf->at_phent);\n    PUSH_AUXV(AT_PHNUM_LINUX, elf->at_phnum);\n    PUSH_AUXV(AT_ENTRY_LINUX, elf->at_entry);\n    if (elf->at_base != -1) {\n      PUSH_AUXV(AT_BASE_LINUX, elf->at_base);\n    }\n  }\n  unassert(!naux);\n  for (*--p = 0, i = nenv; i--;) *--p = PushString(m, vars[i]);\n  for (*--p = 0, i = narg; i--;) *--p = PushString(m, args[i]);\n  *--p = narg;\n  sp = Read64(m->sp);\n  while ((sp - nall * sizeof(i64)) & (STACKALIGN - 1)) --sp;\n  sp -= nall * sizeof(i64);\n  Write64(m->sp, sp);\n  Write64(m->dx, dx);\n  Write64(m->di, 0); /* or ape detects freebsd */\n  bytes = (u8 *)malloc(nall * 8);\n  for (i = 0; i < nall; ++i) {\n    Write64(bytes + i * 8, bloc[i]);\n  }\n  unassert(!CopyToUser(m, sp, bytes, nall * 8));\n  free(bytes);\n  free(bloc);\n}\n"
  },
  {
    "path": "blink/assert.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/assert.h\"\n\n#include <errno.h>\n#include <stdio.h>\n\n#include \"blink/debug.h\"\n#include \"blink/flag.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/thread.h\"\n#include \"blink/util.h\"\n\nvoid AssertFailed(const char *file, int line, const char *msg) {\n  _Thread_local static bool noreentry;\n  _Thread_local static char bp[20000];\n  WriteErrorString(\"assertion failed\\n\");\n  if (!noreentry) {\n    noreentry = true;\n    FLAG_nologstderr = false;\n    RestoreIp(g_machine);\n    snprintf(bp, sizeof(bp),\n             \"%s:%d:%d assertion failed: %s (%s)\\n\"\n             \"\\t%s\\n\"\n             \"\\t%s\\n\",\n             file, line, g_machine ? g_machine->tid : 666, msg,\n             DescribeHostErrno(errno), GetBacktrace(g_machine),\n             GetBlinkBacktrace());\n    WriteErrorString(bp);\n  }\n  Abort();\n}\n"
  },
  {
    "path": "blink/assert.h",
    "content": "#ifndef BLINK_ASSERT_H_\n#define BLINK_ASSERT_H_\n#include \"blink/builtin.h\"\n\n#ifndef NDEBUG\n#define unassert(x)                         \\\n  do {                                      \\\n    if (__builtin_expect(!(x), 0)) {        \\\n      AssertFailed(__FILE__, __LINE__, #x); \\\n    }                                       \\\n  } while (0)\n#elif (__clang__ + __INTEL_COMPILER + _MSC_VER + 0 || \\\n       (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 405)\n#define unassert(x)                  \\\n  do {                               \\\n    if (__builtin_expect(!(x), 0)) { \\\n      __builtin_unreachable();       \\\n    }                                \\\n  } while (0)\n#else\n#define unassert(x) ((void)(x))\n#endif\n\n_Noreturn void AssertFailed(const char *, int, const char *);\n\n#endif /* BLINK_ASSERT_H_ */\n"
  },
  {
    "path": "blink/atomic.h",
    "content": "#ifndef BLINK_ATOMIC_H_\n#define BLINK_ATOMIC_H_\n#include \"blink/builtin.h\"\n#include \"blink/thread.h\"\n#if defined(HAVE_FORK) || defined(HAVE_THREADS)\n#include <stdatomic.h>\n#else\n#include \"blink/types.h\"\n\n#define _Atomic(t) t\n\n#define atomic_thread_fence(order) (void)0\n\n#define atomic_load_explicit(ptr, order) *(ptr)\n\n#define atomic_store_explicit(ptr, val, order) (*(ptr) = (val))\n\n#define atomic_exchange(ptr, val)                        \\\n  (sizeof(*(ptr)) == 8   ? Exchange64((u64 *)(ptr), val) \\\n   : sizeof(*(ptr)) == 4 ? Exchange32((u32 *)(ptr), val) \\\n   : sizeof(*(ptr)) == 2 ? Exchange16((u16 *)(ptr), val) \\\n                         : Exchange8((u8 *)(ptr), val))\n\n#define atomic_exchange_explicit(ptr, val, order) atomic_exchange(ptr, val)\n\n#define atomic_compare_exchange_strong_explicit(                             \\\n    ifthing, isequaltome, replaceitwithme, success_order, failure_order)     \\\n  (*(ifthing) == *(isequaltome)                                              \\\n       ? (*(isequaltome) = *(ifthing), *(ifthing) = (replaceitwithme), true) \\\n       : (*(isequaltome) = *(ifthing), false))\n\n#define atomic_compare_exchange_weak_explicit(x, y, z, s, f) \\\n  atomic_compare_exchange_strong_explicit(x, y, z, s, f)\n\n#define atomic_fetch_add_explicit(ptr, delta, order)       \\\n  (sizeof(*(ptr)) == 8   ? FetchAdd64((u64 *)(ptr), delta) \\\n   : sizeof(*(ptr)) == 4 ? FetchAdd32((u32 *)(ptr), delta) \\\n                         : FetchAddAbort())\n\nstatic inline u64 Exchange64(u64 *ptr, u64 val) {\n  u64 tmp = *ptr;\n  *ptr = val;\n  return tmp;\n}\n\nstatic inline u32 Exchange32(u32 *ptr, u32 val) {\n  u32 tmp = *ptr;\n  *ptr = val;\n  return tmp;\n}\n\nstatic inline u16 Exchange16(u16 *ptr, u16 val) {\n  u16 tmp = *ptr;\n  *ptr = val;\n  return tmp;\n}\n\nstatic inline u8 Exchange8(u8 *ptr, u8 val) {\n  u8 tmp = *ptr;\n  *ptr = val;\n  return tmp;\n}\n\nstatic inline u64 FetchAdd64(u64 *ptr, u64 val) {\n  u64 res = *ptr;\n  *ptr += val;\n  return res;\n}\n\nstatic inline u32 FetchAdd32(u32 *ptr, u32 val) {\n  u32 res = *ptr;\n  *ptr += val;\n  return res;\n}\n\nstatic inline u32 FetchAddAbort(void) {\n  volatile u32 x = 0;\n  return 1 / x;\n}\n\n#endif /* !HAVE_FORK && !HAVE_THREADS */\n#endif /* BLINK_ATOMIC_H_ */\n"
  },
  {
    "path": "blink/bcd.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/machine.h\"\n#include \"blink/x86.h\"\n\nstatic relegated dontinline void BcdFlags(struct Machine *m, bool af, bool cf) {\n  m->flags = SetFlag(m->flags, FLAGS_CF, cf);\n  m->flags = SetFlag(m->flags, FLAGS_AF, af);\n  m->flags = SetFlag(m->flags, FLAGS_ZF, !m->al);\n  m->flags = SetFlag(m->flags, FLAGS_SF, (i8)m->al < 0);\n  m->flags = SetLazyParityByte(m->flags, m->al);\n}\n\nrelegated void OpDas(P) {\n  u8 al;\n  bool af, cf;\n  al = m->al;\n  af = cf = 0;\n  if ((al & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) {\n    cf = m->al < 6 || GetFlag(m->flags, FLAGS_CF);\n    m->al -= 0x06;\n    af = 1;\n  }\n  if (al > 0x99 || GetFlag(m->flags, FLAGS_CF)) {\n    m->al -= 0x60;\n    cf = 1;\n  }\n  BcdFlags(m, af, cf);\n}\n\nrelegated void OpAaa(P) {\n  bool af, cf;\n  af = cf = 0;\n  if ((m->al & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) {\n    cf = m->al < 6 || GetFlag(m->flags, FLAGS_CF);\n    Put16(m->ax, Get16(m->ax) + 0x106);\n    af = cf = 1;\n  }\n  m->al &= 0x0f;\n  BcdFlags(m, af, cf);\n}\n\nrelegated void OpAas(P) {\n  bool af, cf;\n  af = cf = 0;\n  if ((m->al & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) {\n    cf = m->al < 6 || GetFlag(m->flags, FLAGS_CF);\n    Put16(m->ax, Get16(m->ax) - 0x106);\n    af = cf = 1;\n  }\n  m->al &= 0x0f;\n  BcdFlags(m, af, cf);\n}\n\nrelegated void OpAam(P) {\n  u8 imm = m->xedd->op.uimm0;\n  if (!imm) RaiseDivideError(m);\n  m->ah = m->al / imm;\n  m->al = m->al % imm;\n  BcdFlags(m, 0, 0);\n}\n\nrelegated void OpAad(P) {\n  u8 imm = m->xedd->op.uimm0;\n  Put16(m->ax, (m->ah * imm + m->al) & 255);\n  BcdFlags(m, 0, 0);\n}\n\n// http://www.righto.com/2023/01/understanding-x86s-decimal-adjust-after.html\nrelegated void OpDaa(P) {\n  u8 old_al;\n  old_al = m->al;\n  if ((m->al & 0x0f) > 9 || GetFlag(m->flags, FLAGS_AF)) {\n    m->al += 6;\n    m->flags = SetFlag(m->flags, FLAGS_AF, true);\n  }\n  if ((old_al > 0x99) || GetFlag(m->flags, FLAGS_CF)) {\n    m->al += 0x60;\n    m->flags = SetFlag(m->flags, FLAGS_CF, true);\n  }\n}\n"
  },
  {
    "path": "blink/bda.h",
    "content": "#ifndef BLINK_BDA_H_\n#define BLINK_BDA_H_\n#include \"blink/blinkenlights.h\"\n#include \"blink/machine.h\"\n#include \"blink/endian.h\"\n\n#define GetBda8(o)     Read8(m->system->real + 0x400 + (o))\n#define SetBda8(o, v)  Write8(m->system->real + 0x400 + (o), (v))\n#define GetBda16(o)    Read16(m->system->real + 0x400 + (o))\n#define SetBda16(o, v) Write16(m->system->real + 0x400 + (o), (v))\n#define GetBda32(o)    Read32(m->system->real + 0x400 + (o))\n#define SetBda32(o, v) Write32(m->system->real + 0x400 + (o), (v))\n\n#define    BdaCom1          GetBda16(0x00)\n#define SetBdaCom1(v)       SetBda16(0x00, (v))\n#define    BdaEbda          GetBda16(0x0E)\n#define SetBdaEbda(v)       SetBda16(0x0E, (v))\n\n#define    BdaEquip         GetBda16(0x10)\n#define SetBdaEquip(v)      SetBda16(0x10, (v))\n#define    BdaMemsz         GetBda16(0x13)\n#define SetBdaMemsz(v)      SetBda16(0x13, (v))\n\n#define    BdaVmode         GetBda8(0x49)\n#define SetBdaVmode(v)      SetBda8(0x49, (v))\n#define    BdaCols          GetBda16(0x4A)       // returns actual # columns\n#define SetBdaCols(v)       SetBda16(0x4A, (v))  // BIOS stores # columns\n#define    BdaPagesz        GetBda16(0x4C)\n#define SetBdaPagesz(v)     SetBda16(0x4C, (v))\n#define    BdaCurx          GetBda8(0x50)\n#define SetBdaCurx(v)       SetBda8(0x50, (v))\n#define    BdaCury          GetBda8(0x51)\n#define SetBdaCury(v)       SetBda8(0x51, (v))\n#define    BdaCurend        GetBda8(0x60)\n#define SetBdaCurend(v)     SetBda8(0x60, (v))\n#define    BdaCurstart      GetBda8(0x61)\n#define SetBdaCurstart(v)   SetBda8(0x61, (v))\n#define BdaCurhidden        ((BdaCurstart & 0x20) || (BdaCurstart > BdaCurend))\n#define    BdaCurpage       GetBda8(0x62)\n#define SetBdaCurpage(v)    SetBda8(0x62, (v))\n#define    BdaCrtc          GetBda16(0x64)\n#define SetBdaCrtc(v)       SetBda16(0x64, (v))\n\n#define    BdaTimer         GetBda32(0x6C)\n#define SetBdaTimer(v)      SetBda32(0x6C, (v))\n#define    Bda24hr          GetBda8(0x70)\n#define SetBda24hr(v)       SetBda8(0x70, (v))\n\n#define    BdaLines         (GetBda8(0x84) + 1)     // returns actual # lines\n#define SetBdaLines(v)      SetBda8(0x84, (v) - 1) // BIOS stores # lines - 1\n\n#endif /* BLINK_BDA_H_ */\n"
  },
  {
    "path": "blink/bios.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <fcntl.h>\n#include <poll.h>\n#include <stdbool.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n\n#include \"blink/assert.h\"\n#include \"blink/bda.h\"\n#include \"blink/biosrom.h\"\n#include \"blink/blinkenlights.h\"\n#include \"blink/bus.h\"\n#include \"blink/cga.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/loader.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/mda.h\"\n#include \"blink/pty.h\"\n#include \"blink/timespec.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n\nstatic const struct Chs {\n  ssize_t imagesize;\n  short c, h, s;\n  bool isfloppy;\n} kChs[] = {\n    {163840, 40, 1, 8, true},    //\n    {184320, 40, 1, 9, true},    //\n    {327680, 40, 2, 8, true},    //\n    {368640, 40, 2, 9, true},    //\n    {737280, 80, 2, 9, true},    //\n    {1228800, 80, 2, 15, true},  //\n    {1474560, 80, 2, 18, true},  //\n    {2949120, 80, 2, 36, true},  //\n};\n\nstatic off_t diskimagesize = 0;\nstatic int diskcyls = 1023;\nstatic int diskheads = 16;  // default to 16 heads/cylinder, following QEMU\nstatic int disksects = 63;\nstatic bool diskisfloppy = false;\n\nstatic u64 prevday = 0;  // day number of last call to int 0x1A, ah = 0, for\n                         // calculating elapsed midnight count\n\nstatic size_t GetLastIndex(size_t size, unsigned unit, int i, unsigned limit) {\n  unsigned q, r;\n  if (!size) return 0;\n  q = size / unit;\n  r = size % unit;\n  if (!r) --q;\n  q += i;\n  if (q > limit) q = limit;\n  return q;\n}\n\nstatic void OnDiskServiceReset(void) {\n  m->ah = 0x00;\n  SetCarry(false);\n}\n\nstatic void OnDiskServiceBadCommand(void) {\n  m->ah = 0x01;\n  SetCarry(true);\n}\n\nstatic void DetermineChs(void) {\n  int i;\n  struct stat st;\n  off_t size = diskimagesize;\n  if (size) return;  // do nothing if disk geometry already detected\n  unassert(!VfsStat(AT_FDCWD, m->system->elf.prog, &st, 0));\n  diskimagesize = size = st.st_size;\n  for (i = 0; i < ARRAYLEN(kChs); ++i) {\n    if (size == kChs[i].imagesize) {\n      diskcyls = kChs[i].c;\n      diskheads = kChs[i].h;\n      disksects = kChs[i].s;\n      diskisfloppy = kChs[i].isfloppy;\n      return;\n    }\n  }\n}\n\nstatic bool DetermineChsAndSanityCheck(u8 drive) {\n  DetermineChs();\n  if (diskisfloppy) {\n    if ((drive & 0x80) != 0) {\n      // reading from hard disk drive, but image is floppy image\n      m->ah = 0x80;  // drive not ready\n      SetCarry(true);\n      return false;\n    }\n  } else {\n    if ((drive & 0x80) == 0) {\n      // reading from floppy drive, but image is hard disk image\n      m->ah = 0x80;  // drive not ready\n      SetCarry(true);\n      return false;\n    }\n  }\n  return true;\n}\n\nstatic void OnDiskServiceGetParams(void) {\n  size_t lastsector, lastcylinder, lasthead;\n  u8 drive = m->dl;\n  if (!DetermineChsAndSanityCheck(drive)) return;\n  lastcylinder =\n      GetLastIndex(diskimagesize, 512 * disksects * diskheads, 0, 1023);\n  lasthead = GetLastIndex(diskimagesize, 512 * disksects, 0, diskheads - 1);\n  lastsector = GetLastIndex(diskimagesize, 512, 1, disksects);\n  m->dl = 1;\n  m->dh = lasthead;\n  m->cl = lastcylinder >> 8 << 6 | lastsector;\n  m->ch = lastcylinder;\n  m->bl = 4;  // CMOS drive type: 1.4M floppy\n  m->ah = 0;\n  if ((drive & 0x80) == 0) {\n    u32 ddpt = GetDefaultBiosDisketteParamTable();\n    m->es.sel = ddpt >> 16;\n    m->es.base = ddpt >> 16 << 4;\n    Put16(m->di, (u16)ddpt);\n  }\n  SetCarry(false);\n}\n\nstatic void OnDiskServiceReadSectors(void) {\n  int fd;\n  i64 addr, size, rsize, ursize;\n  i64 sectors, drive, head, cylinder, sector, offset;\n  sectors = m->al;\n  drive = m->dl;\n  if (!DetermineChsAndSanityCheck(drive)) {\n    m->al = 0x00;\n    return;\n  }\n  head = m->dh;\n  cylinder = (m->cl & 192) << 2 | m->ch;\n  sector = (m->cl & 63) - 1;\n  size = sectors * 512;\n  offset = sector * 512 + head * 512 * disksects +\n           cylinder * 512 * disksects * diskheads;\n  ELF_LOGF(\"bios read sectors %\" PRId64 \" \"\n           \"@ sector %\" PRId64 \" cylinder %\" PRId64 \" head %\" PRId64\n           \" drive %\" PRId64 \" offset %#\" PRIx64 \" from %s\",\n           sectors, sector, cylinder, head, drive, offset, m->system->elf.prog);\n  addr = m->es.base + Get16(m->bx);\n  if (addr >= kRealSize || size > kRealSize || addr + size > kRealSize) {\n    LOGF(\"bios disk read exceeded real memory\");\n    m->al = 0x00;\n    m->ah = 0x02;  // cannot find address mark\n    SetCarry(true);\n    return;\n  }\n  errno = 0;\n  if ((fd = VfsOpen(AT_FDCWD, m->system->elf.prog, O_RDONLY, 0)) != -1 &&\n      (rsize = VfsPread(fd, m->system->real + addr, size, offset)) >= 0) {\n    ursize = ROUNDUP(rsize, 512);\n    if (ursize != rsize) {\n      memset(m->system->real + addr + rsize, 0, ursize - rsize);\n    }\n    SetWriteAddr(m, addr, ursize);\n    if (ursize == size) {\n      m->ah = 0x00;  // success\n      SetCarry(false);\n    } else {\n      sectors = ursize / 512;\n      LOGF(\"bios read sectors: partial read %\" PRId64 \" sectors\", sectors);\n      m->al = sectors;\n      m->ah = 0x04;  // sector not found\n      SetCarry(true);\n    }\n  } else {\n    LOGF(\"bios read sectors failed: %s\", DescribeHostErrno(errno));\n    m->al = 0x00;\n    m->ah = 0x0d;  // invalid number of sector\n    SetCarry(true);\n  }\n  VfsClose(fd);\n}\n\nstatic void OnDiskServiceProbeExtended(void) {\n  u8 drive = m->dl;\n  u16 magic = Get16(m->bx);\n  (void)drive;\n  if (magic == 0x55AA) {\n    Put16(m->bx, 0xAA55);\n    m->ah = 0x30;\n    SetCarry(false);\n  } else {\n    m->ah = 0x01;\n    SetCarry(true);\n  }\n}\n\nstatic void OnDiskServiceReadSectorsExtended(void) {\n  int fd;\n  u8 drive = m->dl;\n  i64 pkt_addr = m->ds.base + Get16(m->si), addr, sectors, size, lba, offset,\n      rsize, ursize;\n  u8 pkt_size, *pkt;\n  SetReadAddr(m, pkt_addr, 1);\n  pkt = m->system->real + pkt_addr;\n  pkt_size = Get8(pkt);\n  if ((pkt_size != 0x10 && pkt_size != 0x18) || Get8(pkt + 1) != 0) {\n    m->ah = 0x01;\n    SetCarry(true);\n  } else {\n    SetReadAddr(m, pkt_addr, pkt_size);\n    addr = Read32(pkt + 4);\n    if (addr == 0xFFFFFFFF && pkt_size == 0x18) {\n      addr = Read64(pkt + 0x10);\n    } else {\n      addr = (addr >> 16 << 4) + (addr & 0xFFFF);\n    }\n    sectors = Read16(pkt + 2);\n    size = sectors * 512;\n    lba = Read32(pkt + 8);\n    offset = lba * 512;\n    ELF_LOGF(\"bios read sector ext \"\n             \"lba=%\" PRId64 \" \"\n             \"offset=%\" PRIx64 \" \"\n             \"size=%\" PRIx64,\n             lba, offset, size);\n    if (!DetermineChsAndSanityCheck(drive)) {\n      Write16(pkt + 2, 0);\n      return;\n    }\n    if (addr >= kRealSize || size > kRealSize || addr + size > kRealSize) {\n      LOGF(\"bios disk read exceeded real memory\");\n      SetWriteAddr(m, pkt_addr + 2, 2);\n      Write16(pkt + 2, 0);\n      m->ah = 0x02;  // cannot find address mark\n      SetCarry(true);\n      return;\n    }\n    errno = 0;\n    if ((fd = VfsOpen(AT_FDCWD, m->system->elf.prog, O_RDONLY, 0)) != -1 &&\n        (rsize = VfsPread(fd, m->system->real + addr, size, offset)) >= 0) {\n      ursize = ROUNDUP(rsize, 512);\n      if (ursize != rsize) {\n        memset(m->system->real + addr + rsize, 0, ursize - rsize);\n      }\n      SetWriteAddr(m, addr, ursize);\n      if (ursize == size) {\n        m->ah = 0x00;  // success\n        SetCarry(false);\n      } else {\n        sectors = ursize / 512;\n        LOGF(\"bios read sectors: partial read %\" PRId64 \" sectors\", sectors);\n        Write16(pkt + 2, sectors);\n        m->ah = 0x04;  // sector not found\n        SetCarry(true);\n      }\n    } else {\n      LOGF(\"bios read sector failed: %s\", DescribeHostErrno(errno));\n      SetWriteAddr(m, pkt_addr + 2, 2);\n      Write16(pkt + 2, 0);\n      m->ah = 0x0d;  // invalid number of sectors\n      SetCarry(true);\n    }\n    VfsClose(fd);\n  }\n}\n\nstatic void OnDiskService(void) {\n  switch (m->ah) {\n    case 0x00:\n      OnDiskServiceReset();\n      break;\n    case 0x02:\n      OnDiskServiceReadSectors();\n      break;\n    case 0x08:\n      OnDiskServiceGetParams();\n      break;\n    case 0x41:\n      OnDiskServiceProbeExtended();\n      break;\n    case 0x42:\n      OnDiskServiceReadSectorsExtended();\n      break;\n    default:\n      OnDiskServiceBadCommand();\n      break;\n  }\n}\n\n#define page_offsetw() 0  // TODO(ghaerr): implement screen pages\n#define video_ram()    (m->system->real + ((vidya == 7) ? 0xb0000 : 0xb8000))\n#define ATTR_DEFAULT   0x07\n\n/* clear screen from x1,y1 up to but not including x2, y2 */\nstatic void VidyaServiceClearScreen(int x1, int y1, int x2, int y2, u8 attr) {\n  int x, y, xn;\n  u16 *vram;\n  unassert(x1 >= 0 && x1 <= BdaCols);\n  unassert(x2 >= 0 && x2 <= BdaCols);\n  unassert(y1 >= 0 && y1 <= BdaLines);\n  unassert(y2 >= 0 && y2 <= BdaLines);\n  vram = (u16 *)video_ram();\n  xn = BdaCols;\n  for (y = y1; y < y2; y++) {\n    for (x = x1; x < x2; x++) {\n      vram[page_offsetw() + y * xn + x] = ' ' | (attr << 8);\n    }\n  }\n}\n\n/* clear line y from x1 up to and including x2 to attribute attr */\nstatic void VidyaServiceClearLine(int x1, int x2, int y, u8 attr) {\n  int x, xn;\n  u16 *vram;\n  unassert(x1 >= 0 && x1 < BdaCols);\n  unassert(x2 >= 0 && x2 < BdaCols);\n  unassert(y >= 0 && y < BdaLines);\n  vram = (u16 *)video_ram();\n  xn = BdaCols;\n  for (x = x1; x <= x2; x++) {\n    vram[page_offsetw() + y * xn + x] = ' ' | (attr << 8);\n  }\n}\n\n/* scroll video ram up from line y1 up to and including line y2 */\nstatic void VidyaServiceScrollUp(int y1, int y2, u8 attr) {\n  int xn, pitch;\n  u8 *vid;\n  unassert(y1 >= 0 && y1 < BdaLines);\n  unassert(y2 >= 0 && y2 < BdaLines);\n  xn = BdaCols;\n  vid = video_ram() + (page_offsetw() + y1 * xn) * 2;\n  pitch = xn * 2;\n  memcpy(vid, vid + pitch, (BdaLines - y1) * pitch);\n  VidyaServiceClearLine(0, xn - 1, y2, attr);\n}\n\n/* scroll adapter RAM down from line y1 up to and including line y2 */\nstatic void VidyaServiceScrollDown(int y1, int y2, u8 attr) {\n  int y, xn, pitch;\n  u8 *vid;\n  unassert(y1 >= 0 && y1 < BdaLines);\n  unassert(y2 >= 0 && y2 < BdaLines);\n  xn = BdaCols;\n  vid = video_ram() + (page_offsetw() + (BdaLines - 1) * xn) * 2;\n  pitch = xn * 2;\n  y = y2;\n  while (--y >= y1) {\n    memcpy(vid, vid - pitch, pitch);\n    vid -= pitch;\n  }\n  VidyaServiceClearLine(0, xn - 1, y1, attr);\n}\n\nstatic void OnVidyaServiceScrollUp(void) {\n  unsigned i, n;\n  unassert(m->cl < BdaCols);\n  unassert(m->ch < BdaLines);\n  unassert(m->dl < BdaCols);\n  unassert(m->dh < BdaLines);\n  n = m->al;\n  if (n > BdaLines) n = BdaLines;\n  if (n == 0) {\n    VidyaServiceClearScreen(m->cl, m->ch, m->dl + 1, m->dh + 1, m->bh);\n  } else {\n    for (i = n; i; i--) {\n      VidyaServiceScrollUp(m->ch, m->dh, m->bh);\n    }\n  }\n}\n\nstatic void OnVidyaServiceScrollDown(void) {\n  unsigned i, n;\n  unassert(m->cl < BdaCols);\n  unassert(m->ch < BdaLines);\n  unassert(m->dl < BdaCols);\n  unassert(m->dh < BdaLines);\n  n = m->al;\n  if (n > BdaLines) n = BdaLines;\n  if (n == 0) {\n    VidyaServiceClearScreen(m->cl, m->ch, m->dl + 1, m->dh + 1, m->bh);\n  } else {\n    for (i = n; i; i--) {\n      VidyaServiceScrollDown(m->ch, m->dh, m->bh);\n    }\n  }\n}\n\n/* write char/attr to video adapter ram */\nstatic void VidyaServiceWriteCharacter(u8 ch, u8 attr, int n, bool useattr) {\n  int x, y, xn, offset;\n  u8 *vram;\n  x = BdaCurx;\n  y = BdaCury;\n  unassert(y < BdaLines);\n  unassert(x < BdaCols);\n  xn = BdaCols;\n  vram = video_ram();\n  while (n-- > 0) {\n    offset = page_offsetw() + (y * xn + x) * 2;\n    vram[offset] = ch;\n    if (useattr) {\n      vram[offset + 1] = attr;\n    }\n    if (++x >= xn) {\n      x = 0;\n      y++;\n    }\n  }\n}\n\n/* write char only (no attribute) as teletype output */\nstatic void VidyaServiceWriteTeletype(u8 ch) {\n  u8 attr;\n  u8 *vram;\n  int x, y, xn;\n  x = BdaCurx;\n  y = BdaCury;\n  unassert(y < BdaLines);\n  unassert(x < BdaCols);\n  xn = BdaCols;\n  vram = video_ram();\n  switch (ch) {\n    case '\\r':\n      x = 0;\n      goto update;\n    case '\\n':\n      goto scroll;\n    case '\\b':\n      if (x > 0) {\n        x--;\n      }\n      goto update;\n    case '\\0':\n    case '\\a':\n      return;\n  }\n  vram[page_offsetw() + (y * xn + x) * 2] = ch;\n  if (++x >= xn) {\n    x = 0;\n  scroll:\n    if (++y >= BdaLines) {\n      y = BdaLines - 1;\n      attr = vram[page_offsetw() + ((y * xn + BdaCols - 1) * 2) + 1];\n      VidyaServiceScrollUp(0, BdaLines - 1, attr);\n    }\n  }\nupdate:\n  SetBdaCurx(x);\n  SetBdaCury(y);\n}\n\nvoid VidyaServiceSetMode(int mode) {\n  int cols, lines;\n  vidya = mode;\n  if (SpyAddress(m, 0xB0000)) {\n    ptyisenabled = true;\n    lines = 25;\n    switch (mode) {\n      case 0:  // CGA 40x25 16-gray\n      case 1:  // CGA 40x25 16-color\n        cols = 40;\n        break;\n      case 2:  // CGA 80x25 16-gray\n      case 3:  // CGA 80x25 16-color\n      case 7:  // MDA 80x25 4-gray\n        cols = 80;\n        break;\n      default:\n        unassert(mode == kModePty);\n        pty->conf &= ~kPtyNocursor;\n        break;\n    }\n    if (mode == kModePty) return;\n    SetBdaVmode(mode);\n    SetBdaLines(lines);  // EGA BIOS - max valid line #\n    SetBdaCols(cols);\n    SetBdaPagesz(cols * BdaLines * 2);\n    SetBdaCurpage(0);\n    SetBdaCurx(0);\n    SetBdaCury(0);\n    SetBdaCurstart(5);  // cursor ▂ scan lines 5..7 of 0..7\n    SetBdaCurend(7);\n    SetBdaCrtc(0x3D4);\n    VidyaServiceClearScreen(0, 0, cols, BdaLines, ATTR_DEFAULT);\n  } else {\n    LOGF(\"maybe you forgot -r flag\");\n  }\n}\n\nstatic void OnVidyaServiceGetMode(void) {\n  m->al = vidya;\n  m->ah = BdaCols;\n  m->bh = 0;  // page\n}\n\nstatic void OnVidyaServiceSetCursorType(void) {\n  if (vidya == kModePty) {\n    if (m->ch & 0x20) {\n      pty->conf |= kPtyNocursor;\n    } else {\n      pty->conf &= ~kPtyNocursor;\n    }\n  } else {\n    SetBdaCurstart(m->ch);\n    SetBdaCurend(m->cl);\n  }\n}\n\nstatic void OnVidyaServiceSetCursorPosition(void) {\n  int x, y;\n  x = m->dl;\n  y = m->dh;\n  if (vidya == kModePty) {\n    PtySetX(pty, x);\n    PtySetY(pty, y);\n  } else {\n    SetBdaCurx(x);\n    SetBdaCury(y);\n  }\n}\n\nstatic void OnVidyaServiceGetCursorPosition(void) {\n  if (vidya == kModePty) {\n    m->dh = pty->y;\n    m->dl = pty->x;\n    // cursor ▂ scan lines 5..7 of 0..7 and hidden bit 0x20\n    m->ch = 5 | !!(pty->conf & kPtyNocursor) << 5;\n    m->cl = 7;\n  } else {\n    m->dh = BdaCury;\n    m->dl = BdaCurx;\n    m->ch = BdaCurstart;\n    m->cl = BdaCurend;\n  }\n}\n\nstatic void OnVidyaServiceReadCharacter(void) {\n  u16 *vram;\n  u16 chattr;\n  int x, y, xn;\n  x = BdaCurx;\n  y = BdaCury;\n  xn = BdaCols;\n  vram = (u16 *)video_ram();\n  chattr = vram[page_offsetw() + y * xn + x];\n  Put16(m->ax, chattr);\n}\n\n/* write character and possibly attribute, no cursor change */\nstatic void OnVidyaServiceWriteCharacter(bool useattr) {\n  int i, n;\n  u64 w;\n  char *p, buf[32];\n  if (vidya != kModePty) {\n    n = Get16(m->cx);\n    unassert(n > 0 && n + BdaCurx <= BdaCols);\n    unassert(BdaCury < BdaLines);\n    VidyaServiceWriteCharacter(m->al, m->bl, n, useattr);\n    return;\n  }\n  p = buf;\n  p += FormatCga(m->bl, p);\n  p = stpcpy(p, \"\\0337\");\n  w = tpenc(GetVidyaByte(m->al));\n  do {\n    *p++ = w;\n  } while ((w >>= 8));\n  p = stpcpy(p, \"\\0338\");\n  for (i = Get16(m->cx); i; --i) {\n    PtyWrite(pty, buf, p - buf);\n  }\n}\n\nstatic wint_t VidyaServiceXlatTeletype(u8 c) {\n  switch (c) {\n    case '\\a':\n    case '\\b':\n    case '\\r':\n    case '\\n':\n    case 0177:\n      return c;\n    default:\n      return GetVidyaByte(c);\n  }\n}\n\nstatic void OnVidyaServiceWriteTeletype(void) {\n  int n;\n  u64 w;\n  char buf[12];\n  if (!ptyisenabled) {\n    ptyisenabled = true;\n    ReactiveDraw();\n  }\n  if (vidya != kModePty) {\n    VidyaServiceWriteTeletype(m->al);\n    return;\n  }\n  n = 0 /* FormatCga(ATTR_DEFAULT, buf) */;\n  w = tpenc(VidyaServiceXlatTeletype(m->al));\n  do {\n    buf[n++] = w;\n  } while ((w >>= 8));\n  PtyWrite(pty, buf, n);\n}\n\nstatic void OnVidyaService(void) {\n  switch (m->ah) {\n    case 0x00:\n      VidyaServiceSetMode(m->al);\n      break;\n    case 0x01:\n      OnVidyaServiceSetCursorType();\n      break;\n    case 0x02:\n      OnVidyaServiceSetCursorPosition();\n      break;\n    case 0x03:\n      OnVidyaServiceGetCursorPosition();\n      break;\n    case 0x06:\n      OnVidyaServiceScrollUp();\n      break;\n    case 0x07:\n      OnVidyaServiceScrollDown();\n      break;\n    case 0x08:\n      OnVidyaServiceReadCharacter();\n      break;\n    case 0x09:\n      OnVidyaServiceWriteCharacter(true);\n      Redraw(false);\n      DrawDisplayOnly();\n      break;\n    case 0x0A:\n      OnVidyaServiceWriteCharacter(false);\n      Redraw(false);\n      DrawDisplayOnly();\n      break;\n    case 0x0E:\n      OnVidyaServiceWriteTeletype();\n      Redraw(false);\n      DrawDisplayOnly();\n      break;\n    case 0x0F:\n      OnVidyaServiceGetMode();\n      break;\n    default:\n      LOGF(\"Unimplemented vidya service 0x%x\\n\", m->ah);\n      break;\n  }\n}\n\nstatic void OnSerialServiceReset(void) {\n  if (Get16(m->dx) == 0) {\n    m->al = 0xb0;  // following QEMU\n    m->ah = 0x60;\n  } else {\n    m->al = 0x00;  // Ralf Brown's Interrupt List says \"AX = 9E00h if\n    m->ah = 0x9e;  // disconnected (ArtiCom)\"\n  }\n}\n\nstatic void OnSerialService(void) {\n  switch (m->ah) {\n    case 0x00:\n      OnSerialServiceReset();\n      break;\n    default:\n      m->al = 0x00;\n      m->ah = 0x9e;\n      break;\n  }\n}\n\n/* Convert from ANSI keyboard sequence to scancode */\nint AnsiToScancode(char *buf, int n) {\n  if (n >= 1 && buf[0] == 033) {\n    if (buf[1] == '[') {\n      if (n == 3) {       /* xterm sequences */\n        switch (buf[2]) { /* ESC [ A etc */\n          case 'A':\n            return 0x48;  // kUpArrow\n          case 'B':\n            return 0x50;  // kDownArrow\n          case 'C':\n            return 0x4D;  // kRightArrow\n          case 'D':\n            return 0x4B;  // kLeftArrow\n          case 'F':\n            return 0x4F;  // kEnd\n          case 'H':\n            return 0x47;  // kHome\n        }\n      } else if (n == 4 && buf[2] == '1') { /* ESC [ 1 P etc */\n        switch (buf[3]) {\n          case 'P':\n            return 0x3B;  // kF1\n          case 'Q':\n            return 0x3C;  // kF2\n          case 'R':\n            return 0x3D;  // kF3\n          case 'S':\n            return 0x3E;  // kF4\n        }\n      }\n      if (n > 3 && buf[n - 1] == '~') { /* vt sequences */\n        switch (atoi(buf + 2)) {\n          case 1:\n            return 0x47;  // kHome\n          case 2:\n            return 0x52;  // kInsert\n          case 3:\n            return 0x53;  // kDelete\n          case 4:\n            return 0x4F;  // kEnd\n          case 5:\n            return 0x49;  // kPageUp\n          case 6:\n            return 0x51;  // kPageDown\n          case 7:\n            return 0x47;  // kHome\n          case 8:\n            return 0x4F;  // kEnd\n          case 11:\n            return 0x3B;  // kF1\n          case 12:\n            return 0x3C;  // kF2\n          case 13:\n            return 0x3D;  // kF3\n          case 14:\n            return 0x3E;  // kF4\n          case 15:\n            return 0x3F;  // kF5\n          case 17:\n            return 0x40;  // kF6\n          case 18:\n            return 0x41;  // kF7\n          case 19:\n            return 0x42;  // kF8\n          case 20:\n            return 0x43;  // kF9\n          case 21:\n            return 0x44;  // kF10\n          case 23:\n            return 0x85;  // kF11\n          case 24:\n            return 0x86;  // kF12\n        }\n      }\n    }\n  }\n  return 0;\n}\n\nstatic bool savechar;  // TODO(ghaerr): implement kbd input queue\nstatic u8 saveah;\nstatic u8 saveal;\n\nstatic void OnKeyboardServiceReadKeyPress(void) {\n  uint8_t b;\n  ssize_t rc;\n  static char buf[32];\n  static size_t pending;\n  LOGF(\"OnKeyboardServiceReadKeyPress\");\n  if (savechar) {\n    savechar = false;\n    m->ah = saveah;\n    m->al = saveal;\n    return;\n  }\n  if (!ptyisenabled) {\n    ptyisenabled = true;\n    ReactiveDraw();\n  }\n  pty->conf |= kPtyBlinkcursor;\n  if (!pending) {\n    rc = ReadAnsi(ttyin, buf, sizeof(buf));\n    if (rc > 0) {\n      pending = rc;\n    } else {\n      HandleAppReadInterrupt(rc != -1 || errno != EINTR);\n      return;\n    }\n  }\n  pty->conf &= ~kPtyBlinkcursor;\n  unassert((int)pending > 0 && pending < 32);\n  ReactiveDraw();\n  if (m->metal) {\n    int r = AnsiToScancode(buf, pending);\n    if (r) {\n      m->al = 0;\n      m->ah = r;\n      pending = 0;\n      return;\n    }\n  }\n  b = buf[0];\n  if (pending > 1) {\n    memmove(buf, buf + 1, pending - 1);\n  }\n  --pending;\n  if (b == 0177) b = '\\b';\n  m->al = b;\n  m->ah = 0;\n}\n\nstatic void OnKeyboardServiceCheckKeyPress(void) {\n  if (savechar) {\n    m->ah = saveah;\n    m->al = saveal;\n    return;\n  }\n  bool b = HasPendingKeyboard();\n  m->flags = SetFlag(m->flags, FLAGS_ZF, !b); /* ZF=0 if key pressed */\n  if (b) {\n    OnKeyboardServiceReadKeyPress();\n    savechar = true;\n    saveah = m->ah;\n    saveal = m->al;\n  } else {\n    m->ah = 0;\n    m->al = 0;\n  }\n}\n\nstatic void OnKeyboardService(void) {\n  switch (m->ah) {\n    case 0x00:\n      OnKeyboardServiceReadKeyPress();\n      break;\n    case 0x01:\n      OnKeyboardServiceCheckKeyPress();\n      break;\n    default:\n      break;\n  }\n}\n\nstatic void OnApmService(void) {\n  if (Get16(m->ax) == 0x5300 && Get16(m->bx) == 0x0000) {\n    Put16(m->bx, 'P' << 8 | 'M');\n    SetCarry(false);\n  } else if (Get16(m->ax) == 0x5301 && Get16(m->bx) == 0x0000) {\n    SetCarry(false);\n  } else if (Get16(m->ax) == 0x5307 && m->bl == 1 && m->cl == 3) {\n    LOGF(\"APM SHUTDOWN\");\n    exit(EXIT_SUCCESS);\n  } else {\n    SetCarry(true);\n  }\n}\n\nstatic void OnE820(void) {\n  i64 addr;\n  u8 p[20];\n  addr = m->es.base + Get16(m->di);\n  if (Get32(m->dx) == 0x534D4150 && Get32(m->cx) == 24 &&\n      addr + (int)sizeof(p) <= kRealSize) {\n    if (!Get32(m->bx)) {\n      Store64(p + 0, 0);\n      Store64(p + 8, kRealSize);\n      Store32(p + 16, 1);\n      memcpy(m->system->real + addr, p, sizeof(p));\n      SetWriteAddr(m, addr, sizeof(p));\n      Put32(m->cx, sizeof(p));\n      Put32(m->bx, 1);\n    } else {\n      Put32(m->bx, 0);\n      Put32(m->cx, 0);\n    }\n    Put32(m->ax, 0x534D4150);\n    SetCarry(false);\n  } else {\n    SetCarry(true);\n  }\n}\n\nstatic void OnInt15h(void) {\n  int timeout;\n  if (Get32(m->ax) == 0xE820) {\n    OnE820();\n  } else if (m->ah == 0x53) {\n    OnApmService();\n  } else if (m->ah == 0x86) {  // microsecond delay\n    timeout = (((Get16(m->cx) << 16) | Get16(m->dx)) + 999) / 1000;\n    poll(0, 0, timeout);\n  } else {\n    SetCarry(true);\n  }\n}\n\nstatic void OnEquipmentListService(void) {\n  Put16(m->ax, BdaEquip);\n}\n\nstatic void OnBaseMemSizeService(void) {\n  Put16(m->ax, BdaMemsz);\n}\n\nstatic void OnPrinterService(void) {\n  m->ah = 0xb0;  // \"no printer\": not busy, out of paper, selected\n}\n\nstatic void OnTimeServiceGetSystemTime(void) {\n  u64 DAY_SECS = 24UL * 60 * 60;\n  struct timespec now = GetTime();\n  u64 currday, daytime;\n  u8 midnights = 0;\n  unassert(now.tv_sec >= DAY_SECS);\n  currday = (u64)now.tv_sec / DAY_SECS;\n  // calculate the number of midnights elapsed since the last call here\n  // this will also reset the midnight count\n  if (prevday != 0) {\n    if (currday > prevday) midnights = currday - prevday;\n  }\n  prevday = currday;\n  // calculate nanoseconds from day start\n  daytime = (u64)now.tv_sec - currday * DAY_SECS;\n  daytime = daytime * 1000000000L + now.tv_nsec;\n  // calculate BIOS system timer ticks from day start\n  daytime = daytime * (0x1800B0L / 80) / (DAY_SECS * 1000000000L / 80);\n  Put16(m->cx, daytime >> 16);\n  Put16(m->dx, daytime);\n  m->al = midnights;\n}\n\nstatic u8 ToBcdByte(u8 binary) {\n  static const u8 bcd[] = {\n      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11,\n      0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23,\n      0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,\n      0x36, 0x37, 0x38, 0x39, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,\n      0x48, 0x49, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,\n      0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71,\n      0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x80, 0x81, 0x82, 0x83,\n      0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95,\n      0x96, 0x97, 0x98, 0x99};\n  unassert(binary <= 99);\n  return bcd[binary];\n}\n\nstatic void OnTimeServiceGetRtcTime(void) {\n  struct timespec now = GetTime();\n  struct tm tm;\n  unassert(gmtime_r(&now.tv_sec, &tm));\n  m->ch = ToBcdByte(tm.tm_hour);\n  m->cl = ToBcdByte(tm.tm_min);\n  m->dh = ToBcdByte(tm.tm_sec);\n  m->dl = tm.tm_isdst;\n  SetCarry(false);\n}\n\nstatic void OnTimeServiceGetRtcDate(void) {\n  struct timespec now = GetTime();\n  struct tm tm;\n  unassert(gmtime_r(&now.tv_sec, &tm));\n  m->ch = ToBcdByte((tm.tm_year / 100U + 19) % 100U);\n  m->cl = ToBcdByte(tm.tm_year % 100U);\n  m->dh = ToBcdByte(tm.tm_mon + 1U);\n  m->dl = ToBcdByte(tm.tm_mday);\n  SetCarry(false);\n}\n\nstatic void OnTimeService(void) {\n  switch (m->ah) {\n    case 0x00:\n      OnTimeServiceGetSystemTime();\n      break;\n    case 0x02:\n      OnTimeServiceGetRtcTime();\n      break;\n    case 0x04:\n      OnTimeServiceGetRtcDate();\n      break;\n    default:\n      SetCarry(true);\n  }\n}\n\nbool OnCallBios(int interrupt) {\n  switch (interrupt) {\n    case 0x10:\n      OnVidyaService();\n      return true;\n    case 0x13:\n      OnDiskService();\n      return true;\n    case 0x14:\n      OnSerialService();\n      return true;\n    case 0x15:\n      OnInt15h();\n      return true;\n    case 0x16:\n      OnKeyboardService();\n      return true;\n    case 0x11:\n      OnEquipmentListService();\n      return true;\n    case 0x12:\n      OnBaseMemSizeService();\n      return true;\n    case 0x17:\n      OnPrinterService();\n      return true;\n    case 0x19:\n      DetermineChs();\n      BootProgram(m, &m->system->elf, diskisfloppy ? 0x00 : 0x80);\n      VidyaServiceSetMode(vidya);\n      return true;\n    case 0x1A:\n      OnTimeService();\n      Redraw(false);\n      return true;\n  }\n  return false;\n}\n"
  },
  {
    "path": "blink/biosrom.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ This is free and unencumbered software released into the public domain.      │\n│                                                                              │\n│ Anyone is free to copy, modify, publish, use, compile, sell, or              │\n│ distribute this software, either in source code form or as a compiled        │\n│ binary, for any purpose, commercial or non-commercial, and by any            │\n│ means.                                                                       │\n│                                                                              │\n│ In jurisdictions that recognize copyright laws, the author or authors        │\n│ of this software dedicate any and all copyright interest in the              │\n│ software to the public domain. We make this dedication for the benefit       │\n│ of the public at large and to the detriment of our heirs and                 │\n│ successors. We intend this dedication to be an overt act of                  │\n│ relinquishment in perpetuity of all present and future rights to this        │\n│ software under copyright law.                                                │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,              │\n│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF           │\n│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.       │\n│ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR            │\n│ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,        │\n│ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR        │\n│ OTHER DEALINGS IN THE SOFTWARE.                                              │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/biosrom.h\"\n\n#include <errno.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/bda.h\"\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/overlays.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n\n#define kBiosArrayBase  ROUNDDOWN(kBiosEntry - (0x1D * 4 + 12 + 8 * 4), 0x10)\n#define kBiosDefInt0x00 kBiosArrayBase\n#define kBiosDefInt0x01 (kBiosDefInt0x00 + 4)\n#define kBiosDefInt0x02 (kBiosDefInt0x01 + 4)\n#define kBiosDefInt0x03 (kBiosDefInt0x02 + 4)\n#define kBiosDefInt0x04 (kBiosDefInt0x03 + 4)\n#define kBiosDefInt0x05 (kBiosDefInt0x04 + 4)\n#define kBiosDefInt0x06 (kBiosDefInt0x05 + 4)\n#define kBiosDefInt0x07 (kBiosDefInt0x06 + 4)\n#define kBiosDefInt0x08 (kBiosDefInt0x07 + 4)\n#define kBiosDefInt0x09 (kBiosDefInt0x08 + 4)\n#define kBiosDefInt0x0A (kBiosDefInt0x09 + 4)\n#define kBiosDefInt0x0B (kBiosDefInt0x0A + 4)\n#define kBiosDefInt0x0C (kBiosDefInt0x0B + 4)\n#define kBiosDefInt0x0D (kBiosDefInt0x0C + 4)\n#define kBiosDefInt0x0E (kBiosDefInt0x0D + 4)\n#define kBiosDefInt0x0F (kBiosDefInt0x0E + 4)\n#define kBiosDefInt0x10 (kBiosDefInt0x0F + 4)\n#define kBiosDefInt0x11 (kBiosDefInt0x10 + 4)\n#define kBiosDefInt0x12 (kBiosDefInt0x11 + 4)\n#define kBiosDefInt0x13 (kBiosDefInt0x12 + 4)\n#define kBiosDefInt0x14 (kBiosDefInt0x13 + 4)\n#define kBiosDefInt0x15 (kBiosDefInt0x14 + 4)\n#define kBiosDefInt0x16 (kBiosDefInt0x15 + 4)\n#define kBiosDefInt0x17 (kBiosDefInt0x16 + 4)\n#define kBiosDefInt0x18 (kBiosDefInt0x17 + 4)\n#define kBiosDefInt0x19 (kBiosDefInt0x18 + 4)\n#define kBiosDefInt0x1A (kBiosDefInt0x19 + 4)\n#define kBiosDefInt0x1B (kBiosDefInt0x1A + 4)\n#define kBiosDefInt0x1C (kBiosDefInt0x1B + 4)\n#define kBiosDefInt0x1E (kBiosDefInt0x1C + 4)\n#define kBiosDefInt0x70 (kBiosDefInt0x1E + 12)\n#define kBiosDefInt0x71 (kBiosDefInt0x70 + 4)\n#define kBiosDefInt0x72 (kBiosDefInt0x71 + 4)\n#define kBiosDefInt0x73 (kBiosDefInt0x72 + 4)\n#define kBiosDefInt0x74 (kBiosDefInt0x73 + 4)\n#define kBiosDefInt0x75 (kBiosDefInt0x74 + 4)\n#define kBiosDefInt0x76 (kBiosDefInt0x75 + 4)\n#define kBiosDefInt0x77 (kBiosDefInt0x76 + 4)\n\n#define BIOS_BYTES_AT(addr, ...) [((addr)) - kBiosArrayBase] = __VA_ARGS__\n\nstatic const u8 kDefBios[] = {\n    BIOS_BYTES_AT(kBiosDefInt0x00, 0x0F, 0xFF, 0067),        // hvtailcall 0x00\n    BIOS_BYTES_AT(kBiosDefInt0x01, 0x0F, 0xFF, 0167, 0x01),  // hvtailcall 0x01\n    BIOS_BYTES_AT(kBiosDefInt0x02, 0x0F, 0xFF, 0167, 0x02),  // hvtailcall 0x02\n    BIOS_BYTES_AT(kBiosDefInt0x03, 0x0F, 0xFF, 0167, 0x03),  // hvtailcall 0x03\n    BIOS_BYTES_AT(kBiosDefInt0x04, 0x0F, 0xFF, 0167, 0x04),  // hvtailcall 0x04\n    BIOS_BYTES_AT(kBiosDefInt0x05, 0x0F, 0xFF, 0167, 0x05),  // hvtailcall 0x05\n    BIOS_BYTES_AT(kBiosDefInt0x06, 0x0F, 0xFF, 0167, 0x06),  // hvtailcall 0x06\n    BIOS_BYTES_AT(kBiosDefInt0x07, 0x0F, 0xFF, 0167, 0x07),  // hvtailcall 0x07\n    BIOS_BYTES_AT(kBiosDefInt0x08, 0x0F, 0xFF, 0167, 0x08),  // hvtailcall 0x08\n    BIOS_BYTES_AT(kBiosDefInt0x09, 0x0F, 0xFF, 0167, 0x09),  // hvtailcall 0x09\n    BIOS_BYTES_AT(kBiosDefInt0x0A, 0x0F, 0xFF, 0167, 0x0A),  // hvtailcall 0x0A\n    BIOS_BYTES_AT(kBiosDefInt0x0B, 0x0F, 0xFF, 0167, 0x0B),  // hvtailcall 0x0B\n    BIOS_BYTES_AT(kBiosDefInt0x0C, 0x0F, 0xFF, 0167, 0x0C),  // hvtailcall 0x0C\n    BIOS_BYTES_AT(kBiosDefInt0x0D, 0x0F, 0xFF, 0167, 0x0D),  // hvtailcall 0x0D\n    BIOS_BYTES_AT(kBiosDefInt0x0E, 0x0F, 0xFF, 0167, 0x0E),  // hvtailcall 0x0E\n    BIOS_BYTES_AT(kBiosDefInt0x0F, 0x0F, 0xFF, 0167, 0x0F),  // hvtailcall 0x0F\n    BIOS_BYTES_AT(kBiosDefInt0x10, 0x0F, 0xFF, 0167, 0x10),  // hvtailcall 0x10\n    BIOS_BYTES_AT(kBiosDefInt0x11, 0x0F, 0xFF, 0167, 0x11),  // hvtailcall 0x11\n    BIOS_BYTES_AT(kBiosDefInt0x12, 0x0F, 0xFF, 0167, 0x12),  // hvtailcall 0x12\n    BIOS_BYTES_AT(kBiosDefInt0x13, 0x0F, 0xFF, 0167, 0x13),  // hvtailcall 0x13\n    BIOS_BYTES_AT(kBiosDefInt0x14, 0x0F, 0xFF, 0167, 0x14),  // hvtailcall 0x14\n    BIOS_BYTES_AT(kBiosDefInt0x15, 0x0F, 0xFF, 0167, 0x15),  // hvtailcall 0x15\n    BIOS_BYTES_AT(kBiosDefInt0x16, 0x0F, 0xFF, 0167, 0x16),  // hvtailcall 0x16\n    BIOS_BYTES_AT(kBiosDefInt0x17, 0x0F, 0xFF, 0167, 0x17),  // hvtailcall 0x17\n    BIOS_BYTES_AT(kBiosDefInt0x18, 0x0F, 0xFF, 0167, 0x18),  // hvtailcall 0x18\n    BIOS_BYTES_AT(kBiosDefInt0x19, 0x0F, 0xFF, 0167, 0x19),  // hvtailcall 0x19\n    BIOS_BYTES_AT(kBiosDefInt0x1A, 0x0F, 0xFF, 0167, 0x1A),  // hvtailcall 0x1A\n    BIOS_BYTES_AT(kBiosDefInt0x1B, 0x0F, 0xFF, 0167, 0x1B),  // hvtailcall 0x1B\n    BIOS_BYTES_AT(kBiosDefInt0x1C, 0x0F, 0xFF, 0167, 0x1C),  // hvtailcall 0x1C\n    // default diskette parameter table per Jun 1985 PC AT BIOS; see p. 5-192 @\n    // https://archive.org/details/IBMPCATIBM5170TechnicalReference6280070SEP85\n    BIOS_BYTES_AT(kBiosDefInt0x1E,                           //\n                  0xDF, 2, 37, 2, 15,                        //\n                  0x1B, 0xFF, 0x54, 0xF6, 15, 8),            //\n    BIOS_BYTES_AT(kBiosDefInt0x70, 0x0F, 0xFF, 0167, 0x70),  // hvtailcall 0x70\n    BIOS_BYTES_AT(kBiosDefInt0x71, 0x0F, 0xFF, 0167, 0x71),  // hvtailcall 0x71\n    BIOS_BYTES_AT(kBiosDefInt0x72, 0x0F, 0xFF, 0167, 0x72),  // hvtailcall 0x72\n    BIOS_BYTES_AT(kBiosDefInt0x73, 0x0F, 0xFF, 0167, 0x73),  // hvtailcall 0x73\n    BIOS_BYTES_AT(kBiosDefInt0x74, 0x0F, 0xFF, 0167, 0x74),  // hvtailcall 0x74\n    BIOS_BYTES_AT(kBiosDefInt0x75, 0x0F, 0xFF, 0167, 0x75),  // hvtailcall 0x75\n    BIOS_BYTES_AT(kBiosDefInt0x76, 0x0F, 0xFF, 0167, 0x76),  // hvtailcall 0x76\n    BIOS_BYTES_AT(kBiosDefInt0x77, 0x0F, 0xFF, 0167, 0x77),  // hvtailcall 0x77\n    BIOS_BYTES_AT(kBiosEntry,                                //\n                  0x0F, 0xFF, 0177, 0x19,                    // hvcall 0x19\n                  0xEB, 0xFA),                               // jmp .-4\n    BIOS_BYTES_AT(kBiosEnd - 1, 0x00)};\n\nvoid LoadBios(struct Machine *m, const char *biosprog) {\n  off_t size;\n  if (biosprog) {\n    off_t kBiosMinSize = kBiosEnd - kBiosEntry,\n          kBiosMaxSize = kBiosEnd - kBiosOptBase;\n    int fd;\n    struct stat st;\n    char tmp[64];\n    if ((fd = VfsOpen(AT_FDCWD, biosprog, O_RDONLY, 0)) == -1 ||\n        VfsFstat(fd, &st) == -1) {\n      WriteErrorString(biosprog);\n      WriteErrorString(\": failed to load alternate BIOS (errno \");\n      FormatInt64(tmp, errno);\n      WriteErrorString(tmp);\n      WriteErrorString(\")\\n\");\n      exit(EXIT_FAILURE_EXEC_FAILED);\n    } else if ((size = st.st_size) < kBiosMinSize) {\n      WriteErrorString(biosprog);\n      WriteErrorString(\": failed to load alternate BIOS (file too small)\\n\");\n      exit(EXIT_FAILURE_EXEC_FAILED);\n    } else if (size > kBiosMaxSize) {\n      WriteErrorString(biosprog);\n      WriteErrorString(\": failed to load alternate BIOS (file too large)\\n\");\n      exit(EXIT_FAILURE_EXEC_FAILED);\n    } else if (VfsRead(fd, m->system->real + kBiosEnd - size, size) != size) {\n      WriteErrorString(biosprog);\n      WriteErrorString(\": failed to load alternate BIOS (errno \");\n      FormatInt64(tmp, errno);\n      WriteErrorString(tmp);\n      WriteErrorString(\")\\n\");\n      exit(EXIT_FAILURE_EXEC_FAILED);\n    }\n  } else {\n    // if no BIOS image file name is given, then load a default BIOS image\n    size = sizeof(kDefBios);\n    memcpy(m->system->real + kBiosEnd - size, kDefBios, size);\n  }\n#ifndef DISABLE_ROM\n  // try to protect the BIOS ROM area\n  // BeginStore() & EndStore() will avoid scribbling in this area of\n  // memory: so writes to the guest ROM area are effectively ignored\n  size_t protstart, protend;\n  protstart = ROUNDUP(kBiosOptBase, FLAG_pagesize);\n  protend = ROUNDDOWN(kBiosEnd, FLAG_pagesize);\n  if (protstart < protend) {\n    Mprotect(m->system->real + protstart, protend - protstart, PROT_READ,\n             \"bios\");\n  }\n#endif\n  // load %cs:%rip\n  m->cs.sel = kBiosSeg;\n  m->cs.base = kBiosBase;\n  m->ip = kBiosEntry - kBiosBase;\n}\n\nvoid SetDefaultBiosIntVectors(struct Machine *m) {\n  struct System *s = m->system;\n  s->idt_base = 0;\n  s->idt_limit = 0x100 * 4 - 1;\n  memset(s->real + 0x1D * 4, 0, (0x100 - 0x1D) * 4);\n  Put32(s->real + 0x00 * 4, kBiosSeg << 16 | (kBiosDefInt0x00 - kBiosBase));\n  Put32(s->real + 0x01 * 4, kBiosSeg << 16 | (kBiosDefInt0x01 - kBiosBase));\n  Put32(s->real + 0x02 * 4, kBiosSeg << 16 | (kBiosDefInt0x02 - kBiosBase));\n  Put32(s->real + 0x03 * 4, kBiosSeg << 16 | (kBiosDefInt0x03 - kBiosBase));\n  Put32(s->real + 0x04 * 4, kBiosSeg << 16 | (kBiosDefInt0x04 - kBiosBase));\n  Put32(s->real + 0x05 * 4, kBiosSeg << 16 | (kBiosDefInt0x05 - kBiosBase));\n  Put32(s->real + 0x06 * 4, kBiosSeg << 16 | (kBiosDefInt0x06 - kBiosBase));\n  Put32(s->real + 0x07 * 4, kBiosSeg << 16 | (kBiosDefInt0x07 - kBiosBase));\n  Put32(s->real + 0x08 * 4, kBiosSeg << 16 | (kBiosDefInt0x08 - kBiosBase));\n  Put32(s->real + 0x09 * 4, kBiosSeg << 16 | (kBiosDefInt0x09 - kBiosBase));\n  Put32(s->real + 0x0A * 4, kBiosSeg << 16 | (kBiosDefInt0x0A - kBiosBase));\n  Put32(s->real + 0x0B * 4, kBiosSeg << 16 | (kBiosDefInt0x0B - kBiosBase));\n  Put32(s->real + 0x0C * 4, kBiosSeg << 16 | (kBiosDefInt0x0C - kBiosBase));\n  Put32(s->real + 0x0D * 4, kBiosSeg << 16 | (kBiosDefInt0x0D - kBiosBase));\n  Put32(s->real + 0x0E * 4, kBiosSeg << 16 | (kBiosDefInt0x0E - kBiosBase));\n  Put32(s->real + 0x0F * 4, kBiosSeg << 16 | (kBiosDefInt0x0F - kBiosBase));\n  Put32(s->real + 0x10 * 4, kBiosSeg << 16 | (kBiosDefInt0x10 - kBiosBase));\n  Put32(s->real + 0x11 * 4, kBiosSeg << 16 | (kBiosDefInt0x11 - kBiosBase));\n  Put32(s->real + 0x12 * 4, kBiosSeg << 16 | (kBiosDefInt0x12 - kBiosBase));\n  Put32(s->real + 0x13 * 4, kBiosSeg << 16 | (kBiosDefInt0x13 - kBiosBase));\n  Put32(s->real + 0x14 * 4, kBiosSeg << 16 | (kBiosDefInt0x14 - kBiosBase));\n  Put32(s->real + 0x15 * 4, kBiosSeg << 16 | (kBiosDefInt0x15 - kBiosBase));\n  Put32(s->real + 0x16 * 4, kBiosSeg << 16 | (kBiosDefInt0x16 - kBiosBase));\n  Put32(s->real + 0x17 * 4, kBiosSeg << 16 | (kBiosDefInt0x17 - kBiosBase));\n  Put32(s->real + 0x18 * 4, kBiosSeg << 16 | (kBiosDefInt0x18 - kBiosBase));\n  Put32(s->real + 0x19 * 4, kBiosSeg << 16 | (kBiosDefInt0x19 - kBiosBase));\n  Put32(s->real + 0x1A * 4, kBiosSeg << 16 | (kBiosDefInt0x1A - kBiosBase));\n  Put32(s->real + 0x1B * 4, kBiosSeg << 16 | (kBiosDefInt0x1B - kBiosBase));\n  Put32(s->real + 0x1C * 4, kBiosSeg << 16 | (kBiosDefInt0x1C - kBiosBase));\n  Put32(s->real + 0x1E * 4, kBiosSeg << 16 | (kBiosDefInt0x1E - kBiosBase));\n  Put32(s->real + 0x70 * 4, kBiosSeg << 16 | (kBiosDefInt0x70 - kBiosBase));\n  Put32(s->real + 0x71 * 4, kBiosSeg << 16 | (kBiosDefInt0x71 - kBiosBase));\n  Put32(s->real + 0x72 * 4, kBiosSeg << 16 | (kBiosDefInt0x72 - kBiosBase));\n  Put32(s->real + 0x73 * 4, kBiosSeg << 16 | (kBiosDefInt0x73 - kBiosBase));\n  Put32(s->real + 0x74 * 4, kBiosSeg << 16 | (kBiosDefInt0x74 - kBiosBase));\n  Put32(s->real + 0x75 * 4, kBiosSeg << 16 | (kBiosDefInt0x75 - kBiosBase));\n  Put32(s->real + 0x76 * 4, kBiosSeg << 16 | (kBiosDefInt0x76 - kBiosBase));\n  Put32(s->real + 0x77 * 4, kBiosSeg << 16 | (kBiosDefInt0x77 - kBiosBase));\n}\n\nvoid SetDefaultBiosDataArea(struct Machine *m) {\n  memset(m->system->real + 0x400, 0, 0x100);\n  SetBdaCom1(0x3F8);\n  SetBdaEbda(0xB0000 >> 4);\n  SetBdaEquip(1 << 0 |  // floppy drive\n              1 << 1 |  // math coprocessor\n              3 << 4 |  // initial video mode\n              0 << 6 |  // no. of floppy drives - 1\n              1 << 9);  // no. of serial devices\n  SetBdaMemsz(0xB0000 / 1024);\n  SetBdaCols(80);\n  SetBdaLines(25);\n}\n\nu32 GetDefaultBiosDisketteParamTable(void) {\n  return kBiosSeg << 16 | (kBiosDefInt0x1E - kBiosBase);\n}\n"
  },
  {
    "path": "blink/biosrom.h",
    "content": "#ifndef BLINK_BIOSROM_H_\n#define BLINK_BIOSROM_H_\n\n#define kBiosBase    0x000F0000        // nominal base address of BIOS image\n#define kBiosSeg     (kBiosBase >> 4)  // nominal base segment of BIOS image\n#define kBiosEnd     0x00100000        // address immediately after BIOS image\n#define kBiosEntry   0x000FFFF0        // entry point\n#define kBiosOptBase 0x000C0000        // lowest possible base address of\n                                       // BIOS image, including option ROMs\n\n#if !(__ASSEMBLER__ + __LINKER__ + 0)\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/likely.h\"\n#include \"blink/machine.h\"\n\nMICRO_OP_SAFE bool IsRomAddress(struct Machine *m, u8 *r) {\n#ifndef DISABLE_ROM\n  if (m->metal) {\n    struct System *s = m->system;\n    u8 *real = s->real;\n#if CAN_ABUSE_POINTERS\n    ptrdiff_t d = r - real;\n    // gcc optimizes this conjunction into subtraction followed by comparison\n    // FIXME: find better way to figure out if we can abuse ptrdiff_t like so\n    if (UNLIKELY(kBiosOptBase <= d && d < kBiosEnd))\n#else\n    if (UNLIKELY(&real[kBiosOptBase] <= r && r < &real[kBiosEnd]))\n#endif\n    {\n      if (s->onromwriteattempt) s->onromwriteattempt(m, r);\n      return true;\n    }\n  }\n#endif\n  return false;\n}\n\nvoid LoadBios(struct Machine *, const char *);\nvoid SetDefaultBiosIntVectors(struct Machine *);\nvoid SetDefaultBiosDataArea(struct Machine *);\nu32 GetDefaultBiosDisketteParamTable(void);\n#endif /*  !(__ASSEMBLER__ + __LINKER__ + 0) */\n\n#endif /* BLINK_BIOSROM_H_ */\n"
  },
  {
    "path": "blink/bit.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/bus.h\"\n#include \"blink/flags.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n\nstatic u64 Bts(u64 x, u64 y) {\n  return x | y;\n}\n\nstatic u64 Btr(u64 x, u64 y) {\n  return x & ~y;\n}\n\nstatic u64 Btc(u64 x, u64 y) {\n  return (x & ~y) | (~x & y);\n}\n\nvoid OpBit(P) {\n  u8 *p;\n  int op;\n  i64 bitdisp;\n  unsigned bit;\n  u64 v, x, y, z;\n  u8 w, W[2][2] = {{2, 3}, {1, 3}};\n  w = W[Osz(rde)][Rexw(rde)];\n  if (Opcode(rde) == 0xBA) {\n    op = ModrmReg(rde);\n    bit = uimm0 & ((8 << w) - 1);\n    bitdisp = 0;\n  } else {\n    op = (Opcode(rde) & 070) >> 3;\n    bitdisp = ReadRegisterSigned(rde, RegRexrReg(m, rde));\n    bit = bitdisp & ((8 << w) - 1);\n    bitdisp &= -(8 << w);\n    bitdisp >>= 3;\n  }\n  if (IsModrmRegister(rde)) {\n    p = RegRexbRm(m, rde);\n  } else {\n    v = MaskAddress(Eamode(rde), ComputeAddress(A) + bitdisp);\n    p = ReserveAddress(m, v, 1 << w, op != 4);\n  }\n  if (Lock(rde)) LockBus(p);\n  y = 1;\n  y <<= bit;\n  if (Lock(rde)) {\n    x = ReadMemoryUnlocked(rde, p);\n  } else {\n    x = ReadMemory(rde, p);\n  }\n  m->flags = SetFlag(m->flags, FLAGS_CF, !!(y & x));\n  switch (op) {\n    case 4:\n      return;\n    case 5:\n      z = Bts(x, y);\n      break;\n    case 6:\n      z = Btr(x, y);\n      break;\n    case 7:\n      z = Btc(x, y);\n      break;\n    default:\n      OpUdImpl(m);\n  }\n  WriteRegisterOrMemory(rde, p, z);\n  if (Lock(rde)) UnlockBus(p);\n}\n"
  },
  {
    "path": "blink/bitscan.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/bitscan.h\"\n\nstatic const char kDebruijn[64] = {\n    0,  47, 1,  56, 48, 27, 2,  60, 57, 49, 41, 37, 28, 16, 3,  61,\n    54, 58, 35, 52, 50, 42, 21, 44, 38, 32, 29, 23, 17, 11, 4,  62,\n    46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43, 31, 22, 10, 45,\n    25, 39, 14, 33, 19, 30, 9,  24, 13, 18, 8,  12, 7,  6,  5,  63,\n};\n\nint(bsr)(u64 x) {\n  x |= x >> 1;\n  x |= x >> 2;\n  x |= x >> 4;\n  x |= x >> 8;\n  x |= x >> 16;\n  x |= x >> 32;\n  return kDebruijn[(x * 0x03f79d71b4cb0a89) >> 58];\n}\n\nint(bsf)(u64 x) {\n  u32 l, r;\n  x &= -x;\n  l = x | x >> 32;\n  r = !!(x >> 32), r <<= 1;\n  r += !!((l & 0xffff0000)), r <<= 1;\n  r += !!((l & 0xff00ff00)), r <<= 1;\n  r += !!((l & 0xf0f0f0f0)), r <<= 1;\n  r += !!((l & 0xcccccccc)), r <<= 1;\n  r += !!((l & 0xaaaaaaaa));\n  return r;\n}\n"
  },
  {
    "path": "blink/bitscan.h",
    "content": "#ifndef BLINK_BITSCAN_H_\n#define BLINK_BITSCAN_H_\n#include \"blink/builtin.h\"\n#include \"blink/types.h\"\n#ifndef __GNUC__\n\nint bsr(u64);\nint bsf(u64);\nint popcount(u64);\n\n#else\n#define bsf(x)      __builtin_ctzll(x)\n#define bsr(x)      (__builtin_clzll(x) ^ 63)\n#define popcount(x) __builtin_popcountll(x)\n#endif /* GNUC */\n#endif /* BLINK_BITSCAN_H_ */\n"
  },
  {
    "path": "blink/blink-shell.html",
    "content": "<!doctype html>\n<html lang=\"en-us\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n    <title>blink online preview</title>\n    <!-- BLINK SPECIFIC STYLE -->\n    <style>\n      #controls { display: none!important }\n      #output { display: none!important }\n      [class^=\"emscripten\"]:has(canvas) { display: none!important }\n\n      .blink { display: block; margin-top: 5px; margin-bottom: 5px; }\n\n      .blink-terminal {\n        width: 100%;\n        margin: 0 auto;\n        margin-top: 10px;\n        border-left: 0px;\n        border-right: 0px;\n        padding-left: 0px;\n        padding-right: 0px;\n        display: block;\n        background-color: black;\n        color: white;\n        font-family: 'Lucida Console', Monaco, monospace;\n        outline: none;\n      }\n    </style>\n    <!-- BLINK SPECIFIC: Enable SharedArrayBuffer -->\n    <script src=\"coi-serviceworker.js\"></script>\n    <script src=\"xterm.min.js\"></script>\n    <link rel=\"stylesheet\" href=\"xterm.css\"/>\n    <style>\n      body {\n        font-family: arial;\n        margin: 0;\n        padding: none;\n      }\n\n      .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }\n      div.emscripten { text-align: center; }\n      div.emscripten_border { border: 1px solid black; }\n      /* the canvas *must not* have any border or padding, or mouse coords will be wrong */\n      canvas.emscripten { border: 0px none; background-color: black; }\n\n      #emscripten_logo {\n        display: inline-block;\n        margin: 0;\n      }\n\n      .spinner {\n        height: 30px;\n        width: 30px;\n        margin: 0;\n        margin-top: 20px;\n        margin-left: 20px;\n        display: inline-block;\n        vertical-align: top;\n\n        -webkit-animation: rotation .8s linear infinite;\n        -moz-animation: rotation .8s linear infinite;\n        -o-animation: rotation .8s linear infinite;\n        animation: rotation 0.8s linear infinite;\n\n        border-left: 5px solid rgb(235, 235, 235);\n        border-right: 5px solid rgb(235, 235, 235);\n        border-bottom: 5px solid rgb(235, 235, 235);\n        border-top: 5px solid rgb(120, 120, 120);\n\n        border-radius: 100%;\n        background-color: rgb(189, 215, 46);\n      }\n\n      @-webkit-keyframes rotation {\n        from {-webkit-transform: rotate(0deg);}\n        to {-webkit-transform: rotate(360deg);}\n      }\n      @-moz-keyframes rotation {\n        from {-moz-transform: rotate(0deg);}\n        to {-moz-transform: rotate(360deg);}\n      }\n      @-o-keyframes rotation {\n        from {-o-transform: rotate(0deg);}\n        to {-o-transform: rotate(360deg);}\n      }\n      @keyframes rotation {\n        from {transform: rotate(0deg);}\n        to {transform: rotate(360deg);}\n      }\n\n      #status {\n        display: inline-block;\n        vertical-align: top;\n        margin-top: 30px;\n        margin-left: 20px;\n        font-weight: bold;\n        color: rgb(120, 120, 120);\n      }\n\n      #progress {\n        height: 20px;\n        width: 300px;\n      }\n\n      #controls {\n        display: inline-block;\n        float: right;\n        vertical-align: top;\n        margin-top: 30px;\n        margin-right: 20px;\n      }\n\n      #output {\n        width: 100%;\n        height: 200px;\n        margin: 0 auto;\n        margin-top: 10px;\n        border-left: 0px;\n        border-right: 0px;\n        padding-left: 0px;\n        padding-right: 0px;\n        display: block;\n        background-color: black;\n        color: white;\n        font-family: 'Lucida Console', Monaco, monospace;\n        outline: none;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"spinner\" id='spinner'></div>\n    <div class=\"emscripten\" id=\"status\">Downloading...</div>\n\n    <span id='controls'>\n      <span><input type=\"checkbox\" id=\"resize\">Resize canvas</span>\n      <span><input type=\"checkbox\" id=\"pointerLock\" checked>Lock/hide mouse pointer &nbsp;&nbsp;&nbsp;</span>\n      <span><input type=\"button\" value=\"Fullscreen\" onclick=\"Module.requestFullscreen(document.getElementById('pointerLock').checked,\n                                                                                document.getElementById('resize').checked)\">\n      </span>\n    </span>\n\n    <div class=\"emscripten\">\n      <progress value=\"0\" max=\"100\" id=\"progress\" hidden=1></progress>\n    </div>\n\n    <div class=\"emscripten_border\">\n      <canvas class=\"emscripten\" id=\"canvas\" oncontextmenu=\"event.preventDefault()\" tabindex=-1></canvas>\n    </div>\n    <textarea id=\"output\" rows=\"8\"></textarea>\n\n    <script type='text/javascript'>\n      var statusElement = document.getElementById('status');\n      var progressElement = document.getElementById('progress');\n      var spinnerElement = document.getElementById('spinner');\n\n      var stdinBuffer = [];\n\n      var terminal = new Terminal({convertEol: true});\n      terminal.onData(function(data) {\n        for (var i = 0; i < data.length; ++i) {\n          stdinBuffer.push(data.charCodeAt(i));\n        }\n      });\n\n      var Module = {\n        preRun: [function() {\n          let ops = {\n            get_char: function(tty) {\n              if (stdinBuffer.length > 0) {\n                return stdinBuffer.shift();\n              } else {\n                return undefined;\n              }\n            },\n            put_char: function(tty, val) {\n                terminal.write(new Uint8Array([val]));\n            },\n            flush: function(tty) {},\n            fsync: function(tty) {},\n            poll: function(tty) {\n              if (stdinBuffer.length > 0) return 1|4; // POLLIN | POLLOUT\n              return 4; // POLLOUT\n            },\n          };\n\n          TTY.register(FS.makedev(5, 0), ops);\n          TTY.register(FS.makedev(6, 0), ops);\n\n          // TTY doesn't handle poll. Set our own stream handler.\n          FS.devices[FS.makedev(5, 0)].stream_ops.poll = ops.poll;\n          FS.devices[FS.makedev(6, 0)].stream_ops.poll = ops.poll;\n        }],\n        postRun: [],\n        canvas: (function() {\n          var canvas = document.getElementById('canvas');\n\n          // As a default initial behavior, pop up an alert when webgl context is lost. To make your\n          // application robust, you may want to override this behavior before shipping!\n          // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2\n          canvas.addEventListener(\"webglcontextlost\", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);\n\n          return canvas;\n        })(),\n        setStatus: function(text) {\n          if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };\n          if (text === Module.setStatus.last.text) return;\n          var m = text.match(/([^(]+)\\((\\d+(\\.\\d+)?)\\/(\\d+)\\)/);\n          var now = Date.now();\n          if (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon\n          Module.setStatus.last.time = now;\n          Module.setStatus.last.text = text;\n          if (m) {\n            text = m[1];\n            progressElement.value = parseInt(m[2])*100;\n            progressElement.max = parseInt(m[4])*100;\n            progressElement.hidden = false;\n            spinnerElement.hidden = false;\n          } else {\n            progressElement.value = null;\n            progressElement.max = null;\n            progressElement.hidden = true;\n            if (!text) spinnerElement.style.display = 'none';\n          }\n          statusElement.innerHTML = text;\n        },\n        totalDependencies: 0,\n        monitorRunDependencies: function(left) {\n          this.totalDependencies = Math.max(this.totalDependencies, left);\n          Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');\n        }\n      };\n      Module.setStatus('Downloading...');\n      window.onerror = function(event) {\n        // TODO: do not warn on ok events like simulating an infinite loop or exitStatus\n        Module.setStatus('Exception thrown, see JavaScript console');\n        spinnerElement.style.display = 'none';\n        Module.setStatus = function(text) {\n          if (text) console.error('[post-exception status] ' + text);\n        };\n      };\n    </script>\n    {{{ SCRIPT }}}\n    <div class=\"blink blink-terminal\" id=\"terminal\">\n    </div>\n    <div class=\"blink\">\n      Upload an executable file:\n    </div>\n    <div class=\"blink\">\n      <input type=\"file\" id=\"fileInput\" onchange=\"fileLoad(event, 'executable')\" />\n    </div>\n    <div class=\"blink\">\n      <textarea class=\"blink-terminal\" id=\"argsInput\" rows=\"4\" placeholder=\"Space-separated arguments for the target binary...\"></textarea>\n    </div>\n    <button id=\"runButton\" onclick=\"runExecutable()\">Run</button>\n    <!-- BLINK SPECIFIC: Load and run the assembly. -->\n    <script type='text/javascript'>\n      function fileLoad(event, filename) {\n        var file = event.target.files[0];\n        var reader = new FileReader();\n        reader.onloadend = function(event) {\n          if(event.target.readyState == FileReader.DONE)\n            FS.writeFile(filename, new Uint8Array(event.target.result), {encoding: 'binary', mode: 0o755});\n        };\n        reader.readAsArrayBuffer(file);\n      }\n\n      function runExecutable() {\n        let args = ['executable'].concat(document.getElementById('argsInput').value.split(' ').filter((e) => e != \"\"));\n        let ret = Module.callMain(args);\n      }\n\n      terminal.open(document.getElementById(\"terminal\"));\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "blink/blink.1",
    "content": ".\\\" Copyright 2023 Justine Alexandra Roberts Tunney\n.\\\"\n.\\\" Permission to use, copy, modify, and/or distribute this software for\n.\\\" any purpose with or without fee is hereby granted, provided that the\n.\\\" above copyright notice and this permission notice appear in all copies.\n.\\\"\n.\\\" THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL\n.\\\" WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED\n.\\\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE\n.\\\" AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\n.\\\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\n.\\\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n.\\\" TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n.\\\" PERFORMANCE OF THIS SOFTWARE.\n.\\\"\n.Dd March 6, 2023\n.Dt BLINK 1\n.Os\n.Sh NAME\n.Nm blink\n.Nd headless blinkenlights x86-64-linux virtual machine\n.Sh SYNOPSIS\n.Nm\n.Op Fl hvjemZs\n.Op Fl L Ar logfile\n.Op Fl C Ar chroot\n.Ar program\n.Op Ar argv1...\n.Nm\n.Op Fl hvjemZs\n.Op Fl L Ar logfile\n.Op Fl C Ar chroot\n.Fl 0\n.Ar program\n.Op Ar argv0...\n.Sh DESCRIPTION\n.Nm\nis a JITing virtual machine that uses x86_64 as its byte code language\nand implements the Linux Kernel ABI.\n.Nm\nmay be used to run prebuilt binaries intended for x86_64 Linux on other\nPOSIX platforms.\n.Sh ARGUMENTS\n.Pp\nThe\n.Ar program\nargument is a\n.Ev PATH\nsearched command, which may be:\n.Pp\n.Bl -dash -compact\n.It\nAn x86_64-linux ELF executable (either static or dynamic)\n.It\nAn Actually Portable Executable (either MZqFpD or jartsr magic)\n.It\nA flat executable (if\n.Ar program\nends with .bin, .img, or .raw)\n.It\nA shell script whose #!interpreter meets the above criteria\n.El\n.Pp\nThe\n.Fl 0\nflag allows\n.Li argv[0]\nto be specified on the command line. Under normal circumstances,\n.Bd -literal -offset indent\nblink cmd arg1\n.Ed\n.Pp\nis equivalent to\n.Bd -literal -offset indent\nexecve(\"cmd\", {\"cmd\", \"arg1\"})\n.Ed\n.Pp\nsince that's how most programs are launched. However if you\nneed the full power of execve() process spawning, you can say\n.Bd -literal -offset indent\nblink -0 cmd arg0 arg1\n.Ed\n.Pp\nwhich is equivalent to\n.Bd -literal -offset indent\nexecve(\"cmd\", {\"arg0\", \"arg1\"})\n.Ed\n.Pp\n.Sh OPTIONS\nThe following options are available:\n.Bl -tag -width indent\n.It Fl h\nPrints condensed help.\n.It Fl v\nShows\n.Nm\nversion and build configuration details.\n.It Fl e\nLog to standard error (fd 2) in addition to the log file. If logging to\n.Em only\nstandard error is desired, then\n.Li -eL/dev/null\nmay be passed as flags.\n.It Fl s\nEnables system call logging (repeatable).\n.Pp\nThis will emit to the log file\nthe names of system calls each time a SYSCALL instruction in executed,\nalong with its arguments and result. System calls are logged once\nthey've completed, so that the result can be shown.\n.Pp\nSystem calls are\nalso sometimes logged upon entry too, in which case\n.Li syscall(arg) -> ...\nwill be logged to show that the system call has not yet completed.\nWhether or not this happens depends on how many times the\n.Fl s\nflag is supplied.\n.Pp\n.Bl -dash -compact\n.It\nPassing\n.Fl s\n(once) will only log the entries of system calls that are defined as\nhaving read + write parameters (e.g. poll, select)\n.It\nPassing\n.Fl ss\n(twice) will also log the entries of cancellation points that are likely\nto block (e.g. read, accept, wait, pause).\n.It\nPassing\n.Fl sss\n(thrice) will log the entries of system calls that POSIX defines as\ncancellation points but are unlikely to block (e.g. write, close, open)\nwhich we try to avoid doing in order to reduce log noise.\n.It\nPassing\n.Fl ssss\n(4x) will log the entry of every single system call, even harmless ones\nthat have no business being emitted to the log twice (e.g. sigaction).\nThis should only be useful for the Blink dev team when the rare need\narises to troubleshoot a system call that's crashing.\n.El\n.Pp\nSystem call logging isn't available in\n.Li MODE=rel\nand\n.Li MODE=tiny\nbuilds, in which case this flag is ignored.\n.It Fl m\nEnables full memory virtualization. Under normal circumstances,\n.Nm\naims to share the same address space as the guest program. Depending on\nthe program's memory requirements (i.e. if it uses MAP_FIXED) and the\nconstraints imposed by the host platform, this so-called linear memory\noptimization may lead to an mmap() crisis that causes Blink to not work\nproperly. Using this option will cause\n.Nm\nto virtualize the x86_64 address space precicely and reliably, however\nthe use of this flag carries the tradeoff of causing\n.Nm\nto go at least 2x slower.\n.It Fl j\nDisables Just-In-Time (JIT) compilation. Using this option will cause\n.Nm\nto go ~10x or possibly even ~100x slower.\n.It Fl L Ar path\nSpecifies the log path. The default log path is\n.Ar blink.log\nin the current directory at startup. This log file won't be created\nuntil something is actually logged. If logging to a file isn't desired,\nthen -L /dev/null may be used. See also the\n.Fl e\nflag for logging to standard error.\n.It Fl C Ar path\nLaunch\n.Ar program\nin a chroot'd environment. This flag is both equivalent to and overrides\nthe\n.Ev BLINK_OVERLAYS\nenvironment variable.\n.It Fl Z\nPrints internal statistics to standard error on exit. Each line will\ndisplay a monitoring metric. Most metrics will either be integer\ncounters or floating point running averages. Most but not all integer\ncounters are monotonic. In the interest of not negatively impacting\nBlink's performance, statistics are computed on a best effort basis\nwhich currently isn't guaranteed to be atomic in a multi-threaded\nenvironment. Statistics aren't available in MODE=rel and MODE=tiny\nbuilds, in which case this flag is ignored.\n.El\n.Sh ENVIRONMENT\nThe following environment variables are recognized:\n.Bl -tag -width indent\n.It Ev BLINK_LOG_FILENAME\nmay be specified to supply a log path to be used in cases where the\n.Fl L Ar path\nflag isn't specified. This value should be an absolute path. If logging\nto standard error is desired, use the\n.Fl e\nflag.\n.It Ev BLINK_OVERLAYS\nspecifies one or more directories to use as the root filesystem.\nSimilar to\n.Ev PATH\nthis is a colon delimited list of pathnames. If relative paths are\nspecified, they'll be resolved to an absolute path at startup time.\nOverlays only apply to IO system calls that specify an absolute path.\nThe empty string overlay means use the normal / root filesystem. The\ndefault value is\n.Li :o\nwhich means if the absolute path\n.Li /$f\nis opened, then first check if\n.Li /$f\nexists, and if it doesn't, then check if\n.Li o/$f\nexists, in which case open that instead. Blink uses this convention to\nopen shared object tests. It favors the system version if it exists, but\nalso downloads\n.Li ld-musl-x86_64.so.1\nto\n.Li o/lib/ld-musl-x86_64.so.1\nso the dynamic linker can transparently find it on platforms like Apple,\nthat don't let users put files in the root folder. On the other hand,\nit's possible to say\n.Li BLINK_OVERLAYS=o:\nso that\n.Li o/...\ntakes precedence over\n.Li /...\n(noting again that empty string means root). If a single overlay is\nspecified that isn't empty string, then it'll effectively act as a\nrestricted chroot environment.\n.El\n.Sh QUIRKS\nHere's the current list of Blink's known quirks and tradeoffs.\n.Ss \"Flags\"\nFlag dependencies may not carry across function call boundaries under\nlong mode. This is because when Blink's JIT is speculating whether or\nnot it's necessary for an arithmetic instruction to compute flags, it\nconsiders\n.Li RET\nand\n.Li CALL\nterminal ops that break the chain. As such\n64-bit code shouldn't do things we did in the DOS days, such as using\ncarry flag as a return value to indicate error. This should work fine\nwhen\n.Li STC\nis used to set the carry flag, but if the code computes it\ncleverly using instructions like\n.Li SUB\nthen EFLAGS might not change.\n.Ss \"Faults\"\nBlink may not report the precise program counter where a fault occurred\nin\n.Li ucontext_t::uc_mcontext::rip\nwhen signalling a segmentation fault.\nThis is currently only possible when\n.Li PUSH\nor\n.Li POP\naccess bad memory.\nThat's because Blink's JIT tries to avoid updating\n.Li Machine::ip\non ops\nit considers \"pure\" such as those that only access registers, which for\nreasons of performance is defined to include pushing and popping.\n.Ss \"Threads\"\nBlink doesn't have a working implementation of\n.Li set_robust_list()\nyet,\nwhich means robust mutexes might not get unlocked if a process crashes.\n.Ss \"Coherency\"\nPOSIX.1 provides almost no guarantees of coherency, synchronization, and\ndurability when it comes to\n.Li MAP_SHARED\nmappings and recommends that\nmsync() be explicitly used to synchronize memory with file contents. The\nLinux Kernel implements shared memory so well, that this is rarely\nnecessary. However some platforms like OpenBSD lack write coherency.\nThis means if you change a shared writable memory map and then call\npread() on the associated file region, you might get stale data. Blink\nisn't able to polyfill incoherent platforms to be as coherent as Linux,\ntherefore apps that run in Blink should assume the POSIX rules apply.\n.Ss \"Signal Handling\"\nBlink uses\n.Li SIGSYS\nto deliver signals internally. This signal is\nprecious to Blink. It's currently not possible for guest applications to\ncapture it from external processes.\n.Ss \"Memory Protection\"\nBlink offers guest programs a 48-bit virtual address space with a\n4096-byte page size. When programs are run on (1) host systems that have\na larger page (e.g. Apple M1, Cygwin), and (2) the linear memory\noptimization is enabled (i.e. you're *not* using\n.Li blink -m\n) then Blink may need to relax memory protections in cases where the\nmemory intervals defined by the guest aren't aligned to the host system\npage size. Is is recommended, when calling functions like mmap() and\nmprotect(), that both\n.Li addr\nand\n.Li addr + size\nbe aliged to the true page size, which Blink reports to the guest in\n.Li getauxval(AT_PAGESZ).\nThis value should be obtainable via the portable API\n.Li sysconf(_SC_PAGESIZE)\nassuming the C library implements it correctly. Please note that when\nBlink is running in its fully virtualized mode (i.e.\n.Li blink -m\n) this concern does not apply. That's because Blink will allocate a full\nsystem page for every 4096 byte page that gets mapped from a file.\n.Sh EXIT STATUS\nThe\n.Nm\ncommand passes along the exit code of the\n.Ar program\nwhich by convention is 0 on success or >0 on failure. In the event that\n.Nm\nfails to launch\n.Ar program\nthe status 127 shall be returned.\n.Sh SEE ALSO\n.Xr blinkenlights 1\n.Sh STANDARDS\nThe\n.Nm\ncommand implements a superset of the\n.St -p1003.1-2008\nspecification, intended to emulate the behaviors of the Linux Kernel.\n.Sh AUTHORS\n.An \"Justine Alexandra Roberts Tunney\" Aq jtunney@gmail.com\n"
  },
  {
    "path": "blink/blink.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <locale.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/resource.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/case.h\"\n#include \"blink/debug.h\"\n#include \"blink/dll.h\"\n#include \"blink/endian.h\"\n#include \"blink/flag.h\"\n#include \"blink/jit.h\"\n#include \"blink/loader.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/overlays.h\"\n#include \"blink/pml4t.h\"\n#include \"blink/signal.h\"\n#include \"blink/sigwinch.h\"\n#include \"blink/stats.h\"\n#include \"blink/syscall.h\"\n#include \"blink/thread.h\"\n#include \"blink/tunables.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n#include \"blink/web.h\"\n#include \"blink/x86.h\"\n#include \"blink/xlat.h\"\n\n#ifndef BUILD_TIMESTAMP\n#define BUILD_TIMESTAMP __TIMESTAMP__\n#endif\n#ifndef BUILD_MODE\n#define BUILD_MODE \"BUILD_MODE_UNKNOWN\"\n#warning \"-DBUILD_MODE=... should be passed to blink/blink.c\"\n#endif\n#ifndef BUILD_TOOLCHAIN\n#define BUILD_TOOLCHAIN \"BUILD_TOOLCHAIN_UNKNOWN\"\n#warning \"-DBUILD_TOOLCHAIN=... should be passed to blink/blink.c\"\n#endif\n#ifndef BLINK_VERSION\n#define BLINK_VERSION \"BLINK_VERSION_UNKNOWN\"\n#warning \"-DBLINK_VERSION=... should be passed to blink/blink.c\"\n#endif\n#ifndef BLINK_COMMITS\n#define BLINK_COMMITS \"BLINK_COMMITS_UNKNOWN\"\n#warning \"-DBLINK_COMMITS=... should be passed to blink/blink.c\"\n#endif\n#ifndef BLINK_GITSHA\n#define BLINK_GITSHA \"BLINK_GITSHA_UNKNOWN\"\n#warning \"-DBLINK_GITSHA=... should be passed to blink/blink.c\"\n#endif\n#ifndef CONFIG_ARGUMENTS\n#define CONFIG_ARGUMENTS \"CONFIG_ARGUMENTS_UNKNOWN\"\n#warning \"-DCONFIG_ARGUMENTS=... should be passed to blink/blink.c\"\n#endif\n\n#define VERSION \\\n  \"Blink Virtual Machine \" BLINK_VERSION \" (\" BUILD_TIMESTAMP \")\\n\\\nCopyright (c) 2023 Justine Alexandra Roberts Tunney\\n\\\nBlink comes with absolutely NO WARRANTY of any kind.\\n\\\nYou may redistribute copies of Blink under the ISC License.\\n\\\nFor more information, see the file named LICENSE.\\n\\\nToolchain: \" BUILD_TOOLCHAIN \"\\n\\\nRevision: #\" BLINK_COMMITS \" \" BLINK_GITSHA \"\\n\\\nConfig: ./configure MODE=\" BUILD_MODE \" \" CONFIG_ARGUMENTS \"\\n\"\n\n#define OPTS \"hvjemZs0L:C:\"\n\n_Alignas(1) static const char USAGE[] =\n    \" [-\" OPTS \"] PROG [ARGS...]\\n\"\n    \"Options:\\n\"\n    \"  -h                   help\\n\"\n#ifndef DISABLE_JIT\n    \"  -j                   disable jit\\n\"\n#endif\n    \"  -v                   show version\\n\"\n#ifndef NDEBUG\n    \"  -e                   also log to stderr\\n\"\n#endif\n    \"  -0                   to specify argv[0]\\n\"\n    \"  -m                   enable memory safety\\n\"\n#if !defined(DISABLE_STRACE) && !defined(TINY)\n    \"  -s                   enable system call logging\\n\"\n#endif\n#ifndef NDEBUG\n    \"  -Z                   print internal statistics on exit\\n\"\n    \"  -L PATH              log filename (default is blink.log)\\n\"\n#endif\n#if !defined(DISABLE_OVERLAYS) || !defined(DISABLE_VFS)\n    \"  -C PATH              sets chroot dir or overlay spec [default \\\":o\\\"]\\n\"\n#endif\n#if !defined(DISABLE_OVERLAYS) || !defined(NDEBUG)\n    \"Environment:\\n\"\n#endif\n#ifndef DISABLE_OVERLAYS\n    \"  $BLINK_OVERLAYS      file system roots [default \\\":o\\\"]\\n\"\n#endif\n#ifndef DISABLE_VFS\n    \"  $BLINK_PREFIX        file system root [default \\\"/\\\"]\\n\"\n#endif\n#ifndef NDEBUG\n\n    \"  $BLINK_LOG_FILENAME  log filename (same as -L flag)\\n\"\n#endif\n    ;\n\nextern char **environ;\nstatic bool FLAG_nojit;\nstatic char g_pathbuf[PATH_MAX];\n\nstatic void OnSigSys(int sig) {\n  // do nothing\n}\n\nstatic void PrintDiagnostics(struct Machine *m) {\n  ERRF(\"additional information\\n\"\n       \"\\t%s\\n\"\n       \"%s\\n\"\n       \"%s\",\n       GetBacktrace(m), FormatPml4t(m), GetBlinkBacktrace());\n}\n\nvoid TerminateSignal(struct Machine *m, int sig, int code) {\n  int syssig;\n  struct sigaction sa;\n  unassert(!IsSignalIgnoredByDefault(sig));\n  KillOtherThreads(m->system);\n#ifdef HAVE_JIT\n  DisableJit(&m->system->jit);  // unmapping exec pages is slow\n#endif\n  if (IsSignalSerious(sig)) {\n    ERRF(\"terminating due to %s (\"\n         \"rip=%#\" PRIx64 \" \"\n         \"code=%d \"\n         \"faultaddr=%#\" PRIx64 \")\",\n         DescribeSignal(sig), m->ip, code, m->faultaddr);\n    PrintDiagnostics(m);\n  }\n  if ((syssig = XlatSignal(sig)) == -1) syssig = SIGKILL;\n  FreeMachine(m);\n#ifdef HAVE_JIT\n  ShutdownJit();\n#endif\n  sa.sa_flags = 0;\n  sa.sa_handler = SIG_DFL;\n  sigemptyset(&sa.sa_mask);\n  if (syssig != SIGKILL && syssig != SIGSTOP) {\n    unassert(!sigaction(syssig, &sa, 0));\n  }\n  unassert(!kill(getpid(), syssig));\n  Abort();\n}\n\nstatic void OnFatalSystemSignal(int sig, siginfo_t *si, void *ptr) {\n  struct Machine *m = g_machine;\n#ifdef __APPLE__\n  sig = FixXnuSignal(m, sig, si);\n#elif defined(__powerpc__) && CAN_64BIT\n  sig = FixPpcSignal(m, sig, si);\n#endif\n  SIG_LOGF(\"OnFatalSystemSignal(%s, %p)\", DescribeSignal(UnXlatSignal(sig)),\n           si->si_addr);\n#ifndef DISABLE_JIT\n  if (IsSelfModifyingCodeSegfault(m, si)) return;\n#endif\n  g_siginfo = *si;\n  unassert(m);\n  unassert(m->canhalt);\n  siglongjmp(m->onhalt, kMachineFatalSystemSignal);\n}\n\nstatic void ProgramLimit(struct System *s, int hresource, int gresource) {\n  struct rlimit rlim;\n  if (!getrlimit(hresource, &rlim)) {\n    XlatRlimitToLinux(s->rlim + gresource, &rlim);\n  }\n}\n\nstatic int Exec(char *execfn, char *prog, char **argv, char **envp) {\n  int i;\n  sigset_t oldmask;\n  struct Machine *m, *old;\n  if ((old = g_machine)) KillOtherThreads(old->system);\n  unassert((g_machine = m = NewMachine(NewSystem(XED_MACHINE_MODE_LONG), 0)));\n#ifdef HAVE_JIT\n  if (FLAG_nojit) DisableJit(&m->system->jit);\n#endif\n  m->system->exec = Exec;\n  if (!old) {\n    // this is the first time a program is being loaded\n    LoadProgram(m, execfn, prog, argv, envp, NULL);\n    SetupCod(m);\n    for (i = 0; i < 10; ++i) {\n      AddStdFd(&m->system->fds, i);\n    }\n    ProgramLimit(m->system, RLIMIT_NOFILE, RLIMIT_NOFILE_LINUX);\n  } else {\n#ifdef HAVE_JIT\n    DisableJit(&old->system->jit);  // unmapping exec pages is slow\n#endif\n    unassert(!m->sysdepth);\n    unassert(!m->pagelocks.i);\n    unassert(!FreeVirtual(old->system, -0x800000000000, 0x1000000000000));\n    for (i = 1; i <= 64; ++i) {\n      if (Read64(old->system->hands[i - 1].handler) == SIG_IGN_LINUX) {\n        Write64(m->system->hands[i - 1].handler, SIG_IGN_LINUX);\n      }\n    }\n    memcpy(m->system->rlim, old->system->rlim, sizeof(old->system->rlim));\n    LoadProgram(m, execfn, prog, argv, envp, NULL);\n    m->system->fds.list = old->system->fds.list;\n    old->system->fds.list = 0;\n    // releasing the execve() lock must come after unlocking fds\n    memcpy(&oldmask, &old->system->exec_sigmask, sizeof(oldmask));\n    UNLOCK(&old->system->exec_lock);\n    // freeing the last machine in a system will free its system too\n    FreeMachine(old);\n    // restore the signal mask we had before execve() was called\n    unassert(!pthread_sigmask(SIG_SETMASK, &oldmask, 0));\n  }\n  Blink(m);\n}\n\nstatic void Print(int fd, const char *s) {\n  (void)!write(fd, s, strlen(s));\n}\n\n_Noreturn static void PrintUsage(int argc, char *argv[], int rc, int fd) {\n  Print(fd, \"Usage: \");\n  Print(fd, argc > 0 && argv[0] ? argv[0] : \"blink\");\n  Print(fd, USAGE);\n  exit(rc);\n}\n\n_Noreturn static void PrintVersion(void) {\n  Print(1, VERSION);\n  exit(EXIT_SUCCESS);\n}\n\nstatic void GetOpts(int argc, char *argv[]) {\n  int opt;\n  FLAG_nolinear = !CanHaveLinearMemory();\n#ifndef DISABLE_OVERLAYS\n  FLAG_overlays = getenv(\"BLINK_OVERLAYS\");\n  if (!FLAG_overlays) FLAG_overlays = DEFAULT_OVERLAYS;\n#endif\n#ifndef DISABLE_VFS\n  FLAG_prefix = getenv(\"BLINK_PREFIX\");\n#endif\n#if LOG_ENABLED\n  FLAG_logpath = getenv(\"BLINK_LOG_FILENAME\");\n#endif\n  while ((opt = GetOpt(argc, argv, OPTS)) != -1) {\n    switch (opt) {\n      case '0':\n        FLAG_zero = true;\n        break;\n      case 'j':\n        FLAG_nojit = true;\n        break;\n      case 's':\n        ++FLAG_strace;\n        break;\n      case 'm':\n        FLAG_nolinear = true;\n        break;\n      case 'Z':\n        FLAG_statistics = true;\n        break;\n      case 'e':\n        FLAG_alsologtostderr = true;\n        break;\n      case 'L':\n        FLAG_logpath = optarg_;\n        break;\n      case 'C':\n#if !defined(DISABLE_OVERLAYS)\n        FLAG_overlays = optarg_;\n#elif !defined(DISABLE_VFS)\n        FLAG_prefix = optarg_;\n#else\n        WriteErrorString(\n            \"error: overlays and vfs support were both disabled\\n\");\n#endif\n        break;\n      case 'v':\n        PrintVersion();\n      case 'h':\n        PrintUsage(argc, argv, 0, 1);\n      default:\n        PrintUsage(argc, argv, 48, 2);\n    }\n  }\n#if LOG_ENABLED\n  LogInit(FLAG_logpath);\n#endif\n}\n\nstatic void HandleSigs(void) {\n  struct sigaction sa;\n  signal(SIGPIPE, SIG_IGN);\n  sigfillset(&sa.sa_mask);\n  sa.sa_flags = 0;\n#ifdef HAVE_THREADS\n  sa.sa_handler = OnSigSys;\n  unassert(!sigaction(SIGSYS, &sa, 0));\n#endif\n  sa.sa_sigaction = OnSignal;\n  unassert(!sigaction(SIGINT, &sa, 0));\n  unassert(!sigaction(SIGQUIT, &sa, 0));\n  unassert(!sigaction(SIGHUP, &sa, 0));\n  unassert(!sigaction(SIGTERM, &sa, 0));\n  unassert(!sigaction(SIGXCPU, &sa, 0));\n  unassert(!sigaction(SIGXFSZ, &sa, 0));\n#if !defined(__SANITIZE_THREAD__) && !defined(__SANITIZE_ADDRESS__) && \\\n    !defined(__FILC__)\n  sa.sa_sigaction = OnFatalSystemSignal;\n  sa.sa_flags = SA_SIGINFO;\n  unassert(!sigaction(SIGBUS, &sa, 0));\n  unassert(!sigaction(SIGILL, &sa, 0));\n  unassert(!sigaction(SIGTRAP, &sa, 0));\n  unassert(!sigaction(SIGSEGV, &sa, 0));\n#endif\n}\n\n#if defined(__EMSCRIPTEN__)\nvoid exit(int status) {\n  // main is called multiple times - don't perform cleanup\n  _exit(status);\n}\n#endif\n\nint main(int argc, char *argv[]) {\n  SetupWeb();\n  GetStartDir();\n#ifndef NDEBUG\n  AtAbort(PrintStats);\n#endif\n#ifndef DISABLE_STRACE\n  setlocale(LC_ALL, \"\");\n#endif\n  // Ensure utf-8 is printed correctly on windows, this method\n  // has issues(http://stackoverflow.com/a/10884364/4279) but\n  // should work for at least windows 7 and newer.\n#if defined(_WIN32) && !defined(__CYGWIN__)\n  SetConsoleOutputCP(CP_UTF8);\n#endif\n  g_blink_path = argc > 0 ? argv[0] : 0;\n  WriteErrorInit();\n  InitMap();\n  GetOpts(argc, argv);\n  if (optind_ == argc) {\n    PrintUsage(argc, argv, 48, 2);\n  }\n#ifndef DISABLE_OVERLAYS\n  if (SetOverlays(FLAG_overlays, true)) {\n    WriteErrorString(\"bad blink overlays spec; see log for details\\n\");\n    exit(EXIT_FAILURE);\n  }\n#endif\n#ifndef DISABLE_VFS\n  if (VfsInit(FLAG_prefix)) {\n    WriteErrorString(\"error: vfs initialization failed\\n\");\n    exit(EXIT_FAILURE);\n  }\n#endif\n  HandleSigs();\n  InitBus();\n  if (!Commandv(argv[optind_], g_pathbuf, sizeof(g_pathbuf))) {\n    WriteErrorString(argv[0]);\n    WriteErrorString(\": command not found: \");\n    WriteErrorString(argv[optind_]);\n    WriteErrorString(\"\\n\");\n    exit(EXIT_FAILURE_EXEC_FAILED);\n  }\n  argv[optind_] = g_pathbuf;\n  return Exec(g_pathbuf, g_pathbuf, argv + optind_ + FLAG_zero, environ);\n}\n"
  },
  {
    "path": "blink/blink.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nPKGS += BLINK\nBLINK_FILES := $(wildcard blink/*)\nBLINK_SRCS = $(filter %.c,$(BLINK_FILES))\nBLINK_HDRS = $(filter %.h,$(BLINK_FILES))\nBLINK_SRCS = $(filter %.c,$(BLINK_FILES))\nBLINK_OBJS = $(BLINK_SRCS:%.c=o/$(MODE)/%.o)\n\nBLINK_NEED_BUILDINFO_SRCS =\t\t\t\t\\\n\tblink/blink.c\t\t\t\t\t\\\n\tblink/syscall.c\t\t\t\t\t\\\n\tblink/blinkenlights.c\n\nBLINK_NEED_BUILDINFO_OBJS =\t\t\t\t\\\n\t$(BLINK_NEED_BUILDINFO_SRCS:%.c=o/$(MODE)/%.o)\t\\\n\t$(foreach ARCH,$(ARCHITECTURES),$(foreach SRC,$(BLINK_NEED_BUILDINFO_SRCS),$(SRC:%.c=o/$(MODE)/$(ARCH)/%.o)))\n\n$(BLINK_NEED_BUILDINFO_OBJS): private CPPFLAGS += $(CONFIG_CPPFLAGS)\n\n# micro-ops need to be compiled with the greatest of care\no/$(MODE)/blink/uop.o: private CFLAGS += $(UOPFLAGS)\n\n# avoid impossible to address errors in ./configure --posix mode\nifeq ($(HOST_SYSTEM), Darwin)\no/$(MODE)/blink/jit.o: private CPPFLAGS += -D_DARWIN_C_SOURCE\no/$(MODE)/blink/syscall.o: private CPPFLAGS += -D_DARWIN_C_SOURCE\no/$(MODE)/blink/xlat.o: private CPPFLAGS += -D_DARWIN_C_SOURCE\nendif\n\n# Actually Portable Executable\n# make m=cosmo o/cosmo/blink/blink.com\n# needs cosmopolitan/tool/scripts/cosmocc\no/cosmo/blink/blink.com: o/$(MODE)/blink/blink\n\tobjcopy -S -O binary $< $@\no/cosmo/blink/blinkenlights.com: o/$(MODE)/blink/blinkenlights\n\tobjcopy -S -O binary $< $@\n\n# vectorization makes code smaller\no/$(MODE)/blink/sse2.o: private CFLAGS += -O3\no/$(MODE)/x86_64/blink/sse2.o: private CFLAGS += -O3\no/$(MODE)/x86_64-gcc49/blink/sse2.o: private CFLAGS += -O3\no/$(MODE)/aarch64/blink/sse2.o: private CFLAGS += -O3\n\n# these files have big switch statements\no/tiny/x86_64/blink/cvt.o: private CFLAGS += -fpie\no/tiny/x86_64-gcc49/blink/cvt.o: private CFLAGS += -fpie\no/tiny/aarch64/blink/cvt.o: private CFLAGS += -fpie\no/tiny/x86_64/blink/xlat.o: private CFLAGS += -fpie\no/tiny/x86_64-gcc49/blink/xlat.o: private CFLAGS += -fpie\no/tiny/aarch64/blink/xlat.o: private CFLAGS += -fpie\no/tiny/x86_64/blink/fpu.o: private CFLAGS += -fpie\no/tiny/x86_64-gcc49/blink/fpu.o: private CFLAGS += -fpie\no/tiny/aarch64/blink/fpu.o: private CFLAGS += -fpie\no/tiny/x86_64/blink/flags.o: private CFLAGS += -fpie\no/tiny/x86_64-gcc49/blink/flags.o: private CFLAGS += -fpie\no/tiny/aarch64/blink/flags.o: private CFLAGS += -fpie\no/tiny/x86_64/blink/x86.o: private CFLAGS += -fno-jump-tables\no/tiny/x86_64-gcc49/blink/x86.o: private CFLAGS += -fno-jump-tables\no/tiny/aarch64/blink/x86.o: private CFLAGS += -fno-jump-tables\no/tiny/x86_64/blink/uop.o: private CFLAGS += -fno-jump-tables\no/tiny/x86_64-gcc49/blink/uop.o: private CFLAGS += -fno-jump-tables\no/tiny/aarch64/blink/uop.o: private CFLAGS += -fno-jump-tables\no/tiny/x86_64/blink/syscall.o: private CFLAGS += -fpie\no/tiny/x86_64-gcc49/blink/syscall.o: private CFLAGS += -fpie\no/tiny/aarch64/blink/syscall.o: private CFLAGS += -fpie\n\no/$(MODE)/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_OBJS)))\no/$(MODE)/i486/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/i486/%.o)))\no/$(MODE)/m68k/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/m68k/%.o)))\no/$(MODE)/x86_64/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/x86_64/%.o)))\no/$(MODE)/x86_64-gcc49/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/x86_64-gcc49/%.o)))\no/$(MODE)/arm/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/arm/%.o)))\no/$(MODE)/aarch64/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/aarch64/%.o)))\no/$(MODE)/riscv64/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/riscv64/%.o)))\no/$(MODE)/mips/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/mips/%.o)))\no/$(MODE)/mipsel/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/mipsel/%.o)))\no/$(MODE)/mips64/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/mips64/%.o)))\no/$(MODE)/mips64el/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/mips64el/%.o)))\no/$(MODE)/s390x/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/s390x/%.o)))\no/$(MODE)/microblaze/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/microblaze/%.o)))\no/$(MODE)/powerpc/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/powerpc/%.o)))\no/$(MODE)/powerpc64le/blink/blink.a: $(filter-out %/blink.o,$(filter-out %/blinkenlights.o,$(BLINK_SRCS:%.c=o/$(MODE)/powerpc64le/%.o)))\n\no/$(MODE)/blink/blink: o/$(MODE)/blink/blink.o o/$(MODE)/blink/blink.a\n\t$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/i486/blink/blink: o/$(MODE)/i486/blink/blink.o o/$(MODE)/i486/blink/blink.a\n\t$(VM) o/third_party/gcc/i486/bin/i486-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/m68k/blink/blink: o/$(MODE)/m68k/blink/blink.o o/$(MODE)/m68k/blink/blink.a\n\t$(VM) o/third_party/gcc/m68k/bin/m68k-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/x86_64/blink/blink: o/$(MODE)/x86_64/blink/blink.o o/$(MODE)/x86_64/blink/blink.a\n\t$(VM) o/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/x86_64-gcc49/blink/blink: o/$(MODE)/x86_64-gcc49/blink/blink.o o/$(MODE)/x86_64-gcc49/blink/blink.a\n\t$(VM) o/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/arm/blink/blink: o/$(MODE)/arm/blink/blink.o o/$(MODE)/arm/blink/blink.a\n\t$(VM) o/third_party/gcc/arm/bin/arm-linux-musleabi-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/aarch64/blink/blink: o/$(MODE)/aarch64/blink/blink.o o/$(MODE)/aarch64/blink/blink.a\n\t$(VM) o/third_party/gcc/aarch64/bin/aarch64-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/riscv64/blink/blink: o/$(MODE)/riscv64/blink/blink.o o/$(MODE)/riscv64/blink/blink.a\n\t$(VM) o/third_party/gcc/riscv64/bin/riscv64-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/mips/blink/blink: o/$(MODE)/mips/blink/blink.o o/$(MODE)/mips/blink/blink.a\n\t$(VM) o/third_party/gcc/mips/bin/mips-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/mipsel/blink/blink: o/$(MODE)/mipsel/blink/blink.o o/$(MODE)/mipsel/blink/blink.a\n\t$(VM) o/third_party/gcc/mipsel/bin/mipsel-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/mips64/blink/blink: o/$(MODE)/mips64/blink/blink.o o/$(MODE)/mips64/blink/blink.a\n\t$(VM) o/third_party/gcc/mips64/bin/mips64-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/mips64el/blink/blink: o/$(MODE)/mips64el/blink/blink.o o/$(MODE)/mips64el/blink/blink.a\n\t$(VM) o/third_party/gcc/mips64el/bin/mips64el-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/s390x/blink/blink: o/$(MODE)/s390x/blink/blink.o o/$(MODE)/s390x/blink/blink.a\n\t$(VM) o/third_party/gcc/s390x/bin/s390x-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/microblaze/blink/blink: o/$(MODE)/microblaze/blink/blink.o o/$(MODE)/microblaze/blink/blink.a\n\t$(VM) o/third_party/gcc/microblaze/bin/microblaze-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/powerpc/blink/blink: o/$(MODE)/powerpc/blink/blink.o o/$(MODE)/powerpc/blink/blink.a\n\t$(VM) o/third_party/gcc/powerpc/bin/powerpc-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/powerpc64le/blink/blink: o/$(MODE)/powerpc64le/blink/blink.o o/$(MODE)/powerpc64le/blink/blink.a\n\t$(VM) o/third_party/gcc/powerpc64le/bin/powerpc64le-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\n\no/$(MODE)/blink/blinkenlights.html: o/$(MODE)/blink/blinkenlights.o o/$(MODE)/blink/blink.a $(ZLIB)\n\t$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/blink/blinkenlights: o/$(MODE)/blink/blinkenlights.o o/$(MODE)/blink/blink.a $(ZLIB)\n\t$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/i486/blink/blinkenlights: o/$(MODE)/i486/blink/blinkenlights.o o/$(MODE)/i486/blink/blink.a o/$(MODE)/i486/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/i486/bin/i486-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/m68k/blink/blinkenlights: o/$(MODE)/m68k/blink/blinkenlights.o o/$(MODE)/m68k/blink/blink.a o/$(MODE)/m68k/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/m68k/bin/m68k-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/x86_64/blink/blinkenlights: o/$(MODE)/x86_64/blink/blinkenlights.o o/$(MODE)/x86_64/blink/blink.a o/$(MODE)/x86_64/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/x86_64-gcc49/blink/blinkenlights: o/$(MODE)/x86_64-gcc49/blink/blinkenlights.o o/$(MODE)/x86_64-gcc49/blink/blink.a o/$(MODE)/x86_64-gcc49/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/arm/blink/blinkenlights: o/$(MODE)/arm/blink/blinkenlights.o o/$(MODE)/arm/blink/blink.a o/$(MODE)/arm/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/arm/bin/arm-linux-musleabi-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/aarch64/blink/blinkenlights: o/$(MODE)/aarch64/blink/blinkenlights.o o/$(MODE)/aarch64/blink/blink.a o/$(MODE)/aarch64/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/aarch64/bin/aarch64-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/riscv64/blink/blinkenlights: o/$(MODE)/riscv64/blink/blinkenlights.o o/$(MODE)/riscv64/blink/blink.a o/$(MODE)/riscv64/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/riscv64/bin/riscv64-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/mips/blink/blinkenlights: o/$(MODE)/mips/blink/blinkenlights.o o/$(MODE)/mips/blink/blink.a o/$(MODE)/mips/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/mips/bin/mips-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/mipsel/blink/blinkenlights: o/$(MODE)/mipsel/blink/blinkenlights.o o/$(MODE)/mipsel/blink/blink.a o/$(MODE)/mipsel/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/mipsel/bin/mipsel-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/mips64/blink/blinkenlights: o/$(MODE)/mips64/blink/blinkenlights.o o/$(MODE)/mips64/blink/blink.a o/$(MODE)/mips64/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/mips64/bin/mips64-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/mips64el/blink/blinkenlights: o/$(MODE)/mips64el/blink/blinkenlights.o o/$(MODE)/mips64el/blink/blink.a o/$(MODE)/mips64el/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/mips64el/bin/mips64el-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/s390x/blink/blinkenlights: o/$(MODE)/s390x/blink/blinkenlights.o o/$(MODE)/s390x/blink/blink.a o/$(MODE)/s390x/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/s390x/bin/s390x-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/microblaze/blink/blinkenlights: o/$(MODE)/microblaze/blink/blinkenlights.o o/$(MODE)/microblaze/blink/blink.a o/$(MODE)/microblaze/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/microblaze/bin/microblaze-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/powerpc/blink/blinkenlights: o/$(MODE)/powerpc/blink/blinkenlights.o o/$(MODE)/powerpc/blink/blink.a o/$(MODE)/powerpc/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/powerpc/bin/powerpc-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\no/$(MODE)/powerpc64le/blink/blinkenlights: o/$(MODE)/powerpc64le/blink/blinkenlights.o o/$(MODE)/powerpc64le/blink/blink.a o/$(MODE)/powerpc64le/third_party/libz/zlib.a\n\t$(VM) o/third_party/gcc/powerpc64le/bin/powerpc64le-linux-musl-gcc $(LDFLAGS_STATIC) $^ -o $@\n\no/$(MODE)/blink/oneoff.com: o/$(MODE)/blink/oneoff.o o/$(MODE)/blink/blink.a\n\t$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\n\no/$(MODE)/blink:\t\t\t\t\\\n\t\to/$(MODE)/blink/blinkenlights\t\\\n\t\to/$(MODE)/blink/blink\t\t\\\n\t\t$(BLINK_HDRS:%=o/$(MODE)/%.ok)\n"
  },
  {
    "path": "blink/blinkenlights.1",
    "content": ".\\\" Copyright 2023 Justine Alexandra Roberts Tunney\n.\\\"\n.\\\" Permission to use, copy, modify, and/or distribute this software for\n.\\\" any purpose with or without fee is hereby granted, provided that the\n.\\\" above copyright notice and this permission notice appear in all copies.\n.\\\"\n.\\\" THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL\n.\\\" WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED\n.\\\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE\n.\\\" AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\n.\\\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\n.\\\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n.\\\" TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n.\\\" PERFORMANCE OF THIS SOFTWARE.\n.\\\"\n.Dd March 6, 2023\n.Dt BLINKENLIGHTS 1\n.Os\n.Sh NAME\n.Nm blinkenlights\n.Nd x86-64-linux visualizer\n.Sh SYNOPSIS\n.Nm\n.Op Ar options\n.Ar program\n.Op Ar argv1...\n.Nm\n.Op Ar options\n.Fl 0\n.Ar program\n.Op Ar argv0...\n.Sh DESCRIPTION\n.Nm\nis a terminal user interface for debugging x86_64-linux (or i8086)\nprograms on POSIX platforms. It focuses on visualizing how program\nexecution impacts memory. It uses UNICODE IBM Code Page 437 characters\nto display binary memory panels, which change as you step through your\nprogram's assembly code. These memory panels may be scrolled and zoomed\nusing your mouse wheel.\n.Nm\nalso permits reverse debugging, where scroll wheeling over the assembly\ndisplay allows the rewinding of execution history.\n.Sh ARGUMENTS\n.Pp\nThe\n.Ar program\nargument is a\n.Ev PATH\nsearched command, which may be:\n.Pp\n.Bl -dash -compact\n.It\nAn x86_64-linux ELF executable (either static or dynamic)\n.It\nAn Actually Portable Executable (either MZqFpD or jartsr magic)\n.It\nA flat executable (if\n.Ar program\nends with .bin, .img, or .raw)\n.It\nA shell script whose #!interpreter meets the above criteria\n.El\n.Pp\nThe\n.Fl 0\nflag allows\n.Li argv[0]\nto be specified on the command line. Under normal circumstances,\n.Bd -literal -offset indent\nblinkenlights cmd arg1\n.Ed\n.Pp\nis equivalent to\n.Bd -literal -offset indent\nexecve(\"cmd\", {\"cmd\", \"arg1\"})\n.Ed\n.Pp\nsince that's how most programs are launched. However if you\nneed the full power of execve() process spawning, you can say\n.Bd -literal -offset indent\nblinkenlights -0 cmd arg0 arg1\n.Ed\n.Pp\nwhich is equivalent to\n.Bd -literal -offset indent\nexecve(\"cmd\", {\"arg0\", \"arg1\"})\n.Ed\n.Pp\n.Sh OPTIONS\nThe following options are available:\n.Bl -tag -width indent\n.It Fl h\nPrints condensed help.\n.It Fl v\nShows\n.Nm\nversion and build configuration details.\n.It Fl N\nEnables natural scrolling.\n.It Fl H\nDisables syntax highlighting.\n.It Fl r\nPuts your virtual machine in real mode. This may be used to run 16-bit\ni8086 programs, such as SectorLISP. It's also used for booting programs\nfrom Blinkenlights's simulated BIOS.\n.It Fl b Ar addr\nPushes a breakpoint, which may be specified as a raw hexadecimal\naddress, or a symbolic name that's defined by your ELF binary (or its\nassociated\n.Li .dbg\nfile). When pressing\n.Li c\n(continue) or\n.Li C\n(continue harder) in the TUI, Blink will immediately stop upon reaching\nan instruction that's listed as a breakpoint, after which a modal dialog\nis displayed. The modal dialog may be cleared by\n.Li ENTER\nafter which the TUI resumes its normal state.\n.It Fl w Ar addr\nPushes a watchpoint, which may be specified as a raw hexadecimal\naddress, or a symbolic name that's defined by your ELF binary (or its\nassociated\n.Li .dbg\nfile). When pressing\n.Li c\n(continue) or\n.Li C\n(continue\nharder) in the TUI, Blink will immediately stop upon reaching an\ninstruction that either (a) has a ModR/M encoding that references an\naddress that's listed as a watchpoint, or (b) manages to mutate the\nmemory stored at a watchpoint address by some other means. When\nBlinkenlights is stopped at a watchpoint, a modal dialog will be\ndisplayed which may be cleared by pressing\n.Li ENTER\nafter which the TUI\nresumes its normal state.\n.It Fl t\nMay be used to disable Blinkenlights TUI mode. This makes the program\nbehave similarly to the\n.Xr blink 1\ncommand, however not as good. We're currently using this flag for unit\ntesting real mode programs, which are encouraged to use the\n.Li SYSCALL\ninstruction to report their exit status.\n.It Fl s\nEnables system call logging (repeatable).\n.Pp\nThis will emit to the log file\nthe names of system calls each time a SYSCALL instruction in executed,\nalong with its arguments and result. System calls are logged once\nthey've completed, so that the result can be shown.\n.Pp\nSystem calls are\nalso sometimes logged upon entry too, in which case\n.Li syscall(arg) -> ...\nwill be logged to show that the system call has not yet completed.\nWhether or not this happens depends on how many times the\n.Fl s\nflag is supplied.\n.Pp\n.Bl -dash -compact\n.It\nPassing\n.Fl s\n(once) will only log the entries of system calls that are defined as\nhaving read + write parameters (e.g. poll, select)\n.It\nPassing\n.Fl ss\n(twice) will also log the entries of cancellation points that are likely\nto block (e.g. read, accept, wait, pause).\n.It\nPassing\n.Fl sss\n(thrice) will log the entries of system calls that POSIX defines as\ncancellation points but are unlikely to block (e.g. write, close, open)\nwhich we try to avoid doing in order to reduce log noise.\n.It\nPassing\n.Fl ssss\n(4x) will log the entry of every single system call, even harmless ones\nthat have no business being emitted to the log twice (e.g. sigaction).\nThis should only be useful for the Blink dev team when the rare need\narises to troubleshoot a system call that's crashing.\n.El\n.Pp\nSystem call logging isn't available in\n.Li MODE=rel\nand\n.Li MODE=tiny\nbuilds, in which case this flag is ignored.\n.It Fl j\nEnables Just-In-Time (JIT) compilation. This will make Blinkenlights go\nsignificantly faster, at the cost of taking away the ability to step\nthrough each instruction. The TUI will visualize JIT path formation in\nthe assembly display; see the JIT Path Glyphs section below to learn\nmore. Please note this flag has the opposite meaning as it does in the\n.Xr blink 1\ncommand.\n.It Fl m\nEnables the linear memory optimization. This makes\n.Nm\ncapable of faster emulation, at the cost of losing some statistics. It\nno longer becomes possible to display which percentage of a memory map\nhas been activated. Blinkenlights will also remove the commit / reserve\n/ free page statistics from the status panel on the bottom right of the\ndisplay. Please note this flag has the opposite meaning as it does in\nthe\n.Xr blink 1\ncommand.\n.It Fl L Ar path\nSpecifies the log path. The default log path is\n.Ar blink.log\nin the current directory at startup. This log file won't be created\nuntil something is actually logged. If logging to a file isn't desired,\nthen -L /dev/null may be used. See also the\n.Fl e\nflag for logging to standard error.\n.It Fl C Ar path\nLaunch\n.Ar program\nin a chroot'd environment. This flag is both equivalent to and overrides\nthe\n.Ev BLINK_OVERLAYS\nenvironment variable.\n.It Fl z\n[repeatable] May be specified to zoom the memory panels, so they display\na larger amount of memory in a smaller space. By default, one terminal\ncell corresponds to a single byte of memory. When memory has been zoomed\nthe magic kernel is used (similar to Lanczos) to decimate the number of\nbytes by half, for each\n.Fl z\nthat's specified. Normally this would be\naccomplished by using\n.Li CTRL+MOUSEWHEEL\nwhere the mouse cursor is hovered over the panel that should be zoomed.\nHowever, many terminal emulators (especially on Windows), do not support\nthis xterm feature and as such, this flag is provided as an alternative.\n.It Fl Z\nPrints internal statistics to standard error on exit. Each line will\ndisplay a monitoring metric. Most metrics will either be integer\ncounters or floating point running averages. Most but not all integer\ncounters are monotonic. In the interest of not negatively impacting\nBlink's performance, statistics are computed on a best effort basis\nwhich currently isn't guaranteed to be atomic in a multi-threaded\nenvironment. Statistics aren't available in MODE=rel and MODE=tiny\nbuilds, in which case this flag is ignored.\n.It Fl V\n[repeatable] Increases verbosity.\n.It Fl R\nDisables reactive error mode.\n.El\n.Sh KEYBOARD SHORTCUTS\nThe following keystrokes are recognized by the user interface:\n.Bl -tag -width indent\n.It Li ?\nShows help dialog.\n.It Nm q\nQuit.\n.It Nm s\nStep. This executes a single instruction, stepping forward by one.\n.It Nm n\nNext. This is the same as\n.Nm s\n(Step) except it won't recurse into\n.Li CALL\ninstructions.\n.It Nm c\nContinue. This will step automatically and display an animation of the\nprogram execution as it progresses. In continue mode, Blinkenlights will\nexecute as many instructions as possible, and only render a limited\nnumber of 60 frames per second to the terminal. Snapshots are captured\nin the background of the in-between steps that aren't displayed. They\nmay still be viewed by pausing execution using\n.Nm CTRL-C\n(Interrupt) and then pressing UP arrow to scroll backwards through\nexecution history. For large programs, this animation can be sped up (at\nthe cost of losing frames) by using the\n.Nm CTRL-T\n(Turbo) shortcut.\n.It Nm C\nContinue Harder. This will execute the program in the background as\nquickly as possible until some kind of halting event occurs, such as\nexit_group() being called, or a segmentation fault. No animation is\ndisplayed during this time.\n.It Nm CTRL-C\nInterrupt. Pressing this key will interrupt the TUI animation when in\n.Nm c\n(Continue) mode. Control will then return to the main interface, and\nkeyboard shortcuts such as\n.Nm s\n(Step) may once again be used. Pressing\n.Nm CTRL-C\nalso has the same effect if the embedded teletypewriter is blocked on a\nread() call, awaiting keyboard input.\n.It Nm CTRL-T\nTurbo. The turbo key may be pressed multiple times to specify how many\nsteps should happen per frame in\n.Nm c\n(Continue) mode. Each time this key is pressed, the status bar on the\nbottom left-hand side of the display will be updated with the current\nspeed, which defaults to 1.\n.It Nm ALT-T\nSlowmo. The slowmo keyboard shortcut has the opposite effect of\n.Nm CTRL-T\n(Turbo) in the sense that it slows down the speed of the\n.Nm c\n(Continue) mode animation. Each time this key is pressed, the status bar\non the bottom left-hand side of the display will be updated with the\ncurrent speed, which defaults to 1, and descends into negative numbers.\nPositive values are defined as the number of steps per frame. Negative\nnumbers will result in sleep delays being inserted between steps.\n.It Nm p\nProfiling Mode. Pressing the\n.Nm p\nkey will cause the TUI to cycle between the profiling and backtrace\npanels. When\n.Nm blinkenlights\nis running, it maintains a naive count of the number of assembly opcodes\nexecuted at each memory address. When the profiling panel is displayed,\nthose counters will be grouped by function, ranked, and displayed as a\npercentage of the total. This is intended to help identify, in real time\nas execution progresses, which functions are execution hotspots.\n.It Nm t\nSSE Type. When the SSE panel is being displayed, the TUI will determine\nthe type of each XMM register based on the instructions used. The three\ndifferent types defined for this purpose are (1) integral, (2) single,\nand (3) double.\n.It Nm T\nSSE Size. When the SSE panel is being displayed, pressing this key will\ncycle the vector element size of XMM registers in integral mode. The\nfollowing sizes are defined: 1 (byte), 2 (word), 4 (dword), 8 (qword).\n.It Nm x\nSSE Radix. When the SSE panel is being displayed, pressing this key will\ncycle the display of XMM registers currently in integral mode, so that\nthey're displayed as either (1) hexadecimal, (2) characters (CP437), or\n(3) decimal. Floating point XMM registers aren't impacted, unless the\n.Nm t\n(Sse Type) key is pressed beforehand to cycle them into integral mode.\n.It Nm M\nThe\n.Nm M\nkey may be pressed to toggle xterm mouse tracking. This may be useful\nfor terminals that do not allow copying and pasting terminal content\nwhen mouse tracking is enabled (try shift+drag too).\n.It Nm MOUSEWHEEL\nScroll. Using the mouse wheel has a different effect depending on which\npanel the mouse cursor is currently hovering over. When the mouse is\nabove the disassembly panel, scrolling the mouse wheel will rewind and\nreplay the history of program execution. When above memory panels, mouse\nwheel will display different memory addresses.\n.It Nm CTRL-MOUSEWHEEL\nZoom. On platforms such as Linux that support the necessary xterm escape\ncode for doing this, using mousewheel while holding down the control key\nwhen the mouse cursor is hovering above one of the memory panels, will\ncause that memory panel to become zoomed. Under normal circumstances,\neach TTY cell corresponds to a single byte of memory. Zooming by one\nnotch will cause each cell to display two bytes of memory. Then four.\nThen eight. This is accomplished by successively applying an image\nscaling algorithm to the adjacent memory.\n.It Nm CTRL-Z\nStop. Pressing this shortcut will place\n.Nm\nin the background and return control to the shell. You may resume your\ndebugging session later by running the\n.Nm fg\ncommand.\n.It Nm CTRL-L\nRefresh. Pressing this keyboard shortcut will cause the display to be\nredrawn. This may be useful on the oft chance the terminal state becomes\ncorrupted.\n.It Nm CTRL-D\nEOF (End Of File). This keystroke has two different meanings depending\non context. When control is held by the debugger TUI, this will ask\n.Nm\nto exit. When control is held by the guest program invoking read() in\nthe teletypewriter, this will close the standard input handle.\n.El\n.Sh ENVIRONMENT\nThe following environment variables are recognized:\n.Bl -tag -width indent\n.It Ev BLINK_LOG_FILENAME\nmay be specified to supply a log path to be used in cases where the\n.Fl L Ar path\nflag isn't specified. This value should be an absolute path. If logging\nto standard error is desired, use the\n.Fl e\nflag.\n.It Ev BLINK_OVERLAYS\nspecifies one or more directories to use as the root filesystem.\nSimilar to\n.Ev PATH\nthis is a colon delimited list of pathnames. If relative paths are\nspecified, they'll be resolved to an absolute path at startup time.\nOverlays only apply to IO system calls that specify an absolute path.\nThe empty string overlay means use the normal / root filesystem. The\ndefault value is\n.Li :o\nwhich means if the absolute path\n.Li /$f\nis opened, then first check if\n.Li /$f\nexists, and if it doesn't, then check if\n.Li o/$f\nexists, in which case open that instead. Blink uses this convention to\nopen shared object tests. It favors the system version if it exists, but\nalso downloads\n.Li ld-musl-x86_64.so.1\nto\n.Li o/lib/ld-musl-x86_64.so.1\nso the dynamic linker can transparently find it on platforms like Apple,\nthat don't let users put files in the root folder. On the other hand,\nit's possible to say\n.Li BLINK_OVERLAYS=o:\nso that\n.Li o/...\ntakes precedence over\n.Li /...\n(noting again that empty string means root). If a single overlay is\nspecified that isn't empty string, then it'll effectively act as a\nrestricted chroot environment.\n.El\n.Sh EXIT STATUS\nThe\n.Nm\ncommand passes along the exit code of the\n.Ar program\nwhich by convention is 0 on success or >0 on failure. In the event that\n.Nm\nfails to launch\n.Ar program\nthe status 127 shall be returned.\n.Sh SEE ALSO\n.Xr blink 1\n.Sh AUTHORS\n.An \"Justine Alexandra Roberts Tunney\" Aq jtunney@gmail.com\n.Sh QUIRKS\nBlinkenlights TUI currently isn't suitable for debugging programs that\nspawn threads / processes. While such programs may be debugged, separate\nthreads and processes can not be controlled reliably by the keyboard.\n"
  },
  {
    "path": "blink/blinkenlights.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/blinkenlights.h\"\n\n#include <ctype.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <inttypes.h>\n#include <locale.h>\n#include <poll.h>\n#include <signal.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <time.h>\n#include <unistd.h>\n#include <wchar.h>\n#include <wctype.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/bda.h\"\n#include \"blink/biosrom.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/breakpoint.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/case.h\"\n#include \"blink/cga.h\"\n#include \"blink/debug.h\"\n#include \"blink/dis.h\"\n#include \"blink/endian.h\"\n#include \"blink/errno.h\"\n#include \"blink/fds.h\"\n#include \"blink/flag.h\"\n#include \"blink/flags.h\"\n#include \"blink/fpu.h\"\n#include \"blink/high.h\"\n#include \"blink/linux.h\"\n#include \"blink/loader.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/mda.h\"\n#include \"blink/overlays.h\"\n#include \"blink/panel.h\"\n#include \"blink/pml4t.h\"\n#include \"blink/pty.h\"\n#include \"blink/rde.h\"\n#include \"blink/signal.h\"\n#include \"blink/sigwinch.h\"\n#include \"blink/stats.h\"\n#include \"blink/strwidth.h\"\n#include \"blink/syscall.h\"\n#include \"blink/thompike.h\"\n#include \"blink/timespec.h\"\n#include \"blink/tsan.h\"\n#include \"blink/types.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n#include \"blink/watch.h\"\n#include \"blink/web.h\"\n#include \"blink/xlat.h\"\n#include \"blink/xmmtype.h\"\n\n#ifndef BUILD_TIMESTAMP\n#define BUILD_TIMESTAMP __TIMESTAMP__\n#endif\n#ifndef BUILD_MODE\n#define BUILD_MODE \"BUILD_MODE_UNKNOWN\"\n#warning \"-DBUILD_MODE=... should be passed to blink/blinkenlights.c\"\n#endif\n#ifndef BUILD_TOOLCHAIN\n#define BUILD_TOOLCHAIN \"BUILD_TOOLCHAIN_UNKNOWN\"\n#warning \"-DBUILD_TOOLCHAIN=... should be passed to blink/blinkenlights.c\"\n#endif\n#ifndef BLINK_VERSION\n#define BLINK_VERSION \"BLINK_VERSION_UNKNOWN\"\n#warning \"-DBLINK_VERSION=... should be passed to blink/blinkenlights.c\"\n#endif\n#ifndef BLINK_COMMITS\n#define BLINK_COMMITS \"BLINK_COMMITS_UNKNOWN\"\n#warning \"-DBLINK_COMMITS=... should be passed to blink/blinkenlights.c\"\n#endif\n#ifndef BLINK_GITSHA\n#define BLINK_GITSHA \"BLINK_GITSHA_UNKNOWN\"\n#warning \"-DBLINK_GITSHA=... should be passed to blink/blinkenlights.c\"\n#endif\n#ifndef CONFIG_ARGUMENTS\n#define CONFIG_ARGUMENTS \"CONFIG_ARGUMENTS_UNKNOWN\"\n#warning \"-DCONFIG_ARGUMENTS=... should be passed to blink/blinkenlights.c\"\n#endif\n\n#define VERSION \\\n  \"Blinkenlights \" BLINK_VERSION \" (\" BUILD_TIMESTAMP \")\\n\\\nCopyright (c) 2023 Justine Alexandra Roberts Tunney\\n\\\nBlinkenlights comes with absolutely NO WARRANTY of any kind.\\n\\\nYou may redistribute copies of Blinkenlights under the ISC License.\\n\\\nFor more information, see the file named LICENSE.\\n\\\nToolchain: \" BUILD_TOOLCHAIN \"\\n\\\nRevision: #\" BLINK_COMMITS \" \" BLINK_GITSHA \"\\n\\\nConfig: ./configure MODE=\" BUILD_MODE \" \" CONFIG_ARGUMENTS \"\\n\"\n\n#define USAGE \\\n  \" [-?HhrRsZtv] [ROM] [ARGS...]\\n\\\n\\n\\\nDESCRIPTION\\n\\\n\\n\\\n  blinkenlights - x86_64-linux virtual machine tui\\n\\\n\\n\\\nFLAGS\\n\\\n\\n\\\n  -h        help\\n\\\n  -z        zoom\\n\\\n  -v        version\\n\\\n  -r        real mode (i8086)\\n\\\n  -s        system call trace\\n\\\n  -H        disable highlight\\n\\\n  -t        disable tui mode\\n\\\n  -R        disable reactive\\n\\\n  -b ADDR   push a breakpoint\\n\\\n  -w ADDR   push a watchpoint\\n\\\n  -L PATH   log file location\\n\\\n  -B PATH   alternate BIOS image\\n\\\n  -Z        internal statistics\\n\\\n\\n\\\nARGUMENTS\\n\\\n\\n\\\n  ROM files may be ELF, Actually Portable Executable, or flat.\\n\\\n  It should use x86_64 in accordance with the System Five ABI.\\n\\\n  The SYSCALL ABI is defined as it is written in Linux Kernel.\\n\\\n\\n\\\nFEATURES\\n\\\n\\n\\\n  8086, 8087, i386, x86_64, SSE3, SSSE3, POPCNT, MDA, CGA, TTY\\n\\\n  Type ? for keyboard shortcuts and CLI flags inside emulator.\\n\\\n\\n\"\n\n#define FPS        60     // frames per second written to tty\n#define TURBO      true   // to keep executing between frames\n#define HISTORY    65536  // number of rewind renders to ring\n#define WHEELDELTA 1      // how much impact scroll wheel has\n#define MAXZOOM    16     // lg2 maximum memory panel scaling\n#define DISPWIDTH  80     // size of the embedded tty display\n#define DUMPWIDTH  64     // columns of bytes in memory panel\n#define ASMWIDTH   40     // seed the width of assembly panel\n#define ASMRAWMIN  (m->mode.omode == XED_MODE_REAL ? 50 : 65)\n\n#define RESTART  0x001\n#define REDRAW   0x002\n#define CONTINUE 0x004\n#define STEP     0x008\n#define NEXT     0x010\n#define FINISH   0x020\n#define MODAL    0x040\n#define WINCHED  0x080\n#define INT      0x100\n#define QUIT     0x200\n#define EXIT     0x400\n#define ALARM    0x800\n\n#define kXmmDecimal 0\n#define kXmmHex     1\n#define kXmmChar    2\n\n#define kMouseLeftDown      0\n#define kMouseMiddleDown    1\n#define kMouseRightDown     2\n#define kMouseLeftUp        4\n#define kMouseMiddleUp      5\n#define kMouseRightUp       6\n#define kMouseLeftDrag      32\n#define kMouseMiddleDrag    33\n#define kMouseRightDrag     34\n#define kMouseWheelUp       64\n#define kMouseWheelDown     65\n#define kMouseCtrlWheelUp   80\n#define kMouseCtrlWheelDown 81\n\n#define kAsanScale              3\n#define kAsanMagic              0x7fff8000\n#define kAsanHeapFree           -1\n#define kAsanStackFree          -2\n#define kAsanRelocated          -3\n#define kAsanHeapUnderrun       -4\n#define kAsanHeapOverrun        -5\n#define kAsanGlobalOverrun      -6\n#define kAsanGlobalUnregistered -7\n#define kAsanStackUnderrun      -8\n#define kAsanStackOverrun       -9\n#define kAsanAllocaUnderrun     -10\n#define kAsanAllocaOverrun      -11\n#define kAsanUnscoped           -12\n#define kAsanUnmapped           -13\n\n#define Ctrl(C) ((C) ^ 0100)\n\n#ifdef IUTF8\n#define HR   L'─'\n#define BULB \"◎\"\n#else\n#define HR   '-'\n#define BULB \"@\"\n#endif\n\nstruct Mouse {\n  short y;\n  short x;\n  int e;\n};\n\nstruct MemoryView {\n  i64 start;\n  int zoom;\n};\n\nstruct Keystrokes {\n  unsigned i;\n  char p[4][32];\n  struct timespec s[4];\n};\n\nstruct Panels {\n  union {\n    struct {\n      struct Panel disassembly;\n      struct Panel breakpointshr;\n      struct Panel breakpoints;\n      struct Panel mapshr;\n      struct Panel maps;\n      struct Panel frameshr;\n      struct Panel frames;\n      struct Panel displayhr;\n      struct Panel display;\n      struct Panel registers;\n      struct Panel ssehr;\n      struct Panel sse;\n      struct Panel codehr;\n      struct Panel code;\n      struct Panel readhr;\n      struct Panel readdata;\n      struct Panel writehr;\n      struct Panel writedata;\n      struct Panel stackhr;\n      struct Panel stack;\n      struct Panel status;\n    };\n    struct Panel p[21];\n  };\n};\n\nstruct Rendering {\n  u64 cycle;\n  void *data;\n  unsigned compsize;\n  unsigned origsize;\n};\n\nstruct History {\n  unsigned index;\n  unsigned count;\n  unsigned viewing;\n  struct Rendering p[HISTORY];\n};\n\nstruct ProfSym {\n  int sym;  // dis->syms.p[sym]\n  unsigned long hits;\n};\n\nstruct ProfSyms {\n  int i, n;\n  unsigned long toto;\n  struct ProfSym *p;\n};\n\nstatic const char kHelp[] = \"\\\n\\033[1mBlinkenlights \" BLINK_VERSION \"\\033[22m\\\n                https://github.com/jart/blink/\\n\\\n\\n\\\nKEYBOARD SHORTCUTS                CLI FLAGS\\n\\\n\\n\\\nctrl-c  interrupt                 -t       no tui\\n\\\ns       step                      -r       real mode\\n\\\nn       next                      -Z       statistics\\n\\\nc       continue                  -b ADDR  push breakpoint\\n\\\nC       continue harder           -w ADDR  push watchpoint\\n\\\nq       quit                      -L PATH  log file location\\n\\\nf       finish                    -R       deliver crash sigs\\n\\\nR       restart                   -H       disable highlighting\\n\\\n?       help                      -v       blinkenlights version\\n\\\nx       sse radix                 -j       enables jit\\n\\\nt       sse type                  -m       disables memory safety\\n\\\nT       sse size                  -N       natural scroll wheel\\n\\\nb       push breakpoint           -s       system call logging\\n\\\nB       pop breakpoint\\n\\\np       profiling mode            -C PATH  chroot directory\\n\\\nctrl-t  turbo                     -B PATH  alternate BIOS image\\n\\\nalt-t   slowmo                    -z       zoom\\n\\\n2       toggle column 2           -h       help\\n\\\n3       toggle column 3\";\n\nstatic const char kRipName[3][4] = {\"IP\", \"EIP\", \"RIP\"};\n\nstatic const char kRegisterNames[3][16][4] = {\n    {\"AX\", \"CX\", \"DX\", \"BX\", \"SP\", \"BP\", \"SI\", \"DI\"},\n    {\"EAX\", \"ECX\", \"EDX\", \"EBX\", \"ESP\", \"EBP\", \"ESI\", \"EDI\"},\n    {\"RAX\", \"RCX\", \"RDX\", \"RBX\", \"RSP\", \"RBP\", \"RSI\", \"RDI\",  //\n     \"R8\", \"R9\", \"R10\", \"R11\", \"R12\", \"R13\", \"R14\", \"R15\"},\n};\n\nextern char **environ;\n\n/* shared variables with bios.c */\nbool tuimode;\nbool ptyisenabled;\n\nint vidya;\nint ttyin;\n\nstruct Pty *pty;\nstruct Machine *m;\n\nstatic bool belay;\nstatic bool react;\nstatic bool alarmed;\nstatic bool natural;\nstatic bool mousemode;\nstatic bool wantmetal;\nstatic bool displayexec; /* 'D' -> DrawDisplayOnly during Exec() */\nstatic bool showhighsse;\nstatic bool showprofile;\nstatic bool readingteletype;\nstatic bool showcolumn2 = true;\nstatic bool showcolumn3 = true;\n\nstatic int tyn;\nstatic int txn;\nstatic int tick;\nstatic int speed;\nstatic int action;\nstatic int ttyout;\nstatic int opline;\nstatic int xmmdisp;\nstatic int verbose;\nstatic int exitcode;\n\nstatic long ips;\nstatic u64 cycle;\nstatic i64 opstart;\nstatic int lastfds;\nstatic i64 lastrss;\nstatic i64 lastvss;\nstatic u64 readaddr;\nstatic u64 readsize;\nstatic u64 writeaddr;\nstatic u64 writesize;\nstatic i64 mapsstart;\nstatic u64 last_cycle;\nstatic char *codepath;\nstatic i64 framesstart;\nstatic jmp_buf *onbusted;\nstatic const char *dialog;\nstatic char *statusmessage;\nstatic i64 breakpointsstart;\nstatic unsigned long *ophits;\nstatic struct ProfSyms profsyms;\n\nstatic struct Panels pan;\nstatic struct Keystrokes keystrokes;\nstatic struct Breakpoints breakpoints;\nstatic struct Watchpoints watchpoints;\nstatic struct MemoryView codeview;\nstatic struct MemoryView readview;\nstatic struct MemoryView writeview;\nstatic struct MemoryView stackview;\nstatic struct MachineState laststate;\nstatic struct MachineMemstat lastmemstat;\nstatic struct XmmType xmmtype;\nstatic struct Dis dis[1];\n\nstatic struct timespec last_draw;\nstatic struct timespec statusexpires;\nstatic struct termios oldterm;\nstatic char systemfailure[128];\nstatic struct sigaction oldsig[4];\nstatic char pathbuf[PATH_MAX];\nstruct History g_history;\n\nstatic void SetupDraw(void);\nstatic void HandleKeyboard(const char *);\n\nconst char kXedErrorNames[] = \"\\\nnone\\0\\\nbuffer too short\\0\\\ngeneral error\\0\\\ninvalid for chip\\0\\\nbad register\\0\\\nbad lock prefix\\0\\\nbad rep prefix\\0\\\nbad legacy prefix\\0\\\nbad rex prefix\\0\\\nbad evex ubit\\0\\\nbad map\\0\\\nbad evex v prime\\0\\\nbad evex z no masking\\0\\\nno output pointer\\0\\\nno agen call back registered\\0\\\nbad memop index\\0\\\ncallback problem\\0\\\ngather regs\\0\\\ninstr too long\\0\\\ninvalid mode\\0\\\nbad evex ll\\0\\\nunimplemented\\0\\\n\";\n\nstatic char *xasprintf(const char *fmt, ...) {\n  char *s;\n  va_list va;\n  va_start(va, fmt);\n  unassert(vasprintf(&s, fmt, va) != -1);\n  va_end(va);\n  return s;\n}\n\nstatic char *FormatDouble(char buf[32], double x) {\n  snprintf(buf, 32, \"%g\", x);\n  return buf;\n}\n\nstatic char *FormatLongDouble(char buf[32], long double x) {\n  snprintf(buf, 32, \"%Lg\", x);\n  return buf;\n}\n\nstatic i64 SignExtend(u64 x, char b) {\n  char k;\n  unassert(1 <= b && b <= 64);\n  k = 64 - b;\n  return (i64)(x << k) >> k;\n}\n\nvoid SetCarry(bool cf) {\n  m->flags = SetFlag(m->flags, FLAGS_CF, cf);\n}\n\nstatic bool IsCall(void) {\n  switch (Mopcode(m->xedd->op.rde)) {\n    case 0x0CC:\n    case 0x0CD:\n    case 0x0CE:\n    case 0x0E8:\n      return true;\n    case 0x0FF:\n      return ModrmReg(m->xedd->op.rde) == 2;\n    default:\n      return false;\n  }\n}\n\nstatic bool IsDebugBreak(void) {\n  return m->trapno == 3 && Mopcode(m->xedd->op.rde) == 0x0CC;\n}\n\nstatic bool IsRet(void) {\n  switch (Mopcode(m->xedd->op.rde)) {\n    case 0x0C2:\n    case 0x0C3:\n    case 0x0CA:\n    case 0x0CB:\n    case 0x0CF:\n      return true;\n    default:\n      return false;\n  }\n}\n\nstatic int GetXmmTypeCellCount(int r) {\n  switch (xmmtype.type[r]) {\n    case kXmmIntegral:\n      return 16 / xmmtype.size[r];\n    case kXmmFloat:\n      return 4;\n    case kXmmDouble:\n      return 2;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic u8 CycleXmmType(u8 t) {\n  switch (t) {\n    default:\n    case kXmmIntegral:\n      return kXmmFloat;\n    case kXmmFloat:\n      return kXmmDouble;\n    case kXmmDouble:\n      return kXmmIntegral;\n  }\n}\n\nstatic u8 CycleXmmDisp(u8 t) {\n  switch (t) {\n    default:\n    case kXmmDecimal:\n      return kXmmHex;\n    case kXmmHex:\n      return kXmmChar;\n    case kXmmChar:\n      return kXmmDecimal;\n  }\n}\n\nstatic u8 CycleXmmSize(u8 w) {\n  switch (w) {\n    default:\n    case 1:\n      return 2;\n    case 2:\n      return 4;\n    case 4:\n      return 8;\n    case 8:\n      return 1;\n  }\n}\n\nstatic int GetPointerWidth(void) {\n  return 2 << m->mode.omode;\n}\n\nstatic i64 GetSp(void) {\n  switch (GetPointerWidth()) {\n    default:\n    case 8:\n      return Read64(m->sp);\n    case 4:\n      return m->ss.base + Read32(m->sp);\n    case 2:\n      return m->ss.base + Read16(m->sp);\n  }\n}\n\nstatic void AppendPanel(struct Panel *p, i64 line, const char *s) {\n  if (0 <= line && line < p->bottom - p->top) {\n    AppendStr(&p->lines[line], s);\n  }\n}\n\nstatic int CompareProfSyms(const void *p, const void *q) {\n  const struct ProfSym *a = (const struct ProfSym *)p;\n  const struct ProfSym *b = (const struct ProfSym *)q;\n  if (a->hits > b->hits) return -1;\n  if (a->hits < b->hits) return +1;\n  return 0;\n}\n\nstatic void SortProfSyms(void) {\n  qsort(profsyms.p, profsyms.i, sizeof(*profsyms.p), CompareProfSyms);\n}\n\nstatic int AddProfSym(int sym, unsigned long hits) {\n  if (!hits) return -1;\n  if (profsyms.i == profsyms.n) {\n    profsyms.p = (struct ProfSym *)realloc(profsyms.p,\n                                           ++profsyms.n * sizeof(*profsyms.p));\n  }\n  profsyms.p[profsyms.i].sym = sym;\n  profsyms.p[profsyms.i].hits = hits;\n  return profsyms.i++;\n}\n\nstatic unsigned long TallyHits(i64 addr, int size) {\n  i64 pc;\n  unsigned long hits;\n  for (hits = 0, pc = addr; pc < addr + size; ++pc) {\n    hits += ophits[pc - m->system->codestart];\n  }\n  return hits;\n}\n\nstatic void GenerateProfile(void) {\n  int sym;\n  profsyms.i = 0;\n  if (!ophits) return;\n  profsyms.toto = TallyHits(m->system->codestart, m->system->codesize);\n  for (sym = 0; sym < dis->syms.i; ++sym) {\n    if (dis->syms.p[sym].addr >= m->system->codestart &&\n        dis->syms.p[sym].addr + dis->syms.p[sym].size <\n            m->system->codestart + m->system->codesize) {\n      AddProfSym(sym, TallyHits(dis->syms.p[sym].addr, dis->syms.p[sym].size));\n    }\n  }\n  SortProfSyms();\n  profsyms.i = MIN(50, profsyms.i);\n}\n\nstatic void DrawProfile(struct Panel *p) {\n  int i;\n  char line[256];\n  GenerateProfile();\n  for (i = 0; i < profsyms.i; ++i) {\n    snprintf(line, sizeof(line), \"%7.3f%% %s\",\n             (double)profsyms.p[i].hits / profsyms.toto * 100,\n             dis->syms.p[profsyms.p[i].sym].name);\n    AppendPanel(p, i - framesstart, line);\n  }\n}\n\nstatic void CopyMachineState(struct MachineState *ms) {\n  ms->ip = m->ip;\n  ms->cs = m->cs;\n  ms->ss = m->ss;\n  ms->es = m->es;\n  ms->ds = m->ds;\n  ms->fs = m->fs;\n  ms->gs = m->gs;\n  memcpy(ms->weg, m->weg, sizeof(m->weg));\n  memcpy(ms->xmm, m->xmm, sizeof(m->xmm));\n  memcpy(&ms->fpu, &m->fpu, sizeof(m->fpu));\n  memcpy(&ms->mxcsr, &m->mxcsr, sizeof(m->mxcsr));\n}\n\n/**\n * Handles file mapped page faults in valid page but past eof.\n */\nstatic void OnSigBusted(int sig) {\n  longjmp(*onbusted, 1);\n}\n\n/**\n * Returns true if 𝑣 is a shadow memory virtual address.\n */\nstatic bool IsShadow(i64 v) {\n  return 0x7fff8000 <= v && v < 0x100080000000;\n}\n\n/**\n * Returns glyph representing byte at virtual address 𝑣.\n */\nstatic int VirtualBing(i64 v) {\n  u8 *p;\n  int rc;\n  jmp_buf busted;\n  onbusted = &busted;\n  if ((p = SpyAddress(m, v))) {\n    if (!setjmp(busted)) {\n      rc = kCp437[p[0] & 255];\n    } else {\n      rc = L'≀';\n    }\n  } else {\n    rc = L'⋅';\n  }\n  onbusted = NULL;\n  return rc;\n}\n\n/**\n * Returns ASAN shadow uint8 concomitant to address 𝑣 or -1.\n */\nstatic int VirtualShadow(i64 v) {\n  int rc;\n  char *p;\n  jmp_buf busted;\n  if (IsShadow(v)) return -2;\n  onbusted = &busted;\n  if ((p = (char *)SpyAddress(m, (v >> 3) + 0x7fff8000))) {\n    if (!setjmp(busted)) {\n      rc = p[0] & 0xff;\n    } else {\n      rc = -1;\n    }\n  } else {\n    rc = -1;\n  }\n  onbusted = NULL;\n  return rc;\n}\n\nstatic void ScrollOp(struct Panel *p, i64 op) {\n  i64 n;\n  opline = op;\n  if ((n = p->bottom - p->top) > 1) {\n    if (!(opstart + 1 <= op && op < opstart + n)) {\n      opstart = MIN(MAX(0, op - n / 8), MAX(0, dis->ops.i - n));\n    }\n  }\n}\n\nstatic int TtyWriteString(const char *s) {\n  return VfsWrite(ttyout, s, strlen(s));\n}\n\nstatic void OnFeed(void) {\n  TtyWriteString(\"\\033[K\\033[2J\");\n}\n\nstatic void HideCursor(void) {\n  TtyWriteString(\"\\033[?25l\");\n}\n\nstatic void ShowCursor(void) {\n  if (tuimode) {\n    TtyWriteString(\"\\033[?25h\");\n  }\n}\n\nstatic void EnableMouseTracking(void) {\n  mousemode = true;\n  TtyWriteString(\"\\033[?1000;1002;1015;1006h\");\n}\n\nstatic void DisableMouseTracking(void) {\n  if (mousemode) {\n    TtyWriteString(\"\\033[?1000;1002;1015;1006l\");\n    mousemode = false;\n  }\n}\n\nstatic void ToggleMouseTracking(void) {\n  if (mousemode) {\n    DisableMouseTracking();\n  } else {\n    EnableMouseTracking();\n  }\n}\n\nstatic void LeaveScreen(void) {\n  char buf[64];\n  if (tuimode) {\n    sprintf(buf, \"\\033[%d;%dH\\033[S\\n\", tyn, txn);\n    TtyWriteString(buf);\n  }\n}\n\nstatic void GetTtySize(int fd) {\n  struct winsize wsize;\n  wsize.ws_row = tyn;\n  wsize.ws_col = txn;\n  VfsIoctl(fd, TIOCGWINSZ, &wsize);\n  tyn = wsize.ws_row;\n  txn = wsize.ws_col;\n}\n\nstatic void TuiRejuvinate(void) {\n  struct termios term;\n  struct sigaction sa;\n  LOGF(\"TuiRejuvinate\");\n  GetTtySize(ttyout);\n  HideCursor();\n  memcpy(&term, &oldterm, sizeof(term));\n  term.c_cc[VMIN] = 1;\n  term.c_cc[VTIME] = 1;\n  term.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);\n  term.c_iflag &= ~(IXOFF | PARMRK | INLCR | IGNCR | IGNPAR);\n  term.c_iflag |= IGNBRK;\n  term.c_lflag &=\n      ~(IEXTEN | ICANON | ECHO | ECHOE | ECHONL | NOFLSH | TOSTOP | ECHOK);\n  term.c_lflag |= ISIG;\n  term.c_cflag &= ~(CSIZE | PARENB);\n  term.c_cflag |= CS8 | CREAD;\n  term.c_oflag |= OPOST | ONLCR;\n  term.c_lflag &= ~ECHOK;\n#ifdef IMAXBEL\n  term.c_iflag &= ~IMAXBEL;\n#endif\n#ifdef PENDIN\n  term.c_lflag &= ~PENDIN;\n#endif\n#ifdef IUTF8\n  term.c_iflag |= IUTF8;\n#endif\n  VfsTcsetattr(ttyout, TCSANOW, &term);\n  memset(&sa, 0, sizeof(sa));\n  sa.sa_handler = OnSigBusted;\n  sa.sa_flags = SA_NODEFER;\n  sigaction(SIGBUS, &sa, 0);\n  EnableMouseTracking();\n}\n\nstatic void OnQ(void) {\n  action |= EXIT;\n}\n\nstatic void OnV(void) {\n  int mode;\n  mode = vidya == kModePty ? 3 : kModePty;\n  VidyaServiceSetMode(mode);\n}\n\nstatic void OnSigSys(int sig) {\n  // do nothing\n}\n\nstatic void OnSigWinch(int sig) {\n  EnqueueSignal(m, SIGWINCH_LINUX);\n  action |= WINCHED;\n}\n\nstatic void OnSigInt(int sig) {\n  action |= INT;\n}\n\nstatic void OnSigAlrm(int sig) {\n  action |= ALARM;\n}\n\nstatic void TtyRestore(void) {\n  LOGF(\"TtyRestore\");\n  TtyWriteString(\"\\033[0m\");\n  DisableMouseTracking();\n  ShowCursor();\n  VfsTcsetattr(ttyout, TCSANOW, &oldterm);\n}\n\nstatic void TuiCleanup(void) {\n  LOGF(\"TuiCleanup\");\n  sigaction(SIGCONT, oldsig + 2, 0);\n  TtyRestore();\n}\n\nstatic void OnSigTstp(int sig) {\n  TtyRestore();\n  raise(SIGSTOP);\n}\n\nstatic void OnSigCont(int sig) {\n  if (tuimode) {\n    TuiRejuvinate();\n    Redraw(true);\n  }\n  EnqueueSignal(m, SIGCONT);\n}\n\nstatic void ResolveBreakpoints(void) {\n  long i, sym;\n  for (i = 0; i < breakpoints.i; ++i) {\n    if (breakpoints.p[i].symbol && !breakpoints.p[i].addr) {\n      if ((sym = DisFindSymByName(dis, breakpoints.p[i].symbol)) != -1) {\n        breakpoints.p[i].addr = dis->syms.p[sym].addr;\n      }\n    }\n  }\n}\n\nstatic void ResolveWatchpoints(void) {\n  long i, sym;\n  for (i = 0; i < watchpoints.i; ++i) {\n    if (watchpoints.p[i].symbol && !watchpoints.p[i].addr) {\n      if ((sym = DisFindSymByName(dis, watchpoints.p[i].symbol)) != -1) {\n        watchpoints.p[i].addr = dis->syms.p[sym].addr;\n      }\n    }\n  }\n}\n\nstatic void BreakAtNextInstruction(void) {\n  struct Breakpoint b;\n  memset(&b, 0, sizeof(b));\n  b.addr = GetPc(m) + m->xedd->length;\n  b.oneshot = true;\n  PushBreakpoint(&breakpoints, &b);\n}\n\nstatic void BreakAtCurrentInstruction(void) {\n  struct Breakpoint b;\n  if (IsAtBreakpoint(&breakpoints, m->ip) != -1) return;\n  memset(&b, 0, sizeof(b));\n  b.addr = m->ip;\n  PushBreakpoint(&breakpoints, &b);\n}\n\nstatic int DrainInput(int fd) {\n  char buf[32];\n  struct pollfd fds[1];\n  for (;;) {\n    fds[0].fd = fd;\n    fds[0].events = POLLIN;\n    if (VfsPoll(fds, ARRAYLEN(fds), 0) == -1) return -1;\n    if (!(fds[0].revents & POLLIN)) break;\n    if (VfsRead(fd, buf, sizeof(buf)) == -1) return -1;\n  }\n  return 0;\n}\n\nstatic int ReadCursorPosition(int *out_y, int *out_x) {\n  int y, x;\n  char *p, buf[32];\n  if (readansi(ttyin, buf, sizeof(buf)) == 1) return -1;\n  p = buf;\n  if (*p == 033) ++p;\n  if (*p == '[') ++p;\n  y = strtol(p, &p, 10);\n  if (*p == ';') ++p;\n  x = strtol(p, &p, 10);\n  if (*p != 'R') {\n    errno = EBADMSG;\n    return -1;\n  }\n  if (out_y) *out_y = MAX(1, y) - 1;\n  if (out_x) *out_x = MAX(1, x) - 1;\n  return 0;\n}\n\nstatic int GetCursorPosition(int *out_y, int *out_x) {\n  TtyWriteString(\"\\033[6n\");\n  return ReadCursorPosition(out_y, out_x);\n}\n\nvoid OnSymbols(struct System *s) {\n  ResolveBreakpoints();\n  ResolveWatchpoints();\n}\n\nvoid CommonSetup(void) {\n  static bool once;\n  if (!once) {\n    if (tuimode || breakpoints.i || watchpoints.i) {\n      m->system->dis = dis;\n      m->system->onsymbols = OnSymbols;\n      LoadDebugSymbols(m->system);\n    }\n    once = true;\n  }\n}\n\nvoid TuiSetup(void) {\n  int y;\n  bool report;\n  char buf[64];\n  static bool once;\n  struct itimerval it;\n  struct sigaction sa;\n  report = false;\n  if (!once) {\n    LOGF(\"loaded program %s\\n%s\", codepath, FormatPml4t(m));\n    CommonSetup();\n    VfsTcgetattr(ttyout, &oldterm);\n    atexit(TtyRestore);\n    AtAbort(TtyRestore);\n    once = true;\n    report = true;\n  }\n  memset(&it, 0, sizeof(it));\n  setitimer(ITIMER_REAL, &it, 0);\n  memset(&sa, 0, sizeof(sa));\n  sa.sa_handler = OnSigCont;\n  sa.sa_flags = SA_RESTART | SA_NODEFER;\n  sigaction(SIGCONT, &sa, oldsig + 2);\n  sa.sa_handler = OnSigTstp;\n  sigaction(SIGTSTP, &sa, 0);\n  CopyMachineState(&laststate);\n  TuiRejuvinate();\n  if (report) {\n    DrainInput(ttyin);\n    y = 0;\n    if (GetCursorPosition(&y, NULL) != -1) {\n      sprintf(buf, \"\\033[%dS\", y);\n      TtyWriteString(buf);\n    }\n  }\n}\n\nstatic void ExecSetup(void) {\n  struct itimerval it;\n  CommonSetup();\n  it.it_interval.tv_sec = 0;\n  it.it_interval.tv_usec = 1. / FPS * 1e6;\n  it.it_value.tv_sec = 0;\n  it.it_value.tv_usec = 1. / FPS * 1e6;\n  if (!m->metal) setitimer(ITIMER_REAL, &it, 0);\n}\n\nstatic void pcmpeqb(u8 x[16], const u8 y[16]) {\n  for (int i = 0; i < 16; ++i) x[i] = -(x[i] == y[i]);\n}\n\nstatic unsigned pmovmskb(const u8 p[16]) {\n  unsigned i, m;\n  for (m = i = 0; i < 16; ++i) m |= !!(p[i] & 0x80) << i;\n  return m;\n}\n\nstatic bool IsXmmNonZero(i64 start, i64 end) {\n  i64 i;\n  u8 v1[16], vz[16];\n  for (i = start; i < end; ++i) {\n    memset(vz, 0, 16);\n    memcpy(v1, m->xmm[i], 16);\n    pcmpeqb(v1, vz);\n    if (pmovmskb(v1) != 0xffff) {\n      return true;\n    }\n  }\n  return false;\n}\n\nstatic bool IsSegNonZero(void) {\n  unsigned i;\n  for (i = 0; i < 6; ++i) {\n    if (GetSegmentBase(DISPATCH_NOTHING, i)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nstatic int PickNumberOfXmmRegistersToShow(void) {\n  if (IsXmmNonZero(0, 8) || IsXmmNonZero(8, 16)) {\n    if (showhighsse || IsXmmNonZero(8, 16)) {\n      showhighsse = true;\n      return 16;\n    } else {\n      return 8;\n    }\n  } else {\n    showhighsse = false;\n    return 0;\n  }\n}\n\nstatic int GetRegHexWidth(void) {\n  switch (m->mode.omode) {\n    case XED_MODE_LONG:\n      return 16;\n    case XED_MODE_LEGACY:\n      return 8;\n    case XED_MODE_REAL:\n      if ((Read64(m->ax) >> 16) || (Read64(m->cx) >> 16) ||\n          (Read64(m->dx) >> 16) || (Read64(m->bx) >> 16) ||\n          (Read64(m->sp) >> 16) || (Read64(m->bp) >> 16) ||\n          (Read64(m->si) >> 16) || (Read64(m->di) >> 16)) {\n        return 8;\n      } else {\n        return 4;\n      }\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic int GetAddrHexWidth(void) {\n  switch (m->mode.omode) {\n    case XED_MODE_LONG:\n      return 12;\n    case XED_MODE_LEGACY:\n      return 8;\n    case XED_MODE_REAL:\n      if (m->fs.base >= 0x10fff0 || m->gs.base >= 0x10fff0) {\n        return 8;\n      } else {\n        return 6;\n      }\n    default:\n      __builtin_unreachable();\n  }\n}\n\nbool ShouldShowDisplay(void) {\n  if (vidya != kModePty) return true;  // in bios video mode\n  if (displayexec) return true;\n  return ptyisenabled;\n}\n\nstatic void SetupDraw(void) {\n  int i, j, n, a, b, yn, fit, cpuy, ssey, dx[2], c2y[3], c3y[5];\n\n  cpuy = 9;\n  if (IsSegNonZero()) cpuy += 2;\n  ssey = PickNumberOfXmmRegistersToShow();\n  if (ssey) ++ssey;\n\n  int column[3] = {\n      GetAddrHexWidth() + 1 + ASMWIDTH,\n      DISPWIDTH,\n      GetAddrHexWidth() + 1 + DUMPWIDTH,\n  };\n  if (!showcolumn2) column[1] = 0;\n  if (!showcolumn3) column[2] = 0;\n  bool growable[3] = {\n      true,\n      false,\n      false,\n  };\n  bool shrinkable[3] = {\n      true,\n      true,\n      false,\n  };\n  for (i = 0;; ++i) {\n    for (fit = j = 0; j < ARRAYLEN(column); ++j) {\n      fit += column[j];\n    }\n    if (fit > txn) {\n      if (shrinkable[i % ARRAYLEN(column)]) {\n        --column[i % ARRAYLEN(column)];\n      }\n    } else if (fit < txn) {\n      if (growable[i % ARRAYLEN(column)]) {\n        ++column[i % ARRAYLEN(column)];\n      }\n    } else {\n      break;\n    }\n  }\n  dis->noraw = column[0] < ASMRAWMIN;\n  dx[0] = column[0];\n  dx[1] = column[0] + column[1];\n\n  yn = tyn - 1;\n  a = 1 / 8. * yn;\n  b = 3 / 8. * yn;\n  if (ShouldShowDisplay()) {\n    c2y[0] = breakpoints.i || watchpoints.i ? a * .7 : 0;\n    c2y[1] = a * 2.3;\n    c2y[2] = a * 2 + b;\n    if (yn - c2y[2] > 26) {\n      c2y[1] -= yn - c2y[2] - 26;\n      c2y[2] = yn - 26;\n    }\n    if (yn - c2y[2] < 26) {\n      c2y[2] = yn - 26;\n    }\n  } else {\n    c2y[0] = breakpoints.i || watchpoints.i ? a * .7 : 0;\n    c2y[1] = yn / 20 * 12;\n    c2y[2] = yn;\n  }\n\n  a = (yn - (cpuy + ssey) - 3) / 4;\n  c3y[0] = cpuy;\n  c3y[1] = cpuy + ssey;\n  c3y[2] = cpuy + ssey + 1 + 1 + a * 1;\n  c3y[3] = cpuy + ssey + 1 + 1 + a * 2 + 1;\n  c3y[4] = cpuy + ssey + 1 + 1 + 1 + a * 3 + 1;\n\n  /* COLUMN #1: DISASSEMBLY */\n\n  pan.disassembly.top = 0;\n  pan.disassembly.left = 0;\n  pan.disassembly.bottom = yn;\n  pan.disassembly.right = dx[0] - 1;\n\n  /* COLUMN #2: BREAKPOINTS, MEMORY MAPS, BACKTRACE, DISPLAY */\n\n  pan.breakpointshr.top = 0;\n  pan.breakpointshr.left = dx[0];\n  pan.breakpointshr.bottom = breakpoints.i || watchpoints.i;\n  pan.breakpointshr.right = dx[1] - 1;\n\n  pan.breakpoints.top = 1;\n  pan.breakpoints.left = dx[0];\n  pan.breakpoints.bottom = c2y[0];\n  pan.breakpoints.right = dx[1] - 1;\n\n  pan.mapshr.top = c2y[0];\n  pan.mapshr.left = dx[0];\n  pan.mapshr.bottom = c2y[0] + 1;\n  pan.mapshr.right = dx[1] - 1;\n\n  pan.maps.top = c2y[0] + 1;\n  pan.maps.left = dx[0];\n  pan.maps.bottom = c2y[1];\n  pan.maps.right = dx[1] - 1;\n\n  pan.frameshr.top = c2y[1];\n  pan.frameshr.left = dx[0];\n  pan.frameshr.bottom = c2y[1] + 1;\n  pan.frameshr.right = dx[1] - 1;\n\n  pan.frames.top = c2y[1] + 1;\n  pan.frames.left = dx[0];\n  pan.frames.bottom = c2y[2];\n  pan.frames.right = dx[1] - 1;\n\n  pan.displayhr.top = c2y[2];\n  pan.displayhr.left = dx[0];\n  pan.displayhr.bottom = c2y[2] + ShouldShowDisplay();\n  pan.displayhr.right = dx[1] - 1;\n\n  pan.display.top = c2y[2] + 1;\n  pan.display.left = dx[0];\n  pan.display.bottom = yn;\n  pan.display.right = dx[1] - 1;\n  if (wantmetal) {\n    unassert(pan.display.right - pan.display.left <= 80);\n    unassert(pan.display.bottom - pan.display.top == 25);\n  }\n\n  /* COLUMN #3: REGISTERS, VECTORS, CODE, MEMORY READS, MEMORY WRITES, STACK */\n\n  pan.registers.top = 0;\n  pan.registers.left = dx[1];\n  pan.registers.bottom = c3y[0];\n  pan.registers.right = txn;\n\n  pan.ssehr.top = c3y[0];\n  pan.ssehr.left = dx[1];\n  pan.ssehr.bottom = c3y[0] + (ssey ? 1 : 0);\n  pan.ssehr.right = txn;\n\n  pan.sse.top = c3y[0] + (ssey ? 1 : 0);\n  pan.sse.left = dx[1];\n  pan.sse.bottom = c3y[1];\n  pan.sse.right = txn;\n\n  pan.codehr.top = c3y[1];\n  pan.codehr.left = dx[1];\n  pan.codehr.bottom = c3y[1] + 1;\n  pan.codehr.right = txn;\n\n  pan.code.top = c3y[1] + 1;\n  pan.code.left = dx[1];\n  pan.code.bottom = c3y[2];\n  pan.code.right = txn;\n\n  pan.readhr.top = c3y[2];\n  pan.readhr.left = dx[1];\n  pan.readhr.bottom = c3y[2] + 1;\n  pan.readhr.right = txn;\n\n  pan.readdata.top = c3y[2] + 1;\n  pan.readdata.left = dx[1];\n  pan.readdata.bottom = c3y[3];\n  pan.readdata.right = txn;\n\n  pan.writehr.top = c3y[3];\n  pan.writehr.left = dx[1];\n  pan.writehr.bottom = c3y[3] + 1;\n  pan.writehr.right = txn;\n\n  pan.writedata.top = c3y[3] + 1;\n  pan.writedata.left = dx[1];\n  pan.writedata.bottom = c3y[4];\n  pan.writedata.right = txn;\n\n  pan.stackhr.top = c3y[4];\n  pan.stackhr.left = dx[1];\n  pan.stackhr.bottom = c3y[4] + 1;\n  pan.stackhr.right = txn;\n\n  pan.stack.top = c3y[4] + 1;\n  pan.stack.left = dx[1];\n  pan.stack.bottom = yn;\n  pan.stack.right = txn;\n\n  pan.status.top = yn;\n  pan.status.left = 0;\n  pan.status.bottom = yn + 1;\n  pan.status.right = txn;\n\n  for (i = 0; i < ARRAYLEN(pan.p); ++i) {\n    if (pan.p[i].left > pan.p[i].right) {\n      pan.p[i].left = pan.p[i].right = 0;\n    }\n    if (pan.p[i].top > pan.p[i].bottom) {\n      pan.p[i].top = pan.p[i].bottom = 0;\n    }\n    n = pan.p[i].bottom - pan.p[i].top;\n    if (n == pan.p[i].n) {\n      for (j = 0; j < n; ++j) {\n        pan.p[i].lines[j].i = 0;\n      }\n    } else {\n      for (j = 0; j < pan.p[i].n; ++j) {\n        free(pan.p[i].lines[j].p);\n      }\n      free(pan.p[i].lines);\n      pan.p[i].lines = (struct Buffer *)calloc(n, sizeof(struct Buffer));\n      pan.p[i].n = n;\n    }\n  }\n\n  PtyResize(pty, pan.display.bottom - pan.display.top,\n            pan.display.right - pan.display.left);\n}\n\nstatic i64 Disassemble(void) {\n  i64 lines;\n  lines = pan.disassembly.bottom - pan.disassembly.top * 2;\n  if (Dis(dis, m, GetPc(m), m->ip, lines) != -1) {\n    return DisFind(dis, GetPc(m));\n  } else {\n    return -1;\n  }\n}\n\nstatic i64 GetDisIndex(void) {\n  i64 i;\n  if ((i = DisFind(dis, GetPc(m) - m->oplen)) != -1 ||\n      (i = Disassemble()) != -1) {\n    while (i + 1 < dis->ops.i) {\n      if (!dis->ops.p[i].size) {\n        ++i;\n      } else {\n        break;\n      }\n    }\n  }\n  return i;\n}\n\nstatic void DrawDisassembly(struct Panel *p) {\n  i64 i, j;\n  for (i = 0; i < p->bottom - p->top; ++i) {\n    j = opstart + i;\n    if (0 <= j && j < dis->ops.i) {\n      if (j == opline) AppendPanel(p, i, \"\\033[7m\");\n      AppendPanel(p, i, DisGetLine(dis, m, j));\n      if (j == opline) AppendPanel(p, i, \"\\033[27m\");\n    }\n  }\n}\n\nstatic void DrawHr(struct Panel *p, const char *s) {\n  i64 i, wp, ws, wl, wr;\n  if (p->bottom - p->top < 1) return;\n  wp = p->right - p->left;\n  ws = 8;\n  wl = wp / 4 - ws / 2;\n  wr = wp - (wl + strwidth(s, 0));\n  for (i = 0; i < wl; ++i) AppendWide(&p->lines[0], HR);\n  AppendStr(&p->lines[0], s);\n  for (i = 0; i < wr; ++i) AppendWide(&p->lines[0], HR);\n  AppendStr(&p->lines[0], \"\\033[0m\");\n}\n\nstatic void DrawTerminalHr(struct Panel *p) {\n  i64 i, wp, ws, wl;\n  struct itimerval it;\n  if (p->bottom == p->top) return;\n  if (pty->conf & kPtyBell) {\n    if (!alarmed) {\n      alarmed = true;\n      it.it_interval.tv_sec = 0;\n      it.it_interval.tv_usec = 0;\n      it.it_value.tv_sec = 0;\n      it.it_value.tv_usec = 800000;\n      setitimer(ITIMER_REAL, &it, 0);\n    }\n    AppendStr(&p->lines[0], \"\\033[1m\");\n  }\n  wp = p->right - p->left;\n  ws = 8;\n  wl = wp / 4 - ws / 2;\n  for (i = 0; i < wl; ++i) AppendWide(&p->lines[0], HR);\n  AppendFmt(&p->lines[0], \"%sTELETYPEWRITER%s──%s──%s──%s──%s\",\n            readingteletype ? \"\\033[1m\" : \"\", readingteletype ? \"\\033[22m\" : \"\",\n            (pty->conf & kPtyLed1) ? \"\\033[1;31m\" BULB \"\\033[0m\" : \"○\",\n            (pty->conf & kPtyLed2) ? \"\\033[1;32m\" BULB \"\\033[0m\" : \"○\",\n            (pty->conf & kPtyLed3) ? \"\\033[1;33m\" BULB \"\\033[0m\" : \"○\",\n            (pty->conf & kPtyLed4) ? \"\\033[1;34m\" BULB \"\\033[0m\" : \"○\");\n  for (i = 26 + wl; i < p->right - p->left; ++i) {\n    AppendWide(&p->lines[0], HR);\n  }\n}\n\nstatic void DrawTerminal(struct Panel *p) {\n  i64 y, yn;\n  if (p->top == p->bottom) return;\n  for (yn = MIN(pty->yn, p->bottom - p->top), y = 0; y < yn; ++y) {\n    PtyAppendLine(pty, p->lines + y, y);\n    AppendStr(p->lines + y, \"\\033[0m\");\n  }\n}\n\nstatic void DrawDisplay(struct Panel *p) {\n  switch (vidya) {\n    case 0:  // CGA 40x25 16-gray\n    case 1:  // CGA 40x25 16-color\n    case 2:  // CGA 80x25 16-gray\n    case 3:  // CGA 80x25 16-color\n      DrawHr(&pan.displayhr, \"COLOR GRAPHICS ADAPTER\");\n      DrawCga(p, m->system->real + 0xb8000);\n      break;\n    case 7:  // MDA 80x25 4-gray\n      DrawHr(&pan.displayhr, \"MONOCHROME DISPLAY ADAPTER\");\n      DrawMda(p, (u8(*)[80][2])(m->system->real + 0xb0000), pty->x, pty->y);\n      break;\n    case kModePty:\n    default:\n      DrawTerminalHr(&pan.displayhr);\n      DrawTerminal(p);\n      break;\n  }\n}\n\nstatic void DrawFlag(struct Panel *p, i64 i, char name, bool value) {\n  char str[3] = \"  \";\n  if (value) str[1] = name;\n  AppendPanel(p, i, str);\n}\n\nstatic void DrawRegister(struct Panel *p, i64 i, i64 r, bool first) {\n  char buf[32];\n  u64 value, previous;\n  value = Read64(m->weg[r]);\n  previous = Read64(laststate.weg[r]);\n  if (value != previous) AppendPanel(p, i, \"\\033[7m\");\n  snprintf(buf, sizeof(buf), \"%-3s\", kRegisterNames[m->mode.omode][r]);\n  AppendPanel(p, i, buf);\n  AppendPanel(p, i, \" \");\n  snprintf(buf, sizeof(buf), \"%0*\" PRIx64, GetRegHexWidth(), value);\n  AppendPanel(p, i, buf);\n  if (value != previous) AppendPanel(p, i, \"\\033[27m\");\n  AppendPanel(p, i, \"  \");\n}\n\nstatic void DrawSegment(struct Panel *p, i64 i, struct DescriptorCache value,\n                        struct DescriptorCache previous, const char *name,\n                        bool fsgs) {\n  bool changed = value.sel != previous.sel || value.base != previous.base;\n  char buf[32];\n  if (changed) AppendPanel(p, i, \"\\033[7m\");\n  snprintf(buf, sizeof(buf), \"%-3s\", name);\n  AppendPanel(p, i, buf);\n  AppendPanel(p, i, \" \");\n  if (fsgs) {\n    // only FS & GS can have segment bases beyond the 4 GiB mark\n    snprintf(buf, sizeof(buf), \"%04\" PRIx16 \" @ %016\" PRIx64, value.sel,\n             value.base);\n  } else {\n    snprintf(buf, sizeof(buf), \"%04\" PRIx16 \" @ %08\" PRIx64, value.sel,\n             value.base);\n  }\n  AppendPanel(p, i, buf);\n  if (changed) AppendPanel(p, i, \"\\033[27m\");\n  AppendPanel(p, i, \"  \");\n}\n\nstatic void DrawSt(struct Panel *p, i64 i, i64 r) {\n#ifndef DISABLE_X87\n  char buf[32];\n  bool isempty, chg;\n  long double value;\n  isempty = FpuGetTag(m, r) == kFpuTagEmpty;\n  if (isempty) AppendPanel(p, i, \"\\033[38;5;241m\");\n  value = m->fpu.st[(r + ((m->fpu.sw & kFpuSwSp) >> 11)) & 7];\n  chg = value != laststate.fpu.st[(r + ((m->fpu.sw & kFpuSwSp) >> 11)) & 7];\n  if (!isempty && chg) AppendPanel(p, i, \"\\033[7m\");\n  snprintf(buf, sizeof(buf), \"ST%\" PRId64 \" \", r);\n  AppendPanel(p, i, buf);\n  AppendPanel(p, i, FormatLongDouble(buf, value));\n  if (chg) AppendPanel(p, i, \"\\033[27m\");\n  AppendPanel(p, i, \"  \");\n  if (isempty) AppendPanel(p, i, \"\\033[39m\");\n#endif\n}\n\nstatic void DrawCpu(struct Panel *p) {\n  char buf[48];\n  if (p->top == p->bottom) return;\n  DrawRegister(p, 0, 7, 1), DrawRegister(p, 0, 0, 0), DrawSt(p, 0, 0);\n  DrawRegister(p, 1, 6, 1), DrawRegister(p, 1, 3, 0), DrawSt(p, 1, 1);\n  DrawRegister(p, 2, 2, 1), DrawRegister(p, 2, 5, 0), DrawSt(p, 2, 2);\n  DrawRegister(p, 3, 1, 1), DrawRegister(p, 3, 4, 0), DrawSt(p, 3, 3);\n  DrawRegister(p, 4, 8, 1), DrawRegister(p, 4, 12, 0), DrawSt(p, 4, 4);\n  DrawRegister(p, 5, 9, 1), DrawRegister(p, 5, 13, 0), DrawSt(p, 5, 5);\n  DrawRegister(p, 6, 10, 1), DrawRegister(p, 6, 14, 0), DrawSt(p, 6, 6);\n  DrawRegister(p, 7, 11, 1), DrawRegister(p, 7, 15, 0), DrawSt(p, 7, 7);\n  snprintf(buf, sizeof(buf), \"%-3s %0*\" PRIx64 \"  FLG\", kRipName[m->mode.omode],\n           GetRegHexWidth(), m->ip);\n  AppendPanel(p, 8, buf);\n  DrawFlag(p, 8, 'C', GetFlag(m->flags, FLAGS_CF));\n  DrawFlag(p, 8, 'P', GetFlag(m->flags, FLAGS_PF));\n  DrawFlag(p, 8, 'A', GetFlag(m->flags, FLAGS_AF));\n  DrawFlag(p, 8, 'Z', GetFlag(m->flags, FLAGS_ZF));\n  DrawFlag(p, 8, 'S', GetFlag(m->flags, FLAGS_SF));\n  DrawFlag(p, 8, 'I', GetFlag(m->flags, FLAGS_IF));\n  DrawFlag(p, 8, 'D', GetFlag(m->flags, FLAGS_DF));\n  DrawFlag(p, 8, 'O', GetFlag(m->flags, FLAGS_OF));\n  AppendPanel(p, 8, \"    \");\n#ifndef DISABLE_X87\n  if (m->fpu.sw & kFpuSwIe) AppendPanel(p, 8, \" IE\");\n  if (m->fpu.sw & kFpuSwDe) AppendPanel(p, 8, \" DE\");\n  if (m->fpu.sw & kFpuSwZe) AppendPanel(p, 8, \" ZE\");\n  if (m->fpu.sw & kFpuSwOe) AppendPanel(p, 8, \" OE\");\n  if (m->fpu.sw & kFpuSwUe) AppendPanel(p, 8, \" UE\");\n  if (m->fpu.sw & kFpuSwPe) AppendPanel(p, 8, \" PE\");\n  if (m->fpu.sw & kFpuSwSf) AppendPanel(p, 8, \" SF\");\n  if (m->fpu.sw & kFpuSwEs) AppendPanel(p, 8, \" ES\");\n  if (m->fpu.sw & kFpuSwC0) AppendPanel(p, 8, \" C0\");\n  if (m->fpu.sw & kFpuSwC1) AppendPanel(p, 8, \" C1\");\n  if (m->fpu.sw & kFpuSwC2) AppendPanel(p, 8, \" C2\");\n  if (m->fpu.sw & kFpuSwBf) AppendPanel(p, 8, \" BF\");\n#endif\n  DrawSegment(p, 9, m->fs, laststate.fs, \"FS\", true);\n  DrawSegment(p, 9, m->ds, laststate.ds, \"DS\", false);\n  DrawSegment(p, 9, m->cs, laststate.cs, \"CS\", false);\n  DrawSegment(p, 10, m->gs, laststate.gs, \"GS\", true);\n  DrawSegment(p, 10, m->es, laststate.es, \"ES\", false);\n  DrawSegment(p, 10, m->ss, laststate.ss, \"SS\", false);\n}\n\nstatic void DrawXmm(struct Panel *p, i64 i, i64 r) {\n  float f;\n  double d;\n  wchar_t ival;\n  char buf[32];\n  bool changed;\n  u64 itmp;\n  u8 xmm[16];\n  i64 j, k, n;\n  int cells, left, cellwidth, panwidth;\n  memcpy(xmm, m->xmm[r], sizeof(xmm));\n  changed = memcmp(xmm, laststate.xmm[r], sizeof(xmm)) != 0;\n  if (changed) AppendPanel(p, i, \"\\033[7m\");\n  left = sprintf(buf, \"XMM%-2\" PRId64 \"\", r);\n  AppendPanel(p, i, buf);\n  cells = GetXmmTypeCellCount(r);\n  panwidth = p->right - p->left;\n  cellwidth = MIN(MAX(0, (panwidth - left) / cells - 1), (int)sizeof(buf) - 1);\n  for (j = 0; j < cells; ++j) {\n    AppendPanel(p, i, \" \");\n    switch (xmmtype.type[r]) {\n      case kXmmFloat:\n        memcpy(&f, xmm + j * sizeof(f), sizeof(f));\n        FormatDouble(buf, f);\n        break;\n      case kXmmDouble:\n        memcpy(&d, xmm + j * sizeof(d), sizeof(d));\n        FormatDouble(buf, d);\n        break;\n      case kXmmIntegral:\n        ival = 0;\n        for (k = 0; k < xmmtype.size[r]; ++k) {\n          itmp = xmm[j * xmmtype.size[r] + k] & 0xff;\n          itmp <<= k * 8;\n          ival |= itmp;\n        }\n        if (xmmdisp == kXmmHex || xmmdisp == kXmmChar) {\n          if (xmmdisp == kXmmChar && iswalnum(ival)) {\n#ifdef __EMSCRIPTEN__\n            // wat: format specifies type 'wint_t' (aka 'int') but the\n            //      argument has type 'wint_t' (aka 'unsigned int')\n            sprintf(buf, \"%lc\", (int)ival);\n#else\n            sprintf(buf, \"%lc\", (wint_t)ival);\n#endif\n          } else {\n            sprintf(buf, \"%.*x\", xmmtype.size[r] * 8 / 4, (unsigned)ival);\n          }\n        } else {\n          sprintf(buf, \"%\" PRId64, SignExtend(ival, xmmtype.size[r] * 8));\n        }\n        break;\n      default:\n        __builtin_unreachable();\n    }\n    buf[cellwidth] = '\\0';\n    AppendPanel(p, i, buf);\n    n = cellwidth - strlen(buf);\n    for (k = 0; k < n; ++k) {\n      AppendPanel(p, i, \" \");\n    }\n  }\n  if (changed) AppendPanel(p, i, \"\\033[27m\");\n}\n\nstatic void DrawSse(struct Panel *p) {\n  i64 i, n;\n  n = p->bottom - p->top;\n  if (n > 0) {\n    for (i = 0; i < MIN(16, n); ++i) {\n      DrawXmm(p, i, i);\n    }\n  }\n}\n\nstatic void ScrollMemoryView(struct Panel *p, struct MemoryView *v, i64 a) {\n  i64 i, n, w;\n  w = DUMPWIDTH * ((u64)1 << v->zoom);\n  n = p->bottom - p->top;\n  i = a / w;\n  if (!(v->start <= i && i < v->start + n)) {\n    v->start = i - n / 4;\n  }\n}\n\nstatic void ZoomMemoryView(struct MemoryView *v, i64 y, i64 x, int dy) {\n  i64 a, b, i, s;\n  s = v->start;\n  a = v->zoom;\n  b = MIN(MAXZOOM, MAX(0, a + dy));\n  i = y * DUMPWIDTH - x;\n  s *= DUMPWIDTH * (1L << a);\n  s += i * (1L << a) - i * (1L << b);\n  s /= DUMPWIDTH * (1L << b);\n  v->zoom = b;\n  v->start = s;\n}\n\nstatic void ScrollMemoryViews(void) {\n  ScrollMemoryView(&pan.code, &codeview, GetPc(m));\n  ScrollMemoryView(&pan.readdata, &readview, readaddr);\n  ScrollMemoryView(&pan.writedata, &writeview, writeaddr);\n  ScrollMemoryView(&pan.stack, &stackview, GetSp());\n}\n\nstatic void ZoomMemoryViews(struct Panel *p, int y, int x, int dy) {\n  if (p == &pan.code) {\n    ZoomMemoryView(&codeview, y, x, dy);\n  } else if (p == &pan.readdata) {\n    ZoomMemoryView(&readview, y, x, dy);\n  } else if (p == &pan.writedata) {\n    ZoomMemoryView(&writeview, y, x, dy);\n  } else if (p == &pan.stack) {\n    ZoomMemoryView(&stackview, y, x, dy);\n  }\n}\n\nstatic void DrawMemoryZoomed(struct Panel *p, struct MemoryView *view,\n                             long histart, long hiend) {\n  bool high, changed;\n  u8 *canvas, *chunk, *invalid;\n  i64 a, b, c, d, n, i, j, k, size;\n  struct ContiguousMemoryRanges ranges;\n  a = view->start * DUMPWIDTH * ((u64)1 << view->zoom);\n  b = (view->start + (p->bottom - p->top)) * DUMPWIDTH * ((u64)1 << view->zoom);\n  size = (p->bottom - p->top) * DUMPWIDTH;\n  canvas = (u8 *)calloc(1, size);\n  invalid = (u8 *)calloc(1, size);\n  memset(&ranges, 0, sizeof(ranges));\n  FindContiguousMemoryRanges(m, &ranges);\n  for (k = i = 0; i < ranges.i; ++i) {\n    if ((a >= ranges.p[i].a && a < ranges.p[i].b) ||\n        (b >= ranges.p[i].a && b < ranges.p[i].b) ||\n        (a < ranges.p[i].a && b >= ranges.p[i].b)) {\n      c = MAX(a, ranges.p[i].a);\n      d = MIN(b, ranges.p[i].b);\n      n = ROUNDUP(d - c, (u64)1 << view->zoom);\n      chunk = (u8 *)malloc(n);\n      CopyFromUser(m, chunk, c, d - c);\n      memset(chunk + (d - c), 0, n - (d - c));\n      for (j = 0; j < view->zoom; ++j) {\n        Magikarp(chunk, n);\n        n >>= 1;\n      }\n      j = (c - a) / ((u64)1 << view->zoom);\n      memset(invalid + k, -1, j - k);\n      memcpy(canvas + j, chunk, MIN(n, size - j));\n      k = j + MIN(n, size - j);\n      free(chunk);\n    }\n  }\n  memset(invalid + k, -1, size - k);\n  free(ranges.p);\n  high = false;\n  for (c = i = 0; i < p->bottom - p->top; ++i) {\n    AppendFmt(&p->lines[i], \"%0*\" PRIx64 \" \", GetAddrHexWidth(),\n              ((view->start + i) * DUMPWIDTH * ((u64)1 << view->zoom)) &\n                  0x0000ffffffffffff);\n    for (j = 0; j < DUMPWIDTH; ++j, ++c) {\n      a = ((view->start + i) * DUMPWIDTH + j + 0) * ((u64)1 << view->zoom);\n      b = ((view->start + i) * DUMPWIDTH + j + 1) * ((u64)1 << view->zoom);\n      changed = ((histart >= a && hiend < b) ||\n                 (histart && hiend && histart >= a && hiend < b));\n      if (changed && !high) {\n        high = true;\n        AppendStr(&p->lines[i], \"\\033[7m\");\n      } else if (!changed && high) {\n        AppendStr(&p->lines[i], \"\\033[27m\");\n        high = false;\n      }\n      if (invalid[c]) {\n        AppendWide(&p->lines[i], L'⋅');\n      } else {\n        AppendWide(&p->lines[i], kCp437[canvas[c]]);\n      }\n    }\n    if (high) {\n      AppendStr(&p->lines[i], \"\\033[27m\");\n      high = false;\n    }\n  }\n  free(invalid);\n  free(canvas);\n}\n\nstatic void DrawMemoryUnzoomed(struct Panel *p, struct MemoryView *view,\n                               i64 histart, i64 hiend) {\n  int c, s, x, sc;\n  i64 i, j, k;\n  bool high, changed;\n  high = false;\n  for (i = 0; i < p->bottom - p->top; ++i) {\n    AppendFmt(&p->lines[i], \"%0*\" PRIx64 \" \", GetAddrHexWidth(),\n              ((view->start + i) * DUMPWIDTH) & 0xffffffffffff);\n    for (j = 0; j < DUMPWIDTH; ++j) {\n      k = (view->start + i) * DUMPWIDTH + j;\n      c = VirtualBing(k);\n      s = VirtualShadow(k);\n      if (s != -1) {\n        if (s == -2) {\n          /* grey for shadow memory */\n          x = 235;\n        } else {\n          sc = (signed char)s;\n          if (sc > 7) {\n            x = 129; /* PURPLE: shadow corruption */\n          } else if (sc == kAsanHeapFree) {\n            x = 20; /* BLUE: heap freed */\n          } else if (sc == kAsanRelocated) {\n            x = 16; /* BLACK: heap relocated */\n          } else if (sc == kAsanHeapUnderrun || sc == kAsanAllocaUnderrun) {\n            x = 53; /* RED+PURPLETINGE: heap underrun */\n          } else if (sc == kAsanHeapOverrun || sc == kAsanAllocaOverrun) {\n            x = 52; /* RED: heap overrun */\n          } else if (sc < 0) {\n            x = 52; /* RED: uncategorized invalid */\n          } else if (sc > 0 && (k & 7) >= sc) {\n            x = 88; /* BRIGHTRED: invalid address (skew) */\n          } else if (!sc || (sc > 0 && (k & 7) < sc)) {\n            x = 22; /* GREEN: valid address */\n          } else {\n            Abort();\n          }\n        }\n        AppendFmt(&p->lines[i], \"\\033[38;5;253;48;5;%dm\", x);\n      }\n      changed = histart <= k && k < hiend;\n      if (changed && !high) {\n        high = true;\n        AppendStr(&p->lines[i], \"\\033[7m\");\n      } else if (!changed && high) {\n        AppendStr(&p->lines[i], \"\\033[27m\");\n        high = false;\n      }\n      AppendWide(&p->lines[i], c);\n      if (s != -1) {\n        AppendStr(&p->lines[i], \"\\033[39;49m\");\n      }\n    }\n    if (high) {\n      AppendStr(&p->lines[i], \"\\033[27m\");\n      high = false;\n    }\n  }\n}\n\nstatic void DrawMemory(struct Panel *p, struct MemoryView *view, i64 histart,\n                       i64 hiend) {\n  if (p->top == p->bottom) return;\n  if (view->zoom) {\n    DrawMemoryZoomed(p, view, histart, hiend);\n  } else {\n    DrawMemoryUnzoomed(p, view, histart, hiend);\n  }\n}\n\nstatic void DrawMaps(struct Panel *p) {\n  int i;\n  char *p1, *p2;\n  if (p->top == p->bottom) return;\n  p1 = FormatPml4t(m);\n  for (i = 0; p1; ++i, p1 = p2) {\n    if ((p2 = strchr(p1, '\\n'))) *p2++ = '\\0';\n    if (i >= mapsstart) {\n      AppendPanel(p, i - mapsstart, p1);\n    }\n  }\n}\n\nstatic void DrawBreakpoints(struct Panel *p) {\n  i64 addr;\n  const char *name;\n  char *s, buf[256];\n  i64 i, sym, line = 0;\n  if (p->top == p->bottom) return;\n  for (i = watchpoints.i; i--;) {\n    if (watchpoints.p[i].disable) continue;\n    if (line >= breakpointsstart) {\n      addr = watchpoints.p[i].addr;\n      sym = DisFindSym(dis, addr);\n      if (!(name = watchpoints.p[i].symbol)) {\n        name = sym != -1 ? dis->syms.p[sym].name : \"UNKNOWN\";\n      }\n      snprintf(buf, sizeof(buf), \"%0*\" PRIx64 \" %s\", GetAddrHexWidth(), addr,\n               name);\n      AppendPanel(p, line - breakpointsstart, buf);\n      if (sym != -1 && addr != dis->syms.p[sym].addr) {\n        snprintf(buf, sizeof(buf), \"+%#\" PRIx64, addr - dis->syms.p[sym].addr);\n        AppendPanel(p, line - breakpointsstart, buf);\n      }\n      snprintf(buf, sizeof(buf), \" [%#\" PRIx64 \"]\", watchpoints.p[i].oldvalue);\n      AppendPanel(p, line - breakpointsstart, buf);\n    }\n    ++line;\n  }\n  for (i = breakpoints.i; i--;) {\n    if (breakpoints.p[i].disable) continue;\n    if (line >= breakpointsstart) {\n      addr = breakpoints.p[i].addr;\n      sym = DisFindSym(dis, addr);\n      if (!(name = breakpoints.p[i].symbol)) {\n        name = sym != -1 ? dis->syms.p[sym].name : \"UNKNOWN\";\n      }\n      if (addr == m->ip) AppendPanel(p, line - breakpointsstart, \"\\033[7m\");\n      s = buf;\n      s += sprintf(s, \"%0*\" PRIx64 \" \", GetAddrHexWidth(), addr);\n      strcpy(s, name);\n      AppendPanel(p, line - breakpointsstart, buf);\n      if (sym != -1 && addr != dis->syms.p[sym].addr) {\n        snprintf(buf, sizeof(buf), \"+%#\" PRIx64, addr - dis->syms.p[sym].addr);\n        AppendPanel(p, line - breakpointsstart, buf);\n      }\n      if (addr == m->ip) AppendPanel(p, line - breakpointsstart, \"\\033[27m\");\n    }\n    ++line;\n  }\n}\n\nstatic int GetPreferredStackAlignmentMask(void) {\n  switch (m->mode.omode) {\n    case XED_MODE_LONG:\n      return 15;\n    case XED_MODE_LEGACY:\n      return 3;\n    case XED_MODE_REAL:\n      return 3;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic void DrawFrames(struct Panel *p) {\n  int i;\n  i64 sym;\n  u8 *r;\n  const char *name;\n  char *s, line[256];\n  i64 sp, bp, rp;\n  if (p->top == p->bottom) return;\n  rp = m->ip;\n  bp = Read64(m->bp);\n  sp = Read64(m->sp);\n  for (i = 0; i < p->bottom - p->top;) {\n    sym = DisFindSym(dis, rp);\n    name = sym != -1 ? dis->syms.p[sym].name : \"UNKNOWN\";\n    s = line;\n    s += sprintf(s, \"%0*\" PRIx64 \" %0*\" PRIx64 \" \", GetAddrHexWidth(),\n                 m->ss.base + bp, GetAddrHexWidth(), rp);\n    s = Demangle(s, name, DIS_MAX_SYMBOL_LENGTH);\n    AppendPanel(p, i - framesstart, line);\n    if (sym != -1 && rp != dis->syms.p[sym].addr) {\n      snprintf(line, sizeof(line), \"+%#\" PRIx64 \"\", rp - dis->syms.p[sym].addr);\n      AppendPanel(p, i - framesstart, line);\n    }\n    if (!bp) break;\n    if (bp < sp) {\n      AppendPanel(p, i - framesstart, \" [STRAY]\");\n    } else if (bp - sp <= 0x1000) {\n      snprintf(line, sizeof(line), \" %\" PRId64 \" bytes\", bp - sp);\n      AppendPanel(p, i - framesstart, line);\n    }\n    if (bp & GetPreferredStackAlignmentMask() && i) {\n      AppendPanel(p, i - framesstart, \" [MISALIGN]\");\n    }\n    ++i;\n    if (((m->ss.base + bp) & 0xfff) > 0xff0) break;\n    if (!(r = SpyAddress(m, m->ss.base + bp))) {\n      AppendPanel(p, i - framesstart, \"CORRUPT FRAME POINTER\");\n      break;\n    }\n    sp = bp;\n    bp = ReadWordSafely(m->mode.omode, r + 0);\n    rp = ReadWordSafely(m->mode.omode, r + 8);\n  }\n}\n\nstatic void CheckFramePointerImpl(void) {\n  u8 *r;\n  i64 bp, rp;\n  static i64 lastbp;\n  bp = Read64(m->bp);\n  if (bp && bp == lastbp) return;\n  lastbp = bp;\n  rp = m->ip;\n  while (bp) {\n    if (!(r = SpyAddress(m, m->ss.base + bp))) {\n      LOGF(\"corrupt frame: %0*\" PRIx64 \"\", GetAddrHexWidth(), bp);\n      ThrowProtectionFault(m);\n    }\n    bp = Read64(r + 0) - 0;\n    rp = Read64(r + 8) - 1;\n    if (!bp && !(m->bofram[0] <= rp && rp <= m->bofram[1])) {\n      LOGF(\"bad frame !(%0*\" PRIx64 \" <= %0*\" PRIx64 \" <= %0*\" PRIx64 \")\",\n           GetAddrHexWidth(), m->bofram[0], GetAddrHexWidth(), rp,\n           GetAddrHexWidth(), m->bofram[1]);\n      ThrowProtectionFault(m);\n    }\n  }\n}\n\nstatic void CheckFramePointer(void) {\n  if (m->bofram[0]) {\n    CheckFramePointerImpl();\n  }\n}\n\nstatic bool IsExecuting(void) {\n  return (action & (CONTINUE | STEP | NEXT | FINISH)) && !(action & MODAL);\n}\n\nstatic int AppendStat(struct Buffer *b, int width, const char *name, i64 value,\n                      bool changed) {\n  char valbuf[27];\n  AppendChar(b, ' ');\n  if (changed) AppendStr(b, \"\\033[31m\");\n  FormatInt64Thousands(valbuf, value);\n  width = AppendFmt(b, \"%*s %s\", width, valbuf, name);\n  if (changed) AppendStr(b, \"\\033[39m\");\n  return 1 + width;\n}\n\nstatic const char *DescribeAction(void) {\n  static char buf[128];\n  char *p = buf;\n  buf[0] = 0;\n  if (action & RESTART) p = stpcpy(buf, \"|RESTART\");\n  if (action & REDRAW) p = stpcpy(p, \"|REDRAW\");\n  if (action & CONTINUE) p = stpcpy(p, \"|CONTINUE\");\n  if (action & STEP) p = stpcpy(p, \"|STEP\");\n  if (action & NEXT) p = stpcpy(p, \"|NEXT\");\n  if (action & FINISH) p = stpcpy(p, \"|FINISH\");\n  if (action & MODAL) p = stpcpy(p, \"|MODAL\");\n  if (action & WINCHED) p = stpcpy(p, \"|WINCHED\");\n  if (action & INT) p = stpcpy(p, \"|INT\");\n  if (action & QUIT) p = stpcpy(p, \"|QUIT\");\n  if (action & EXIT) p = stpcpy(p, \"|EXIT\");\n  if (action & ALARM) p = stpcpy(p, \"|ALARM\");\n  return buf + !!buf[0];\n}\n\nstatic char *GetStatus(int m) {\n  bool once;\n  unsigned i, n;\n  struct timespec now;\n  struct Buffer s = {0};\n  if (statusmessage && CompareTime(GetTime(), statusexpires)) {\n    AppendStr(&s, statusmessage);\n  } else {\n    AppendStr(&s, \"das blinkenlights\");\n  }\n  n = ARRAYLEN(keystrokes.p);\n  for (once = false, now = GetTime(), i = 1; i <= n; --i) {\n    if (!keystrokes.p[(keystrokes.i - i) % n][0] ||\n        CompareTime(SubtractTime(now, keystrokes.s[(keystrokes.i - i) % n]),\n                    FromSeconds(1)) > 0) {\n      break;\n    }\n    if (!once) {\n      AppendStr(&s, \" (keystroke: \");\n      once = true;\n    } else {\n      AppendChar(&s, ' ');\n    }\n    AppendStr(&s, keystrokes.p[(keystrokes.i - i) % n]);\n  }\n  if (once) {\n    AppendChar(&s, ')');\n  }\n  return s.p;\n}\n\nstatic void DrawStatus(struct Panel *p) {\n#define MEMSTAT(f) m->system->memstat.f, m->system->memstat.f != lastmemstat.f\n  char *status;\n  struct Buffer *s;\n  int yn, xn, rw, fds;\n  rw = 0;\n  yn = p->top - p->bottom;\n  xn = p->right - p->left;\n  if (!yn || !xn) return;\n  fds = CountFds(&m->system->fds);\n  s = (struct Buffer *)malloc(sizeof(*s));\n  memset(s, 0, sizeof(*s));\n  rw += AppendStr(s, DescribeAction());\n  rw += AppendStat(s, 12, \"ips\", ips, false);\n  rw += AppendChar(s, ' ');\n  rw += AppendStat(s, 1, \"fds\", fds, fds != lastfds);\n  rw += AppendChar(s, ' ');\n  rw += AppendStat(s, 1, \"rss\", m->system->rss, m->system->rss != lastrss);\n  rw += AppendChar(s, ' ');\n  rw += AppendStat(s, 1, \"vss\", m->system->vss, m->system->vss != lastvss);\n  rw += AppendChar(s, ' ');\n  if (FLAG_nolinear) {\n    rw += AppendStat(s, 1, \"reserve\", MEMSTAT(reserved));\n    rw += AppendChar(s, ' ');\n    rw += AppendStat(s, 1, \"commit\", MEMSTAT(committed));\n    rw += AppendChar(s, ' ');\n  }\n  rw += AppendStat(s, 1, \"tables\", MEMSTAT(tables));\n  status = GetStatus(xn - rw);\n  AppendFmt(&p->lines[0], \"\\033[7m%-*s%s\\033[0m\", xn - rw, status, s->p);\n  free(status);\n  free(s->p);\n  free(s);\n  lastmemstat = m->system->memstat;\n  lastvss = m->system->vss;\n  lastrss = m->system->rss;\n  lastfds = fds;\n#undef MEMSTAT\n}\n\nbool PreventBufferbloat(void) {\n  bool should_write;\n  struct timespec time, rate;\n  static struct timespec last;\n  time = GetTime();\n  rate = FromMicroseconds(1. / FPS * 1e6);\n  if (CompareTime(SubtractTime(time, last), rate) >= 0) {\n    should_write = true;\n    last = time;\n  } else if (TURBO) {\n    should_write = false;\n  } else {\n    SleepTime(SubtractTime(rate, SubtractTime(time, last)));\n    should_write = true;\n    last = time;\n  }\n  return should_write;\n}\n\nstatic void ClearHistory(void) {\n  unsigned i;\n  for (i = 0; i < HISTORY; ++i) {\n    if (g_history.p[i].data) {\n      free(g_history.p[i].data);\n      g_history.p[i].data = 0;\n    }\n  }\n  g_history.viewing = 0;\n  g_history.count = 0;\n}\n\nstatic void AddHistory(const char *ansi, size_t size) {\n  struct Rendering *r;\n  unassert(g_history.count <= HISTORY);\n  if (g_history.count &&\n      g_history.p[(g_history.index - 1) % HISTORY].cycle == cycle) {\n    return;  // execution hasn't advanced yet\n  }\n  if (g_history.count < HISTORY) {\n    ++g_history.count;\n  }\n  r = g_history.p + g_history.index % HISTORY;\n  free(r->data);\n  r->cycle = cycle;\n  r->origsize = size;\n  r->data = Deflate(ansi, size, &r->compsize);\n  ++g_history.index;\n  STATISTIC(AVERAGE(redraw_compressed_bytes, r->compsize));\n  STATISTIC(AVERAGE(redraw_uncompressed_bytes, r->origsize));\n}\n\nstatic void RewindHistory(int delta) {\n  int count = g_history.count;\n  int viewing = g_history.viewing;\n  g_history.viewing = MAX(0, MIN(viewing + delta, count));\n  // skip over the first history entry, since it doesn't feel right to\n  // need to press up arrow twice to see some real history.\n  if (g_history.viewing == 1) {\n    if (delta > 0) {\n      g_history.viewing = 2;\n    } else if (delta < 0) {\n      g_history.viewing = 0;\n    }\n  }\n  g_history.viewing = MIN(g_history.viewing, g_history.count);\n  // clear the crash dialog box if it exists.\n  action &= ~MODAL;\n}\n\n// we need to handle any shutdown via pipeline explicitly\n// because blink always puts SIGPIPE in the SIG_IGN state\nstatic ssize_t HandleEpipe(ssize_t rc) {\n  if (rc == -1 && errno == EPIPE) {\n    LOGF(\"got EPIPE, shutting down\");\n    exit(EXIT_FAILURE_WITH_SIGNAL(EPIPE));\n  }\n  return rc;\n}\n\nstatic void ShowHistory(void) {\n  char *ansi;\n  size_t len, size;\n  char status[1024];\n  struct Rendering *r;\n  unassert(g_history.viewing > 0);\n  unassert(g_history.viewing <= HISTORY);\n  unassert(g_history.viewing <= g_history.count);\n  r = g_history.p + (g_history.index - g_history.viewing) % HISTORY;\n  unassert(r->data);\n  len = snprintf(status, sizeof(status),\n                 \"\\033[7;35;47m\\033[%d;0H\"\n                 \" [ HISTORY %d/%d CYCLE %\" PRIu64 \" ] \"\n                 \"\\033[0m\\033[%d;%dH\",\n                 tyn, g_history.count - (g_history.viewing - 1),\n                 g_history.count, r->cycle, tyn, txn);\n  unassert(len < sizeof(status));\n  size = r->origsize + len;\n  unassert(ansi = (char *)malloc(size));\n  Inflate(ansi, r->origsize, r->data, r->compsize);\n  memcpy(ansi + r->origsize, status, len);\n  if (PreventBufferbloat()) {\n    HandleEpipe(UninterruptibleWrite(ttyout, ansi, size));\n  }\n  free(ansi);\n}\n\nvoid Redraw(bool force) {\n  int i, j;\n  char *ansi;\n  size_t size;\n  double execsecs;\n  struct timespec start_draw, end_draw;\n  if (displayexec) return;\n  if (g_history.viewing) {\n    ShowHistory();\n    return;\n  }\n  LookupAddress(m, m->ip);         // want page fault\n  LookupAddress(m, Get64(m->sp));  // want page fault\n  BEGIN_NO_PAGE_FAULTS;\n  start_draw = GetTime();\n  execsecs = ToNanoseconds(SubtractTime(start_draw, last_draw)) * 1e-9;\n  ips = last_cycle ? (cycle - last_cycle) / execsecs : 0;\n  SetupDraw();\n  ScrollOp(&pan.disassembly, GetDisIndex());\n  for (i = 0; i < ARRAYLEN(pan.p); ++i) {\n    for (j = 0; j < pan.p[i].bottom - pan.p[i].top; ++j) {\n      pan.p[i].lines[j].i = 0;\n    }\n  }\n  DrawDisassembly(&pan.disassembly);\n  DrawDisplay(&pan.display);\n  DrawCpu(&pan.registers);\n  DrawSse(&pan.sse);\n  DrawHr(&pan.breakpointshr, \"BREAKPOINTS\");\n  DrawHr(&pan.mapshr, \"PML4T\");\n  if (showprofile) {\n    DrawHr(&pan.frameshr, \"PROFILE\");\n  } else if (m->bofram[0]) {\n    DrawHr(&pan.frameshr, \"PROTECTED FRAMES\");\n  } else {\n    DrawHr(&pan.frameshr, \"FRAMES\");\n  }\n  DrawHr(&pan.ssehr, \"SSE\");\n  DrawHr(&pan.codehr, \"CODE\");\n  DrawHr(&pan.readhr, \"READ\");\n  DrawHr(&pan.writehr, \"WRITE\");\n  DrawHr(&pan.stackhr, \"STACK\");\n  DrawMaps(&pan.maps);\n  if (showprofile) {\n    DrawProfile(&pan.frames);\n  } else {\n    DrawFrames(&pan.frames);\n  }\n  DrawBreakpoints(&pan.breakpoints);\n  DrawMemory(&pan.code, &codeview, GetPc(m), GetPc(m) + m->xedd->length);\n  DrawMemory(&pan.readdata, &readview, readaddr, readaddr + readsize);\n  DrawMemory(&pan.writedata, &writeview, writeaddr, writeaddr + writesize);\n  DrawMemory(&pan.stack, &stackview, GetSp(), GetSp() + GetPointerWidth());\n  DrawStatus(&pan.status);\n  unassert(ansi = RenderPanels(ARRAYLEN(pan.p), pan.p, tyn, txn, &size));\n  END_NO_PAGE_FAULTS;\n  end_draw = GetTime();\n  (void)end_draw;\n  STATISTIC(AVERAGE(redraw_latency_us,\n                    ToMicroseconds(SubtractTime(end_draw, start_draw))));\n  if (force || PreventBufferbloat()) {\n    HandleEpipe(UninterruptibleWrite(ttyout, ansi, size));\n  }\n  AddHistory(ansi, size);\n  free(ansi);\n  last_cycle = cycle;\n  last_draw = GetTime();\n}\n\nvoid ReactiveDraw(void) {\n  if (tuimode) {\n    // LOGF(\"%\" PRIx64 \" %s ReactiveDraw\", GetPc(m), tuimode ? \"TUI\" : \"EXEC\");\n    Redraw(true);\n    tick = speed;\n  }\n}\n\nstatic void DescribeKeystroke(char *b, const char *p) {\n  int c;\n  do {\n    c = *p++ & 255;\n    if (c == '\\033') {\n      b = stpcpy(b, \"ALT-\");\n      c = *p++ & 255;\n    }\n    if (c <= 32) {\n      b = stpcpy(b, \"CTRL-\");\n      c = Ctrl(c);\n    }\n    *b++ = c;\n    *b = 0;\n  } while (*p);\n}\n\nstatic void SetStatusDeadline(void) {\n  struct itimerval it;\n  statusexpires = AddTime(GetTime(), FromSeconds(1));\n  it.it_interval.tv_sec = 0;\n  it.it_interval.tv_usec = 0;\n  it.it_value.tv_sec = 1;\n  it.it_value.tv_usec = 0;\n  setitimer(ITIMER_REAL, &it, 0);\n}\n\nstatic void RecordKeystroke(const char *k) {\n  if (!strchr(k, '[')) {\n    keystrokes.s[keystrokes.i] = GetTime();\n    DescribeKeystroke(keystrokes.p[keystrokes.i], k);\n    keystrokes.i = (keystrokes.i + 1) % ARRAYLEN(keystrokes.p);\n    ReactiveDraw();\n    SetStatusDeadline();\n  }\n}\n\nstatic void HandleAlarm(void) {\n  alarmed = false;\n  action &= ~ALARM;\n  pty->conf &= ~kPtyBell;\n  free(statusmessage);\n  statusmessage = NULL;\n}\n\nstatic void HandleTerminalResize(void) {\n  GetTtySize(ttyout);\n  ClearHistory();\n  dis->ops.i = 0;\n}\n\nvoid HandleAppReadInterrupt(bool errflag) {\n  LOGF(\"HandleAppReadInterrupt\");\n  if (errflag) {\n    exitcode = 0;\n    action |= EXIT;\n  }\n  if (action & ALARM) {\n    HandleAlarm();\n  }\n  if (action & WINCHED) {\n    HandleTerminalResize();\n    action &= ~WINCHED;\n  }\n  if (action & INT) {\n    action &= ~INT;\n    RecordKeystroke(\"\\3\");\n    ReactiveDraw();\n    if (action & CONTINUE) {\n      action &= ~CONTINUE;\n    } else {\n      tuimode = true;\n      displayexec = false;\n    }\n  }\n}\n\nstatic int OnPtyFdClose(int fd) {\n  return VfsClose(fd);\n}\n\nstatic bool HasPendingInput(int fd) {\n  struct pollfd fds[1];\n  fds[0].fd = fd;\n  fds[0].events = POLLIN;\n  fds[0].revents = 0;\n  VfsPoll(fds, ARRAYLEN(fds), 0);\n  return fds[0].revents & (POLLIN | POLLERR);\n}\n\nstatic struct Panel *LocatePanel(int y, int x) {\n  int i;\n  for (i = 0; i < ARRAYLEN(pan.p); ++i) {\n    if ((pan.p[i].left <= x && x < pan.p[i].right) &&\n        (pan.p[i].top <= y && y < pan.p[i].bottom)) {\n      return &pan.p[i];\n    }\n  }\n  return 0;\n}\n\nstatic struct Mouse ParseMouse(char *p) {\n  int e, x, y;\n  struct Mouse m;\n  e = strtol(p, &p, 10);\n  if (*p == ';') ++p;\n  x = strtol(p, &p, 10);\n  x = MIN(txn, MAX(1, x)) - 1;\n  if (*p == ';') ++p;\n  y = strtol(p, &p, 10);\n  y = MIN(tyn, MAX(1, y)) - 1;\n  e |= (*p == 'm') << 2;\n  m.y = y;\n  m.x = x;\n  m.e = e;\n  return m;\n}\n\nssize_t ReadAnsi(int fd, char *p, size_t n) {\n  ssize_t rc;\n  struct Mouse mo;\n  for (;;) {\n    LOGF(\"%\" PRIx64 \" %s ReadAnsi\", GetPc(m), tuimode ? \"TUI\" : \"EXEC\");\n    readingteletype = true;\n    ReactiveDraw();\n    rc = readansi(fd, p, n);\n    readingteletype = false;\n    if (rc != -1) {\n      if (tuimode && rc > 3 && p[0] == '\\033' && p[1] == '[') {\n        if (p[2] == '2' && p[3] == '0' && p[4] == '0' && p[5] == '~') {\n          belay = true;\n          continue;\n        }\n        if (p[2] == '2' && p[3] == '0' && p[4] == '1' && p[5] == '~') {\n          belay = false;\n          continue;\n        }\n        if (p[2] == '<') {\n          mo = ParseMouse(p + 3);\n          if (LocatePanel(mo.y, mo.x) != &pan.display) {\n            HandleKeyboard(p);\n            continue;\n          }\n        }\n      }\n      return rc;\n    } else {\n      unassert(errno == EINTR);\n      HandleAppReadInterrupt(false);\n      return eintr();\n    }\n  }\n}\n\nstatic ssize_t ReadPtyFdDirect(int fd) {\n  ssize_t rc;\n  char buf[32];\n  LOGF(\"ReadPtyFdDirect\");\n  pty->conf |= kPtyBlinkcursor;\n  do {\n    rc = ReadAnsi(fd, buf, sizeof(buf));\n  } while (rc == -1 && errno == EINTR);\n  pty->conf &= ~kPtyBlinkcursor;\n  if (rc > 0) {\n    PtyWriteInput(pty, buf, rc);\n    ReactiveDraw();\n    rc = 0;\n  }\n  return rc;\n}\n\nstatic ssize_t OnPtyFdReadv(int fd, const struct iovec *iov, int iovlen) {\n  int i;\n  ssize_t rc;\n  void *data;\n  size_t size;\n  ptyisenabled = true;\n  for (size = i = 0; i < iovlen; ++i) {\n    if (iov[i].iov_len) {\n      data = iov[i].iov_base;\n      size = iov[i].iov_len;\n      break;\n    }\n  }\n  if (size) {\n    for (;;) {\n      if ((rc = PtyRead(pty, data, size))) {\n        return rc;\n      }\n      if (ReadPtyFdDirect(fd) == -1) {\n        return -1;\n      }\n    }\n  } else {\n    return 0;\n  }\n}\n\nstatic int OnPtyFdPoll(struct pollfd *fds, nfds_t nfds, int ms) {\n  nfds_t i;\n  int t, re;\n  bool once;\n  struct pollfd p2;\n  ms &= INT_MAX;\n  ptyisenabled = true;\n  for (once = false, t = i = 0; i < nfds; ++i) {\n    re = 0;\n    if (fds[i].fd >= 0) {\n      if (pty->input.i) {\n        re = POLLIN | POLLOUT;\n        ++t;\n      } else {\n        if (!once) {\n          ReactiveDraw();\n          once = true;\n        }\n        p2.fd = fds[i].fd;\n        p2.events = fds[i].events;\n        switch (VfsPoll(&p2, 1, ms)) {\n          case -1:\n            re = POLLERR;\n            ++t;\n            break;\n          case 0:\n            break;\n          case 1:\n            re = p2.revents;\n            ++t;\n            break;\n          default:\n            __builtin_unreachable();\n        }\n      }\n    }\n    fds[i].revents = re;\n  }\n  return t;\n}\n\nvoid DrawDisplayOnly(void) {\n  struct Panel *p;\n  int i, y, yn, xn, tly, tlx;\n  struct Buffer b;\n  char buf[64];\n  p = &pan.display;\n  yn = MIN(tyn, p->bottom - p->top);\n  xn = MIN(txn, p->right - p->left);\n  for (i = 0; i < yn; ++i) {\n    p->lines[i].i = 0;\n  }\n  DrawDisplay(p);\n  memset(&b, 0, sizeof(b));\n  if (displayexec) {\n    tly = tyn / 2 - yn / 2;\n    tlx = txn / 2 - xn / 2;\n  } else {\n    tly = p->top;\n    tlx = p->left;\n  }\n  AppendStr(&b, \"\\033[0m\\033[H\");\n  for (y = 0; y < tyn; ++y) {\n    if (displayexec && y) AppendStr(&b, \"\\r\\n\");\n    if (tly <= y && y < tly + yn) {\n      if (!displayexec) {\n        sprintf(buf, \"\\033[%d;%dH\", y + 1, tlx + 1);\n        AppendStr(&b, buf);\n      } else {\n        for (i = 0; i < tlx; ++i) {\n          AppendChar(&b, ' ');\n        }\n      }\n      // FIXME truncate on right side, should use RenderPanel\n      AppendData(&b, p->lines[y - tly].p, p->lines[y - tly].i);\n    }\n    AppendStr(&b, \"\\033[0m\");\n    if (displayexec) AppendStr(&b, \"\\033[K\");\n  }\n  UninterruptibleWrite(ttyout, b.p, b.i);\n  free(b.p);\n}\n\nstatic ssize_t OnPtyFdWritev(int fd, const struct iovec *iov, int iovlen) {\n  int i;\n  size_t size;\n  if (!ptyisenabled) {\n    ptyisenabled = true;\n    ReactiveDraw();\n  }\n  for (size = i = 0; i < iovlen; ++i) {\n    PtyWrite(pty, iov[i].iov_base, iov[i].iov_len);\n    size += iov[i].iov_len;\n  }\n  return size;\n}\n\nstatic int OnPtyFdTiocgwinsz(int fd, struct winsize *ws) {\n  ws->ws_row = pty->yn;\n  ws->ws_col = pty->xn;\n  return 0;\n}\n\nstatic int OnPtyFdTiocswinsz(int fd, const struct winsize *ws) {\n  return 0;\n}\n\nstatic int OnPtyFdTcsets(int fd, u64 request, struct termios *c) {\n  return 0;\n}\n\nstatic int OnPtyTcgetattr(int fd, struct termios *c) {\n  // TODO(jart): We should just use the Linux ABI for these.\n  memset(c, 0, sizeof(*c));\n  c->c_iflag = ICRNL | IXON\n#ifdef IUTF8\n               | IUTF8\n#endif\n      ;\n  c->c_oflag = 0\n#ifdef ONLCR\n               | ONLCR\n#endif\n      ;\n  c->c_cflag = CREAD | CS8;\n  c->c_lflag = ISIG | ECHOE | IEXTEN | ECHOK\n#ifdef ECHOCTL\n               | ECHOCTL\n#endif\n#ifdef ECHOKE\n               | ECHOKE\n#endif\n      ;\n  c->c_cc[VMIN] = 1;\n  c->c_cc[VTIME] = 0;\n  c->c_cc[VINTR] = Ctrl('C');\n  c->c_cc[VQUIT] = Ctrl('\\\\');\n  c->c_cc[VERASE] = Ctrl('?');\n  c->c_cc[VKILL] = Ctrl('U');\n  c->c_cc[VEOF] = Ctrl('D');\n  c->c_cc[VSTART] = Ctrl('Q');\n  c->c_cc[VSTOP] = Ctrl('S');\n  c->c_cc[VSUSP] = Ctrl('Z');\n  c->c_cc[VEOL] = Ctrl('@');\n#ifdef VSWTC\n  c->c_cc[VSWTC] = Ctrl('@');\n#endif\n#ifdef VREPRINT\n  c->c_cc[VREPRINT] = Ctrl('R');\n#endif\n#ifdef VDISCARD\n  c->c_cc[VDISCARD] = Ctrl('O');\n#endif\n#ifdef VWERASE\n  c->c_cc[VWERASE] = Ctrl('W');\n#endif\n#ifdef VLNEXT\n  c->c_cc[VLNEXT] = Ctrl('V');\n#endif\n#ifdef VEOL2\n  c->c_cc[VEOL2] = Ctrl('@');\n#endif\n  if (!(pty->conf & kPtyNocanon)) c->c_iflag |= ICANON;\n  if (!(pty->conf & kPtyNoecho)) c->c_iflag |= ECHO;\n  if (!(pty->conf & kPtyNoopost)) c->c_oflag |= OPOST;\n  return 0;\n}\n\nstatic int OnPtyTcsetattr(int fd, int cmd, const struct termios *c) {\n  if (c->c_iflag & ICANON) {\n    pty->conf &= ~kPtyNocanon;\n  } else {\n    pty->conf |= kPtyNocanon;\n  }\n  if (c->c_iflag & ECHO) {\n    pty->conf &= ~kPtyNoecho;\n  } else {\n    pty->conf |= kPtyNoecho;\n  }\n  if (c->c_oflag & OPOST) {\n    pty->conf &= ~kPtyNoopost;\n  } else {\n    pty->conf |= kPtyNoopost;\n  }\n  return 0;\n}\n\nstatic const struct FdCb kFdCbPty = {\n    .close = OnPtyFdClose,\n    .readv = OnPtyFdReadv,\n    .writev = OnPtyFdWritev,\n    .poll = OnPtyFdPoll,\n    .tcgetattr = OnPtyTcgetattr,\n    .tcsetattr = OnPtyTcsetattr,\n    .tcgetwinsize = OnPtyFdTiocgwinsz,\n    .tcsetwinsize = OnPtyFdTiocswinsz,\n};\n\nstatic void LaunchDebuggerReactively(void) {\n  LOGF(\"LaunchDebuggerReactively\");\n  LOGF(\"%s\", systemfailure);\n  action &= ~CONTINUE;\n  if (tuimode) {\n    action |= MODAL;\n  } else {\n    if (react) {\n      tuimode = true;\n      action |= MODAL;\n    } else {\n      fprintf(stderr, \"ERROR: %s\\n\", systemfailure);\n      exit(EXIT_FAILURE);\n    }\n  }\n}\n\nstatic void OnDebug(void) {\n  strcpy(systemfailure, \"IT'S A TRAP\");\n  LaunchDebuggerReactively();\n}\n\nstatic void OnExitTrap(void) {\n  tuimode = true;\n  action |= MODAL;\n  action &= ~CONTINUE;\n  exitcode = m->system->exitcode;\n  snprintf(systemfailure, sizeof(systemfailure), \"guest called exit_group(%d)\",\n           exitcode);\n}\n\nstatic void OnSegmentationFault(void) {\n  snprintf(systemfailure, sizeof(systemfailure),\n           \"SEGMENTATION FAULT %0*\" PRIx64, GetAddrHexWidth(), m->faultaddr);\n  LaunchDebuggerReactively();\n}\n\nstatic void OnProtectionFault(void) {\n  strcpy(systemfailure, \"PROTECTION FAULT\");\n  LaunchDebuggerReactively();\n}\n\nstatic void OnSimdException(void) {\n  strcpy(systemfailure, \"SIMD FAULT\");\n  LaunchDebuggerReactively();\n}\n\nstatic void OnUndefinedInstruction(void) {\n  strcpy(systemfailure, \"UNDEFINED INSTRUCTION\");\n  LaunchDebuggerReactively();\n}\n\nstatic void OnDecodeError(void) {\n  stpcpy(systemfailure, \"INSTRUCTION DECODE ERROR\");\n  LaunchDebuggerReactively();\n}\n\nstatic void OnDivideError(void) {\n  strcpy(systemfailure, \"DIVIDE BY ZERO OR BANE\");\n  LaunchDebuggerReactively();\n}\n\nstatic void OnFpuException(void) {\n  strcpy(systemfailure, \"FPU EXCEPTION\");\n  LaunchDebuggerReactively();\n}\n\nstatic void OnExit(int rc) {\n  if (tuimode) {\n    action |= MODAL;\n    action &= ~CONTINUE;\n  } else {\n    action |= EXIT;\n  }\n  exitcode = rc;\n  if (rc == kMachineHalt) {\n    strcpy(systemfailure, \"SYSTEM HALTED\");\n  } else {\n    snprintf(systemfailure, sizeof(systemfailure), \"UNHANDLED INTERRUPT %#x\",\n             rc);\n  }\n}\n\nbool HasPendingKeyboard(void) {\n  return HasPendingInput(ttyin);\n}\n\nstatic bool OnHalt(int interrupt) {\n  SYS_LOGF(\"%\" PRIx64 \" %s OnHalt(%#x)\", GetPc(m), tuimode ? \"TUI\" : \"EXEC\",\n           interrupt);\n  if (interrupt >= 0) m->oplen = 0;\n  ReactiveDraw();\n  if (OnCallBios(interrupt)) {\n    return true;\n  }\n  switch (interrupt) {\n    case 1:\n    case 3:\n      OnDebug();\n      return false;\n    case kMachineEscape:\n      return true;\n    case kMachineSegmentationFault:\n      OnSegmentationFault();\n      return true;\n    case kMachineProtectionFault:\n      OnProtectionFault();\n      return true;\n    case kMachineSimdException:\n      OnSimdException();\n      return true;\n    case kMachineUndefinedInstruction:\n      OnUndefinedInstruction();\n      return true;\n    case kMachineDecodeError:\n      OnDecodeError();\n      return true;\n    case 0:\n    case kMachineDivideError:\n      OnDivideError();\n      return true;\n    case kMachineFpuException:\n      OnFpuException();\n      return true;\n    case kMachineExitTrap:\n      OnExitTrap();\n      return true;\n    case kMachineHalt:\n    default:\n      OnExit(interrupt);\n      return false;\n  }\n}\n\nstatic void OnBinbase(struct Machine *m) {\n  int i;\n  i64 skew;\n  skew = m->xedd->op.disp * 512;\n  LOGF(\"skew binbase %\" PRId64 \" @ %0*\" PRIx64 \"\", skew, GetAddrHexWidth(),\n       GetPc(m));\n  for (i = 0; i < dis->syms.i; ++i) dis->syms.p[i].addr += skew;\n  for (i = 0; i < dis->loads.i; ++i) dis->loads.p[i].addr += skew;\n  for (i = 0; i < breakpoints.i; ++i) breakpoints.p[i].addr += skew;\n  Disassemble();\n}\n\nstatic void OnLongBranch(struct Machine *m) {\n  if (tuimode) {\n    Disassemble();\n  }\n}\n\n#ifndef DISABLE_ROM\nstatic void OnRomWriteAttempt(struct Machine *m, u8 *r) {\n  int w = GetAddrHexWidth();\n  (void)w;\n  LOGF(\"attempt to write to rom address %0*tx @ %0*\" PRIx64, w,\n       r - m->system->real, w, GetPc(m));\n}\n#endif\n\nstatic void SetStatus(const char *fmt, ...) {\n  char *s;\n  va_list va;\n  va_start(va, fmt);\n  unassert(vasprintf(&s, fmt, va) >= 0);\n  va_end(va);\n  free(statusmessage);\n  statusmessage = s;\n  SetStatusDeadline();\n}\n\nstatic int ClampSpeed(int s) {\n  return MAX(-0x1000, MIN(0x40000000, s));\n}\n\nstatic void OnTurbo(void) {\n  if (!speed || speed == -1) {\n    speed = 1;\n  } else if (speed > 0) {\n    speed = ClampSpeed(speed << 1);\n  } else {\n    speed = ClampSpeed(speed >> 1);\n  }\n  SetStatus(\"speed %d\", speed);\n}\n\nstatic void OnSlowmo(void) {\n  if (!speed || speed == 1) {\n    speed = -1;\n  } else if (speed > 0) {\n    speed = ClampSpeed(speed >> 1);\n  } else {\n    speed = ClampSpeed(speed << 1);\n  }\n  SetStatus(\"speed %d\", speed);\n}\n\nstatic void OnUpArrow(void) {\n  RewindHistory(+1);\n}\n\nstatic void OnDownArrow(void) {\n  RewindHistory(-1);\n}\n\nstatic void OnPageUp(void) {\n  RewindHistory(+100);\n}\n\nstatic void OnPageDown(void) {\n  RewindHistory(-100);\n}\n\nstatic void OnHome(void) {\n  RewindHistory(+g_history.count);\n}\n\nstatic void OnEnd(void) {\n  RewindHistory(-g_history.count);\n}\n\nstatic void OnEnter(void) {\n  dialog = NULL;\n  action &= ~MODAL;\n  m->faultaddr = 0;\n}\n\nstatic void OnUp(void) {\n}\n\nstatic void OnDown(void) {\n}\n\nstatic void OnStep(void) {\n  if (action & MODAL) return;\n  action |= STEP;\n  action &= ~NEXT;\n  action &= ~FINISH;\n  action &= ~CONTINUE;\n}\n\nstatic void OnNext(void) {\n  if (action & MODAL) return;\n  action ^= NEXT;\n  action &= ~STEP;\n  action &= ~FINISH;\n  action &= ~CONTINUE;\n}\n\nstatic void OnFinish(void) {\n  if (action & MODAL) return;\n  action ^= FINISH;\n  action &= ~NEXT;\n  action &= ~MODAL;\n  action &= ~CONTINUE;\n}\n\nstatic void OnContinueTui(void) {\n  action ^= CONTINUE;\n  action &= ~STEP;\n  action &= ~NEXT;\n  action &= ~FINISH;\n  action &= ~MODAL;\n}\n\nstatic void OnContinueExec(void) {\n  tuimode = false;\n  action |= CONTINUE;\n  action &= ~STEP;\n  action &= ~NEXT;\n  action &= ~FINISH;\n  action &= ~MODAL;\n}\n\nstatic void OnInt(void) {\n  action |= INT;\n}\n\nstatic void OnRestart(void) {\n  action |= RESTART;\n}\n\nstatic void OnXmmType(void) {\n  u8 t;\n  unsigned i;\n  t = CycleXmmType(xmmtype.type[0]);\n  for (i = 0; i < 16; ++i) {\n    xmmtype.type[i] = t;\n  }\n}\n\nstatic void SetXmmSize(int bytes) {\n  unsigned i;\n  for (i = 0; i < 16; ++i) {\n    xmmtype.size[i] = bytes;\n  }\n}\n\nstatic void SetXmmDisp(int disp) {\n  xmmdisp = disp;\n}\n\nstatic void OnXmmSize(void) {\n  SetXmmSize(CycleXmmSize(xmmtype.size[0]));\n}\n\nstatic void OnXmmDisp(void) {\n  SetXmmDisp(CycleXmmDisp(xmmdisp));\n}\n\nstatic void Sleep(int ms) {\n  VfsPoll((struct pollfd[]){{ttyin, POLLIN}}, 1, ms);\n}\n\nstatic void OnMouseWheelUp(struct Panel *p, int y, int x) {\n  if (p == &pan.disassembly) {\n    RewindHistory(+WHEELDELTA);\n  } else if (p == &pan.code) {\n    codeview.start -= WHEELDELTA;\n  } else if (p == &pan.readdata) {\n    readview.start -= WHEELDELTA;\n  } else if (p == &pan.writedata) {\n    writeview.start -= WHEELDELTA;\n  } else if (p == &pan.stack) {\n    stackview.start -= WHEELDELTA;\n  } else if (p == &pan.maps) {\n    mapsstart = MAX(0, mapsstart - 1);\n  } else if (p == &pan.frames) {\n    framesstart = MAX(0, framesstart - 1);\n  } else if (p == &pan.breakpoints) {\n    breakpointsstart = MAX(0, breakpointsstart - 1);\n  }\n}\n\nstatic void OnMouseWheelDown(struct Panel *p, int y, int x) {\n  if (p == &pan.disassembly) {\n    RewindHistory(-WHEELDELTA);\n  } else if (p == &pan.code) {\n    codeview.start += WHEELDELTA;\n  } else if (p == &pan.readdata) {\n    readview.start += WHEELDELTA;\n  } else if (p == &pan.writedata) {\n    writeview.start += WHEELDELTA;\n  } else if (p == &pan.stack) {\n    stackview.start += WHEELDELTA;\n  } else if (p == &pan.maps) {\n    mapsstart += 1;\n  } else if (p == &pan.frames) {\n    framesstart += 1;\n  } else if (p == &pan.breakpoints) {\n    breakpointsstart += 1;\n  }\n}\n\nstatic void OnMouseCtrlWheelUp(struct Panel *p, int y, int x) {\n  ZoomMemoryViews(p, y, x, -1);\n}\n\nstatic void OnMouseCtrlWheelDown(struct Panel *p, int y, int x) {\n  ZoomMemoryViews(p, y, x, +1);\n}\n\nstatic void OnMouse(const char *p) {\n  int e, x, y;\n  struct Panel *ep;\n  e = strtol(p, (char **)&p, 10);\n  if (*p == ';') ++p;\n  x = strtol(p, (char **)&p, 10);\n  x = MIN(txn, MAX(1, x)) - 1;\n  if (*p == ';') ++p;\n  y = strtol(p, (char **)&p, 10);\n  y = MIN(tyn, MAX(1, y)) - 1;\n  e |= (*p == 'm') << 2;\n  if ((ep = LocatePanel(y, x))) {\n    y -= ep->top;\n    x -= ep->left;\n    switch (e) {\n      case kMouseWheelUp:\n        if (!natural) {\n          OnMouseWheelUp(ep, y, x);\n        } else {\n          OnMouseWheelDown(ep, y, x);\n        }\n        break;\n      case kMouseWheelDown:\n        if (!natural) {\n          OnMouseWheelDown(ep, y, x);\n        } else {\n          OnMouseWheelUp(ep, y, x);\n        }\n        break;\n      case kMouseCtrlWheelUp:\n        if (!natural) {\n          OnMouseCtrlWheelUp(ep, y, x);\n        } else {\n          OnMouseCtrlWheelDown(ep, y, x);\n        }\n        break;\n      case kMouseCtrlWheelDown:\n        if (!natural) {\n          OnMouseCtrlWheelDown(ep, y, x);\n        } else {\n          OnMouseCtrlWheelUp(ep, y, x);\n        }\n        break;\n      default:\n        break;\n    }\n  }\n}\n\nstatic void OnHelp(void) {\n  dialog = dialog == kHelp ? NULL : kHelp;\n}\n\nstatic void HandleKeyboard(const char *k) {\n  const char *p = k;\n  switch (*p++) {\n    CASE('q', OnQ());\n    CASE('v', OnV());\n    CASE('?', OnHelp());\n    CASE('s', OnStep());\n    CASE('n', OnNext());\n    CASE('f', OnFinish());\n    CASE('c', OnContinueTui());\n    CASE('C', displayexec = false; OnContinueExec());\n    CASE('D', displayexec = true; OnContinueExec());\n    CASE('R', OnRestart());\n    CASE('x', OnXmmDisp());\n    CASE('t', OnXmmType());\n    CASE('T', OnXmmSize());\n    CASE('u', OnUp());\n    CASE('d', OnDown());\n    CASE('V', ++verbose);\n    CASE('p', showprofile = !showprofile);\n    CASE('b', BreakAtCurrentInstruction());\n    CASE('B', PopBreakpoint(&breakpoints));\n    CASE('M', ToggleMouseTracking());\n    CASE('\\r', OnEnter());\n    CASE('\\n', OnEnter());\n    CASE('2', showcolumn2 = !showcolumn2);\n    CASE('3', showcolumn3 = !showcolumn3);\n    CASE(Ctrl('C'), OnInt());\n    CASE(Ctrl('D'), action |= EXIT);\n    CASE(Ctrl('\\\\'), raise(SIGQUIT));\n    CASE(Ctrl('Z'), raise(SIGSTOP));\n    CASE(Ctrl('L'), OnFeed());\n    CASE(Ctrl('P'), OnUpArrow());\n    CASE(Ctrl('N'), OnDownArrow());\n    CASE(Ctrl('V'), OnPageDown());\n    CASE(Ctrl('T'), OnTurbo());\n    case 033:\n      switch (*p++) {\n        CASE('v', OnPageUp()); /* alt+v */\n        CASE('t', OnSlowmo()); /* alt+t */\n        case 'O':\n          switch (*p++) {\n            CASE('P', OnHelp()); /* \\033OP is F1 */\n            default:\n              break;\n          }\n          break;\n        case '[':\n          switch (*p++) {\n            CASE('<', OnMouse(p));\n            CASE('A', OnUpArrow());   /* \\e[A  is up */\n            CASE('B', OnDownArrow()); /* \\e[B  is down */\n            CASE('F', OnEnd());       /* \\e[F  is end */\n            CASE('H', OnHome());      /* \\e[H  is home */\n            CASE('1', OnHome());      /* \\e[1~ is home */\n            CASE('4', OnEnd());       /* \\e[1~ is end */\n            CASE('5', OnPageUp());    /* \\e[1~ is pgup */\n            CASE('6', OnPageDown());  /* \\e[1~ is pgdn */\n            default:\n              break;\n          }\n          break;\n        default:\n          break;\n      }\n      break;\n    default:\n      break;\n  }\n  RecordKeystroke(k);\n}\n\nstatic void ReadKeyboard(void) {\n  char buf[64];\n  memset(buf, 0, sizeof(buf));\n  if (readansi(ttyin, buf, sizeof(buf)) == -1) {\n    if (errno == EINTR) {\n      LOGF(\"ReadKeyboard interrupted\");\n      return;\n    }\n    fprintf(stderr, \"ReadKeyboard failed: %s\\n\", DescribeHostErrno(errno));\n    exit(EXIT_FAILURE);\n  }\n  HandleKeyboard(buf);\n}\n\nstatic i64 ParseHexValue(const char *s) {\n  char *ep;\n  i64 x;\n  x = strtoll(s, &ep, 16);\n  if (*ep) {\n    fputs(\"ERROR: bad hexadecimal: \", stderr);\n    fputs(s, stderr);\n    fputc('\\n', stderr);\n    exit(EXIT_FAILURE);\n  }\n  return x;\n}\n\nstatic void HandleBreakpointFlag(const char *s) {\n  struct Breakpoint b;\n  memset(&b, 0, sizeof(b));\n  if (isdigit(*s)) {\n    b.addr = ParseHexValue(s);\n  } else {\n    b.symbol = optarg_;\n  }\n  PushBreakpoint(&breakpoints, &b);\n}\n\nstatic void HandleWatchpointFlag(const char *s) {\n  struct Watchpoint b;\n  memset(&b, 0, sizeof(b));\n  if (isdigit(*s)) {\n    b.addr = ParseHexValue(s);\n  } else {\n    b.symbol = optarg_;\n  }\n  PushWatchpoint(&watchpoints, &b);\n}\n\n_Noreturn static void PrintUsage(int rc, FILE *f) {\n  fprintf(f, \"SYNOPSIS\\n\\n  %s%s\", \"blink\", USAGE);\n  exit(rc);\n}\n\nstatic void LogInstruction(void) {\n  LOGF(\"EXEC %8\" PRIx64 \" SP %012\" PRIx64 \" AX %016\" PRIx64 \" CX %016\" PRIx64\n       \" DX %016\" PRIx64 \" BX %016\" PRIx64 \" BP %016\" PRIx64 \" SI %016\" PRIx64\n       \" DI %016\" PRIx64 \" R8 %016\" PRIx64 \" R9 %016\" PRIx64 \" R10 %016\" PRIx64\n       \" R11 %016\" PRIx64 \" R12 %016\" PRIx64 \" R13 %016\" PRIx64\n       \" R14 %016\" PRIx64 \" R15 %016\" PRIx64 \" FS %012\" PRIx64\n       \" GS %012\" PRIx64,\n       m->ip, Get64(m->sp) & 0xffffffffffff, Get64(m->ax), Get64(m->cx),\n       Get64(m->dx), Get64(m->bx), Get64(m->bp), Get64(m->si), Get64(m->di),\n       Get64(m->r8), Get64(m->r9), Get64(m->r10), Get64(m->r11), Get64(m->r12),\n       Get64(m->r13), Get64(m->r14), Get64(m->r15), m->fs.base & 0xffffffffffff,\n       m->gs.base & 0xffffffffffff);\n}\n\nstatic void EnterWatchpoint(long bp) {\n  LOGF(\"WATCHPOINT %0*\" PRIx64 \" %s\", GetAddrHexWidth(), watchpoints.p[bp].addr,\n       watchpoints.p[bp].symbol);\n  snprintf(systemfailure, sizeof(systemfailure),\n           \"watchpoint %\" PRIx64 \" triggered%s%s\", watchpoints.p[bp].addr,\n           watchpoints.p[bp].symbol ? \"\\n\" : \"\",\n           watchpoints.p[bp].symbol ? watchpoints.p[bp].symbol : \"\");\n  dialog = systemfailure;\n  action &= ~(FINISH | NEXT | CONTINUE);\n  action |= MODAL;\n  tuimode = true;\n}\n\nstatic void ProfileOp(struct Machine *m, i64 pc) {\n  if (ophits &&                      //\n      pc >= m->system->codestart &&  //\n      pc < m->system->codestart + m->system->codesize) {\n    ++ophits[pc - m->system->codestart];\n  }\n}\n\nstatic void StartOp_Tui(P) {\n  ++cycle;\n  ProfileOp(m, m->ip - m->oplen);\n}\n\nstatic void Execute(void) {\n  u64 c;\n  if (g_history.viewing) {\n    g_history.viewing = 0;\n  }\n  c = cycle;\n  ExecuteInstruction(m);\n  if (c == cycle) {\n    ++cycle;\n    ProfileOp(m, GetPc(m) - m->oplen);\n  }\n  if (atomic_load_explicit(&m->attention, memory_order_acquire)) {\n    CheckForSignals(m);\n  }\n}\n\nstatic void Exec(void) {\n  ssize_t bp;\n  int interrupt;\n  LOGF(\"Exec\");\n  ExecSetup();\n  m->nofault = false;\n  if (!(interrupt = sigsetjmp(m->onhalt, 1))) {\n    m->canhalt = true;\n    if (!(action & CONTINUE) &&\n        (bp = IsAtBreakpoint(&breakpoints, m->ip)) != -1) {\n      LOGF(\"BREAK1 %0*\" PRIx64 \"\", GetAddrHexWidth(), breakpoints.p[bp].addr);\n    ReactToPoint:\n      tuimode = true;\n      LoadInstruction(m, GetPc(m));\n      if (verbose) LogInstruction();\n      Execute();\n      CheckFramePointer();\n    } else if (!(action & CONTINUE) &&\n               (bp = IsAtWatchpoint(&watchpoints, m)) != -1) {\n      LOGF(\"WATCH1 %0*\" PRIx64 \" %s\", GetAddrHexWidth(), watchpoints.p[bp].addr,\n           watchpoints.p[bp].symbol);\n      goto ReactToPoint;\n    } else {\n      action &= ~CONTINUE;\n      for (;;) {\n        LoadInstruction(m, GetPc(m));\n        if ((bp = IsAtBreakpoint(&breakpoints, m->ip)) != -1) {\n          LOGF(\"BREAK2 %0*\" PRIx64 \"\", GetAddrHexWidth(),\n               breakpoints.p[bp].addr);\n          action &= ~(FINISH | NEXT | CONTINUE);\n          tuimode = true;\n          break;\n        }\n        if ((bp = IsAtWatchpoint(&watchpoints, m)) != -1) {\n          EnterWatchpoint(bp);\n          break;\n        }\n        if (verbose) LogInstruction();\n        Execute();\n      KeepGoing:\n        CheckFramePointer();\n        if (action & ALARM) {\n          /* TODO(jart): Fix me */\n          /* DrawDisplayOnly(); */\n          action &= ~ALARM;\n        }\n        if (action & EXIT) {\n          LOGF(\"EXEC EXIT\");\n          break;\n        }\n        if (action & INT) {\n          LOGF(\"EXEC INT\");\n          if (react) {\n            LOGF(\"REACT\");\n            action &= ~(INT | STEP | FINISH | NEXT);\n            tuimode = true;\n            displayexec = false;\n            break;\n          } else {\n            action &= ~INT;\n            EnqueueSignal(m, SIGINT_LINUX);\n          }\n        }\n      }\n    }\n  } else {\n    if (IsMakingPath(m)) {\n      AbandonPath(m);\n    }\n    // if sigsetjmp fake-returned 1, the actual trap number might have been\n    // either 1 or 0; this should have been stored in m->trapno\n    if (interrupt == 1) interrupt = m->trapno;\n    if (OnHalt(interrupt)) {\n      if (!tuimode) {\n        if (displayexec) {\n          DrawDisplayOnly();\n        }\n        goto KeepGoing;\n      }\n    }\n  }\n  m->canhalt = false;\n}\n\nstatic void Tui(void) {\n  int sig;\n  ssize_t bp;\n  int interrupt;\n  bool interactive;\n  LOGF(\"Tui\");\n  TuiSetup();\n  SetupDraw();\n  m->nofault = false;\n  m->system->trapexit = true;\n  ScrollOp(&pan.disassembly, GetDisIndex());\n  if (!(interrupt = sigsetjmp(m->onhalt, 1))) {\n    m->canhalt = true;\n    do {\n      if (!(action & MODAL)) {\n        LoadInstruction(m, GetPc(m));\n        if ((action & (FINISH | NEXT | CONTINUE)) &&\n            (bp = IsAtBreakpoint(&breakpoints, m->ip)) != -1) {\n          action &= ~(FINISH | NEXT | CONTINUE);\n          LOGF(\"BREAK %0*\" PRIx64 \"\", GetAddrHexWidth(),\n               breakpoints.p[bp].addr);\n          ReactiveDraw();\n        } else if ((action & (FINISH | NEXT | CONTINUE)) &&\n                   (bp = IsAtWatchpoint(&watchpoints, m)) != -1) {\n          action &= ~(FINISH | NEXT | CONTINUE);\n          LOGF(\"WATCH %0*\" PRIx64 \" AT PC %\" PRIx64, GetAddrHexWidth(),\n               watchpoints.p[bp].addr, GetPc(m));\n          ReactiveDraw();\n        }\n      } else {\n        m->xedd = (struct XedDecodedInst *)m->opcache->icache[0];\n        m->xedd->length = 1;\n        m->xedd->bytes[0] = 0xCC;\n        m->xedd->op.rde &= ~00000077760000000000000;\n        m->xedd->op.rde &= (u64)0xCC << 40;  // sets mopcode to int3\n      }\n      if (action & WINCHED) {\n        HandleTerminalResize();\n        action &= ~WINCHED;\n      }\n      interactive = ++tick >= speed;\n      if (interactive && speed < 0) {\n        Sleep(-speed);\n      }\n      if (action & ALARM) {\n        HandleAlarm();\n      }\n      if (action & MODAL) {\n        ScrollMemoryViews();\n      }\n      if (!(action & CONTINUE) || interactive) {\n        tick = 0;\n        Redraw(false);\n      }\n      if (dialog) {\n        PrintMessageBox(ttyout, dialog, tyn, txn);\n      }\n      if (action & MODAL) {\n        PrintMessageBox(ttyout, systemfailure, tyn, txn);\n        ReadKeyboard();\n      } else if (dialog || !IsExecuting() ||\n                 (!(action & CONTINUE) && !(action & INT) &&\n                  HasPendingKeyboard())) {\n        ReadKeyboard();\n      }\n      if (action & INT) {\n        LOGF(\"TUI INT\");\n        action &= ~INT;\n        RecordKeystroke(\"\\3\");\n        if (action & (CONTINUE | NEXT | FINISH)) {\n          action &= ~(CONTINUE | NEXT | FINISH | STEP);\n          ReactiveDraw();\n        } else if ((~m->sigmask & ((u64)1 << (SIGINT_LINUX - 1))) &&\n                   Read64(m->system->hands[SIGINT_LINUX - 1].handler) !=\n                       SIG_DFL_LINUX &&\n                   Read64(m->system->hands[SIGINT_LINUX - 1].handler) !=\n                       SIG_IGN_LINUX) {\n          EnqueueSignal(m, SIGINT_LINUX);\n          action |= STEP;\n        } else {\n          SetStatus(\"press q to quit\");\n        }\n      }\n      if (action & EXIT) {\n        LOGF(\"TUI EXIT\");\n        break;\n      }\n      if (action & RESTART) {\n        LOGF(\"TUI RESTART\");\n        break;\n      }\n      if (IsExecuting()) {\n        if (!(action & CONTINUE)) {\n          action &= ~STEP;\n          if (action & NEXT) {\n            action &= ~NEXT;\n            if (IsCall()) {\n              BreakAtNextInstruction();\n              tuimode = false;\n              break;\n            }\n          }\n          if (action & FINISH) {\n            if (IsCall()) {\n              BreakAtNextInstruction();\n              tuimode = false;\n              break;\n            } else if (IsRet()) {\n              action &= ~FINISH;\n            }\n          }\n        }\n        if (!IsDebugBreak() && IsAtWatchpoint(&watchpoints, m) == -1) {\n          UpdateXmmType(m->xedd->op.rde, &xmmtype);\n          if (verbose) LogInstruction();\n          CopyMachineState(&laststate);\n          Execute();\n          ScrollOp(&pan.disassembly, GetDisIndex());\n          if (!IsShadow(m->readaddr) && !IsShadow(m->readaddr + m->readsize)) {\n            readaddr = m->readaddr;\n            readsize = m->readsize;\n          }\n          if (!IsShadow(m->writeaddr) &&\n              !IsShadow(m->writeaddr + m->writesize)) {\n            writeaddr = m->writeaddr;\n            writesize = m->writesize;\n          }\n          ScrollMemoryViews();\n          if (m->signals & ~m->sigmask) {\n            if ((sig = ConsumeSignal(m, 0, 0))) {\n              exit(EXIT_FAILURE_WITH_SIGNAL(sig));\n            }\n          }\n          if (!(action & CONTINUE) || interactive) {\n            if (!(action & CONTINUE)) ReactiveDraw();\n            ScrollMemoryViews();\n          }\n        } else {\n          m->ip += m->xedd->length;\n          action &= ~NEXT;\n          action &= ~FINISH;\n          action &= ~CONTINUE;\n        }\n      KeepGoing:\n        CheckFramePointer();\n        if (!(action & CONTINUE)) {\n          ScrollOp(&pan.disassembly, GetDisIndex());\n          if ((action & FINISH) && IsRet()) action &= ~FINISH;\n          if (((action & NEXT) && IsRet()) || (action & FINISH)) {\n            action &= ~NEXT;\n          }\n        }\n      }\n    } while (tuimode);\n  } else {\n    if (IsMakingPath(m)) {\n      AbandonPath(m);\n    }\n    if (interrupt == 1) interrupt = m->trapno;\n    if (OnHalt(interrupt)) {\n      ReactiveDraw();\n      ScrollMemoryViews();\n      goto KeepGoing;\n    }\n    ReactiveDraw();\n    ScrollOp(&pan.disassembly, GetDisIndex());\n  }\n  if ((action & EXIT)) {\n    m->canhalt = false;\n    TuiCleanup();\n  }\n}\n\n_Noreturn static void PrintVersion(void) {\n  fputs(VERSION, stdout);\n  exit(EXIT_SUCCESS);\n}\n\nstatic void GetOpts(int argc, char *argv[]) {\n  int opt;\n  bool wantunsafe = false;\n  FLAG_nologstderr = true;\n#ifndef DISABLE_OVERLAYS\n  FLAG_overlays = getenv(\"BLINK_OVERLAYS\");\n  if (!FLAG_overlays) FLAG_overlays = DEFAULT_OVERLAYS;\n#endif\n#ifndef DISABLE_VFS\n  FLAG_prefix = getenv(\"BLINK_PREFIX\");\n#endif\n  while ((opt = GetOpt(argc, argv, \"0hjmvVtrzRNsZb:Hw:L:C:B:\")) != -1) {\n    switch (opt) {\n      case '0':\n        FLAG_zero = true;\n        break;\n      case 'j':\n        FLAG_wantjit = true;\n        break;\n      case 't':\n        tuimode = false;\n        break;\n      case 's':\n        ++FLAG_strace;\n        break;\n      case 'm':\n        wantunsafe = true;\n        if (!CanHaveLinearMemory()) {\n          fprintf(stderr,\n                  \"linearization not possible on this system\"\n                  \" (word size is %d bits and page size is %ld)\\n\",\n                  bsr(UINTPTR_MAX) + 1, sysconf(_SC_PAGESIZE));\n          exit(EXIT_FAILURE);\n        }\n        break;\n      case 'R':\n        react = false;\n        break;\n      case 'N':\n        natural = true;\n        break;\n      case 'r':\n        wantmetal = true;\n        break;\n      case 'Z':\n        FLAG_statistics = true;\n        break;\n      case 'b':\n        HandleBreakpointFlag(optarg_);\n        break;\n      case 'w':\n        HandleWatchpointFlag(optarg_);\n        break;\n      case 'H':\n        memset(&g_high, 0, sizeof(g_high));\n        break;\n      case 'v':\n        PrintVersion();\n        break;\n      case 'V':\n        ++verbose;\n        break;\n      case 'L':\n        FLAG_logpath = optarg_;\n        break;\n      case 'C':\n#if !defined(DISABLE_OVERLAYS)\n        FLAG_overlays = optarg_;\n#elif !defined(DISABLE_VFS)\n        FLAG_prefix = optarg_;\n#else\n        WriteErrorString(\"error: overlays support was disabled\\n\");\n#endif\n        break;\n      case 'B':\n        FLAG_bios = optarg_;\n        break;\n      case 'z':\n        ++codeview.zoom;\n        ++readview.zoom;\n        ++writeview.zoom;\n        ++stackview.zoom;\n        break;\n      case 'h':\n        PrintUsage(0, stdout);\n      default:\n        PrintUsage(48, stderr);\n    }\n  }\n  LogInit(FLAG_logpath);\n  if (wantmetal) wantunsafe = false;\n  FLAG_nolinear = !wantunsafe;\n}\n\nstatic void AddPath_StartOp_Tui(P) {\n  Jitter(m, rde, 0, 0, \"qc\", StartOp_Tui);\n}\n\nstatic bool FileExists(const char *path) {\n  return !VfsAccess(AT_FDCWD, path, F_OK, 0);\n}\n\nint VirtualMachine(int argc, char *argv[]) {\n  struct Dll *e;\n  if (FileExists(argv[optind_])) {\n    codepath = argv[optind_];\n  } else if (Commandv(argv[optind_], pathbuf, sizeof(pathbuf))) {\n    codepath = pathbuf;\n  } else {\n    fprintf(stderr, \"%s: command not found: %s\\n\", argv[0], argv[optind_]);\n    exit(EXIT_FAILURE_EXEC_FAILED);\n  }\n  optind_++;\n  do {\n    action = 0;\n    ptyisenabled = false;\n    vidya = m->metal ? 3 : kModePty;\n    if (vidya != kModePty) {\n      VidyaServiceSetMode(vidya);\n    }\n    LoadProgram(m, codepath, codepath, argv + optind_ - 1 + FLAG_zero, environ,\n                FLAG_bios);\n    if (m->system->codesize) {\n      ophits = (unsigned long *)AllocateBig(\n          m->system->codesize * sizeof(unsigned long), PROT_READ | PROT_WRITE,\n          MAP_ANONYMOUS_ | MAP_PRIVATE, -1, 0);\n    }\n    ScrollMemoryViews();\n    AddStdFd(&m->system->fds, 0);\n    AddStdFd(&m->system->fds, 1);\n    AddStdFd(&m->system->fds, 2);\n    if (tuimode) {\n      int tty;\n      if (isatty(0)) {\n        tty = 0;\n      } else if (isatty(1)) {\n        tty = 1;\n      } else {\n        tty = VfsOpen(AT_FDCWD, \"/dev/tty\", O_RDWR | O_NOCTTY, 0);\n      }\n      if (tty != -1) {\n        tty = VfsFcntl(tty, F_DUPFD_CLOEXEC, kMinBlinkFd);\n      }\n      if (tty == -1) {\n        WriteErrorString(\"failed to open /dev/tty\\n\");\n        exit(EXIT_FAILURE);\n      }\n      ttyin = tty;\n      ttyout = tty;\n    } else {\n      ttyin = -1;\n      ttyout = -1;\n    }\n    if (ttyout != -1) {\n      tyn = 24;\n      txn = 80;\n      GetTtySize(ttyout);\n      for (e = dll_first(m->system->fds.list); e;\n           e = dll_next(m->system->fds.list, e)) {\n        if (isatty(FD_CONTAINER(e)->fildes)) {\n          FD_CONTAINER(e)->cb = &kFdCbPty;\n        }\n      }\n    }\n    do {\n      if (!tuimode) {\n        Exec();\n      } else {\n        Tui();\n      }\n    } while (!(action & (RESTART | EXIT)));\n  } while (action & RESTART);\n  DisFree(dis);\n  return exitcode;\n}\n\nvoid FreePanels(void) {\n  int i, j;\n  for (i = 0; i < ARRAYLEN(pan.p); ++i) {\n    for (j = 0; j < pan.p[i].n; ++j) {\n      free(pan.p[i].lines[j].p);\n    }\n    free(pan.p[i].lines);\n  }\n}\n\nvoid TerminateSignal(struct Machine *m, int sig, int code) {\n  if (!react) {\n    LOGF(\"terminating due to signal %s code=%d\", DescribeSignal(sig), code);\n    WriteErrorString(\"\\r\\033[K\\033[J\"\n                     \"terminating due to signal; see log\\n\");\n    exit(EXIT_FAILURE_WITH_SIGNAL(sig));\n  }\n}\n\nstatic void OnSigSegv(int sig, siginfo_t *si, void *uc) {\n  struct Machine *m = g_machine;\n#ifdef __APPLE__\n  sig = FixXnuSignal(m, sig, si);\n#endif\n#ifndef DISABLE_JIT\n  if (IsSelfModifyingCodeSegfault(m, si)) return;\n#endif\n  LOGF(\"OnSigSegv(%p)\", si->si_addr);\n  RestoreIp(m);\n  // TODO(jart): Fix address translation in non-linear mode.\n  m->faultaddr = ConvertHostToGuestAddress(m->system, si->si_addr, 0);\n  ERRF(\"SIGSEGV AT ADDRESS %#\" PRIx64 \" (OR %p) at RIP=%#\" PRIx64, m->faultaddr,\n       si->si_addr, m->ip);\n  ERRF(\"BACKTRACE\\n\\t%s\", GetBacktrace(m));\n  if (!react) {\n    sig = UnXlatSignal(si->si_signo);\n    DeliverSignalToUser(m, sig, UnXlatSiCode(sig, si->si_code));\n  }\n  siglongjmp(m->onhalt, kMachineSegmentationFault);\n}\n\nint main(int argc, char *argv[]) {\n  int rc;\n  struct System *s;\n  static struct sigaction sa;\n  setlocale(LC_ALL, \"\");\n  SetupWeb();\n  GetStartDir();\n  AtAbort(PrintStats);\n#ifndef NDEBUG\n  AtAbort(PrintStats);\n#endif\n  // Ensure utf-8 is printed correctly on windows, this method\n  // has issues(http://stackoverflow.com/a/10884364/4279) but\n  // should work for at least windows 7 and newer.\n#if defined(_WIN32) && !defined(__CYGWIN__)\n  SetConsoleOutputCP(CP_UTF8);\n#endif\n  g_blink_path = argc > 0 ? argv[0] : 0;\n  react = true;\n  tuimode = true;\n  WriteErrorInit();\n  InitMap();\n  GetOpts(argc, argv);\n  InitBus();\n#ifndef DISABLE_OVERLAYS\n  if (SetOverlays(FLAG_overlays, true)) {\n    WriteErrorString(\"bad blink overlays spec; see log for details\\n\");\n    exit(EXIT_FAILURE);\n  }\n#endif\n#ifndef DISABLE_VFS\n  if (VfsInit(FLAG_prefix)) {\n    WriteErrorString(\"error: vfs initialization failed\\n\");\n    exit(EXIT_FAILURE);\n  }\n#endif\n#ifdef HAVE_JIT\n  AddPath_StartOp_Hook = AddPath_StartOp_Tui;\n#endif\n  unassert((pty = NewPty()));\n  unassert((s = NewSystem(wantmetal ? XED_MACHINE_MODE_REAL\n                                    : XED_MACHINE_MODE_LONG)));\n  unassert((m = g_machine = NewMachine(s, 0)));\n#ifdef HAVE_JIT\n  if (!FLAG_wantjit || wantmetal) {\n    DisableJit(&m->system->jit);\n  }\n#endif\n  if (wantmetal) {\n    m->metal = true;\n  }\n  m->system->redraw = Redraw;\n  m->system->onbinbase = OnBinbase;\n  m->system->onlongbranch = OnLongBranch;\n#ifndef DISABLE_ROM\n  m->system->onromwriteattempt = OnRomWriteAttempt;\n#endif\n  speed = 1;\n  SetXmmSize(2);\n  SetXmmDisp(kXmmHex);\n  signal(SIGPIPE, SIG_IGN);\n  sigfillset(&sa.sa_mask);\n  sa.sa_flags = 0;\n  sa.sa_handler = OnSigSys;\n  unassert(!sigaction(SIGSYS, &sa, 0));\n  sa.sa_handler = OnSigInt;\n  unassert(!sigaction(SIGINT, &sa, 0));\n  sa.sa_handler = OnSigWinch;\n  unassert(!sigaction(SIGWINCH, &sa, 0));\n  sa.sa_handler = OnSigAlrm;\n  unassert(!sigaction(SIGALRM, &sa, 0));\n#if !defined(__SANITIZE_THREAD__) && !defined(__FILC__)\n  sa.sa_flags = SA_SIGINFO;\n  sa.sa_sigaction = OnSigSegv;\n  unassert(!sigaction(SIGBUS, &sa, 0));\n  unassert(!sigaction(SIGSEGV, &sa, 0));\n#endif\n  m->system->blinksigs |= (u64)1 << (SIGINT_LINUX - 1) |   //\n                          (u64)1 << (SIGALRM_LINUX - 1) |  //\n                          (u64)1 << (SIGWINCH_LINUX - 1);  //\n  if (optind_ == argc) PrintUsage(48, stderr);\n  rc = VirtualMachine(argc, argv);\n  FreeBig(ophits, m->system->codesize * sizeof(unsigned long));\n  FreeMachine(m);\n  ClearHistory();\n  FreePanels();\n  free(profsyms.p);\n  if (FLAG_statistics) {\n    PrintStats();\n  }\n  return rc;\n}\n"
  },
  {
    "path": "blink/blinkenlights.h",
    "content": "#ifndef BLINK_BLINKENLIGHTS_H_\n#define BLINK_BLINKENLIGHTS_H_\n/* Shared variables and functions with bios.c */\n\n#include <stdbool.h>\n#include <stdlib.h>\n#include <wchar.h>\n#include <sys/types.h>\n\n#include \"blink/likely.h\"\n#include \"blink/util.h\"\n\n#define kModePty 255\n\n/* blinkenlights.c */\nextern int ttyin;\nextern int vidya;\nextern bool tuimode;\nextern struct Pty *pty;\nextern struct Machine *m;\nextern bool ptyisenabled;\n\nvoid SetCarry(bool cf);\nvoid ReactiveDraw(void);\nvoid Redraw(bool force);\nvoid DrawDisplayOnly(void);\nbool HasPendingKeyboard(void);\nvoid HandleAppReadInterrupt(bool errflag);\nssize_t ReadAnsi(int fd, char *p, size_t n);\n\n/* bios.c */\nvoid VidyaServiceSetMode(int);\nbool OnCallBios(int interrupt);\n\nstatic inline wint_t GetVidyaByte(unsigned char b) {\n  if (LIKELY(0x20 <= b && b <= 0x7E)) return b;\n  /*\n   * In the emulated screen, show 0xff as a \"shouldered open box\"\n   * instead of lambda.  The Unicode 4.0 charts tell us that this\n   * glyph is an ISO 9995-7 \"keyboard symbol for No Break Space\".\n   */\n  if (UNLIKELY(b == 0xFF)) return 0x237D;\n  return kCp437[b];\n}\n\n#endif /* BLINK_BLINKENLIGHTS_H_ */\n"
  },
  {
    "path": "blink/bmi2.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n\n#ifndef DISABLE_BMI2\n\n// BMI2\n// BZHI clearing starting at bit\n// MULX flagless unsigned multiply\n// PDEP parallel bits deposit\n// PEXT parallel bits extract\n// RORX flagless rotate right logical\n// SARX flagless shift arithmetic right\n// SHRX flagless shift logical right\n// SHLX flagless shift logical left\n\nstatic u64 Pdep(u64 x, u64 mask) {\n  u64 r, b;\n  for (r = 0, b = 1; mask; mask >>= 1, b <<= 1) {\n    if (mask & 1) {\n      if (x & 1) r |= b;\n      x >>= 1;\n    }\n  }\n  return r;\n}\n\nstatic u64 Pext(u64 x, u64 mask) {\n  u64 r, b;\n  for (r = 0, b = 1; mask; mask >>= 1, x >>= 1) {\n    if (mask & 1) {\n      if (x & 1) r |= b;\n      b <<= 1;\n    }\n  }\n  return r;\n}\n\nstatic void OpPbit(P, u64 op(u64, u64)) {\n  if (Rexw(rde)) {\n    Put64(RegRexrReg(m, rde), op(Get64(RegVreg(m, rde)),\n                                 Load64(GetModrmRegisterWordPointerRead8(A))));\n  } else {\n    Put64(RegRexrReg(m, rde),\n          (u32)op(Get32(RegVreg(m, rde)),\n                  Load32(GetModrmRegisterWordPointerRead4(A))));\n  }\n}\n\nstatic void OpBzhi(P) {\n  int i;\n  u64 x;\n  bool sf;\n  bool cf = 0;\n  i = Get8(RegVreg(m, rde));\n  if (Rexw(rde)) {\n    x = Load64(GetModrmRegisterWordPointerRead8(A));\n    if (i < 64) {\n      x &= ((u64)1 << i) - 1;\n    } else {\n      cf = 1;\n    }\n    sf = (i64)x < 0;\n  } else {\n    x = Load32(GetModrmRegisterWordPointerRead4(A));\n    if (i < 32) {\n      x &= (1u << i) - 1;\n    } else {\n      cf = 1;\n    }\n    sf = (i32)x < 0;\n  }\n  Put64(RegRexrReg(m, rde), x);\n  m->flags = SetFlag(m->flags, FLAGS_ZF, !x);\n  m->flags = SetFlag(m->flags, FLAGS_CF, cf);\n  m->flags = SetFlag(m->flags, FLAGS_SF, sf);\n  m->flags = SetFlag(m->flags, FLAGS_OF, false);\n}\n\nvoid Op2f5(P) {\n  if (Rep(rde) == 2) {\n    OpPbit(A, Pdep);\n  } else if (Rep(rde) == 3) {\n    OpPbit(A, Pext);\n  } else if (!Osz(rde)) {\n    OpBzhi(A);\n#ifndef TINY\n  } else {\n    OpUdImpl(m);\n#endif\n  }\n}\n\nvoid OpRorx(P) {\n  int i;\n  u64 z;\n#ifndef TINY\n  if (Ymm(rde)) OpUdImpl(m);\n#endif\n  if (Rexw(rde)) {\n    u64 x = Load64(GetModrmRegisterWordPointerRead8(A));\n    if ((i = uimm0 & 63)) {\n      x = x >> i | x << (64 - i);\n    }\n    z = x;\n  } else {\n    u32 x = Load32(GetModrmRegisterWordPointerRead4(A));\n    if ((i = uimm0 & 31)) {\n      x = x >> i | x << (32 - i);\n    }\n    z = x;\n  }\n  Put64(RegRexrReg(m, rde), z);\n}\n\nstatic void OpShlx(P) {\n  int i;\n  u64 z;\n  i = Get8(RegVreg(m, rde));\n  if (Rexw(rde)) {\n    u64 x = Load64(GetModrmRegisterWordPointerRead8(A));\n    i &= 63;\n    if (i) x <<= i;\n    z = x;\n  } else {\n    u32 x = Load32(GetModrmRegisterWordPointerRead4(A));\n    i &= 31;\n    if (i) x <<= i;\n    z = x;\n  }\n  Put64(RegRexrReg(m, rde), z);\n}\n\nstatic void OpShrx(P) {\n  int i;\n  u64 z;\n  i = Get8(RegVreg(m, rde));\n  if (Rexw(rde)) {\n    u64 x = Load64(GetModrmRegisterWordPointerRead8(A));\n    i &= 63;\n    if (i) x >>= i;\n    z = x;\n  } else {\n    u32 x = Load32(GetModrmRegisterWordPointerRead4(A));\n    i &= 31;\n    if (i) x >>= i;\n    z = x;\n  }\n  Put64(RegRexrReg(m, rde), z);\n}\n\nstatic void OpSarx(P) {\n  int i;\n  u64 z;\n  i = Get8(RegVreg(m, rde));\n  if (Rexw(rde)) {\n    i64 x = Load64(GetModrmRegisterWordPointerRead8(A));\n    i &= 63;\n    if (i) x >>= i;\n    z = x;\n  } else {\n    i32 x = Load32(GetModrmRegisterWordPointerRead4(A));\n    i &= 31;\n    if (i) x >>= i;\n    z = (u32)x;\n  }\n  Put64(RegRexrReg(m, rde), z);\n}\n\nvoid OpShx(P) {\n#ifndef TINY\n  if (Ymm(rde)) OpUdImpl(m);\n#endif\n  if (Osz(rde)) {\n    OpShlx(A);\n  } else if (Rep(rde) == 2) {\n    OpShrx(A);\n  } else if (Rep(rde) == 3) {\n    OpSarx(A);\n#ifndef TINY\n  } else {\n    OpUdImpl(m);\n#endif\n  }\n}\n\n#endif /* DISABLE_BMI2 */\n"
  },
  {
    "path": "blink/breakpoint.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/breakpoint.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/builtin.h\"\n\nvoid PopBreakpoint(struct Breakpoints *bps) {\n  if (bps->i) {\n    --bps->i;\n  }\n}\n\nssize_t PushBreakpoint(struct Breakpoints *bps, struct Breakpoint *b) {\n  int i;\n  for (i = 0; i < bps->i; ++i) {\n    if (bps->p[i].disable) {\n      memcpy(&bps->p[i], b, sizeof(*b));\n      return i;\n    }\n  }\n  if (bps->i++ == bps->n) {\n    bps->n = bps->i + (bps->i >> 1);\n    bps->p = (struct Breakpoint *)realloc(bps->p, bps->n * sizeof(*bps->p));\n  }\n  bps->p[bps->i - 1] = *b;\n  return bps->i - 1;\n}\n\nssize_t IsAtBreakpoint(struct Breakpoints *bps, i64 addr) {\n  int i;\n  for (i = bps->i; i--;) {\n    if (bps->p[i].disable) continue;\n    if (bps->p[i].addr == addr) {\n      if (bps->p[i].oneshot) {\n        bps->p[i].disable = true;\n        if (i == bps->i - 1) {\n          --bps->i;\n        }\n      }\n      return i;\n    }\n  }\n  return -1;\n}\n"
  },
  {
    "path": "blink/breakpoint.h",
    "content": "#ifndef BLINK_BREAKPOINT_H_\n#define BLINK_BREAKPOINT_H_\n#include <stdbool.h>\n#include <stddef.h>\n#include <sys/types.h>\n\n#include \"blink/types.h\"\n\nstruct Breakpoint {\n  i64 addr;\n  const char *symbol;\n  bool disable;\n  bool oneshot;\n};\n\nstruct Breakpoints {\n  int i, n;\n  struct Breakpoint *p;\n};\n\nssize_t IsAtBreakpoint(struct Breakpoints *, i64);\nssize_t PushBreakpoint(struct Breakpoints *, struct Breakpoint *);\nvoid PopBreakpoint(struct Breakpoints *);\n\n#endif /* BLINK_BREAKPOINT_H_ */\n"
  },
  {
    "path": "blink/breg.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/modrm.h\"\n#include \"blink/types.h\"\n\n// Byte register offsets.\n//\n// for (i = 0; i < 2; ++i) {      // rex\n//   for (j = 0; j < 2; ++j) {    // rexb, or rexr\n//     for (k = 0; k < 8; ++k) {  // reg, rm, or srm\n//       kByteReg[i << 4 | j << 3 | k] =\n//           i ? (j << 3 | k) * 8 : (k & 3) * 8 + ((k & 4) >> 2);\n//     }\n//   }\n// }\nconst u8 kByteReg[32] = {0000, 0010, 0020, 0030, 0001, 0011, 0021, 0031,\n                         0000, 0010, 0020, 0030, 0001, 0011, 0021, 0031,\n                         0000, 0010, 0020, 0030, 0040, 0050, 0060, 0070,\n                         0100, 0110, 0120, 0130, 0140, 0150, 0160, 0170};\n"
  },
  {
    "path": "blink/buffer.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/buffer.h\"\n\n#include <errno.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"blink/macros.h\"\n#include \"blink/memcpy.h\"\n#include \"blink/stats.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n\nstatic bool GrowBuffer(struct Buffer *b, int need) {\n  char *p;\n  unsigned n;\n  n = MAX(b->i + need, MAX(16, b->n + (b->n >> 1)));\n  if (!(p = (char *)realloc(b->p, n))) return false;\n  b->p = p;\n  b->n = n;\n  return true;\n}\n\nvoid AppendData(struct Buffer *b, const char *data, int len) {\n  if (b->i + len + 1 > b->n && !GrowBuffer(b, len + 1)) return;\n  memcpy(b->p + b->i, data, len);\n  b->p[b->i += len] = 0;\n}\n\nint AppendChar(struct Buffer *b, char c) {\n  if (b->i + 2 > b->n && !GrowBuffer(b, 2)) return 0;\n  b->p[b->i++] = c;\n  b->p[b->i] = 0;\n  return 1;\n}\n\nint AppendStr(struct Buffer *b, const char *s) {\n  int n = strlen(s);\n  AppendData(b, s, n);\n  return n;\n}\n\nint AppendWide(struct Buffer *b, wint_t wc) {\n  u64 wb;\n  if (0 <= wc && wc <= 0x7f) {\n    AppendChar(b, wc);\n  } else {\n    if (b->i + 8 > b->n && !GrowBuffer(b, 8)) return 0;\n    wb = tpenc(wc);\n    do {\n      b->p[b->i++] = wb & 0xFF;\n    } while ((wb >>= 8));\n    b->p[b->i] = 0;\n  }\n  return 1;\n}\n\nint AppendFmt(struct Buffer *b, const char *fmt, ...) {\n  int n;\n  va_list va, vb;\n  va_start(va, fmt);\n  va_copy(vb, va);\n  n = vsnprintf(b->p + b->i, b->n - b->i, fmt, va);\n  if (b->i + n + 1 > b->n) {\n    do {\n      if (b->n) {\n        b->n += b->n >> 1;\n      } else {\n        b->n = 16;\n      }\n    } while (b->i + n + 1 > b->n);\n    b->p = (char *)realloc(b->p, b->n);\n    vsnprintf(b->p + b->i, b->n - b->i, fmt, vb);\n  }\n  va_end(vb);\n  va_end(va);\n  b->i += n;\n  return n;\n}\n\nssize_t UninterruptibleWrite(int fd, const void *p, size_t n) {\n  size_t i;\n  ssize_t rc;\n  for (i = 0; i < n; i += rc) {\n  TryAgain:\n    rc = VfsWrite(fd, (const char *)p + i, n - i);\n    if (rc == -1 && errno == EINTR) goto TryAgain;\n    if (rc == -1) return -1;\n  }\n  return n;\n}\n"
  },
  {
    "path": "blink/buffer.h",
    "content": "#ifndef BLINK_BUFFER_H_\n#define BLINK_BUFFER_H_\n#include <sys/types.h>\n#include <wchar.h>\n\n#include \"blink/builtin.h\"\n\nstruct Buffer {\n  int i, n;\n  char *p;\n};\n\nint AppendChar(struct Buffer *, char);\nvoid AppendData(struct Buffer *, const char *, int);\nint AppendStr(struct Buffer *, const char *);\nint AppendWide(struct Buffer *, wint_t);\nint AppendFmt(struct Buffer *, const char *, ...) printf_attr(2);\n\n#endif /* BLINK_BUFFER_H_ */\n"
  },
  {
    "path": "blink/builtin.h",
    "content": "#ifndef BLINK_BUILTIN_H_\n#define BLINK_BUILTIN_H_\n#include <limits.h>\n\n#include \"config.h\"\n\n#if __GNUC__ + 0 < 2\n#undef __GNUC__\n#elif defined(__GNUC__) && defined(SWIG) /* lool */\n#undef __GNUC__\n#elif defined(__GNUC__) && defined(__NVCC__) /* lool */\n#undef __GNUC__\n#elif !defined(__GNUC__) && defined(__APPLE__) /* modesty */\n#define __GNUC__            4\n#define __GNUC_MINOR__      2\n#define __GNUC_PATCHLEVEL__ 1\n#elif !defined(__GNUC__) && defined(__TINYC__)\n#define __GNUC__            2\n#define __GNUC_MINOR__      0\n#define __GNUC_PATCHLEVEL__ 0\n#endif\n\n#ifdef __STRICT_ANSI__\n#define asm __asm__\n#endif\n\n#if __GNUC__ + 0 < 2\n#define __attribute__(x)\n#endif\n\n#ifndef __has_builtin\n#define __has_builtin(x) 0\n#endif\n\n#ifndef __has_attribute\n#define __has_attribute(x) 0\n#endif\n\n#ifndef __has_feature\n#define __has_feature(x) 0\n#endif\n\n#if !defined(__SANITIZE_THREAD__) && __has_feature(thread_sanitizer)\n#define __SANITIZE_THREAD__\n#endif\n\n#if !defined(__SANITIZE_ADDRESS__) && __has_feature(address_sanitizer)\n#define __SANITIZE_ADDRESS__\n#endif\n\n#ifndef __BIGGEST_ALIGNMENT__\n#define __BIGGEST_ALIGNMENT__ 16\n#endif\n\n#ifdef _MSC_VER\n#define __builtin_unreachable() __assume(0)\n#elif !((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 405 || \\\n        defined(__clang__) || defined(__INTEL_COMPILER))\n#define __builtin_unreachable() \\\n  for (;;) {                    \\\n  }\n#endif\n\n#if !(defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__))\n#define __builtin_expect(x, y) (x)\n#endif\n\n#if !__has_builtin(__builtin___clear_cache) && \\\n    (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) < 403\n#define __builtin___clear_cache(x, y) (void)0\n#endif\n\n#ifndef thatispacked\n#define thatispacked __attribute__((__packed__))\n#endif\n\n#ifndef pureconst\n#define pureconst __attribute__((__const__))\n#endif\n\n#ifndef dontinline\n#ifdef _MSC_VER\n#define dontinline __declspec(noinline)\n#elif __has_attribute(__noinline__) || \\\n    (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 301\n#define dontinline __attribute__((__noinline__))\n#else\n#define dontinline\n#endif\n#endif\n\n#ifndef nosideeffect\n#if __has_attribute(__pure__) || \\\n    (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 296\n#define nosideeffect __attribute__((__pure__))\n#else\n#define nosideeffect\n#endif\n#endif\n\n#ifndef forceinline\n#ifdef __cplusplus\n#define forceinline inline\n#else\n#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 302\n#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403 || \\\n    !defined(__cplusplus) ||                              \\\n    (defined(__clang__) &&                                \\\n     (defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__)))\n#if defined(__GNUC_STDC_INLINE__) || defined(__cplusplus)\n#define forceinline                                                 \\\n  static __inline __attribute__((__always_inline__, __gnu_inline__, \\\n                                 __no_instrument_function__, __unused__))\n#else\n#define forceinline                                 \\\n  static __inline __attribute__((__always_inline__, \\\n                                 __no_instrument_function__, __unused__))\n#endif /* __GNUC_STDC_INLINE__ */\n#endif /* GCC >= 4.3 */\n#elif defined(_MSC_VER)\n#define forceinline __forceinline\n#else\n#define forceinline static inline\n#endif /* !ANSI && GCC >= 3.2 */\n#endif /* __cplusplus */\n#endif\n\n#ifndef flattencalls\n#define flattencalls __attribute__((__flatten__))\n#endif\n\n#ifndef relegated\n#if __has_attribute(__cold__) || \\\n    (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403\n#define relegated __attribute__((__cold__))\n#else\n#define relegated\n#endif\n#endif\n\n#ifndef returnsaligned\n#if __has_attribute(__assume_aligned__) || \\\n    (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409\n#define returnsaligned(x) __attribute__((__assume_aligned__ x))\n#else\n#define returnsaligned(x)\n#endif\n#endif\n\n#ifndef optimizesize\n#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \\\n    __has_attribute(__optimize__)\n#define optimizesize __attribute__((__optimize__(\"s\")))\n#else\n#define optimizesize\n#endif\n#endif\n\n#ifndef dontclone\n#if __has_attribute(__noclone__) || \\\n    (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 405\n#define dontclone __attribute__((__noclone__))\n#else\n#define dontclone\n#endif\n#endif\n\n#ifndef noinstrument\n#if __has_attribute(__no_instrument_function__) || \\\n    (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 204\n#define noinstrument __attribute__((__no_instrument_function__))\n#else\n#define noinstrument\n#endif\n#endif\n\n#ifndef noasan\n#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \\\n    __has_attribute(__no_sanitize_address__)\n#define noasan __attribute__((__no_sanitize_address__))\n#else\n#define noasan\n#endif\n#endif\n\n#ifndef notsan\n#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \\\n    __has_attribute(__no_sanitize_thread__)\n#define notsan __attribute__((__no_sanitize_thread__))\n#else\n#define notsan\n#endif\n#endif\n\n#ifndef noubsan\n#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \\\n    __has_attribute(__no_sanitize_undefined__)\n#define noubsan __attribute__((__no_sanitize_undefined__))\n#else\n#define noubsan\n#endif\n#endif\n\n#ifndef nomsan\n#if __has_feature(memory_sanitizer)\n#define __SANITIZE_MEMORY__\n#define nomsan __attribute__((__no_sanitize__(\"memory\")))\n#else\n#define nomsan\n#endif\n#endif\n\n#ifndef dontdiscard\n#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 304 || \\\n     __has_attribute(__warn_unused_result__))\n#define dontdiscard __attribute__((__warn_unused_result__))\n#else\n#define dontdiscard\n#endif\n#endif\n\n#ifndef nostackprotector\n#if __has_attribute(__no_stack_protector__)\n#define nostackprotector __attribute__((__no_stack_protector__))\n#elif (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \\\n    __has_attribute(__optimize__)\n#define nostackprotector __attribute__((__optimize__(\"-fno-stack-protector\")))\n#else\n#define nostackprotector\n#endif\n#endif\n\n#ifdef __GNUC__\n#define printf_attr(n) __attribute__((__format__(__printf__, n, n + 1)))\n#else\n#define printf_attr(n)\n#endif\n\n#ifdef __x86_64__\n#define CAN_64BIT 1\n#elif LONG_BIT >= 64\n#define CAN_64BIT 1\n#else\n#define CAN_64BIT 0\n#endif\n\n#if CAN_64BIT && !defined(__STRICT_ANSI__) && \\\n    ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 406 || defined(__llvm__))\n#define HAVE_INT128\n#endif\n\n#if !defined(__SANITIZE_THREAD__) && defined(TSAN)\n#define __SANITIZE_THREAD__\n#endif\n\n#if !defined(__SANITIZE_UNDEFINED__) && defined(UBSAN)\n#define __SANITIZE_UNDEFINED__\n#endif\n\n#if !defined(DISABLE_JIT) && (defined(__x86_64__) || defined(__aarch64__)) && \\\n    !defined(__SANITIZE_MEMORY__) && !defined(__SANITIZE_THREAD__) &&         \\\n    !defined(__NetBSD__) && !defined(NOJIT) && !defined(__FILC__)\n#define HAVE_JIT\n#endif\n\n#if defined(HAVE_JIT) && defined(__GNUC__) && !defined(__SANITIZE_ADDRESS__)\n#ifndef __OPTIMIZE__\n#define TRIVIALLY_RELOCATABLE \\\n  noinstrument dontclone noubsan nostackprotector optimizesize\n#else\n#define TRIVIALLY_RELOCATABLE noinstrument dontclone noubsan nostackprotector\n#endif\n#define MICRO_OP_SAFE TRIVIALLY_RELOCATABLE forceinline\n#define MICRO_OP      TRIVIALLY_RELOCATABLE\n#else\n#define MICRO_OP_SAFE static inline\n#define MICRO_OP\n#endif\n\n#if defined(__GNUC__) || defined(__llvm__)\n#pragma GCC diagnostic ignored \"-Wtype-limits\"\n#pragma GCC diagnostic ignored \"-Wsign-compare\"\n#pragma GCC diagnostic ignored \"-Wunused-function\"\n#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n#pragma GCC diagnostic error \"-Wpointer-arith\"\n#pragma GCC diagnostic error \"-Wnonnull\"\n#pragma GCC diagnostic error \"-Wunused-result\"\n#ifndef __cplusplus\n#pragma GCC diagnostic error \"-Wimplicit-function-declaration\"\n#if __GNUC__ >= 6\n#pragma GCC diagnostic error \"-Wincompatible-pointer-types\"\n#if __GNUC__ >= 8\n#pragma GCC diagnostic error \"-Wmultistatement-macros\"\n#pragma GCC diagnostic error \"-Wpacked-not-aligned\"\n#pragma GCC diagnostic error \"-Wcast-align=strict\"\n#pragma GCC diagnostic error \"-Wif-not-aligned\"\n#endif /* GCC 8+ */\n#endif /* GCC 6+ */\n#endif /* __cplusplus */\n#endif /* GCC || LLVM */\n\n#if defined(__GNUC__) && !defined(__llvm__)\n#pragma GCC diagnostic error \"-Wwrite-strings\"\n#pragma GCC diagnostic error \"-Wtrampolines\"\n#if __GNUC__ >= 6\n#pragma GCC diagnostic error \"-Wnonnull-compare\"\n#pragma GCC diagnostic error \"-Wframe-larger-than=16384\"\n#if __GNUC__ >= 9\n#pragma GCC diagnostic error \"-Walloca-larger-than=1024\"\n#pragma GCC diagnostic error \"-Wvla-larger-than=1024\"\n#endif /* GCC 9+ */\n#elif __GNUC__ >= 9\n#pragma GCC diagnostic error /* e.g. fabs not abs */ \"-Wabsolute-value\"\n#endif /* GCC 6+ */\n#endif /* GCC && !LLVM */\n\n#ifdef __llvm__\n#pragma clang diagnostic error \"-Wassume\"\n#endif /* !GCC && LLVM */\n\n#endif /* BLINK_BUILTIN_H_ */\n"
  },
  {
    "path": "blink/bus.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/bus.h\"\n\n#include <limits.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/dll.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/rde.h\"\n#include \"blink/swap.h\"\n#include \"blink/thread.h\"\n#include \"blink/tsan.h\"\n\n#ifdef HAVE_PTHREAD_PROCESS_SHARED\n#define BUS_MEMORY MAP_SHARED\n#else\n#define BUS_MEMORY MAP_PRIVATE\n#endif\n\nstruct Bus *g_bus;\n\nvoid InitBus(void) {\n  unsigned i;\n  pthread_condattr_t_ cattr;\n  pthread_mutexattr_t_ mattr;\n#ifndef HAVE_PTHREAD_PROCESS_SHARED\n  if (g_bus) FreeBig(g_bus, sizeof(*g_bus));\n#endif\n  unassert(g_bus =\n               (struct Bus *)AllocateBig(sizeof(*g_bus), PROT_READ | PROT_WRITE,\n                                         BUS_MEMORY | MAP_ANONYMOUS_, -1, 0));\n  unassert(!pthread_condattr_init(&cattr));\n  unassert(!pthread_mutexattr_init(&mattr));\n#ifdef HAVE_PTHREAD_PROCESS_SHARED\n  unassert(!pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED));\n  unassert(!pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED));\n#endif\n#ifdef HAVE_THREADS\n  for (i = 0; i < kBusCount; ++i)\n    unassert(!pthread_mutex_init(&g_bus->lock[i], 0));\n#endif\n  unassert(!pthread_mutex_init(&g_bus->futexes.lock, &mattr));\n  for (i = 0; i < kFutexMax; ++i) {\n    unassert(!pthread_cond_init(&g_bus->futexes.mem[i].cond, &cattr));\n    unassert(!pthread_mutex_init(&g_bus->futexes.mem[i].lock, &mattr));\n    dll_init(&g_bus->futexes.mem[i].elem);\n    dll_make_last(&g_bus->futexes.free, &g_bus->futexes.mem[i].elem);\n  }\n  unassert(!pthread_mutexattr_destroy(&mattr));\n  unassert(!pthread_condattr_destroy(&cattr));\n}\n\nvoid LockBus(const u8 *locality) {\n#ifdef HAVE_THREADS\n  /* A locked instruction is guaranteed to lock only the area of memory\n     defined by the destination operand, but may be interpreted by the\n     system as a lock for a larger memory area. ──Intel V.3 §8.1.2.2 */\n  _Static_assert(IS2POW(kBusCount), \"virtual bus count must be two-power\");\n  _Static_assert(IS2POW(kBusRegion), \"virtual bus region must be two-power\");\n  _Static_assert(kBusRegion >= 16, \"virtual bus region must be at least 16\");\n  LOCK(&g_bus->lock[(uintptr_t)locality / kBusRegion % kBusCount]);\n#endif\n}\n\nvoid UnlockBus(const u8 *locality) {\n#ifdef HAVE_THREADS\n  UNLOCK(&g_bus->lock[(uintptr_t)locality / kBusRegion % kBusCount]);\n#endif\n}\n\ni64 Load8(const u8 p[1]) {\n  return atomic_load_explicit((_Atomic(u8) *)p, memory_order_acquire);\n}\n\ni64 Load16(const u8 p[2]) {\n  i64 z;\n#if (defined(__x86_64__) || defined(__i386__)) && \\\n    !defined(__SANITIZE_UNDEFINED__) && !defined(__FILC__)\n  z = atomic_load_explicit((_Atomic(u16) *)p, memory_order_relaxed);\n#else\n  if (!((uintptr_t)p & 1)) {\n    z = Little16(atomic_load_explicit((_Atomic(u16) *)p, memory_order_acquire));\n  } else {\n    z = Read16(p);\n  }\n#endif\n  return z;\n}\n\ni64 Load32(const u8 p[4]) {\n  i64 z;\n#if (defined(__x86_64__) || defined(__i386__)) && \\\n    !defined(__SANITIZE_UNDEFINED__) && !defined(__FILC__)\n  z = atomic_load_explicit((_Atomic(u32) *)p, memory_order_relaxed);\n#else\n  if (!((uintptr_t)p & 3)) {\n    z = Little32(atomic_load_explicit((_Atomic(u32) *)p, memory_order_acquire));\n  } else {\n    z = Read32(p);\n  }\n#endif\n  return z;\n}\n\ni64 Load64(const u8 p[8]) {\n  i64 z;\n#if CAN_64BIT\n#if defined(__x86_64__) && !defined(__SANITIZE_UNDEFINED__) && \\\n    !defined(__FILC__)\n  z = atomic_load_explicit((_Atomic(u64) *)p, memory_order_relaxed);\n#else\n  if (!((uintptr_t)p & 7)) {\n    z = Little64(atomic_load_explicit((_Atomic(u64) *)p, memory_order_acquire));\n  } else {\n    z = Read64(p);\n  }\n#endif\n#else\n  LockBus(p);\n  z = Read64(p);\n  UnlockBus(p);\n#endif\n  return z;\n}\n\ni64 Load64Unlocked(const u8 p[8]) {\n  i64 z;\n#if CAN_64BIT\n  z = Load64(p);\n#else\n  z = Read64(p);\n#endif\n  return z;\n}\n\nvoid Store8(u8 p[1], u64 x) {\n  atomic_store_explicit((_Atomic(u8) *)p, x, memory_order_release);\n}\n\nvoid Store16(u8 p[2], u64 x) {\n#if (defined(__x86_64__) || defined(__i386__)) && \\\n    !defined(__SANITIZE_UNDEFINED__) && !defined(__FILC__)\n  atomic_store_explicit((_Atomic(u16) *)p, x, memory_order_relaxed);\n#else\n  if (!((uintptr_t)p & 1)) {\n    atomic_store_explicit((_Atomic(u16) *)p, Little16(x), memory_order_release);\n  } else {\n    Write16(p, x);\n  }\n#endif\n}\n\nvoid Store32(u8 p[4], u64 x) {\n#if (defined(__x86_64__) || defined(__i386__)) && \\\n    !defined(__SANITIZE_UNDEFINED__) && !defined(__FILC__)\n  atomic_store_explicit((_Atomic(u32) *)p, x, memory_order_relaxed);\n#else\n  if (!((uintptr_t)p & 3)) {\n    atomic_store_explicit((_Atomic(u32) *)p, Little32(x), memory_order_release);\n  } else {\n    Write32(p, x);\n  }\n#endif\n}\n\nvoid Store64(u8 p[8], u64 x) {\n#if CAN_64BIT\n#if defined(__x86_64__) && !defined(__SANITIZE_UNDEFINED__) && \\\n    !defined(__FILC__)\n  atomic_store_explicit((_Atomic(u64) *)p, x, memory_order_relaxed);\n#else\n  if (!((uintptr_t)p & 7)) {\n    atomic_store_explicit((_Atomic(u64) *)p, Little64(x), memory_order_release);\n  } else {\n    Write64(p, x);\n  }\n#endif\n#else\n  LockBus(p);\n  Write64(p, x);\n  UnlockBus(p);\n#endif\n}\n\nvoid Store64Unlocked(u8 p[8], u64 x) {\n#if CAN_64BIT\n  Store64(p, x);\n#else\n  Write64(p, x);\n#endif\n}\n\nu64 ReadRegister(u64 rde, u8 p[8]) {\n  if (Rexw(rde)) {\n    return Get64(p);\n  } else if (!Osz(rde)) {\n    return Get32(p);\n  } else {\n    return Get16(p);\n  }\n}\n\ni64 ReadRegisterSigned(u64 rde, u8 p[8]) {\n  if (Rexw(rde)) {\n    return (i64)Get64(p);\n  } else if (!Osz(rde)) {\n    return (i32)Get32(p);\n  } else {\n    return (i16)Get16(p);\n  }\n}\n\nvoid WriteRegister(u64 rde, u8 p[8], u64 x) {\n  if (Rexw(rde)) {\n    Put64(p, x);\n  } else if (!Osz(rde)) {\n    Put64(p, x & 0xffffffff);\n  } else {\n    Put16(p, x);\n  }\n}\n\nu64 ReadMemory(u64 rde, u8 p[8]) {\n  if (Rexw(rde)) {\n    return Load64(p);\n  } else if (!Osz(rde)) {\n    return Load32(p);\n  } else {\n    return Load16(p);\n  }\n}\n\nu64 ReadMemoryUnlocked(u64 rde, u8 p[8]) {\n  if (Rexw(rde)) {\n    return Load64Unlocked(p);\n  } else if (!Osz(rde)) {\n    return Load32(p);\n  } else {\n    return Load16(p);\n  }\n}\n\nu64 ReadMemorySigned(u64 rde, u8 p[8]) {\n  if (Rexw(rde)) {\n    return (i64)Load64(p);\n  } else if (!Osz(rde)) {\n    return (i32)Load32(p);\n  } else {\n    return (i16)Load16(p);\n  }\n}\n\nvoid WriteMemory(u64 rde, u8 p[8], u64 x) {\n  if (Rexw(rde)) {\n    Store64(p, x);\n  } else if (!Osz(rde)) {\n    Store32(p, x);\n  } else {\n    Store16(p, x);\n  }\n}\n\nvoid WriteRegisterOrMemory(u64 rde, u8 p[8], u64 x) {\n  if (IsModrmRegister(rde)) {\n    WriteRegister(rde, p, x);\n  } else {\n    WriteMemory(rde, p, x);\n  }\n}\n\nvoid WriteRegisterBW(u64 rde, u8 p[8], u64 x) {\n  switch (RegLog2(rde)) {\n    case 3:\n      Put64(p, x);\n      break;\n    case 2:\n      Put64(p, x & 0xffffffff);\n      break;\n    case 0:\n      Put8(p, x);\n      break;\n    case 1:\n      Put16(p, x);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\ni64 ReadRegisterBW(u64 rde, u8 p[8]) {\n  switch (RegLog2(rde)) {\n    case 3:\n      return Get64(p);\n    case 2:\n      return Get32(p);\n    case 0:\n      return Get8(p);\n    case 1:\n      return Get16(p);\n    default:\n      __builtin_unreachable();\n  }\n}\n\ni64 ReadMemoryBW(u64 rde, u8 p[8]) {\n  switch (RegLog2(rde)) {\n    case 3:\n      return Load64(p);\n    case 2:\n      return Load32(p);\n    case 0:\n      return Load8(p);\n    case 1:\n      return Load16(p);\n    default:\n      __builtin_unreachable();\n  }\n}\n\nvoid WriteMemoryBW(u64 rde, u8 p[8], u64 x) {\n  switch (RegLog2(rde)) {\n    case 3:\n      Store64(p, x);\n      break;\n    case 2:\n      Store32(p, x);\n      break;\n    case 0:\n      Store8(p, x);\n      break;\n    case 1:\n      Store16(p, x);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nvoid WriteRegisterOrMemoryBW(u64 rde, u8 p[8], u64 x) {\n  if (IsModrmRegister(rde)) {\n    WriteRegisterBW(rde, p, x);\n  } else {\n    WriteMemoryBW(rde, p, x);\n  }\n}\n\ni64 ReadRegisterOrMemoryBW(u64 rde, u8 p[8]) {\n  if (IsModrmRegister(rde)) {\n    return ReadRegisterBW(rde, p);\n  } else {\n    return ReadMemoryBW(rde, p);\n  }\n}\n"
  },
  {
    "path": "blink/bus.h",
    "content": "#ifndef BLINK_MOP_H_\n#define BLINK_MOP_H_\n#include <limits.h>\n#include <stdbool.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/dll.h\"\n#include \"blink/endian.h\"\n#include \"blink/thread.h\"\n#include \"blink/tsan.h\"\n#include \"blink/tunables.h\"\n#include \"blink/types.h\"\n\n#define FUTEX_CONTAINER(e) DLL_CONTAINER(struct Futex, elem, e)\n\nstruct Futex {\n  i64 addr;\n  int waiters;\n  struct Dll elem;\n  pthread_cond_t_ cond;\n  pthread_mutex_t_ lock;\n};\n\nstruct Futexes {\n  struct Dll *active;\n  struct Dll *free;\n  pthread_mutex_t_ lock;\n  struct Futex mem[kFutexMax];\n};\n\nstruct Bus {\n  pthread_mutex_t_ lock[kBusCount];\n  struct Futexes futexes;\n};\n\nextern struct Bus *g_bus;\n\nvoid InitBus(void);\nvoid LockBus(const u8 *);\nvoid UnlockBus(const u8 *);\n\ni64 Load8(const u8[1]) nosideeffect;\ni64 Load16(const u8[2]) nosideeffect;\ni64 Load32(const u8[4]) nosideeffect;\ni64 Load64(const u8[8]) nosideeffect;\ni64 Load64Unlocked(const u8[8]) nosideeffect;\n\nvoid Store8(u8[1], u64);\nvoid Store16(u8[2], u64);\nvoid Store32(u8[4], u64);\nvoid Store64(u8[8], u64);\nvoid Store64Unlocked(u8[8], u64);\n\ni64 ReadRegisterSigned(u64, u8[8]);\nu64 ReadMemory(u64, u8[8]);\nu64 ReadMemorySigned(u64, u8[8]);\nu64 ReadMemoryUnlocked(u64, u8[8]);\nu64 ReadRegister(u64, u8[8]);\nvoid WriteMemory(u64, u8[8], u64);\nvoid WriteRegister(u64, u8[8], u64);\nvoid WriteRegisterOrMemory(u64, u8[8], u64);\n\ni64 ReadMemoryBW(u64, u8[8]);\ni64 ReadRegisterBW(u64, u8[8]);\nvoid WriteMemoryBW(u64, u8[8], u64);\nvoid WriteRegisterBW(u64, u8[8], u64);\ni64 ReadRegisterOrMemoryBW(u64, u8[8]);\nvoid WriteRegisterOrMemoryBW(u64, u8[8], u64);\nu64 LoadPte32_(const u8 *) nosideeffect;\nbool CasPte32_(u8 *, u64, u64);\nvoid StorePte32_(u8 *, u64);\n\nnosideeffect static inline u64 LoadPte(const u8 *pte) {\n#if CAN_64BIT\n  return Little64(\n      atomic_load_explicit((_Atomic(u64) *)pte, memory_order_acquire));\n#else\n  return LoadPte32_(pte);\n#endif\n}\n\nstatic inline void StorePte(u8 *pte, u64 val) {\n#if CAN_64BIT\n  atomic_store_explicit((_Atomic(u64) *)pte, Little64(val),\n                        memory_order_release);\n#else\n  StorePte32_(pte, val);\n#endif\n}\n\nstatic inline bool CasPte(u8 *pte, u64 oldval, u64 newval) {\n#if CAN_64BIT\n  oldval = Little64(oldval);\n  return atomic_compare_exchange_strong_explicit(\n      (_Atomic(u64) *)pte, &oldval, Little64(newval),  //\n      memory_order_release, memory_order_relaxed);\n#else\n  return CasPte32_(pte, oldval, newval);\n#endif\n}\n\n#endif /* BLINK_MOP_H_ */\n"
  },
  {
    "path": "blink/case.h",
    "content": "#ifndef BLINK_CASE_H_\n#define BLINK_CASE_H_\n\n#define CASE(OP, CODE) \\\n  case OP:             \\\n    CODE;              \\\n    break\n\n#define CASR(OP, CODE) \\\n  case OP:             \\\n    CODE;              \\\n    return\n\n#define XLAT(x, y) \\\n  case x:          \\\n    return y\n\n#endif /* BLINK_CASE_H_ */\n"
  },
  {
    "path": "blink/cga.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/cga.h\"\n#include \"blink/bda.h\"\n\n#include <stdio.h>\n#include <termios.h>\n\n#include \"blink/blinkenlights.h\"\n#include \"blink/buffer.h\"\n#include \"blink/macros.h\"\n#include \"blink/util.h\"\n\n/*                                blk blu grn cyn red mag yel wht */\nstatic const u8 kCgaToAnsi[16] = {30, 34, 32, 36, 31, 35, 33, 37,\n                                  90, 94, 92, 96, 91, 95, 93, 97};\n\nsize_t FormatCga(u8 bgfg, char buf[11]) {\n  return sprintf(buf, \"\\033[%d;%dm\", kCgaToAnsi[(bgfg & 0xF0) >> 4] + 10,\n                 kCgaToAnsi[bgfg & 0x0F]);\n}\n\n#ifdef IUTF8\n#define CURSOR L'▂'\n#else\n#define CURSOR '_'\n#endif\n\nvoid DrawCga(struct Panel *p, u8 *vram) {\n  unsigned y, x, ny, nx, a, ch, attr, curx, cury;\n  u8 *v;\n  wint_t wch;\n  char buf[11];\n  ny = MIN(BdaLines, p->bottom - p->top);\n  nx = BdaCols;\n  curx = BdaCurx;\n  cury = BdaCury;\n  for (y = 0; y < ny; ++y) {\n    a = -1;\n    v = vram + y * nx * 2;\n    for (x = 0; x < nx; ++x) {\n      ch = *v++;\n      attr = *v++;\n      if (!BdaCurhidden && x == curx && y == cury) {\n        if (ch == ' ' || ch == '\\0') {\n          wch = CURSOR;\n        } else {\n          wch = GetVidyaByte(ch);\n          attr = (attr & 0xF0) >> 4 | (attr & 0x0F) << 4;\n        }\n        a = -1;\n      } else {\n        wch = GetVidyaByte(ch);\n      }\n      if (attr != a) {\n        AppendData(&p->lines[y], buf, FormatCga((a = attr), buf));\n      }\n      AppendWide(&p->lines[y], wch);\n    }\n    AppendStr(&p->lines[y], \"\\033[0m\");\n  }\n}\n"
  },
  {
    "path": "blink/cga.h",
    "content": "#ifndef BLINK_CGA_H_\n#define BLINK_CGA_H_\n#include \"blink/panel.h\"\n#include \"blink/types.h\"\n\nvoid DrawCga(struct Panel *, u8 *);\nsize_t FormatCga(u8, char[11]);\n\n#endif /* BLINK_CGA_H_ */\n"
  },
  {
    "path": "blink/checked.h",
    "content": "#ifndef EASYCKDINT_H_\n#define EASYCKDINT_H_\n\n#ifdef __has_include\n#if __has_include(<stdckdint.h>)\n#include <stdckdint.h>\n#ifndef ckd_add\n#error \"<stdckdint.h> lacks ckd_add() macro?\"\n#endif /* !ckd_add */\n#endif /* <stdckdint.h> */\n#endif /* __has_include */\n\n#ifndef ckd_add\n\n#define __STDC_VERSION_STDCKDINT_H__ 202311L\n\n#if defined(__GNUC__) && __GNUC__ >= 5 && !defined(__ICC)\n#define ckd_add(res, x, y) __builtin_add_overflow((x), (y), (res))\n#define ckd_sub(res, x, y) __builtin_sub_overflow((x), (y), (res))\n#define ckd_mul(res, x, y) __builtin_mul_overflow((x), (y), (res))\n#endif /* __GNUC__ >= 5 && !__ICC */\n\n#if !defined(ckd_add) && defined(__has_builtin)\n#if __has_builtin(__builtin_add_overflow) && \\\n    __has_builtin(__builtin_sub_overflow) && \\\n    __has_builtin(__builtin_mul_overflow)\n#define ckd_add(res, x, y) __builtin_add_overflow((x), (y), (res))\n#define ckd_sub(res, x, y) __builtin_sub_overflow((x), (y), (res))\n#define ckd_mul(res, x, y) __builtin_mul_overflow((x), (y), (res))\n#endif /* __builtin_..._overflow */\n#endif /* !ckd_add && __has_builtin */\n\n#ifndef ckd_add /* FIXME */\n#define ckd_add(res, x, y) (*(res) = (x) + (y), 0)\n#define ckd_sub(res, x, y) (*(res) = (x) - (y), 0)\n#define ckd_mul(res, x, y) (*(res) = (x) * (y), 0)\n#endif /* !ckd_add */\n\n#endif /* !ckd_add */\n\n#endif /* EASYCKDINT_H_ */\n"
  },
  {
    "path": "blink/clmul.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/bitscan.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n\nstruct clmul {\n  u64 x, y;\n};\n\nstatic struct clmul clmul(u64 a, u64 b) {\n  u64 t, x = 0, y = 0;\n  if (a && b) {\n    if (bsr(a) < bsr(b)) t = a, a = b, b = t;\n    for (t = 0; b; a <<= 1, b >>= 1) {\n      if (b & 1) x ^= a, y ^= t;\n      t = t << 1 | a >> 63;\n    }\n  }\n  return (struct clmul){x, y};\n}\n\nvoid OpSsePclmulqdq(P) {\n  struct clmul res;\n  if (Osz(rde)) {\n    res = clmul(\n        Get64(XmmRexrReg(m, rde) + ((uimm0 & 0x01) << 3)),\n        Read64(GetModrmRegisterXmmPointerRead16(A) + ((uimm0 & 0x10) >> 1)));\n    Put64(XmmRexrReg(m, rde) + 0, res.x);\n    Put64(XmmRexrReg(m, rde) + 8, res.y);\n  } else {\n    OpUdImpl(m);\n  }\n}\n"
  },
  {
    "path": "blink/close.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/debug.h\"\n#include \"blink/dll.h\"\n#include \"blink/errno.h\"\n#include \"blink/fds.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/syscall.h\"\n#include \"blink/thread.h\"\n#include \"blink/vfs.h\"\n\nstatic int CloseFd(struct Fd *fd) {\n  int rc;\n  unassert(fd->cb);\n  if (fd->dirstream) {\n    rc = VfsClosedir(fd->dirstream);\n  } else {\n    rc = fd->cb->close(fd->fildes);\n  }\n  FreeFd(fd);\n  return rc;\n}\n\nstatic int CloseFds(struct Dll *fds) {\n  int rc = 0;\n  struct Dll *e, *e2;\n  for (e = dll_first(fds); e; e = e2) {\n    e2 = dll_next(fds, e);\n    dll_remove(&fds, e);\n    rc |= CloseFd(FD_CONTAINER(e));\n  }\n  return rc;\n}\n\nstatic int FinishClose(struct Machine *m, int rc) {\n  if (rc == -1 && errno == EINTR && !CheckInterrupt(m, true)) rc = 0;\n  return rc;\n}\n\nint SysClose(struct Machine *m, i32 fildes) {\n  struct Fd *fd;\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    dll_remove(&m->system->fds.list, &fd->elem);\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!fd) return -1;\n  return FinishClose(m, CloseFd(fd));\n}\n\nvoid SysCloseExec(struct System *s) {\n  struct Fd *fd;\n  struct Dll *e, *e2, *fds;\n  LOCK(&s->fds.lock);\n  for (fds = 0, e = dll_first(s->fds.list); e; e = e2) {\n    fd = FD_CONTAINER(e);\n    e2 = dll_next(s->fds.list, e);\n    if (fd->oflags & O_CLOEXEC) {\n      dll_remove(&s->fds.list, e);\n      dll_make_last(&fds, e);\n    }\n  }\n  UNLOCK(&s->fds.lock);\n  CloseFds(fds);\n}\n\n#ifndef DISABLE_NONPOSIX\n\nstatic int SysCloseRangeCloexec(struct Machine *m, u32 first, u32 last) {\n  struct Fd *fd;\n  struct Dll *e;\n  LOCK(&m->system->fds.lock);\n  for (e = dll_first(m->system->fds.list); e;\n       e = dll_next(m->system->fds.list, e)) {\n    fd = FD_CONTAINER(e);\n    if (first <= (u32)fd->fildes && (u32)fd->fildes <= last) {\n      if (~fd->oflags & O_CLOEXEC) {\n        fd->oflags |= O_CLOEXEC;\n        VfsFcntl(fd->fildes, F_SETFD, FD_CLOEXEC);\n      }\n    }\n  }\n  UNLOCK(&m->system->fds.lock);\n  return 0;\n}\n\nint SysCloseRange(struct Machine *m, u32 first, u32 last, u32 flags) {\n  int rc;\n  struct Fd *fd;\n  sigset_t block, oldmask;\n  struct Dll *e, *e2, *fds;\n  if ((flags & ~CLOSE_RANGE_CLOEXEC_LINUX) || first > last) {\n    return einval();\n  }\n  if (flags & CLOSE_RANGE_CLOEXEC_LINUX) {\n    return SysCloseRangeCloexec(m, first, last);\n  }\n  LOCK(&m->system->fds.lock);\n  for (fds = 0, e = dll_first(m->system->fds.list); e; e = e2) {\n    fd = FD_CONTAINER(e);\n    e2 = dll_next(m->system->fds.list, e);\n    if (first <= (u32)fd->fildes && (u32)fd->fildes <= last) {\n      dll_remove(&m->system->fds.list, e);\n      dll_make_last(&fds, e);\n    }\n  }\n  UNLOCK(&m->system->fds.lock);\n  unassert(!sigfillset(&block));\n  unassert(!pthread_sigmask(SIG_BLOCK, &block, &oldmask));\n  rc = CloseFds(fds);\n  unassert(!pthread_sigmask(SIG_SETMASK, &oldmask, 0));\n  unassert(!(rc == -1 && errno == EINTR));\n  return rc;\n}\n\n#endif /* DISABLE_NONPOSIX */\n"
  },
  {
    "path": "blink/cmpxchg.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/alu.h\"\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/thread.h\"\n\nvoid OpCmpxchgEbAlGb(P) {\n  u8 *p = GetModrmRegisterBytePointerWrite1(A);\n  u8 *q = ByteRexrReg(m, rde);\n  u8 ax = atomic_load_explicit((_Atomic(u8) *)m->ax, memory_order_relaxed);\n  atomic_compare_exchange_strong_explicit(\n      (_Atomic(u8) *)p, &ax,\n      atomic_load_explicit((_Atomic(u8) *)q, memory_order_relaxed),\n      memory_order_acq_rel, memory_order_acquire);\n  Sub8(m, Get8(m->ax), Little8(ax));\n  atomic_store_explicit((_Atomic(u8) *)m->ax, ax, memory_order_relaxed);\n}\n\nstatic void LockCmpxchgMem32(struct Machine *m, u64 rde, u8 *p) {\n  u8 *q;\n  int c;\n  u32 x, z;\n  bool didit;\n  q = RegRexrReg(m, rde);\n  if (!((uintptr_t)p & 3)) {\n    x = atomic_load_explicit((_Atomic(u32) *)m->ax, memory_order_relaxed);\n    didit = atomic_compare_exchange_strong_explicit(\n        (_Atomic(u32) *)p, &x,\n        atomic_load_explicit((_Atomic(u32) *)q, memory_order_relaxed),\n        memory_order_acq_rel, memory_order_acquire);\n    z = Get32(m->ax) - Little32(x);\n    c = Get32(m->ax) < z;\n    m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n    if (!didit) Put64(m->ax, Little32(x));\n  } else {\n    LockBus(p);\n    x = Load32(p);\n    Sub32(m, Get32(m->ax), x);\n    if ((didit = x == Get32(m->ax))) {\n      Store32(p, Get32(q));\n    } else {\n      Put64(m->ax, x);\n    }\n    UnlockBus(p);\n  }\n}\n\nstatic void Cmpxchg(struct Machine *m, u64 rde, u8 *p) {\n  u8 *q;\n  bool didit;\n  q = RegRexrReg(m, rde);\n  if (Rexw(rde)) {\n    u64 x;\n#if CAN_64BIT\n    if (Lock(rde) && !((uintptr_t)p & 7)) {\n      x = atomic_load_explicit((_Atomic(u64) *)m->ax, memory_order_relaxed);\n      atomic_compare_exchange_strong_explicit(\n          (_Atomic(u64) *)p, &x,\n          atomic_load_explicit((_Atomic(u64) *)q, memory_order_relaxed),\n          memory_order_acq_rel, memory_order_acquire);\n      Sub64(m, Get64(m->ax), Little64(x));\n      atomic_store_explicit((_Atomic(u64) *)m->ax, x, memory_order_relaxed);\n      return;\n    }\n#endif\n    if (Lock(rde)) {\n      LockBus(p);\n      x = Load64Unlocked(p);\n      Sub64(m, Get64(m->ax), x);\n      if ((didit = x == Get64(m->ax))) {\n        Store64Unlocked(p, Get64(q));\n      } else {\n        Put64(m->ax, x);\n      }\n      UnlockBus(p);\n    } else {\n      x = Load64(p);\n      Sub64(m, Get64(m->ax), x);\n      if ((didit = x == Get64(m->ax))) {\n        Store64(p, Get64(q));\n      } else {\n        Put64(m->ax, x);\n      }\n    }\n  } else if (!Osz(rde)) {\n    if (Lock(rde) && !((uintptr_t)p & 3)) {\n      u32 ax =\n          atomic_load_explicit((_Atomic(u32) *)m->ax, memory_order_relaxed);\n      didit = atomic_compare_exchange_strong_explicit(\n          (_Atomic(u32) *)p, &ax,\n          atomic_load_explicit((_Atomic(u32) *)q, memory_order_relaxed),\n          memory_order_acq_rel, memory_order_acquire);\n      Sub32(m, Get32(m->ax), Little32(ax));\n      if (!didit) Put64(m->ax, Little32(ax));\n    } else {\n      if (Lock(rde)) LockBus(p);\n      u32 x = Load32(p);\n      Sub32(m, Get32(m->ax), x);\n      if ((didit = x == Get32(m->ax))) {\n        Store32(p, Get32(q));\n      } else {\n        Put64(m->ax, x);\n      }\n      if (Lock(rde)) UnlockBus(p);\n    }\n    if (IsModrmRegister(rde)) {\n      Put32(p + 4, 0);\n    }\n  } else {\n    if (Lock(rde) && !((uintptr_t)p & 1)) {\n      u16 ax =\n          atomic_load_explicit((_Atomic(u16) *)m->ax, memory_order_relaxed);\n      atomic_compare_exchange_strong_explicit(\n          (_Atomic(u16) *)p, &ax,\n          atomic_load_explicit((_Atomic(u16) *)q, memory_order_relaxed),\n          memory_order_acq_rel, memory_order_acquire);\n      Sub16(m, Get16(m->ax), Little16(ax));\n      atomic_store_explicit((_Atomic(u16) *)m->ax, ax, memory_order_relaxed);\n    } else {\n      if (Lock(rde)) LockBus(p);\n      u16 x = Load16(p);\n      Sub16(m, Get16(m->ax), x);\n      if ((didit = x == Get16(m->ax))) {\n        Store16(p, Get16(q));\n      } else {\n        Put16(m->ax, x);\n      }\n      if (Lock(rde)) UnlockBus(p);\n    }\n  }\n}\n\nvoid OpCmpxchgEvqpRaxGvqp(P) {\n  Cmpxchg(m, rde, GetModrmRegisterWordPointerWriteOszRexw(A));\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"P\"      // res0 = GetRegOrMemPointer(RexbRm)\n           \"r0a2=\"  // arg2 = res0\n           \"a1i\"    // arg1 = rde\n           \"q\"      // arg0 = m\n           \"c\",     // call function\n           rde,\n           (Lock(rde) && !IsModrmRegister(rde) && !Rexw(rde) && !Osz(rde) &&\n            !(GetNeededFlags(m, m->ip, CF | ZF | SF | OF | AF | PF) &\n              (SF | OF | AF | PF)))\n               ? LockCmpxchgMem32\n               : Cmpxchg);\n  }\n}\n"
  },
  {
    "path": "blink/commandv.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <ctype.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/overlays.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n\nstruct PathSearcher {\n  char *path;\n  size_t pathlen;\n  size_t namelen;\n  const char *name;\n  const char *syspath;\n};\n\nstatic char EndsWithIgnoreCase(const char *p, unsigned long n, const char *s) {\n  unsigned long i, m;\n  if (n >= (m = strlen(s))) {\n    for (i = n - m; i < n; ++i) {\n      if (tolower(p[i]) != *s++) {\n        return 0;\n      }\n    }\n    return 1;\n  } else {\n    return 0;\n  }\n}\n\nstatic char IsComPath(struct PathSearcher *ps) {\n  return EndsWithIgnoreCase(ps->name, ps->namelen, \".com\") ||\n         EndsWithIgnoreCase(ps->name, ps->namelen, \".exe\") ||\n         EndsWithIgnoreCase(ps->name, ps->namelen, \".com.dbg\");\n}\n\nstatic char AccessCommand(struct PathSearcher *ps, const char *suffix,\n                          unsigned long pathlen) {\n  unsigned long suffixlen;\n  suffixlen = strlen(suffix);\n  if (pathlen + 1 + ps->namelen + suffixlen + 1 > ps->pathlen) return 0;\n  if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';\n  memcpy(ps->path + pathlen, ps->name, ps->namelen);\n  memcpy(ps->path + pathlen + ps->namelen, suffix, suffixlen + 1);\n  return !VfsAccess(AT_FDCWD, ps->path, X_OK, 0);\n}\n\nstatic char SearchPath(struct PathSearcher *ps, const char *suffix) {\n  const char *p;\n  unsigned long i;\n  for (p = ps->syspath;;) {\n    for (i = 0; p[i] && p[i] != ':'; ++i) {\n      if (i < ps->pathlen) {\n        ps->path[i] = p[i];\n      }\n    }\n    if (AccessCommand(ps, suffix, i)) {\n      return 1;\n    } else if (p[i] == ':') {\n      p += i + 1;\n    } else {\n      return 0;\n    }\n  }\n}\n\nstatic char FindCommand(struct PathSearcher *ps, const char *suffix) {\n  if (memchr(ps->name, '/', ps->namelen) ||\n      memchr(ps->name, '\\\\', ps->namelen)) {\n    ps->path[0] = 0;\n    return AccessCommand(ps, suffix, 0);\n  } else {\n    if (AccessCommand(ps, suffix, 0)) return 1;\n  }\n  return SearchPath(ps, suffix);\n}\n\n/**\n * Searches for command `name` on system `$PATH`.\n */\nchar *Commandv(const char *name, char *buf, size_t size) {\n  struct PathSearcher ps;\n  ps.path = buf;\n  ps.pathlen = size;\n  ps.syspath = getenv(\"PATH\");\n  if (!ps.syspath) ps.syspath = \"/usr/local/bin:/bin:/usr/bin\";\n  if (!(ps.namelen = strlen((ps.name = name)))) return 0;\n  if (ps.namelen + 1 > ps.pathlen) return 0;\n  if (FindCommand(&ps, \"\") || (!IsComPath(&ps) && FindCommand(&ps, \".com\"))) {\n    return ps.path;\n  } else {\n    return 0;\n  }\n}\n"
  },
  {
    "path": "blink/compress.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdlib.h>\n#include <zlib.h>\n\n#include \"blink/assert.h\"\n#include \"blink/util.h\"\n\nvoid *Deflate(const void *data, unsigned size, unsigned *out_size) {\n  void *res;\n  uLong bound;\n  z_stream zs = {0};\n  bound = compressBound(size);\n  unassert(res = malloc(bound));\n  unassert(deflateInit2(&zs, 4, Z_DEFLATED, -MAX_WBITS, 8,\n                        Z_DEFAULT_STRATEGY) == Z_OK);\n  zs.next_in = (z_const Bytef *)data;\n  zs.avail_in = size;\n  zs.avail_out = bound;\n  zs.next_out = (Bytef *)res;\n  unassert(deflate(&zs, Z_FINISH) == Z_STREAM_END);\n  unassert(deflateEnd(&zs) == Z_OK);\n  unassert(res = realloc(res, zs.total_out));\n  *out_size = zs.total_out;\n  return res;\n}\n\nvoid Inflate(void *out, unsigned outsize, const void *in, unsigned insize) {\n  z_stream zs;\n  zs.next_in = (z_const Bytef *)in;\n  zs.avail_in = insize;\n  zs.total_in = insize;\n  zs.next_out = (Bytef *)out;\n  zs.avail_out = outsize;\n  zs.total_out = outsize;\n  zs.zalloc = Z_NULL;\n  zs.zfree = Z_NULL;\n  unassert(inflateInit2(&zs, -MAX_WBITS) == Z_OK);\n  unassert(inflate(&zs, Z_FINISH) == Z_STREAM_END);\n  unassert(inflateEnd(&zs) == Z_OK);\n}\n"
  },
  {
    "path": "blink/cp437.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/util.h\"\n\n/*\n * The original hardware displayed 0x00, 0x20, and 0xff as space. It\n * made sense for viewing sparse binary data that 0x00 be blank. But\n * it doesn't make sense for dense data too, and we don't need three\n * space characters. So we diverge in our implementation and display\n * 0xff as lambda.\n */\nconst short kCp437[256] = /* clang-format off */ {\n  0x00a0,0x263a,0x263b,0x2665,0x2666,0x2663,0x2660,0x2022, /*00: ☺☻♥♦♣♠•*/\n  0x25d8,0x25cb,0x25d9,0x2642,0x2640,0x266a,0x266b,0x263c, /*08:◘○◙♂♀♪♫☼*/\n  0x25ba,0x25c4,0x2195,0x203c,0x00b6,0x00a7,0x25ac,0x21a8, /*10:►◄↕‼¶§▬↨*/\n  0x2191,0x2193,0x2192,0x2190,0x221f,0x2194,0x25b2,0x25bc, /*18:↑↓→←∟↔▲▼*/\n  0x0020,0x0021,0x201c,0x0023,0x0024,0x0025,0x0026,0x2018, /*20: !“#$%&‘*/\n  0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, /*28:()*+,-./*/\n  0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, /*30:01234567*/\n  0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x2047, /*38:89:;<=>⁇*/\n  0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, /*40:@ABCDEFG*/\n  0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, /*48:HIJKLMNO*/\n  0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, /*50:PQRSTUVW*/\n  0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, /*58:XYZ[\\]^_*/\n  0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, /*60:`abcdefg*/\n  0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, /*68:hijklmno*/\n  0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, /*70:pqrstuvw*/\n  0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x2302, /*78:xyz{|}~⌂*/\n  0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7, /*80:Çüéâäàåç*/\n  0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, /*88:êëèïîìÄÅ*/\n  0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9, /*90:ÉæÆôöòûù*/\n  0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20ac,0x0192, /*98:ÿÖÜ¢£¥€ƒ*/\n  0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba, /*a0:áíóúñÑªº*/\n  0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, /*a8:¿⌐¬½¼¡«»*/\n  0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, /*b0:░▒▓│┤╡╢╖*/\n  0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, /*b8:╕╣║╗╝╜╛┐*/\n  0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, /*c0:└┴┬├─┼╞╟*/\n  0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, /*c8:╚╔╩╦╠═╬╧*/\n  0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, /*d0:╨╤╥╙╘╒╓╫*/\n  0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, /*d8:╪┘┌█▄▌▐▀*/\n  0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x03bc,0x03c4, /*e0:αßΓπΣσμτ*/\n  0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, /*e8:ΦΘΩδ∞φε∩*/\n  0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248, /*f0:≡±≥≤⌠⌡÷≈*/\n  0x00b0,0x2219,0x00d7,0x221a,0x207f,0x00b2,0x25a0,0x03bb, /*f8:°∙×√ⁿ²■λ*/\n} /* clang-format on */;\n"
  },
  {
    "path": "blink/cpucount.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <sys/param.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/macros.h\"\n#include \"blink/util.h\"\n\n#ifdef HAVE_SCHED_H\n#include <sched.h>\n#endif\n\n#ifdef HAVE_SYSCTL\n#include <sys/sysctl.h>\n#endif\n\nstatic _Atomic(int) g_cpucount;\n\nstatic int GetCpuCountImpl(void) {\n#ifdef HAVE_SCHED_GETAFFINITY\n  cpu_set_t s;\n  if (sched_getaffinity(0, sizeof(s), &s) == -1) return -1;\n  return CPU_COUNT(&s);\n#elif defined(HAVE_SYSCTL)\n  int x;\n  size_t n = sizeof(x);\n  int mib[] = {CTL_HW, HW_NCPU};\n  if (sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1) return -1;\n  return x;\n#elif defined(_SC_NPROCESSORS_ONLN)\n  return sysconf(_SC_NPROCESSORS_ONLN);\n#else\n  return 1;\n#endif /* HAVE_SYSCTL */\n}\n\nint GetCpuCount(void) {\n  int rc;\n  if (!(rc = g_cpucount)) {\n    if ((rc = GetCpuCountImpl()) < 1) rc = 1;\n    g_cpucount = rc;\n  }\n  return rc;\n}\n"
  },
  {
    "path": "blink/cpuid.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/assert.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n\n#define INTEL    \"GenuineIntel\"\n#define BLINK    \"GenuineBlink\"\n#define LINUX_   \"Linux\\0\\0\\0\\0\\0\\0\\0\"\n#define FREEBSD_ \"FreeBSD\\0\\0\\0\\0\\0\\0\"\n#define NETBSD_  \"NetBSD\\0\\0\\0\\0\\0\\0\"\n#define OPENBSD_ \"OpenBSD\\0\\0\\0\\0\\0\"\n#define XNU_     \"XNU\\0\\0\\0\\0\\0\\0\\0\\0\\0\"\n#define WINDOWS_ \"Windows\\0\\0\\0\\0\\0\"\n#define CYGWIN_  \"Cygwin\\0\\0\\0\\0\\0\\0\"\n#define HAIKU_   \"Haiku\\0\\0\\0\\0\\0\\0\\0\"\n#define UNKNOWN_ \"Unknown\\0\\0\\0\\0\\0\\0\"\n\n#ifdef __COSMOPOLITAN__\n#define OS                  \\\n  (IsLinux()     ? LINUX_   \\\n   : IsFreebsd() ? FREEBSD_ \\\n   : IsNetbsd()  ? NETBSD_  \\\n   : IsOpenbsd() ? OPENBSD_ \\\n   : IsXnu()     ? XNU_     \\\n   : IsWindows() ? WINDOWS_ \\\n                 : UNKNOWN_)\n#elif defined(__linux)\n#define OS LINUX_\n#elif defined(__FreeBSD__)\n#define OS FREEBSD_\n#elif defined(__NetBSD__)\n#define OS NETBSD_\n#elif defined(__OpenBSD__)\n#define OS OPENBSD_\n#elif defined(__APPLE__)\n#define OS XNU_\n#elif defined(__CYGWIN__)\n#define OS CYGWIN_\n#elif defined(__HAIKU__)\n#define OS HAIKU_\n#else\n#define OS UNKNOWN_\n#endif\n\n#define X86_64_  \"x86_64\\0\\0\\0\\0\\0\\0\"\n#define I386_    \"i386\\0\\0\\0\\0\\0\\0\\0\\0\"\n#define AARCH64_ \"aarch64\\0\\0\\0\\0\\0\"\n#define ARM_     \"arm\\0\\0\\0\\0\\0\\0\\0\\0\\0\"\n#define PPC64_   \"ppc64\\0\\0\\0\\0\\0\\0\\0\"\n#define PPC64LE_ \"ppc64le\\0\\0\\0\\0\\0\"\n#define PPC_     \"ppc\\0\\0\\0\\0\\0\\0\\0\\0\\0\"\n#define S390X_   \"s390x\\0\\0\\0\\0\\0\\0\\0\"\n#define RISCV64_ \"riscv64\\0\\0\\0\\0\\0\"\n#define RISCV32_ \"riscv32\\0\\0\\0\\0\\0\"\n\n#if defined(__x86_64__)\n#define ARCH_NAME X86_64_\n#elif defined(__i386__)\n#define ARCH_NAME I386_\n#elif defined(__aarch64__)\n#define ARCH_NAME AARCH64_\n#elif defined(__ARMEL__)\n#define ARCH_NAME ARM_\n#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__)\n#define ARCH_NAME PPC64LE_\n#elif defined(__powerpc64__)\n#define ARCH_NAME PPC64_\n#elif defined(__powerpc__)\n#define ARCH_NAME PPC_\n#elif defined(__s390x__)\n#define ARCH_NAME S390X_\n#elif defined(__riscv) && __riscv_xlen == 64\n#define ARCH_NAME RISCV64_\n#elif defined(__riscv) && __riscv_xlen == 32\n#define ARCH_NAME RISCV32_\n#else\n#define ARCH_NAME UNKNOWN_\n#endif\n\nvoid OpCpuid(P) {\n  u32 ax, bx, cx, dx, jit;\n  if (m->trapcpuid) {\n    ThrowSegmentationFault(m, 0);\n  }\n  ax = bx = cx = dx = 0;\n  switch (Get32(m->ax)) {\n    case 0:\n      ax = 7;\n      goto vendor;\n    case 0x80000000:\n      ax = 0x80000001;\n    vendor:\n      // glibc binaries won't run unless we report blink as a\n      // modern linux kernel on top of genuine intel hardware\n      bx = Read32((const u8 *)INTEL + 0);\n      dx = Read32((const u8 *)INTEL + 4);\n      cx = Read32((const u8 *)INTEL + 8);\n      break;\n    case 0x40000000:\n      bx = Read32((const u8 *)BLINK + 0);\n      cx = Read32((const u8 *)BLINK + 4);\n      dx = Read32((const u8 *)BLINK + 8);\n      break;\n    case 0x40031337:\n      bx = Read32((const u8 *)OS + 0);\n      cx = Read32((const u8 *)OS + 4);\n      dx = Read32((const u8 *)OS + 8);\n      break;\n    case 0x40031338:\n      bx = Read32((const u8 *)ARCH_NAME + 0);\n      cx = Read32((const u8 *)ARCH_NAME + 4);\n      dx = Read32((const u8 *)ARCH_NAME + 8);\n      break;\n    case 1:\n      cx |= 1 << 0;    // sse3\n      cx |= 1 << 1;    // pclmulqdq\n      cx |= 1 << 9;    // ssse3\n      cx |= 1 << 23;   // popcnt\n      cx |= 1 << 30;   // rdrnd\n      cx |= 0 << 25;   // aes\n      cx |= 1 << 13;   // cmpxchg16b\n      cx |= 1u << 31;  // hypervisor\n      dx |= 1 << 4;    // tsc\n      dx |= 1 << 6;    // pae\n      dx |= 1 << 8;    // cmpxchg8b\n      dx |= 1 << 15;   // cmov\n      dx |= 1 << 19;   // clflush\n      dx |= 1 << 23;   // mmx\n      dx |= 1 << 24;   // fxsave\n      dx |= 1 << 25;   // sse\n      dx |= 1 << 26;   // sse2\n      cx |= 0 << 19;   // sse4.1\n      cx |= 0 << 20;   // sse4.2\n#ifndef DISABLE_X87\n      dx |= 1 << 0;  // fpu\n#endif\n      break;\n    case 2:  // Cache and TLB information\n      ax = 0x76035a01;\n      bx = 0x00f0b0ff;\n      cx = 0x00000000;\n      dx = 0x00ca0000;\n      break;\n    case 7:\n      switch (Get32(m->cx)) {\n        case 0:\n          bx |= 1 << 0;   // fsgsbase\n          bx |= 1 << 9;   // erms\n          bx |= 1 << 18;  // rdseed\n          cx |= 1 << 22;  // rdpid\n#ifndef DISABLE_BMI2\n          bx |= 1 << 8;   // bmi2\n          bx |= 1 << 19;  // adx\n#endif\n          break;\n        default:\n          break;\n      }\n      break;\n    case 0x80000001:\n      jit = !IsJitDisabled(&m->system->jit);\n      cx |= 1 << 0;     // lahf\n      cx |= jit << 31;  // jit\n      dx |= 1 << 0;     // fpu\n      dx |= 1 << 8;     // cmpxchg8b\n      dx |= 1 << 11;    // syscall\n      dx |= 1 << 15;    // cmov\n      dx |= 1 << 20;    // nx\n      dx |= 1 << 23;    // mmx\n      dx |= 1 << 24;    // fxsave\n      dx |= 1 << 27;    // rdtscp\n      dx |= 1 << 29;    // long\n      break;\n    case 0x80000007:\n      dx |= 1 << 8;  // invtsc\n      break;\n    case 4:  // cpu cache information\n      // - Level 1 data 8-way 32,768 byte cache w/ 64 sets of 64 byte\n      //   lines shared across 2 threads\n      // - Level 1 code 8-way 32,768 byte cache w/ 64 sets of 64 byte\n      //   lines shared across 2 threads\n      // - Level 2 8-way 262,144 byte cache w/ 512 sets of 64 byte lines\n      //   shared across 2 threads\n      // - Level 3 complexly-indexed 16-way 8,388,608 byte cache w/ 8,192\n      //   sets of 64 byte lines shared across 16 threads\n      switch (Get32(m->cx)) {\n        case 0:\n          ax = 0x1c004121;\n          bx = 0x01c0003f;\n          cx = 0x0000003f;\n          dx = 0x00000000;\n          break;\n        case 1:\n          ax = 0x1c004122;\n          bx = 0x01c0003f;\n          cx = 0x0000003f;\n          dx = 0x00000000;\n          break;\n        case 2:\n          ax = 0x1c004143;\n          bx = 0x01c0003f;\n          cx = 0x000001ff;\n          dx = 0x00000000;\n          break;\n        case 3:\n          ax = 0x1c03c163;\n          bx = 0x03c0003f;\n          cx = 0x00001fff;\n          dx = 0x00000006;\n          break;\n        default:\n          break;\n      }\n      break;\n    case 6:  // thermal and power management leaf\n      ax = 0x00000077;\n      bx = 0x00000002;\n      cx = 0x0000000b;\n      dx = 0x00000000;\n      break;\n    default:\n      break;\n  }\n  Put64(m->ax, ax);\n  Put64(m->bx, bx);\n  Put64(m->cx, cx);\n  Put64(m->dx, dx);\n}\n"
  },
  {
    "path": "blink/crc32.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/swap.h\"\n#include \"blink/types.h\"\n\nstatic u32 kCastagnoli[256];\n\nstatic void InitializeCrc32(u32 table[256], u32 polynomial) {\n  u32 d, i, r;\n  for (d = 0; d < 256; ++d) {\n    r = d;\n    for (i = 0; i < 8; ++i) {\n      r = r >> 1 ^ (r & 1 ? polynomial : 0);\n    }\n    table[d] = r;\n  }\n}\n\nstatic u32 ReverseBits32(u32 x) {\n  x = SWAP32(x);\n  x = (x & 0xaaaaaaaa) >> 1 | (x & 0x55555555) << 1;\n  x = (x & 0xcccccccc) >> 2 | (x & 0x33333333) << 2;\n  x = (x & 0xf0f0f0f0) >> 4 | (x & 0x0f0f0f0f) << 4;\n  return x;\n}\n\nstatic u32 Castagnoli(u32 h, u64 w, long n) {\n  long i;\n  static int once;\n  if (!once) {\n    InitializeCrc32(kCastagnoli, ReverseBits32(0x1edc6f41));\n    once = 1;\n  }\n  for (i = 0; i < n; ++i) {\n    h = h >> 8 ^ kCastagnoli[(h & 255) ^ (w & 255)];\n    w >>= 8;\n  }\n  return h;\n}\n\nstatic void OpCrc32(P) {\n  Put64(RegRexrReg(m, rde),\n        Castagnoli(Get32(RegRexrReg(m, rde)),\n                   ReadRegisterOrMemoryBW(rde, GetModrmReadBW(A)),\n                   1 << RegLog2(rde)));\n}\n\nvoid Op2f01(P) {\n  if (!Rep(rde) && !Osz(rde)) {\n    OpUdImpl(m);  // TODO: movbe\n  } else if (Rep(rde) == 2 && !Osz(rde)) {\n    OpCrc32(A);\n  } else {\n    OpUdImpl(m);\n  }\n}\n"
  },
  {
    "path": "blink/cvt.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <math.h>\n#include <string.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/fpu.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/modrm.h\"\n#include \"blink/pun.h\"\n#include \"blink/stats.h\"\n\n#define kOpCvt0f2a  0\n#define kOpCvtt0f2c 4\n#define kOpCvt0f2d  8\n#define kOpCvt0f5a  12\n#define kOpCvt0f5b  16\n#define kOpCvt0fE6  20\n\nstatic double SseRoundDouble(struct Machine *m, double x) {\n  switch ((m->mxcsr & kMxcsrRc) >> 13) {\n    case 0:\n      return rint(x);\n    case 1:\n      return floor(x);\n    case 2:\n      return ceil(x);\n    case 3:\n      return trunc(x);\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic void OpGdqpWssCvttss2si(P) {\n  i64 n;\n  union FloatPun f;\n  f.i = Read32(GetModrmRegisterXmmPointerRead4(A));\n  n = f.f;\n  if (!Rexw(rde)) n &= 0xffffffff;\n  Put64(RegRexrReg(m, rde), n);\n}\n\nstatic void OpGdqpWsdCvttsd2si(P) {\n  i64 n;\n  union DoublePun d;\n  d.i = Read64(GetModrmRegisterXmmPointerRead8(A));\n  n = d.f;\n  if (!Rexw(rde)) n &= 0xffffffff;\n  Put64(RegRexrReg(m, rde), n);\n}\n\nstatic void OpGdqpWssCvtss2si(P) {\n  i64 n;\n  union FloatPun f;\n  f.i = Read32(GetModrmRegisterXmmPointerRead4(A));\n  n = rintf(f.f);\n  if (!Rexw(rde)) n &= 0xffffffff;\n  Put64(RegRexrReg(m, rde), n);\n}\n\nstatic void OpGdqpWsdCvtsd2si(P) {\n  i64 n;\n  union DoublePun d;\n  d.i = Read64(GetModrmRegisterXmmPointerRead8(A));\n  n = SseRoundDouble(m, d.f);\n  if (!Rexw(rde)) n &= 0xffffffff;\n  Put64(RegRexrReg(m, rde), n);\n}\n\nstatic void OpVssEdqpCvtsi2ss(P) {\n  union FloatPun f;\n  if (Rexw(rde)) {\n    i64 n = Read64(GetModrmRegisterWordPointerRead8(A));\n    f.f = n;\n    Put32(XmmRexrReg(m, rde), f.i);\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"z3B\"    // res0 = GetRegOrMem[force64bit](RexbRm)\n             \"a2i\"    // arg2 = RexrReg(rde)\n             \"s0a1=\"  // arg1 = machine\n             \"t\"      // arg0 = res0\n             \"m\",     // call function (d1)\n             RexrReg(rde), Int64ToFloat);\n    }\n  } else {\n    i32 n = Read32(GetModrmRegisterWordPointerRead4(A));\n    f.f = n;\n    Put32(XmmRexrReg(m, rde), f.i);\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"z2B\"    // res0 = GetRegOrMem[force32bit](RexbRm)\n             \"a2i\"    // arg2 = RexrReg(rde)\n             \"s0a1=\"  // arg1 = machine\n             \"t\"      // arg0 = res0\n             \"m\",     // call function (d1)\n             RexrReg(rde), Int32ToFloat);\n    }\n  }\n}\n\nstatic void OpVsdEdqpCvtsi2sd(P) {\n  union DoublePun d;\n  if (Rexw(rde)) {\n    d.f = (i64)Read64(GetModrmRegisterWordPointerRead8(A));\n    Put64(XmmRexrReg(m, rde), d.i);\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"z3B\"    // res0 = GetRegOrMem[force64bit](RexbRm)\n             \"a2i\"    // arg2 = RexrReg(rde)\n             \"s0a1=\"  // arg1 = machine\n             \"t\"      // arg0 = res0\n             \"m\",     // call function (d1)\n             RexrReg(rde), Int64ToDouble);\n    }\n  } else {\n    d.f = (i32)Read32(GetModrmRegisterWordPointerRead4(A));\n    Put64(XmmRexrReg(m, rde), d.i);\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"z2B\"    // res0 = GetRegOrMem[force32bit](RexbRm)\n             \"a2i\"    // arg2 = RexrReg(rde)\n             \"s0a1=\"  // arg1 = machine\n             \"t\"      // arg0 = res0\n             \"m\",     // call function (d1)\n             RexrReg(rde), Int32ToDouble);\n    }\n  }\n}\n\nstatic void OpVpsQpiCvtpi2ps(P) {\n  u8 *p;\n  i32 i[2];\n  union FloatPun f[2];\n  p = GetModrmRegisterMmPointerRead8(A);\n  i[0] = Read32(p + 0);\n  i[1] = Read32(p + 4);\n  f[0].f = i[0];\n  f[1].f = i[1];\n  Put32(XmmRexrReg(m, rde) + 0, f[0].i);\n  Put32(XmmRexrReg(m, rde) + 4, f[1].i);\n}\n\nstatic void OpVpdQpiCvtpi2pd(P) {\n  u8 *p;\n  i32 n[2];\n  union DoublePun f[2];\n  p = GetModrmRegisterMmPointerRead8(A);\n  n[0] = Read32(p + 0);\n  n[1] = Read32(p + 4);\n  f[0].f = n[0];\n  f[1].f = n[1];\n  Put64(XmmRexrReg(m, rde) + 0, f[0].i);\n  Put64(XmmRexrReg(m, rde) + 8, f[1].i);\n}\n\nstatic void OpPpiWpsqCvtps2pi(P) {\n  u8 *p;\n  unsigned i;\n  i32 n[2];\n  union FloatPun f[2];\n  p = GetModrmRegisterXmmPointerRead8(A);\n  f[0].i = Read32(p + 0 * 4);\n  f[1].i = Read32(p + 1 * 4);\n  switch ((m->mxcsr & kMxcsrRc) >> 13) {\n    case 0:\n      for (i = 0; i < 2; ++i) n[i] = rintf(f[i].f);\n      break;\n    case 1:\n      for (i = 0; i < 2; ++i) n[i] = floorf(f[i].f);\n      break;\n    case 2:\n      for (i = 0; i < 2; ++i) n[i] = ceilf(f[i].f);\n      break;\n    case 3:\n      for (i = 0; i < 2; ++i) n[i] = truncf(f[i].f);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n  Put32(MmReg(m, rde) + 0, n[0]);\n  Put32(MmReg(m, rde) + 4, n[1]);\n}\n\nstatic void OpPpiWpsqCvttps2pi(P) {\n  u8 *p;\n  i32 n[2];\n  union FloatPun f[2];\n  p = GetModrmRegisterXmmPointerRead8(A);\n  f[0].i = Read32(p + 0);\n  f[1].i = Read32(p + 4);\n  n[0] = f[0].f;\n  n[1] = f[1].f;\n  Put32(MmReg(m, rde) + 0, n[0]);\n  Put32(MmReg(m, rde) + 4, n[1]);\n}\n\nstatic void OpPpiWpdCvtpd2pi(P) {\n  u8 *p;\n  unsigned i;\n  i32 n[2];\n  union DoublePun d[2];\n  p = GetModrmRegisterXmmPointerRead16(A);\n  d[0].i = Read64(p + 0);\n  d[1].i = Read64(p + 8);\n  for (i = 0; i < 2; ++i) n[i] = SseRoundDouble(m, d[i].f);\n  Put32(MmReg(m, rde) + 0, n[0]);\n  Put32(MmReg(m, rde) + 4, n[1]);\n}\n\nstatic void OpPpiWpdCvttpd2pi(P) {\n  u8 *p;\n  i32 n[2];\n  union DoublePun d[2];\n  p = GetModrmRegisterXmmPointerRead16(A);\n  d[0].i = Read64(p + 0);\n  d[1].i = Read64(p + 8);\n  n[0] = d[0].f;\n  n[1] = d[1].f;\n  Put32(MmReg(m, rde) + 0, n[0]);\n  Put32(MmReg(m, rde) + 4, n[1]);\n}\n\nstatic void OpVpdWpsCvtps2pd(P) {\n  u8 *p;\n  union FloatPun f[2];\n  union DoublePun d[2];\n  p = GetModrmRegisterXmmPointerRead8(A);\n  f[0].i = Read32(p + 0);\n  f[1].i = Read32(p + 4);\n  d[0].f = f[0].f;\n  d[1].f = f[1].f;\n  Put64(XmmRexrReg(m, rde) + 0, d[0].i);\n  Put64(XmmRexrReg(m, rde) + 8, d[1].i);\n}\n\nstatic void OpVpsWpdCvtpd2ps(P) {\n  u8 *p;\n  union FloatPun f[2];\n  union DoublePun d[2];\n  p = GetModrmRegisterXmmPointerRead16(A);\n  d[0].i = Read64(p + 0);\n  d[1].i = Read64(p + 8);\n  f[0].f = d[0].f;\n  f[1].f = d[1].f;\n  Put32(XmmRexrReg(m, rde) + 0, f[0].i);\n  Put32(XmmRexrReg(m, rde) + 4, f[1].i);\n}\n\nstatic void OpVssWsdCvtsd2ss(P) {\n  union FloatPun f;\n  union DoublePun d;\n  d.i = Read64(GetModrmRegisterXmmPointerRead8(A));\n  f.f = d.f;\n  Put32(XmmRexrReg(m, rde), f.i);\n}\n\nstatic void OpVsdWssCvtss2sd(P) {\n  union FloatPun f;\n  union DoublePun d;\n  f.i = Read32(GetModrmRegisterXmmPointerRead4(A));\n  d.f = f.f;\n  Put64(XmmRexrReg(m, rde), d.i);\n}\n\nstatic void OpVpsWdqCvtdq2ps(P) {\n  u8 *p;\n  i32 n[4];\n  union FloatPun f[4];\n  p = GetModrmRegisterXmmPointerRead16(A);\n  n[0] = Read32(p + 0 * 4);\n  n[1] = Read32(p + 1 * 4);\n  n[2] = Read32(p + 2 * 4);\n  n[3] = Read32(p + 3 * 4);\n  f[0].f = n[0];\n  f[1].f = n[1];\n  f[2].f = n[2];\n  f[3].f = n[3];\n  Put32(XmmRexrReg(m, rde) + 0 * 4, f[0].i);\n  Put32(XmmRexrReg(m, rde) + 1 * 4, f[1].i);\n  Put32(XmmRexrReg(m, rde) + 2 * 4, f[2].i);\n  Put32(XmmRexrReg(m, rde) + 3 * 4, f[3].i);\n}\n\nstatic void OpVpdWdqCvtdq2pd(P) {\n  u8 *p;\n  i32 n[2];\n  union DoublePun d[2];\n  p = GetModrmRegisterXmmPointerRead8(A);\n  n[0] = Read32(p + 0 * 4);\n  n[1] = Read32(p + 1 * 4);\n  d[0].f = n[0];\n  d[1].f = n[1];\n  Put64(XmmRexrReg(m, rde) + 0, d[0].i);\n  Put64(XmmRexrReg(m, rde) + 8, d[1].i);\n}\n\nstatic void OpVdqWpsCvttps2dq(P) {\n  u8 *p;\n  i32 n[4];\n  union FloatPun f[4];\n  p = GetModrmRegisterXmmPointerRead16(A);\n  f[0].i = Read32(p + 0 * 4);\n  f[1].i = Read32(p + 1 * 4);\n  f[2].i = Read32(p + 2 * 4);\n  f[3].i = Read32(p + 3 * 4);\n  n[0] = f[0].f;\n  n[1] = f[1].f;\n  n[2] = f[2].f;\n  n[3] = f[3].f;\n  Put32(XmmRexrReg(m, rde) + 0 * 4, n[0]);\n  Put32(XmmRexrReg(m, rde) + 1 * 4, n[1]);\n  Put32(XmmRexrReg(m, rde) + 2 * 4, n[2]);\n  Put32(XmmRexrReg(m, rde) + 3 * 4, n[3]);\n}\n\nstatic void OpVdqWpsCvtps2dq(P) {\n  u8 *p;\n  unsigned i;\n  i32 n[4];\n  union FloatPun f[4];\n  p = GetModrmRegisterXmmPointerRead16(A);\n  f[0].i = Read32(p + 0 * 4);\n  f[1].i = Read32(p + 1 * 4);\n  f[2].i = Read32(p + 2 * 4);\n  f[3].i = Read32(p + 3 * 4);\n  switch ((m->mxcsr & kMxcsrRc) >> 13) {\n    case 0:\n      for (i = 0; i < 4; ++i) n[i] = rintf(f[i].f);\n      break;\n    case 1:\n      for (i = 0; i < 4; ++i) n[i] = floorf(f[i].f);\n      break;\n    case 2:\n      for (i = 0; i < 4; ++i) n[i] = ceilf(f[i].f);\n      break;\n    case 3:\n      for (i = 0; i < 4; ++i) n[i] = truncf(f[i].f);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n  Put32(XmmRexrReg(m, rde) + 0 * 4, n[0]);\n  Put32(XmmRexrReg(m, rde) + 1 * 4, n[1]);\n  Put32(XmmRexrReg(m, rde) + 2 * 4, n[2]);\n  Put32(XmmRexrReg(m, rde) + 3 * 4, n[3]);\n}\n\nstatic void OpVdqWpdCvttpd2dq(P) {\n  u8 *p;\n  i32 n[2];\n  union DoublePun d[2];\n  p = GetModrmRegisterXmmPointerRead16(A);\n  d[0].i = Read64(p + 0);\n  d[1].i = Read64(p + 8);\n  n[0] = d[0].f;\n  n[1] = d[1].f;\n  Put32(XmmRexrReg(m, rde) + 0, n[0]);\n  Put32(XmmRexrReg(m, rde) + 4, n[1]);\n}\n\nstatic void OpVdqWpdCvtpd2dq(P) {\n  u8 *p;\n  i32 n[2];\n  unsigned i;\n  union DoublePun d[2];\n  p = GetModrmRegisterXmmPointerRead16(A);\n  d[0].i = Read64(p + 0);\n  d[1].i = Read64(p + 8);\n  for (i = 0; i < 2; ++i) n[i] = SseRoundDouble(m, d[i].f);\n  Put32(XmmRexrReg(m, rde) + 0, n[0]);\n  Put32(XmmRexrReg(m, rde) + 4, n[1]);\n}\n\nstatic void OpCvt(P, unsigned long op) {\n  IGNORE_RACES_START();\n  switch (op | Rep(rde) | Osz(rde)) {\n    case kOpCvt0f2a + 0:\n      OpVpsQpiCvtpi2ps(A);\n      break;\n    case kOpCvt0f2a + 1:\n      OpVpdQpiCvtpi2pd(A);\n      break;\n    case kOpCvt0f2a + 2:\n      OpVsdEdqpCvtsi2sd(A);  // #1 hot (6796033)\n      break;\n    case kOpCvt0f2a + 3:\n      OpVssEdqpCvtsi2ss(A);\n      break;\n    case kOpCvtt0f2c + 0:\n      OpPpiWpsqCvttps2pi(A);\n      break;\n    case kOpCvtt0f2c + 1:\n      OpPpiWpdCvttpd2pi(A);\n      break;\n    case kOpCvtt0f2c + 2:  // #2 hot (111540)\n      OpGdqpWsdCvttsd2si(A);\n      break;\n    case kOpCvtt0f2c + 3:\n      OpGdqpWssCvttss2si(A);\n      break;\n    case kOpCvt0f2d + 0:\n      OpPpiWpsqCvtps2pi(A);\n      break;\n    case kOpCvt0f2d + 1:\n      OpPpiWpdCvtpd2pi(A);\n      break;\n    case kOpCvt0f2d + 2:\n      OpGdqpWsdCvtsd2si(A);\n      break;\n    case kOpCvt0f2d + 3:\n      OpGdqpWssCvtss2si(A);\n      break;\n    case kOpCvt0f5a + 0:\n      OpVpdWpsCvtps2pd(A);\n      break;\n    case kOpCvt0f5a + 1:\n      OpVpsWpdCvtpd2ps(A);\n      break;\n    case kOpCvt0f5a + 2:\n      OpVssWsdCvtsd2ss(A);\n      break;\n    case kOpCvt0f5a + 3:\n      OpVsdWssCvtss2sd(A);\n      break;\n    case kOpCvt0f5b + 0:\n      OpVpsWdqCvtdq2ps(A);\n      break;\n    case kOpCvt0f5b + 1:\n      OpVdqWpsCvtps2dq(A);\n      break;\n    case kOpCvt0f5b + 3:\n      OpVdqWpsCvttps2dq(A);\n      break;\n    case kOpCvt0fE6 + 1:\n      OpVdqWpdCvtpd2dq(A);\n      break;\n    case kOpCvt0fE6 + 2:\n      OpVdqWpdCvttpd2dq(A);\n      break;\n    case kOpCvt0fE6 + 3:\n      OpVpdWdqCvtdq2pd(A);\n      break;\n    default:\n      OpUdImpl(m);\n  }\n  IGNORE_RACES_END();\n}\n\nvoid OpCvt0f2a(P) {\n  OpCvt(A, kOpCvt0f2a);\n}\n\nvoid OpCvtt0f2c(P) {\n  OpCvt(A, kOpCvtt0f2c);\n}\n\nvoid OpCvt0f2d(P) {\n  OpCvt(A, kOpCvt0f2d);\n}\n\nvoid OpCvt0f5a(P) {\n  OpCvt(A, kOpCvt0f5a);\n}\n\nvoid OpCvt0f5b(P) {\n  OpCvt(A, kOpCvt0f5b);\n}\n\nvoid OpCvt0fE6(P) {\n  OpCvt(A, kOpCvt0fE6);\n}\n"
  },
  {
    "path": "blink/debug.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/debug.h\"\n\n#include <errno.h>\n#include <fcntl.h>\n#include <setjmp.h>\n#include <signal.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/dis.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/loader.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/overlays.h\"\n#include \"blink/stats.h\"\n#include \"blink/thread.h\"\n#include \"blink/tsan.h\"\n#include \"blink/util.h\"\n#include \"blink/x86.h\"\n\n#ifdef HAVE_SCHED_H\n#include <sched.h>\n#endif\n\n#if defined(HAVE_LIBUNWIND) && !defined(MUSL_CROSS_MAKE)\n#define UNW_LOCAL_ONLY\n#ifdef __x86_64__\n#include <libunwind-x86_64.h>\n#else\n#include <libunwind.h>\n#endif\n#endif\n\n#define FAKE_WORD 0x6660666066660666\n\n#define MAX_BACKTRACE_LINES 64\n\n#define APPEND(...) o += snprintf(b + o, o > n ? 0 : n - o, __VA_ARGS__)\n\n_Thread_local static jmp_buf g_busted;\n\nconst char *GetBlinkBacktrace(void) {\n#if defined(HAVE_LIBUNWIND) && !defined(MUSL_CROSS_MAKE)\n  _Thread_local static char b[2048];\n  int o = 0;\n  char sym[256];\n  int n = sizeof(b);\n  unw_cursor_t cursor;\n  unw_context_t context;\n  unw_word_t offset, pc;\n  unw_getcontext(&context);\n  unw_init_local(&cursor, &context);\n  APPEND(\"blink backtrace\");\n  while (unw_step(&cursor) > 0) {\n    unw_get_reg(&cursor, UNW_REG_IP, &pc);\n    if (!pc) break;\n    APPEND(\"\\n\\t%lx \", pc);\n    if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {\n      APPEND(\"%s+%ld\", sym, offset);\n    } else {\n      APPEND(\"<unknown>\");\n    }\n  }\n  return b;\n#else\n  return \"<blink backtrace unavailable>\";\n#endif\n}\n\nstatic void OnBusted(int sig) {\n  longjmp(g_busted, sig);\n}\n\nstatic i64 ReadWord(int mode, u8 *p) {\n  switch (mode) {\n    default:\n    case XED_MODE_LONG:\n      return Load64Unlocked(p);\n    case XED_MODE_LEGACY:\n      return Load32(p);\n    case XED_MODE_REAL:\n      return Load16(p);\n  }\n}\n\ni64 ReadWordSafely(int mode, u8 *p) {\n  i64 res;\n  sigset_t oldss, newss;\n  struct sigaction newsa, oldsa[2];\n  newsa.sa_flags = 0;\n  newsa.sa_handler = OnBusted;\n  sigemptyset(&newsa.sa_mask);\n  sigemptyset(&newss);\n  sigaddset(&newss, SIGBUS);\n  sigaddset(&newss, SIGSEGV);\n  sigaction(SIGBUS, &newsa, oldsa + 0);\n  sigaction(SIGSEGV, &newsa, oldsa + 1);\n  pthread_sigmask(SIG_UNBLOCK, &newss, &oldss);\n  if (!setjmp(g_busted)) {\n    res = ReadWord(mode, p);\n  } else {\n    res = FAKE_WORD >> ((8 - (2 << mode)) * 8);\n  }\n  pthread_sigmask(SIG_SETMASK, &oldss, 0);\n  sigaction(SIGSEGV, oldsa + 1, 0);\n  sigaction(SIGBUS, oldsa + 0, 0);\n  return res;\n}\n\n// TODO(jart): This function should be immune to SIGSEGV and SIGBUS.\nint GetInstruction(struct Machine *m, i64 pc, struct XedDecodedInst *x) {\n  int i, rc, err;\n  u8 copy[15], *toil, *addr;\n  BEGIN_NO_PAGE_FAULTS;\n  if ((addr = SpyAddress(m, pc))) {\n    if ((i = 4096 - (pc & 4095)) >= 15) {\n      if (!DecodeInstruction(x, addr, 15, m->mode.omode)) {\n        rc = 0;\n      } else {\n        rc = kMachineDecodeError;\n      }\n    } else if ((toil = SpyAddress(m, pc + i))) {\n      memcpy(copy, addr, i);\n      memcpy(copy + i, toil, 15 - i);\n      if (!DecodeInstruction(x, copy, 15, m->mode.omode)) {\n        rc = 0;\n      } else {\n        rc = kMachineDecodeError;\n      }\n    } else if (!(err = DecodeInstruction(x, addr, i, m->mode.omode))) {\n      rc = 0;\n    } else if (err == XED_ERROR_BUFFER_TOO_SHORT) {\n      rc = kMachineSegmentationFault;\n    } else {\n      rc = kMachineDecodeError;\n    }\n  } else {\n    memset(x, 0, sizeof(*x));\n    rc = kMachineSegmentationFault;\n  }\n  END_NO_PAGE_FAULTS;\n  return rc;\n}\n\nconst char *DescribeCpuFlags(int flags) {\n  _Thread_local static char b[7];\n  b[0] = (flags & OF) ? 'O' : '.';\n  b[1] = (flags & SF) ? 'S' : '.';\n  b[2] = (flags & ZF) ? 'Z' : '.';\n  b[3] = (flags & AF) ? 'A' : '.';\n  b[4] = (flags & PF) ? 'P' : '.';\n  b[5] = (flags & CF) ? 'C' : '.';\n  return b;\n}\n\nconst char *DescribeOp(struct Machine *m, i64 pc) {\n  _Thread_local static char b[256];\n  int e, i, k, o = 0, n = sizeof(b);\n  struct Dis d = {true};\n  if (!(e = GetInstruction(m, pc, d.xedd))) {\n#ifndef DISABLE_DISASSEMBLER\n    char spec[64];\n    o = DisInst(&d, b, DisSpec(d.xedd, spec)) - b;\n#else\n    APPEND(\".byte\");\n#endif\n  }\n  if (e != kMachineSegmentationFault) {\n    k = MAX(8, d.xedd->length);\n    for (i = 0; i < k; ++i) {\n      APPEND(\" %02x\", d.xedd->bytes[i]);\n    }\n  } else {\n    APPEND(\"segfault\");\n  }\n#ifndef DISABLE_DISASSEMBLER\n  DisFree(&d);\n#endif\n  return b;\n}\n\nvoid PrintFds(struct Fds *fds) {\n  struct Dll *e;\n  LOGF(\"%-8s %-8s\", \"fildes\", \"oflags\");\n  for (e = dll_first(fds->list); e; e = dll_next(fds->list, e)) {\n    LOGF(\"%-8d %-8x\", FD_CONTAINER(e)->fildes, FD_CONTAINER(e)->oflags);\n  }\n}\n\nconst char *GetBacktrace(struct Machine *m) {\n  _Thread_local static char b[16384];\n  int o = 0;\n  int n = sizeof(b);\n#ifndef DISABLE_BACKTRACE\n  struct Dis dis = {true};\n  u8 *r;\n  int i;\n  i64 sym, sp, bp, rp;\n  char kAlignmentMask[] = {3, 3, 15};\n#endif\n\n  if (!m) return \"<machine state unavailable>\";\n\n  BEGIN_NO_PAGE_FAULTS;\n\n#ifndef DISABLE_BACKTRACE\n  if (!m->system->dis) {\n    m->system->dis = &dis;\n    LoadDebugSymbols(m->system);\n  }\n#endif\n\n  APPEND(\" PC %\" PRIx64 \" %s\\n\\t\"\n         \" AX %016\" PRIx64 \" \"\n         \" CX %016\" PRIx64 \" \"\n         \" DX %016\" PRIx64 \" \"\n         \" BX %016\" PRIx64 \"\\n\\t\"\n         \" SP %016\" PRIx64 \" \"\n         \" BP %016\" PRIx64 \" \"\n         \" SI %016\" PRIx64 \" \"\n         \" DI %016\" PRIx64 \"\\n\\t\"\n         \" R8 %016\" PRIx64 \" \"\n         \" R9 %016\" PRIx64 \" \"\n         \"R10 %016\" PRIx64 \" \"\n         \"R11 %016\" PRIx64 \"\\n\\t\"\n         \"R12 %016\" PRIx64 \" \"\n         \"R13 %016\" PRIx64 \" \"\n         \"R14 %016\" PRIx64 \" \"\n         \"R15 %016\" PRIx64 \"\\n\\t\"\n         \" FS %016\" PRIx64 \" \"\n         \" GS %016\" PRIx64 \" \"\n         \"OPS %-16ld \"\n         \"FLG %s\\n\\t\"\n         \"%s\\n\\t\",\n         m->cs.base + MaskAddress(m->mode.omode, m->ip),\n         DescribeOp(m, GetPc(m)), Get64(m->ax), Get64(m->cx), Get64(m->dx),\n         Get64(m->bx), Get64(m->sp), Get64(m->bp), Get64(m->si), Get64(m->di),\n         Get64(m->r8), Get64(m->r9), Get64(m->r10), Get64(m->r11),\n         Get64(m->r12), Get64(m->r13), Get64(m->r14), Get64(m->r15), m->fs.base,\n         m->gs.base, GET_COUNTER(instructions_decoded),\n         DescribeCpuFlags(m->flags), g_progname);\n\n#ifndef DISABLE_BACKTRACE\n  rp = m->ip;\n  bp = Get64(m->bp);\n  sp = Get64(m->sp);\n  for (i = 0; i < MAX_BACKTRACE_LINES;) {\n    if (i) APPEND(\"\\n\\t\");\n    sym = DisFindSym(m->system->dis, rp);\n    APPEND(\"%012\" PRIx64 \" %012\" PRIx64 \" %s\", m->ss.base + bp, rp,\n           sym != -1 ? m->system->dis->syms.p[sym].name : \"UNKNOWN\");\n    if (sym != -1 && rp != m->system->dis->syms.p[sym].addr) {\n      APPEND(\"+%#\" PRIx64 \"\", rp - m->system->dis->syms.p[sym].addr);\n    }\n    if (!bp) break;\n    if (bp < sp) {\n      APPEND(\" [STRAY]\");\n    } else if (bp - sp <= 0x1000) {\n      APPEND(\" %\" PRId64 \" bytes\", bp - sp);\n    }\n    if (bp & kAlignmentMask[m->mode.omode] && i) {\n      APPEND(\" [MISALIGN]\");\n    }\n    ++i;\n    if (((m->ss.base + bp) & 0xfff) > 0xff0) break;\n    if (!(r = SpyAddress(m, m->ss.base + bp))) {\n      APPEND(\" [CORRUPT FRAME POINTER]\");\n      break;\n    }\n    sp = bp;\n    bp = ReadWordSafely(m->mode.omode, r + 0);\n    rp = ReadWordSafely(m->mode.omode, r + 8);\n  }\n  if (m->system->dis == &dis) {\n    DisFree(&dis);\n    m->system->dis = 0;\n  }\n#endif\n\n  END_NO_PAGE_FAULTS;\n  return b;\n}\n\nbool CheckMemoryInvariants(struct System *s) {\n  // TODO(jart): rewrite our memory accounting code\n  return true;\n}\n"
  },
  {
    "path": "blink/debug.h",
    "content": "#ifndef BLINK_DEBUG_H_\n#define BLINK_DEBUG_H_\n#include <stddef.h>\n\n#include \"blink/fds.h\"\n#include \"blink/types.h\"\n\nvoid DumpHex(u8 *, size_t);\nvoid PrintFds(struct Fds *);\ni64 ReadWordSafely(int, u8 *);\nconst char *DescribeProt(int);\nconst char *DescribeMopcode(int);\nconst char *DescribeCpuFlags(int);\nconst char *GetBlinkBacktrace(void);\n\n#endif /* BLINK_DEBUG_H_ */\n"
  },
  {
    "path": "blink/debug2.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/dis.h\"\n#include \"blink/dll.h\"\n#include \"blink/elf.h\"\n#include \"blink/endian.h\"\n#include \"blink/fspath.h\"\n#include \"blink/loader.h\"\n#include \"blink/machine.h\"\n#include \"blink/map.h\"\n#include \"blink/overlays.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n\n#define READ32(p) Read32((const u8 *)(p))\n\nstatic void LoadFileMapSymbols(struct System *s, struct FileMap *fm) {\n  int fd;\n  i64 base;\n  void *map;\n  char *path;\n  int oflags;\n  struct stat st;\n  char pathdbg[PATH_MAX];\n  if (fm->offset) return;\n  oflags = O_RDONLY | O_CLOEXEC | O_NOCTTY;\n  snprintf(pathdbg, sizeof(pathdbg), \"%s.dbg\", fm->path);\n  if ((fd = VfsOpen(AT_FDCWD, (path = pathdbg), oflags, 0)) != -1 ||\n      (fd = VfsOpen(AT_FDCWD, (path = fm->path), oflags, 0)) != -1) {\n    if (VfsFstat(fd, &st) != -1 &&\n        (map = Mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0, \"debug\")) !=\n            MAP_FAILED) {\n      if (st.st_size >= sizeof(Elf64_Ehdr_) &&\n          READ32(map) == READ32(\"\\177ELF\") &&\n          GetElfMemorySize((Elf64_Ehdr_ *)map, st.st_size, &base) != -1) {\n        DisLoadElf(s->dis, (Elf64_Ehdr_ *)map, st.st_size, fm->virt - base);\n        if (s->onsymbols) {\n          s->onsymbols(s);\n        }\n      } else {\n        ELF_LOGF(\"%s: not a valid elf image\", path);\n      }\n      unassert(!Munmap(map, st.st_size));\n    } else {\n      ELF_LOGF(\"%s: mmap failed: %s\", path, DescribeHostErrno(errno));\n    }\n    unassert(!VfsClose(fd));\n  } else {\n    ELF_LOGF(\"%s: open failed: %s\", path, DescribeHostErrno(errno));\n  }\n}\n\nvoid LoadDebugSymbols(struct System *s) {\n  struct Dll *e;\n  unassert(s->dis);\n  s->onfilemap = LoadFileMapSymbols;\n  for (e = dll_first(s->filemaps); e; e = dll_next(s->filemaps, e)) {\n    LoadFileMapSymbols(s, FILEMAP_CONTAINER(e));\n  }\n}\n"
  },
  {
    "path": "blink/demangle.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/uio.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/debug.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/sigwinch.h\"\n#include \"blink/thread.h\"\n#include \"blink/util.h\"\n\nstruct CxxFilt {\n  pthread_once_t_ once;\n  pthread_mutex_t_ lock;\n  int reader;\n  int writer;\n  int pid;\n} g_cxxfilt = {\n    PTHREAD_ONCE_INIT_,\n};\n\nstatic void InitCxxFilt(void) {\n  pthread_mutexattr_t attr;\n  unassert(!pthread_mutexattr_init(&attr));\n  unassert(!pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE));\n  unassert(!pthread_mutex_init(&g_cxxfilt.lock, &attr));\n  unassert(!pthread_mutexattr_destroy(&attr));\n}\n\nstatic void CloseCxxFiltUnlocked(void) {\n  sigset_t ss, oldss;\n  if (g_cxxfilt.pid > 0) {\n    LOGF(\"closing pipe to c++filt\");\n    unassert(!sigemptyset(&ss));\n    unassert(!sigaddset(&ss, SIGCHLD));\n    unassert(!pthread_sigmask(SIG_BLOCK, &ss, &oldss));\n    unassert(!close(g_cxxfilt.writer));\n    unassert(waitpid(g_cxxfilt.pid, 0, 0) == g_cxxfilt.pid);\n    unassert(!close(g_cxxfilt.reader));\n    unassert(!pthread_sigmask(SIG_SETMASK, &oldss, 0));\n    g_cxxfilt.pid = -1;\n  }\n}\n\nstatic void CloseCxxFilt(void) {\n  LOCK(&g_cxxfilt.lock);\n  CloseCxxFiltUnlocked();\n  UNLOCK(&g_cxxfilt.lock);\n}\n\nstatic void CxxFiltBeforeFork(void) {\n  LOGF(\"CxxFiltBeforeFork\");\n  LOCK(&g_cxxfilt.lock);\n}\n\nstatic void CxxFiltAfterForkChild(void) {\n  LOGF(\"CxxFiltAfterForkChild\");\n  if (g_cxxfilt.pid > 0) {\n    unassert(!close(g_cxxfilt.writer));\n    unassert(!close(g_cxxfilt.reader));\n    g_cxxfilt.pid = 0;\n  }\n  UNLOCK(&g_cxxfilt.lock);\n}\n\nstatic void CxxFiltAfterForkParent(void) {\n  LOGF(\"CxxFiltAfterForkParent\");\n  UNLOCK(&g_cxxfilt.lock);\n}\n\nstatic void SpawnCxxFilt(void) {\n  sigset_t ss;\n  const char *cxxfilt;\n  char executable[PATH_MAX];\n  int pipefds[2][2] = {{-1, -1}, {-1, -1}};\n  cxxfilt = getenv(\"CXXFILT\");\n  if (cxxfilt && !*cxxfilt) {\n    LOGF(\"$CXXFILT was empty string, disabling c++ demangling\");\n    g_cxxfilt.pid = -1;\n    return;\n  }\n  if (!cxxfilt) cxxfilt = \"c++filt\";\n  if (!Commandv(cxxfilt, executable, sizeof(executable))) {\n    LOGF(\"path lookup of $CXXFILT (%s) failed!\", cxxfilt);\n    g_cxxfilt.pid = -1;\n    return;\n  }\n  LOGF(\"spawning c++ symbol demangler %s\", executable);\n  if (pipe(pipefds[1]) == -1 ||  //\n      pipe(pipefds[0]) == -1 ||  //\n      (g_cxxfilt.pid = fork()) == -1) {\n    LOGF(\"can't launch c++ demangler: %s\", DescribeHostErrno(errno));\n    close(pipefds[0][0]);\n    close(pipefds[0][1]);\n    close(pipefds[1][0]);\n    close(pipefds[1][1]);\n    g_cxxfilt.pid = -1;\n    return;\n  }\n  if (!g_cxxfilt.pid) {\n    unassert(!sigemptyset(&ss));\n    unassert(!sigaddset(&ss, SIGINT));\n    unassert(!sigaddset(&ss, SIGQUIT));\n    unassert(!sigaddset(&ss, SIGWINCH));\n    unassert(!pthread_sigmask(SIG_BLOCK, &ss, 0));\n    unassert(dup2(pipefds[1][0], 0) == 0);\n    unassert(dup2(pipefds[0][1], 1) == 1);\n    if (pipefds[0][0] > 1) unassert(!close(pipefds[0][0]));\n    if (pipefds[0][1] > 1) unassert(!close(pipefds[0][1]));\n    if (pipefds[1][0] > 1) unassert(!close(pipefds[1][0]));\n    if (pipefds[1][1] > 1) unassert(!close(pipefds[1][1]));\n    execv(executable, (char *const[]){(char *)cxxfilt, 0});\n    _exit(EXIT_FAILURE_EXEC_FAILED);\n  }\n  unassert(!close(pipefds[0][1]));\n  unassert(!close(pipefds[1][0]));\n  g_cxxfilt.reader = fcntl(pipefds[0][0], F_DUPFD_CLOEXEC, kMinBlinkFd);\n  unassert(g_cxxfilt.reader != -1);\n  unassert(!close(pipefds[0][0]));\n  g_cxxfilt.writer = fcntl(pipefds[1][1], F_DUPFD_CLOEXEC, kMinBlinkFd);\n  unassert(g_cxxfilt.writer != -1);\n  unassert(!close(pipefds[1][1]));\n  unassert(!atexit(CloseCxxFilt));\n  unassert(!pthread_atfork(CxxFiltBeforeFork,       //\n                           CxxFiltAfterForkParent,  //\n                           CxxFiltAfterForkChild));\n}\n\nstatic char *CopySymbol(char *p, size_t pn, const char *s, size_t sn) {\n  size_t extra;\n  bool showdots, iscomplicated;\n  unassert(pn >= 1 + 3 + 1 + 1);\n  iscomplicated = memchr(s, ' ', sn) || memchr(s, '(', sn);\n  extra = 1;\n  if (iscomplicated) extra += 2;\n  if (sn + extra > pn) {\n    sn = pn - extra - 3;\n    showdots = true;\n  } else {\n    showdots = false;\n  }\n  if (iscomplicated) *p++ = '\"';\n  if (sn) {\n    memcpy(p, s, sn);\n    p = p + sn;\n  }\n  if (showdots) p = stpcpy(p, \"...\");\n  if (iscomplicated) *p++ = '\"';\n  *p = '\\0';\n  return p;\n}\n\nstatic char *DemangleCxxFilt(char *p, size_t pn, const char *s, size_t sn) {\n  char *res;\n  ssize_t rc;\n  size_t got;\n  struct iovec iov[2];\n  static char buf[1024];\n  buf[0] = '\\n';\n  iov[0].iov_base = (void *)s;\n  iov[0].iov_len = sn;\n  iov[1].iov_base = buf;\n  iov[1].iov_len = 1;\n  if (writev(g_cxxfilt.writer, iov, ARRAYLEN(iov)) != -1) {\n    if ((rc = read(g_cxxfilt.reader, buf, sizeof(buf))) != -1) {\n      got = rc;\n      if (got >= 2 && buf[got - 1] == '\\n') {\n        if (buf[got - 2] == '\\r') --got;\n        --got;\n        res = CopySymbol(p, pn, buf, got);\n      } else {\n        LOGF(\"c++filt read didn't end with a newline!\");\n        res = 0;\n      }\n    } else {\n      LOGF(\"failed to read from c++filt pipe: %s\", DescribeHostErrno(errno));\n      res = 0;\n    }\n  } else {\n    LOGF(\"failed to write to c++filt pipe: %s\", DescribeHostErrno(errno));\n    res = 0;\n  }\n  return res;\n}\n\n/**\n * Decrypts C++ symbol.\n *\n * This function turns C++ symbols from their linkable name (e.g.\n * `_ZN15set_early_dwarfD1Ev`) into a readable name (e.g.\n * `set_early_dwarf::~set_early_dwarf()`). If the symbol in question\n * isn't from a C++ program, then the symbol is simply copied to the\n * output. The same applies if the translation fails, which means this\n * function always succeeds.\n *\n * Filtering is performed by piping symbols to the `c++filt` command. If\n * this program isn't on the `$PATH` or has a different name, then that\n * name or path may be set using the `$CXXFILT` environment variable. If\n * this environment variable is present and contains an empty string,\n * then C++ symbol translation will be disabled.\n *\n * @param p is output buffer\n * @param symbol is nul-terminated link-time symbol to translate\n * @param n is the number of bytes available in `p`\n * @return pointer to NUL byte, cf. stcpy()\n */\nchar *Demangle(char *p, const char *symbol, size_t n) {\n  int cs;\n  char *r;\n  size_t sn;\n  sigset_t ss, oldss;\n  sn = strlen(symbol);\n  if (StartsWith(symbol, \"_Z\")) {\n#ifdef HAVE_PTHREAD_SETCANCELSTATE\n    unassert(!pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs));\n#endif\n    unassert(!pthread_once_(&g_cxxfilt.once, InitCxxFilt));\n    LOCK(&g_cxxfilt.lock);\n    if (g_cxxfilt.pid != -1) {\n      unassert(!sigemptyset(&ss));\n      unassert(!sigaddset(&ss, SIGINT));\n      unassert(!sigaddset(&ss, SIGALRM));\n      unassert(!sigaddset(&ss, SIGWINCH));\n      unassert(!pthread_sigmask(SIG_BLOCK, &ss, &oldss));\n      if (!g_cxxfilt.pid) {\n        SpawnCxxFilt();\n      }\n      if (g_cxxfilt.pid != -1) {\n        r = DemangleCxxFilt(p, n, symbol, sn);\n        if (!r) {\n          CloseCxxFiltUnlocked();\n        }\n      } else {\n        r = 0;\n      }\n      unassert(!pthread_sigmask(SIG_SETMASK, &oldss, 0));\n    } else {\n      r = 0;\n    }\n    UNLOCK(&g_cxxfilt.lock);\n#ifdef HAVE_PTHREAD_SETCANCELSTATE\n    unassert(!pthread_setcancelstate(cs, 0));\n#endif\n  } else {\n    r = 0;\n  }\n  if (!r) {\n    r = CopySymbol(p, n, symbol, sn);\n  }\n  return r;\n}\n"
  },
  {
    "path": "blink/deps.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/flags.h\"\n#include \"blink/rde.h\"\n#include \"blink/x86.h\"\n\nstatic bool IsJump(u64 rde) {\n  int op = Mopcode(rde);\n  return op == 0x0E9 ||  // jmp  Jvds\n         op == 0x0EB ||  // jmp  Jbs\n         op == 0x0E8;    // call Jvds\n}\n\nstatic bool IsConditionalJump(u64 rde) {\n  int op = Mopcode(rde);\n  return (0x070 <= op && op <= 0x07F) ||  // Jcc Jbs\n         (0x180 <= op && op <= 0x18F);    // Jcc Jvds\n}\n\nstatic int CrawlFlags(struct Machine *m,  //\n                      i64 pc,             //\n                      int myflags,        //\n                      int look,           //\n                      int depth) {\n  u64 place;\n  int need, deps;\n  for (need = 0;;) {\n    place = pc;\n    SPX_LOGF(\"%\" PRIx64 \" %*s%s\", pc, depth * 2, \"\", DescribeOp(m, pc));\n    if (LoadInstruction2(m, place)) {\n      WriteCod(\"/\\tfailed to speculate instruction at %\" PRIx64 \"\\n\", place);\n      return -1;\n    }\n    pc += Oplength(m->xedd->op.rde);\n    deps = GetFlagDeps(m->xedd->op.rde);\n    if (deps) {\n      WriteCod(\"/\\top at %\" PRIx64 \" needs %s\\n\", place,\n               DescribeCpuFlags(deps));\n    }\n    need |= deps & myflags;\n    if (!(myflags &= ~GetFlagClobbers(m->xedd->op.rde))) {\n      return need;\n    } else if (!--look) {\n      WriteCod(\"/\\tgiving up on speculation\\n\");\n      return -1;\n    } else if (IsJump(m->xedd->op.rde)) {\n      pc += m->xedd->op.disp;\n    } else if (IsConditionalJump(m->xedd->op.rde)) {\n      need |= CrawlFlags(m, pc + m->xedd->op.disp, myflags, look, depth + 1);\n      if (need == -1) return -1;\n    } else if (ClassifyOp(m->xedd->op.rde) != kOpNormal) {\n      WriteCod(\"/\\tspeculated abnormal op at %\" PRIx64 \"\\n\", place);\n      return -1;\n    }\n  }\n}\n\n// returns bitset of flags read by code at pc, or -1 if unknown\nint GetNeededFlags(struct Machine *m, i64 pc, int myflags) {\n  int rc = CrawlFlags(m, pc, myflags, 32, 0);\n  WriteCod(\"/\\t%\" PRIx64 \" needs flags %s\\n\", pc, DescribeCpuFlags(rc));\n  return rc;\n}\n\n// returns bitset of flags set or undefined by operation\nint GetFlagClobbers(u64 rde) {\n  switch (Mopcode(rde)) {\n    default:\n      return 0;\n    case 0xE8:   // call\n    case 0xC3:   // ret\n      if (Rep(rde)) {\n        return 0;\n      } else {\n        return -1;\n      }\n    case 0x105:  // syscall\n      return -1;\n    case 0x000:  // add byte\n    case 0x001:  // add word\n    case 0x002:  // add byte flip\n    case 0x003:  // add word flip\n    case 0x004:  // add %al  $ib\n    case 0x005:  // add %rax $ivds\n    case 0x008:  // or  byte\n    case 0x009:  // or  word\n    case 0x00A:  // or  byte flip\n    case 0x00B:  // or  word flip\n    case 0x00C:  // or  %al  $ib\n    case 0x00D:  // or  %rax $ivds\n    case 0x010:  // adc byte\n    case 0x011:  // adc word\n    case 0x012:  // adc byte flip\n    case 0x013:  // adc word flip\n    case 0x014:  // adc %al  $ib\n    case 0x015:  // adc %rax $ivds\n    case 0x018:  // sbb byte\n    case 0x019:  // sbb word\n    case 0x01A:  // sbb byte flip\n    case 0x01B:  // sbb word flip\n    case 0x01C:  // sbb %al  $ib\n    case 0x01D:  // sbb %rax $ivds\n    case 0x020:  // and byte\n    case 0x021:  // and word\n    case 0x022:  // and byte flip\n    case 0x023:  // and word flip\n    case 0x024:  // and %al  $ib\n    case 0x025:  // and %rax $ivds\n    case 0x028:  // sub byte\n    case 0x029:  // sub word\n    case 0x02A:  // sub byte flip\n    case 0x02B:  // sub word flip\n    case 0x02C:  // sub %al  $ib\n    case 0x02D:  // sub %rax $ivds\n    case 0x030:  // xor byte\n    case 0x031:  // xor word\n    case 0x032:  // xor byte flip\n    case 0x033:  // xor word flip\n    case 0x034:  // xor %al  $ib\n    case 0x035:  // xor %rax $ivds\n    case 0x038:  // cmp byte\n    case 0x039:  // cmp word\n    case 0x03A:  // cmp byte flip\n    case 0x03B:  // cmp word flip\n    case 0x03C:  // cmp %al  $ib\n    case 0x03D:  // cmp %rax $ivds\n    case 0x080:  // alubireg\n    case 0x081:  // aluwireg\n    case 0x082:  // alubireg\n    case 0x083:  // aluwireg\n    case 0x084:  // alubtest\n    case 0x085:  // aluwtest\n    case 0x0A6:  // cmps\n    case 0x0A7:  // cmps\n    case 0x0A8:  // test %al  $ib\n    case 0x0A9:  // test %rax $ivds\n    case 0x0AE:  // scas\n    case 0x0AF:  // scas\n    case 0x069:  // imul\n    case 0x06B:  // Imul\n    case 0x1AF:  // imul\n    case 0x12E:  // comisd\n    case 0x12F:  // comisd\n    case 0x1A4:  // shld $ib\n    case 0x1A5:  // shld %cl\n    case 0x1AC:  // shrd $ib\n    case 0x1AD:  // shrd %cl\n    case 0x1B0:  // cmpxchg byte\n    case 0x1B1:  // cmpxchg word\n    case 0x1BC:  // bsf\n    case 0x1BD:  // bsr\n    case 0x1C0:  // xadd byte\n    case 0x1C1:  // xadd word\n    case 0x02F:  // das\n    case 0x037:  // aaa\n    case 0x03F:  // aas\n    case 0x0D5:  // aad\n      return CF | ZF | SF | OF | AF | PF;\n    case 0x0C0:  // bsu $ib byte\n    case 0x0C1:  // bsu $ib word\n    case 0x0D0:  // bsu $1  byte\n    case 0x0D1:  // bsu $1  word\n    case 0x0D2:  // bsu %cl byte\n    case 0x0D3:  // bsu %cl word\n      switch (ModrmReg(rde)) {\n        case 0:  // rol\n        case 1:  // ror\n        case 2:  // rcl\n        case 3:  // rcr\n          return OF | CF;\n        case 4:  // shl\n        case 5:  // shr\n        case 6:  // sal\n        case 7:  // sar\n          return CF | ZF | SF | OF | AF | PF;\n        default:\n          __builtin_unreachable();\n      }\n    case 0x0DB:  // fpu\n    case 0x0DF:  // fpu\n      if (IsModrmRegister(rde) && (ModrmReg(rde) == 5 || ModrmReg(rde) == 6)) {\n        return OF | SF | AF;  // fucomip, fcomip\n      } else {\n        return 0;\n      }\n    case 0x0F5:  // cmc\n    case 0x0F8:  // clc\n    case 0x0F9:  // stc\n      return CF;\n    case 0x0F6:  // 0f6\n    case 0x0F7:  // 0f7\n      switch (ModrmReg(rde)) {\n        case 2:  // not\n          return 0;\n        case 0:  // test\n        case 1:  // test\n        case 3:  // neg\n        case 4:  // mul\n        case 5:  // imul\n        case 6:  // div\n        case 7:  // idiv\n          return CF | ZF | SF | OF | AF | PF;\n        default:\n          __builtin_unreachable();\n      }\n    case 0x0FE:\n    case 0x0FF:\n      switch (ModrmReg(rde)) {\n        case 0:  // inc\n        case 1:  // dec\n          return ZF | SF | OF | AF | PF;\n        case 2:  // call *Ev\n        case 3:  // callf *Ev\n          return -1;\n        default:  // call, jmp, jmpf, push\n          return 0;\n      }\n    case 0x1A3:  // bit bt\n    case 0x1AB:  // bit bts\n    case 0x1B3:  // bit btr\n    case 0x1BA:  // bit\n    case 0x1BB:  // bit\n      return CF | SF | OF | AF | PF;\n    case 0x09E:  // sahf\n      return CF | ZF | SF | AF | PF;\n    case 0x09D:  // popf\n      return 0x00ffffff;\n    case 0x1b8:\n      if (Rep(rde) == 3) {\n        return CF | ZF | SF | OF | PF;  // popcnt\n      } else {\n        return 0;\n      }\n    case 0x2f5:\n      if (Rep(rde)) {\n        return 0;  // pdep, pext\n      } else if (!Osz(rde)) {\n        return CF | ZF | SF | OF | AF | PF;  // bzhi\n      } else {\n        return 0;\n      }\n    case 0x2f6:\n      if (Osz(rde)) {\n        return CF;  // adcx\n      } else if (Rep(rde) == 3) {\n        return OF;  // adox\n      } else {\n        return 0;\n      }\n  }\n}\n\n// returns bitset of flags read by operation\nint GetFlagDeps(u64 rde) {\n  switch (Mopcode(rde)) {\n    default:\n      return 0;\n    case 0x010:  // adc byte\n    case 0x011:  // adc word\n    case 0x012:  // adc byte flip\n    case 0x013:  // adc word flip\n    case 0x014:  // adc %al  $ib\n    case 0x015:  // adc %rax $ivds\n    case 0x018:  // sbb byte\n    case 0x019:  // sbb word\n    case 0x01A:  // sbb byte flip\n    case 0x01B:  // sbb word flip\n    case 0x01C:  // sbb %al  $ib\n    case 0x01D:  // sbb %rax $ivds\n    case 0x072:  // jb\n    case 0x073:  // jae\n    case 0x142:  // cmovb\n    case 0x143:  // cmovnb\n    case 0x182:  // jb\n    case 0x183:  // jae\n    case 0x192:  // setb\n    case 0x193:  // setae\n    case 0x0D6:  // salc\n    case 0x0F5:  // cmc\n      return CF;\n    case 0x070:  // jo\n    case 0x071:  // jno\n    case 0x140:  // cmovo\n    case 0x141:  // cmovno\n    case 0x180:  // jo\n    case 0x181:  // jno\n    case 0x190:  // seto\n    case 0x191:  // setno\n    case 0x0CE:  // into\n      return OF;\n    case 0x074:  // je\n    case 0x075:  // jne\n    case 0x144:  // cmove\n    case 0x145:  // cmovne\n    case 0x184:  // je\n    case 0x185:  // jne\n    case 0x194:  // sete\n    case 0x195:  // setne\n    case 0x0E0:  // loopne\n    case 0x0E1:  // loope\n      return ZF;\n    case 0x076:  // jbe\n    case 0x077:  // ja\n    case 0x146:  // cmovbe\n    case 0x147:  // cmova\n    case 0x186:  // jbe\n    case 0x187:  // ja\n    case 0x196:  // setbe\n    case 0x197:  // seta\n      return CF | ZF;\n    case 0x078:  // js\n    case 0x079:  // jns\n    case 0x148:  // cmovs\n    case 0x149:  // cmovns\n    case 0x188:  // js\n    case 0x189:  // jns\n    case 0x198:  // sets\n    case 0x199:  // setns\n      return SF;\n    case 0x07A:  // jp\n    case 0x07B:  // jnp\n    case 0x14A:  // cmovp\n    case 0x14B:  // cmovnp\n    case 0x18A:  // jp\n    case 0x18B:  // jnp\n    case 0x19A:  // setp\n    case 0x19B:  // setnp\n      return PF;\n    case 0x07C:  // jl\n    case 0x07D:  // jge\n    case 0x14C:  // cmovl\n    case 0x14D:  // cmovge\n    case 0x18C:  // jl\n    case 0x18D:  // jge\n    case 0x19C:  // setl\n    case 0x19D:  // setge\n      return OF | SF;\n    case 0x07E:  // jle\n    case 0x07F:  // jg\n    case 0x14E:  // cmovle\n    case 0x14F:  // cmovg\n    case 0x18E:  // jle\n    case 0x18F:  // jg\n    case 0x19E:  // setle\n    case 0x19F:  // setg\n      return OF | SF | ZF;\n    case 0x080:  // alu byte $ib\n    case 0x081:  // alu word $iw\n    case 0x082:  // alu byte $ib\n    case 0x083:  // alu word $ibs\n    case 0x0C0:  // bsu byte $ib\n    case 0x0C1:  // bsu word $ib\n    case 0x0D0:  // bsu byte $1\n    case 0x0D1:  // bsu word $1\n    case 0x0D2:  // bsu byte %cl\n    case 0x0D3:  // bsu word %cl\n      switch (ModrmReg(rde)) {\n        case 2:  // adc, rcl\n        case 3:  // sbb, rcr\n          return CF;\n        default:\n          return 0;\n      }\n    case 0x0DA:  // fpu\n    case 0x0DB:  // fpu\n      switch (ModrmReg(rde)) {\n        case 0:  // fcmovb\n          return CF;\n        case 1:  // fcmove\n        case 2:  // fcmovbe\n          return ZF;\n        case 3:  // fcmovu\n          return PF;\n        default:\n          return 0;\n      }\n    case 0x09F:  // lahf\n      return CF | ZF | SF | AF | PF;\n    case 0x02F:  // das\n    case 0x037:  // aaa\n      return CF | AF;\n    case 0x09C:  // pushf\n      return 0x00ffffff;\n    case 0x2f6:\n      if (Osz(rde)) {\n        return CF;  // adcx\n      } else if (Rep(rde) == 3) {\n        return OF;  // adox\n      } else {\n        return 0;\n      }\n  }\n}\n\nint ClassifyOp(u64 rde) {\n  switch (Mopcode(rde)) {\n    default:\n      return kOpNormal;\n    case 0x070:  // OpJo\n    case 0x071:  // OpJno\n    case 0x072:  // OpJb\n    case 0x073:  // OpJae\n    case 0x074:  // OpJe\n    case 0x075:  // OpJne\n    case 0x076:  // OpJbe\n    case 0x077:  // OpJa\n    case 0x078:  // OpJs\n    case 0x079:  // OpJns\n    case 0x07A:  // OpJp\n    case 0x07B:  // OpJnp\n    case 0x07C:  // OpJl\n    case 0x07D:  // OpJge\n    case 0x07E:  // OpJle\n    case 0x07F:  // OpJg\n    case 0x09A:  // OpCallf\n    case 0x0C2:  // OpRetIw\n    case 0x0C3:  // OpRet\n    case 0x0CA:  // OpRetf\n    case 0x0CB:  // OpRetf\n    case 0x0E0:  // OpLoopne\n    case 0x0E1:  // OpLoope\n    case 0x0E2:  // OpLoop1\n    case 0x0E3:  // OpJcxz\n    case 0x0E8:  // OpCallJvds\n    case 0x0E9:  // OpJmp\n    case 0x0EA:  // OpJmpf\n    case 0x0EB:  // OpJmp\n    case 0x0CF:  // OpIret\n    case 0x180:  // OpJo\n    case 0x181:  // OpJno\n    case 0x182:  // OpJb\n    case 0x183:  // OpJae\n    case 0x184:  // OpJe\n    case 0x185:  // OpJne\n    case 0x186:  // OpJbe\n    case 0x187:  // OpJa\n    case 0x188:  // OpJs\n    case 0x189:  // OpJns\n    case 0x18A:  // OpJp\n    case 0x18B:  // OpJnp\n    case 0x18C:  // OpJl\n    case 0x18D:  // OpJge\n    case 0x18E:  // OpJle\n    case 0x18F:  // OpJg\n      return kOpBranching;\n    case 0x0FF:  // Op0ff\n      switch (ModrmReg(rde)) {\n        case 2:  // call *Ev\n        case 3:  // lcall *Ev\n        case 4:  // jmp *Ev\n        case 5:  // ljmp *Ev\n          return kOpBranching;\n        default:\n          return kOpNormal;\n      }\n    case 0x0F1:  // OpInterrupt1\n    case 0x0CC:  // OpInterrupt3\n    case 0x0CD:  // OpInterruptImm\n    case 0x105:  // OpSyscall\n      // precious ops are excluded from jit pathmaking entirely. not\n      // doing this would be inviting disaster, since system calls and\n      // longjmp could do anything. for example, we don't want clone()\n      // to fork a jit path under construction.\n      return kOpPrecious;\n    case 0x130:  // OpWrmsr\n    case 0x1A2:  // OpCpuid\n      return kOpSerializing;\n    case 0x1AE:\n      switch (ModrmReg(rde)) {\n        case 5:  // lfence\n        case 6:  // mfence\n          return kOpSerializing;\n        default:\n          return kOpNormal;\n      }\n  }\n}\n"
  },
  {
    "path": "blink/describeflags.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/describeflags.h\"\n\n#include <stdbool.h>\n\nconst char *DescribeFlagz(char *p, size_t n, const struct DescribeFlagz *d,\n                          size_t m, const char *prefix, unsigned x) {\n  bool t;\n  char b[21];\n  size_t i, j, k;\n  for (t = false, i = j = 0; j < m; ++j) {\n    if (d[j].flag && d[j].flag != -1u && (x & d[j].flag) == d[j].flag) {\n      x &= ~d[j].flag;\n      if (t) {\n        if (i + 1 < n) p[i++] = '|';\n      } else {\n        t = true;\n      }\n      for (k = 0; prefix && prefix[k]; ++k) {\n        if (i + 1 < n) p[i++] = prefix[k];\n      }\n      for (k = 0; d[j].name[k]; ++k) {\n        if (i + 1 < n) p[i++] = d[j].name[k];\n      }\n    }\n  }\n  if (x || !t) {\n    if (t && i + 1 < n) p[i++] = '|';\n    if (i + 1 < n) p[i++] = '0';\n    if (x) {\n      if (i + 1 < n) p[i++] = 'x';\n      k = 0;\n      do {\n        if (i + 1 < n) b[k++] = \"0123456789abcdef\"[x % 16];\n      } while ((x /= 16));\n      while (k--) {\n        if (i + 1 < n) p[i++] = b[k];\n      }\n    }\n  }\n  if (i < n) p[i] = 0;\n  return p;\n}\n"
  },
  {
    "path": "blink/describeflags.h",
    "content": "#ifndef BLINK_DESCRIBEFLAGS_H_\n#define BLINK_DESCRIBEFLAGS_H_\n#include <stddef.h>\n\n#include \"blink/builtin.h\"\n\nstruct DescribeFlagz {\n  unsigned flag;\n  const char *name;\n};\n\nconst char *DescribeFlagz(char *, size_t, const struct DescribeFlagz *, size_t,\n                          const char *, unsigned);\n\n#endif /* BLINK_DESCRIBEFLAGS_H_ */\n"
  },
  {
    "path": "blink/describehosterrno.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n\n#include \"blink/thread.h\"\n#include \"blink/util.h\"\n\nconst char *DescribeHostErrno(int x) {\n  _Thread_local static char buf[21];\n  if (x == EPERM) return \"EPERM\";\n  if (x == ENOENT) return \"ENOENT\";\n  if (x == ESRCH) return \"ESRCH\";\n  if (x == EINTR) return \"EINTR\";\n  if (x == EIO) return \"EIO\";\n  if (x == ENXIO) return \"ENXIO\";\n  if (x == E2BIG) return \"E2BIG\";\n  if (x == ENOEXEC) return \"ENOEXEC\";\n  if (x == EBADF) return \"EBADF\";\n  if (x == ECHILD) return \"ECHILD\";\n  if (x == EAGAIN) return \"EAGAIN\";\n#if EWOULDBLOCK != EAGAIN\n  if (x == EWOULDBLOCK) return \"EWOULDBLOCK\";\n#endif\n  if (x == ENOMEM) return \"ENOMEM\";\n  if (x == EACCES) return \"EACCES\";\n  if (x == EFAULT) return \"EFAULT\";\n#ifdef ENOTBLK\n  if (x == ENOTBLK) return \"ENOTBLK\";\n#endif\n  if (x == EBUSY) return \"EBUSY\";\n  if (x == EEXIST) return \"EEXIST\";\n  if (x == EXDEV) return \"EXDEV\";\n  if (x == ENODEV) return \"ENODEV\";\n  if (x == ENOTDIR) return \"ENOTDIR\";\n  if (x == EISDIR) return \"EISDIR\";\n  if (x == EINVAL) return \"EINVAL\";\n  if (x == ENFILE) return \"ENFILE\";\n  if (x == EMFILE) return \"EMFILE\";\n  if (x == ENOTTY) return \"ENOTTY\";\n  if (x == ETXTBSY) return \"ETXTBSY\";\n  if (x == EFBIG) return \"EFBIG\";\n  if (x == ENOSPC) return \"ENOSPC\";\n  if (x == ESPIPE) return \"ESPIPE\";\n  if (x == EROFS) return \"EROFS\";\n  if (x == EMLINK) return \"EMLINK\";\n  if (x == EPIPE) return \"EPIPE\";\n  if (x == EDOM) return \"EDOM\";\n  if (x == ERANGE) return \"ERANGE\";\n  if (x == EDEADLK) return \"EDEADLK\";\n  if (x == ENAMETOOLONG) return \"ENAMETOOLONG\";\n  if (x == ENOLCK) return \"ENOLCK\";\n  if (x == ENOSYS) return \"ENOSYS\";\n  if (x == ENOTEMPTY) return \"ENOTEMPTY\";\n  if (x == ELOOP) return \"ELOOP\";\n  if (x == ENOMSG) return \"ENOMSG\";\n  if (x == EIDRM) return \"EIDRM\";\n#ifdef EREMOTE\n  if (x == EREMOTE) return \"EREMOTE\";\n#endif\n  if (x == EPROTO) return \"EPROTO\";\n  if (x == EBADMSG) return \"EBADMSG\";\n  if (x == EOVERFLOW) return \"EOVERFLOW\";\n  if (x == EILSEQ) return \"EILSEQ\";\n#ifdef EUSERS\n  if (x == EUSERS) return \"EUSERS\";\n#endif\n  if (x == ENOTSOCK) return \"ENOTSOCK\";\n  if (x == EDESTADDRREQ) return \"EDESTADDRREQ\";\n  if (x == EMSGSIZE) return \"EMSGSIZE\";\n  if (x == EPROTOTYPE) return \"EPROTOTYPE\";\n  if (x == ENOPROTOOPT) return \"ENOPROTOOPT\";\n  if (x == EPROTONOSUPPORT) return \"EPROTONOSUPPORT\";\n#ifdef ESOCKTNOSUPPORT\n  if (x == ESOCKTNOSUPPORT) return \"ESOCKTNOSUPPORT\";\n#endif\n  if (x == ENOTSUP) return \"ENOTSUP\";\n#if EOPNOTSUPP != ENOTSUP\n  if (x == EOPNOTSUPP) return \"EOPNOTSUPP\";\n#endif\n#ifdef EPFNOSUPPORT\n  if (x == EPFNOSUPPORT) return \"EPFNOSUPPORT\";\n#endif\n  if (x == EAFNOSUPPORT) return \"EAFNOSUPPORT\";\n  if (x == EADDRINUSE) return \"EADDRINUSE\";\n  if (x == EADDRNOTAVAIL) return \"EADDRNOTAVAIL\";\n  if (x == ENETDOWN) return \"ENETDOWN\";\n  if (x == ENETUNREACH) return \"ENETUNREACH\";\n  if (x == ENETRESET) return \"ENETRESET\";\n  if (x == ECONNABORTED) return \"ECONNABORTED\";\n  if (x == ECONNRESET) return \"ECONNRESET\";\n  if (x == ENOBUFS) return \"ENOBUFS\";\n  if (x == EISCONN) return \"EISCONN\";\n  if (x == ENOTCONN) return \"ENOTCONN\";\n#ifdef ESHUTDOWN\n  if (x == ESHUTDOWN) return \"ESHUTDOWN\";\n#endif\n#ifdef ETOOMANYREFS\n  if (x == ETOOMANYREFS) return \"ETOOMANYREFS\";\n#endif\n  if (x == ETIMEDOUT) return \"ETIMEDOUT\";\n  if (x == ECONNREFUSED) return \"ECONNREFUSED\";\n#ifdef EHOSTDOWN\n  if (x == EHOSTDOWN) return \"EHOSTDOWN\";\n#endif\n  if (x == EHOSTUNREACH) return \"EHOSTUNREACH\";\n  if (x == EALREADY) return \"EALREADY\";\n  if (x == EINPROGRESS) return \"EINPROGRESS\";\n  if (x == ESTALE) return \"ESTALE\";\n  if (x == EDQUOT) return \"EDQUOT\";\n  if (x == ECANCELED) return \"ECANCELED\";\n#ifdef EOWNERDEAD\n  if (x == EOWNERDEAD) return \"EOWNERDEAD\";\n#endif\n#ifdef ENOTRECOVERABLE\n  if (x == ENOTRECOVERABLE) return \"ENOTRECOVERABLE\";\n#endif\n#ifdef ETIME\n  if (x == ETIME) return \"ETIME\";\n#endif\n#ifdef ENONET\n  if (x == ENONET) return \"ENONET\";\n#endif\n#ifdef ERESTART\n  if (x == ERESTART) return \"ERESTART\";\n#endif\n#ifdef ENOSR\n  if (x == ENOSR) return \"ENOSR\";\n#endif\n#ifdef ENOSTR\n  if (x == ENOSTR) return \"ENOSTR\";\n#endif\n#ifdef ENODATA\n  if (x == ENODATA) return \"ENODATA\";\n#endif\n#ifdef EMULTIHOP\n  if (x == EMULTIHOP) return \"EMULTIHOP\";\n#endif\n#ifdef ENOLINK\n  if (x == ENOLINK) return \"ENOLINK\";\n#endif\n#ifdef ENOMEDIUM\n  if (x == ENOMEDIUM) return \"ENOMEDIUM\";\n#endif\n#ifdef EMEDIUMTYPE\n  if (x == EMEDIUMTYPE) return \"EMEDIUMTYPE\";\n#endif\n  FormatInt64(buf, x);\n  return buf;\n}\n"
  },
  {
    "path": "blink/describeprot.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n#include <sys/mman.h>\n\n#include \"blink/debug.h\"\n#include \"blink/thread.h\"\n#include \"blink/util.h\"\n\nconst char *DescribeProt(int prot) {\n  char *p;\n  bool gotsome;\n  _Thread_local static char buf[64];\n  if (!prot) return \"PROT_NONE\";\n  p = buf;\n  gotsome = false;\n  if (prot & PROT_READ) {\n    if (gotsome) *p++ = '|';\n    p = stpcpy(p, \"PROT_READ\");\n    prot &= ~PROT_READ;\n    gotsome = true;\n  }\n  if (prot & PROT_WRITE) {\n    if (gotsome) *p++ = '|';\n    p = stpcpy(p, \"PROT_WRITE\");\n    prot &= ~PROT_WRITE;\n    gotsome = true;\n  }\n  if (prot & PROT_EXEC) {\n    if (gotsome) *p++ = '|';\n    p = stpcpy(p, \"PROT_EXEC\");\n    prot &= ~PROT_EXEC;\n    gotsome = true;\n  }\n  if (prot) {\n    if (gotsome) *p++ = '|';\n    p = FormatInt64(p, prot);\n  }\n  return buf;\n}\n"
  },
  {
    "path": "blink/describesignal.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n\n#include \"blink/linux.h\"\n#include \"blink/thread.h\"\n#include \"blink/util.h\"\n\n// @asyncsignalsafe\nconst char *DescribeSignal(int sig) {\n  char *p;\n  _Thread_local static char buf[30];\n  switch (sig) {\n    case SIGHUP_LINUX:\n      return \"SIGHUP\";\n    case SIGINT_LINUX:\n      return \"SIGINT\";\n    case SIGQUIT_LINUX:\n      return \"SIGQUIT\";\n    case SIGILL_LINUX:\n      return \"SIGILL\";\n    case SIGTRAP_LINUX:\n      return \"SIGTRAP\";\n    case SIGABRT_LINUX:\n      return \"SIGABRT\";\n    case SIGBUS_LINUX:\n      return \"SIGBUS\";\n    case SIGFPE_LINUX:\n      return \"SIGFPE\";\n    case SIGKILL_LINUX:\n      return \"SIGKILL\";\n    case SIGUSR1_LINUX:\n      return \"SIGUSR1\";\n    case SIGSEGV_LINUX:\n      return \"SIGSEGV\";\n    case SIGUSR2_LINUX:\n      return \"SIGUSR2\";\n    case SIGPIPE_LINUX:\n      return \"SIGPIPE\";\n    case SIGALRM_LINUX:\n      return \"SIGALRM\";\n    case SIGTERM_LINUX:\n      return \"SIGTERM\";\n    case SIGSTKFLT_LINUX:\n      return \"SIGSTKFLT\";\n    case SIGCHLD_LINUX:\n      return \"SIGCHLD\";\n    case SIGCONT_LINUX:\n      return \"SIGCONT\";\n    case SIGSTOP_LINUX:\n      return \"SIGSTOP\";\n    case SIGTSTP_LINUX:\n      return \"SIGTSTP\";\n    case SIGTTIN_LINUX:\n      return \"SIGTTIN\";\n    case SIGTTOU_LINUX:\n      return \"SIGTTOU\";\n    case SIGURG_LINUX:\n      return \"SIGURG\";\n    case SIGXCPU_LINUX:\n      return \"SIGXCPU\";\n    case SIGXFSZ_LINUX:\n      return \"SIGXFSZ\";\n    case SIGVTALRM_LINUX:\n      return \"SIGVTALRM\";\n    case SIGPROF_LINUX:\n      return \"SIGPROF\";\n    case SIGWINCH_LINUX:\n      return \"SIGWINCH\";\n    case SIGIO_LINUX:\n      return \"SIGIO\";\n    case SIGSYS_LINUX:\n      return \"SIGSYS\";\n    case SIGINFO_LINUX:\n      return \"SIGINFO\";\n    case SIGPWR_LINUX:\n      return \"SIGPWR\";\n    default:\n      break;\n  }\n  p = buf;\n  if (SIGRTMIN_LINUX <= sig && sig <= SIGRTMAX_LINUX) {\n    p = stpcpy(p, \"SIGRTMIN+\");\n    p = FormatInt64(p, sig - SIGRTMIN_LINUX);\n  } else {\n    p = FormatInt64(p, sig);\n  }\n  return buf;\n}\n"
  },
  {
    "path": "blink/devfs.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Trung Nguyen                                                  │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/devfs.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/errno.h\"\n#include \"blink/hostfs.h\"\n#include \"blink/log.h\"\n\n#ifndef DISABLE_VFS\n\nstatic int DevfsInit(const char *source, u64 flags, const void *data,\n                     struct VfsDevice **device, struct VfsMount **mount) {\n  int ret;\n  if (source == NULL) {\n    return efault();\n  }\n  if (*source == '\\0') {\n    source = \"/dev\";\n  }\n  VFS_LOGF(\"real devfs not implemented, delegating to hostfs\");\n  if ((ret = HostfsInit(source, flags, data, device, mount)) != -1) {\n    (*device)->ops = &g_devfs.ops;\n  }\n  return ret;\n}\n\nstatic int DevfsReadmountentry(struct VfsDevice *device, char **spec,\n                               char **type, char **mntops) {\n  *spec = strdup(\"none\");\n  if (*spec == NULL) {\n    return enomem();\n  }\n  *type = strdup(\"devtmpfs\");\n  if (type == NULL) {\n    free(*spec);\n    return enomem();\n  }\n  *mntops = NULL;\n  return 0;\n}\n\nstruct VfsSystem g_devfs = {.name = \"devfs\",\n                            .nodev = true,\n                            .ops = {\n                                .Init = DevfsInit,\n                                .Freeinfo = HostfsFreeInfo,\n                                .Freedevice = HostfsFreeDevice,\n                                .Finddir = HostfsFinddir,\n                                .Readmountentry = DevfsReadmountentry,\n                                .Readlink = HostfsReadlink,\n                                .Mkdir = HostfsMkdir,\n                                .Mkfifo = HostfsMkfifo,\n                                .Open = HostfsOpen,\n                                .Access = HostfsAccess,\n                                .Stat = HostfsStat,\n                                .Fstat = HostfsFstat,\n                                .Chmod = HostfsChmod,\n                                .Fchmod = HostfsFchmod,\n                                .Chown = HostfsChown,\n                                .Fchown = HostfsFchown,\n                                .Ftruncate = HostfsFtruncate,\n                                .Link = HostfsLink,\n                                .Unlink = HostfsUnlink,\n                                .Read = HostfsRead,\n                                .Write = HostfsWrite,\n                                .Pread = HostfsPread,\n                                .Pwrite = HostfsPwrite,\n                                .Readv = HostfsReadv,\n                                .Writev = HostfsWritev,\n                                .Preadv = HostfsPreadv,\n                                .Pwritev = HostfsPwritev,\n                                .Seek = HostfsSeek,\n                                .Fsync = HostfsFsync,\n                                .Fdatasync = HostfsFdatasync,\n                                .Flock = HostfsFlock,\n                                .Fcntl = HostfsFcntl,\n                                .Ioctl = HostfsIoctl,\n                                .Dup = HostfsDup,\n#ifdef HAVE_DUP3\n                                .Dup3 = HostfsDup3,\n#endif\n                                .Poll = HostfsPoll,\n                                .Opendir = HostfsOpendir,\n#ifdef HAVE_SEEKDIR\n                                .Seekdir = HostfsSeekdir,\n                                .Telldir = HostfsTelldir,\n#endif\n                                .Readdir = HostfsReaddir,\n                                .Rewinddir = HostfsRewinddir,\n                                .Closedir = HostfsClosedir,\n                                .Bind = HostfsBind,\n                                .Connect = HostfsConnect,\n                                .Connectunix = HostfsConnectUnix,\n                                .Accept = HostfsAccept,\n                                .Listen = HostfsListen,\n                                .Shutdown = HostfsShutdown,\n                                .Recvmsg = HostfsRecvmsg,\n                                .Sendmsg = HostfsSendmsg,\n                                .Recvmsgunix = HostfsRecvmsgUnix,\n                                .Sendmsgunix = HostfsSendmsgUnix,\n                                .Getsockopt = HostfsGetsockopt,\n                                .Setsockopt = HostfsSetsockopt,\n                                .Getsockname = HostfsGetsockname,\n                                .Getpeername = HostfsGetpeername,\n                                .Rename = HostfsRename,\n                                .Utime = HostfsUtime,\n                                .Futime = HostfsFutime,\n                                .Symlink = HostfsSymlink,\n                                .Mmap = HostfsMmap,\n                                .Munmap = HostfsMunmap,\n                                .Mprotect = HostfsMprotect,\n                                .Msync = HostfsMsync,\n                                .Pipe = NULL,\n#ifdef HAVE_PIPE2\n                                .Pipe2 = NULL,\n#endif\n                                .Socket = NULL,\n                                .Socketpair = NULL,\n                                .Tcgetattr = NULL,\n                                .Tcsetattr = NULL,\n                                .Tcflush = NULL,\n                                .Tcdrain = NULL,\n                                .Tcsendbreak = NULL,\n                                .Tcflow = NULL,\n                                .Tcgetsid = NULL,\n                                .Tcgetpgrp = NULL,\n                                .Tcsetpgrp = NULL,\n#ifdef HAVE_SOCKATMARK\n                                .Sockatmark = NULL,\n#endif\n                                .Fexecve = NULL,\n                            }};\n\n#endif /* DISABLE_VFS */\n"
  },
  {
    "path": "blink/devfs.h",
    "content": "#ifndef BLINK_DEVFS_H_\n#define BLINK_DEVFS_H_\n\n#include \"blink/vfs.h\"\n\nextern struct VfsSystem g_devfs;\n\n#endif  // BLINK_DEVFS_H_\n"
  },
  {
    "path": "blink/dis.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/dis.h\"\n\n#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/assert.h\"\n#include \"blink/debug.h\"\n#include \"blink/endian.h\"\n#include \"blink/high.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/types.h\"\n#include \"blink/util.h\"\n\n#define ADDRLEN 8\n#define BYTELEN 11\n#define PFIXLEN 4\n#define NAMELEN 8\n#define CODELEN 40\n#define CODELIM 15\n#define DATALIM 8\n#define PIVOTOP pos_opcode\n\nchar *DisColumn(char *p2, char *p1, long need) {\n  char *p;\n  long have;\n  unassert(p2 >= p1);\n  have = p2 - p1;\n  p = p2;\n  do {\n    *p++ = ' ';\n  } while (++have < need);\n  *p = '\\0';\n  return p;\n}\n\nstatic char *DisOctets(char *p, const u8 *d, size_t n) {\n  size_t i;\n  for (i = 0; i < n; ++i) {\n    if (i) *p++ = ',';\n    *p++ = '0';\n    *p++ = 'x';\n    *p++ = \"0123456789abcdef\"[(d[i] & 0xf0) >> 4];\n    *p++ = \"0123456789abcdef\"[(d[i] & 0x0f) >> 0];\n  }\n  *p = '\\0';\n  return p;\n}\n\nstatic char *DisByte(char *p, const u8 *d, size_t n) {\n  p = HighStart(p, g_high.keyword);\n  p = DisColumn(stpcpy(p, \".byte\"), p, NAMELEN);\n  p = HighEnd(p);\n  p = DisOctets(p, d, n);\n  return p;\n}\n\nstatic char *DisError(struct Dis *d, char *p, int err) {\n  p = DisColumn(DisByte(p, d->xedd->bytes, MIN(15, d->xedd->length)), p,\n                CODELEN);\n  p = HighStart(p, g_high.comment);\n  *p++ = '#';\n  *p++ = ' ';\n  p = stpcpy(p, \"error\");\n  p = HighEnd(p);\n  *p = '\\0';\n  return p;\n}\n\nstatic size_t uint64toarray_fixed16(u64 x, char b[17], u8 k) {\n  char *p;\n  unassert(k <= 64 && !(k & 3));\n  for (p = b; k > 0;) *p++ = \"0123456789abcdef\"[(x >> (k -= 4)) & 15];\n  *p = '\\0';\n  return p - b;\n}\n\nstatic char *DisAddr(struct Dis *d, char *p) {\n  i64 x = d->addr;\n  if (0 <= x && x < 0x10fff0) {\n    return p + uint64toarray_fixed16(x, p, 24);\n  } else if (INT_MIN <= x && x <= INT_MAX) {\n    return p + uint64toarray_fixed16(x, p, 32);\n  } else {\n    return p + uint64toarray_fixed16(x, p, 48);\n  }\n}\n\nstatic char *DisRaw(struct Dis *d, char *p) {\n  long i;\n  int plen;\n  if (0 <= d->addr && d->addr < 0x10fff0) {\n    plen = 2;\n  } else {\n    plen = PFIXLEN;\n  }\n  for (i = 0; i < plen - MIN(plen, d->xedd->op.PIVOTOP); ++i) {\n    *p++ = ' ';\n    *p++ = ' ';\n  }\n  for (i = 0; i < MIN(15, d->xedd->length); ++i) {\n    if (i == d->xedd->op.PIVOTOP) *p++ = ' ';\n    *p++ = \"0123456789abcdef\"[(d->xedd->bytes[i] & 0xf0) >> 4];\n    *p++ = \"0123456789abcdef\"[(d->xedd->bytes[i] & 0x0f) >> 0];\n  }\n  *p = '\\0';\n  return p;\n}\n\nstatic char *DisCode(struct Dis *d, char *p, int err) {\n  char optspecbuf[128];\n  if (!err) {\n    return DisInst(d, p, DisSpec(d->xedd, optspecbuf));\n  } else {\n    return DisError(d, p, err);\n  }\n}\n\nstatic char *DisLineCode(struct Dis *d, char *p, int err) {\n  int blen, plen;\n  if (0 <= d->addr && d->addr < 0x10fff0) {\n    plen = 2;\n    blen = 6;\n  } else {\n    blen = BYTELEN;\n    plen = PFIXLEN;\n  }\n  p = DisColumn(DisAddr(d, p), p, ADDRLEN);\n#ifdef HAVE_JIT\n  if (d->m && !IsJitDisabled(&d->m->system->jit)) {\n    uintptr_t hook;\n    if ((hook = GetJitHook(&d->m->system->jit, d->addr))) {\n      if (hook == (uintptr_t)JitlessDispatch) {\n        *p++ = 'S';  // staging hook\n      } else {\n        *p++ = '*';  // committed jit hook\n      }\n    } else {\n      *p++ = ' ';  // no hook\n    }\n  }\n#else\n  *p++ = ' ';  // no hook\n#endif\n  if (!d->noraw) {\n    p = DisColumn(DisRaw(d, p), p, plen * 2 + 1 + blen * 2);\n  } else {\n    *p++ = ' ';\n    *p++ = ' ';\n  }\n  p = DisCode(d, p, err);\n  return p;\n}\n\nstatic char *DisLabel(struct Dis *d, char *p, const char *name) {\n  p = DisColumn(DisAddr(d, p), p, ADDRLEN);\n  p = HighStart(p, g_high.label);\n  p = Demangle(p, name, DIS_MAX_SYMBOL_LENGTH);\n  p = HighEnd(p);\n  *p++ = ':';\n  *p = '\\0';\n  return p;\n}\n\nlong DisFind(struct Dis *d, i64 addr) {\n  int l, r, m;\n  l = 0;\n  r = d->ops.i - 1;\n  while (l <= r) {\n    m = (l + r) >> 1;\n    if (d->ops.p[m].addr < addr) {\n      l = m + 1;\n    } else if (d->ops.p[m].addr > addr) {\n      r = m - 1;\n    } else {\n      return m;\n    }\n  }\n  return -1;\n}\n\nstatic long DisAppendOpLines(struct Dis *d, struct Machine *m, i64 addr) {\n  u8 *r;\n  i64 ip;\n  unsigned k;\n  u8 *p, b[15];\n  long n, symbol;\n  struct DisOp op;\n  n = 15;\n  ip = addr - m->cs.base;\n  if ((symbol = DisFindSym(d, ip)) != -1) {\n    if (d->syms.p[symbol].addr <= ip &&\n        ip < d->syms.p[symbol].addr + d->syms.p[symbol].size) {\n      n = d->syms.p[symbol].size - (ip - d->syms.p[symbol].addr);\n    }\n    if (ip == d->syms.p[symbol].addr && d->syms.p[symbol].name) {\n      op.addr = addr;\n      op.size = 0;\n      op.active = true;\n      d->addr = addr;\n      DisLabel(d, d->buf, d->syms.p[symbol].name);\n      if (!(op.s = strdup(d->buf))) return -1;\n      if (d->ops.i++ == d->ops.n) {\n        d->ops.n = d->ops.i + (d->ops.i >> 1);\n        d->ops.p =\n            (struct DisOp *)realloc(d->ops.p, d->ops.n * sizeof(*d->ops.p));\n      }\n      d->ops.p[d->ops.i - 1] = op;\n    }\n  }\n  n = MAX(1, MIN(15, n));\n  if (!(r = SpyAddress(m, addr))) return -1;\n  k = 0x1000 - (addr & 0xfff);\n  if (n <= k) {\n    p = (u8 *)r;\n  } else {\n    p = b;\n    memcpy(b, r, k);\n    if ((r = SpyAddress(m, addr + k))) {\n      memcpy(b + k, r, n - k);\n    } else {\n      n = k;\n    }\n  }\n  DecodeInstruction(d->xedd, p, n, m->mode.omode);\n  n = d->xedd->length;\n  op.addr = addr;\n  op.size = n;\n  op.active = true;\n  op.s = NULL;\n  if (d->ops.i++ == d->ops.n) {\n    d->ops.n = d->ops.i + (d->ops.i >> 1);\n    d->ops.p = (struct DisOp *)realloc(d->ops.p, d->ops.n * sizeof(*d->ops.p));\n  }\n  d->ops.p[d->ops.i - 1] = op;\n  return n;\n}\n\nlong Dis(struct Dis *d, struct Machine *m, i64 addr, i64 ip, int lines) {\n  i64 i, j, symbol;\n  DisFreeOps(&d->ops);\n  if ((symbol = DisFindSym(d, addr)) != -1 &&\n      (d->syms.p[symbol].addr < addr &&\n       addr < d->syms.p[symbol].addr + d->syms.p[symbol].size)) {\n    for (i = d->syms.p[symbol].addr; i < addr; i += j) {\n      if ((j = DisAppendOpLines(d, m, i)) == -1) return -1;\n    }\n  }\n  for (i = 0; i < lines; ++i, addr += j) {\n    if ((j = DisAppendOpLines(d, m, addr)) == -1) return -1;\n  }\n  return 0;\n}\n\nconst char *DisGetLine(struct Dis *d, struct Machine *m, int i) {\n  int err;\n  if (i >= d->ops.i) return \"\";\n  if (d->ops.p[i].s) return d->ops.p[i].s;\n  unassert(d->ops.p[i].size <= 15);\n  err = GetInstruction(m, d->ops.p[i].addr, d->xedd);\n  d->m = m;\n  d->addr = d->ops.p[i].addr;\n  if (DisLineCode(d, d->buf, err) - d->buf >= (int)sizeof(d->buf)) Abort();\n  return d->buf;\n}\n"
  },
  {
    "path": "blink/dis.h",
    "content": "#ifndef BLINK_DIS_H_\n#define BLINK_DIS_H_\n#include <stdbool.h>\n#include <stddef.h>\n\n#include \"blink/loader.h\"\n#include \"blink/types.h\"\n#include \"blink/x86.h\"\n\n#define DIS_MAX_SYMBOL_LENGTH 128\n\nstruct DisOp {\n  i64 addr;\n  u8 size;\n  bool active;\n  char *s;\n};\n\nstruct DisOps {\n  int i, n;\n  struct DisOp *p;\n};\n\nstruct DisLoad {\n  i64 addr;\n  int size;\n  bool istext;\n};\n\nstruct DisLoads {\n  int i, n;\n  struct DisLoad *p;\n};\n\nstruct DisSym {\n  i64 addr;\n  char *name;\n  int unique;\n  int size;\n  char rank;\n  bool iscode;\n  bool isabs;\n};\n\nstruct DisSyms {\n  int i, n;\n  struct DisSym *p;\n};\n\nstruct DisEdge {\n  i64 src;\n  i64 dst;\n};\n\nstruct DisEdges {\n  int i, n;\n  struct DisEdge *p;\n};\n\nstruct Dis {\n  bool notab;\n  bool noraw;\n  struct DisOps ops;\n  struct DisLoads loads;\n  struct DisSyms syms;\n  struct DisEdges edges;\n  struct XedDecodedInst xedd[1];\n  struct Machine *m; /* for the segment registers */\n  u64 addr;          /* current effective address */\n  char buf[1024];\n};\n\nlong Dis(struct Dis *, struct Machine *, i64, i64, int);\nlong DisFind(struct Dis *, i64);\nvoid DisFree(struct Dis *);\nvoid DisFreeOp(struct DisOp *);\nvoid DisFreeOps(struct DisOps *);\nvoid DisLoadElf(struct Dis *, Elf64_Ehdr_ *, size_t, i64);\nlong DisFindSym(struct Dis *, i64);\nlong DisFindSymByName(struct Dis *, const char *);\nbool DisIsText(struct Dis *, i64);\nbool DisIsProg(struct Dis *, i64);\nchar *DisInst(struct Dis *, char *, const char *);\nchar *DisArg(struct Dis *, char *, const char *);\nconst char *DisSpec(struct XedDecodedInst *, char *);\nconst char *DisGetLine(struct Dis *, struct Machine *, int);\n\n#endif /* BLINK_DIS_H_ */\n"
  },
  {
    "path": "blink/disarg.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <inttypes.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/dis.h\"\n#include \"blink/endian.h\"\n#include \"blink/high.h\"\n#include \"blink/macros.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n#include \"blink/util.h\"\n\nstatic const char kRiz[2][4] = {\"eiz\", \"riz\"};\nstatic const char kRip[2][4] = {\"eip\", \"rip\"};\nstatic const char kSka[4][4] = {\"\", \",2\", \",4\", \",8\"};\nstatic const char kSeg[8][3] = {\"es\", \"cs\", \"ss\", \"ds\", \"fs\", \"gs\"};\nstatic const char kCtl[8][4] = {\"cr0\", \"wut\", \"cr2\", \"cr3\",\n                                \"cr4\", \"wut\", \"wut\", \"wut\"};\n\nstatic const char kBreg[2][2][8][5] = {\n    {{\"al\", \"cl\", \"dl\", \"bl\", \"ah\", \"ch\", \"dh\", \"bh\"},\n     {\"al\", \"cl\", \"dl\", \"bl\", \"spl\", \"bpl\", \"sil\", \"dil\"}},\n    {{\"wut\", \"wut\", \"wut\", \"wut\", \"wut\", \"wut\", \"wut\", \"wut\"},\n     {\"r8b\", \"r9b\", \"r10b\", \"r11b\", \"r12b\", \"r13b\", \"r14b\", \"r15b\"}},\n};\n\nstatic const char kGreg[2][2][2][8][5] = {\n    {{{\"eax\", \"ecx\", \"edx\", \"ebx\", \"esp\", \"ebp\", \"esi\", \"edi\"},\n      {\"r8d\", \"r9d\", \"r10d\", \"r11d\", \"r12d\", \"r13d\", \"r14d\", \"r15d\"}},\n     {{\"rax\", \"rcx\", \"rdx\", \"rbx\", \"rsp\", \"rbp\", \"rsi\", \"rdi\"},\n      {\"r8\", \"r9\", \"r10\", \"r11\", \"r12\", \"r13\", \"r14\", \"r15\"}}},\n    {{{\"ax\", \"cx\", \"dx\", \"bx\", \"sp\", \"bp\", \"si\", \"di\"},\n      {\"r8w\", \"r9w\", \"r10w\", \"r11w\", \"r12w\", \"r13w\", \"r14w\", \"r15w\"}},\n     {{\"rax\", \"rcx\", \"rdx\", \"rbx\", \"rsp\", \"rbp\", \"rsi\", \"rdi\"},\n      {\"r8\", \"r9\", \"r10\", \"r11\", \"r12\", \"r13\", \"r14\", \"r15\"}}},\n};\n\nstatic i64 RipRelative(struct Dis *d, i64 i) {\n  return d->addr + d->xedd->length + i;\n}\n\nstatic i64 ZeroExtend(u64 rde, i64 i) {\n  switch (Mode(rde)) {\n    case XED_MODE_REAL:\n      return i & 0xffff;\n    case XED_MODE_LEGACY:\n      return i & 0xffffffff;\n    default:\n      return i;\n  }\n}\n\nstatic i64 Unrelative(u64 rde, i64 i) {\n  switch (Eamode(rde)) {\n    case XED_MODE_REAL:\n      return i & 0xffff;\n    case XED_MODE_LEGACY:\n      return i & 0xffffffff;\n    default:\n      return i;\n  }\n}\n\nstatic const char *GetAddrReg(struct Dis *d, u64 rde, u8 x, u8 r) {\n  return kGreg[Eamode(rde) == XED_MODE_REAL][Eamode(rde) == XED_MODE_LONG]\n              [x & 1][r & 7];\n}\n\nstatic char *DisRegister(char *p, const char *s) {\n  p = HighStart(p, g_high.reg);\n  *p++ = '%';\n  p = stpcpy(p, s);\n  p = HighEnd(p);\n  return p;\n}\n\nstatic char *DisRegisterByte(struct Dis *d, u64 rde, char *p, bool g, int r) {\n  return DisRegister(p, kBreg[g][Rex(rde)][r]);\n}\n\nstatic char *DisRegisterWord(struct Dis *d, u64 rde, char *p, bool g, int r) {\n  return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][g][r]);\n}\n\nstatic char *DisInt(char *p, i64 x) {\n  if (-15 <= x && x <= 15) {\n    p += snprintf(p, 32, \"%\" PRId64, x);\n  } else if (x == INT64_MIN) {\n    p = stpcpy(p, \"-0x8000000000000000\");\n  } else if (x < 0 && -x < 0xFFFFFFFF) {\n    p += snprintf(p, 32, \"-0x%\" PRIx64, -x);\n  } else {\n    p += snprintf(p, 32, \"0x%\" PRIx64, x);\n  }\n  return p;\n}\n\nstatic char *DisSymImpl(struct Dis *d, char *p, i64 x, long sym) {\n  i64 addend;\n  const char *name;\n  addend = x - d->syms.p[sym].addr;\n  name = d->syms.p[sym].name;\n  p = Demangle(p, name, DIS_MAX_SYMBOL_LENGTH);\n  if (addend) {\n    *p++ = '+';\n    p = DisInt(p, addend);\n  }\n  return p;\n}\n\nstatic char *DisSym(struct Dis *d, char *p, i64 value, i64 addr) {\n  long sym;\n  if ((sym = DisFindSym(d, addr)) != -1 &&\n      (d->syms.p[sym].name && *d->syms.p[sym].name)) {\n    return DisSymImpl(d, p, addr, sym);\n  } else {\n    return DisInt(p, value);\n  }\n}\n\nstatic char *DisSymLiteral(struct Dis *d, u64 rde, char *p, u64 addr, u64 ip) {\n  *p++ = '$';\n  p = HighStart(p, g_high.literal);\n  p = DisSym(d, p, addr, addr);\n  p = HighEnd(p);\n  return p;\n}\n\nstatic char *DisGvqp(struct Dis *d, u64 rde, char *p) {\n  return DisRegisterWord(d, rde, p, Rexr(rde), ModrmReg(rde));\n}\n\nstatic char *DisGdqp(struct Dis *d, u64 rde, char *p) {\n  return DisRegister(p, kGreg[0][Rexw(rde)][Rexr(rde)][ModrmReg(rde)]);\n}\n\nstatic char *DisBdqp(struct Dis *d, u64 rde, char *p) {\n  return DisRegister(p, kGreg[0][Rexw(rde)][Rexx(rde)][Vreg(rde)]);\n}\n\nstatic char *DisGb(struct Dis *d, u64 rde, char *p) {\n  return DisRegisterByte(d, rde, p, Rexr(rde), ModrmReg(rde));\n}\n\nstatic char *DisSego(struct Dis *d, u64 rde, char *p) {\n  if (Sego(rde)) {\n    p = DisRegister(p, kSeg[Sego(rde) - 1]);\n    *p++ = ':';\n  }\n  return p;\n}\n\nstatic bool IsRealModrmAbsolute(u64 rde) {\n  return Eamode(rde) == XED_MODE_REAL && ModrmRm(rde) == 6 && !ModrmMod(rde);\n}\n\nstatic char *DisDisp(struct Dis *d, u64 rde, char *p) {\n  i64 disp;\n  if (ModrmMod(rde) == 1 || ModrmMod(rde) == 2 || IsRipRelative(rde) ||\n      IsRealModrmAbsolute(rde) ||\n      (Eamode(rde) != XED_MODE_REAL && ModrmMod(rde) == 0 &&\n       ModrmRm(rde) == 4 && SibBase(rde) == 5)) {\n    disp = d->xedd->op.disp;\n    if (IsRipRelative(rde)) {\n      if (Mode(rde) == XED_MODE_LONG) {\n        disp = RipRelative(d, disp);\n      } else {\n        disp = Unrelative(rde, disp);\n      }\n    } else if (IsRealModrmAbsolute(rde)) {\n      disp = Unrelative(rde, disp);\n    }\n    p = DisSym(d, p, disp, disp);\n  }\n  return p;\n}\n\nstatic char *DisBis(struct Dis *d, u64 rde, char *p) {\n  const char *base, *index, *scale;\n  base = index = scale = NULL;\n  if (Eamode(rde) != XED_MODE_REAL) {\n    if (!SibExists(rde)) {\n      if (IsRipRelative(rde)) {\n        if (Mode(rde) == XED_MODE_LONG) {\n          base = kRip[Eamode(rde) == XED_MODE_LONG];\n        }\n      } else {\n        base = GetAddrReg(d, rde, Rexb(rde), ModrmRm(rde));\n      }\n    } else if (!SibIsAbsolute(rde)) {\n      if (SibHasBase(rde)) {\n        base = GetAddrReg(d, rde, Rexb(rde), SibBase(rde));\n      }\n      if (SibHasIndex(rde)) {\n        index = GetAddrReg(d, rde, Rexx(rde), SibIndex(rde));\n      } else if (SibScale(rde)) {\n        index = kRiz[Eamode(rde) == XED_MODE_LONG];\n      }\n      scale = kSka[SibScale(rde)];\n    }\n  } else {\n    switch (ModrmRm(rde)) {\n      case 0:\n        base = \"bx\";\n        index = \"si\";\n        break;\n      case 1:\n        base = \"bx\";\n        index = \"di\";\n        break;\n      case 2:\n        base = \"bp\";\n        index = \"si\";\n        break;\n      case 3:\n        base = \"bp\";\n        index = \"di\";\n        break;\n      case 4:\n        base = \"si\";\n        break;\n      case 5:\n        base = \"di\";\n        break;\n      case 6:\n        if (ModrmMod(rde)) base = \"bp\";\n        break;\n      case 7:\n        base = \"bx\";\n        break;\n      default:\n        __builtin_unreachable();\n    }\n  }\n  if (base || index) {\n    *p++ = '(';\n    if (base) {\n      p = DisRegister(p, base);\n    }\n    if (index) {\n      *p++ = ',';\n      p = DisRegister(p, index);\n      if (scale) {\n        p = stpcpy(p, scale);\n      }\n    }\n    *p++ = ')';\n  }\n  *p = '\\0';\n  return p;\n}\n\nstatic char *DisM(struct Dis *d, u64 rde, char *p) {\n  p = DisSego(d, rde, p);\n  p = DisDisp(d, rde, p);\n  p = DisBis(d, rde, p);\n  return p;\n}\n\nstatic char *DisRegMem(struct Dis *d, u64 rde, char *p,\n                       char *f(struct Dis *, u64, char *)) {\n  if (IsModrmRegister(rde)) {\n    return f(d, rde, p);\n  } else {\n    return DisM(d, rde, p);\n  }\n}\n\nstatic char *DisE(struct Dis *d, u64 rde, char *p,\n                  char *f(struct Dis *, u64, char *, bool, int)) {\n  if (IsModrmRegister(rde)) {\n    return f(d, rde, p, Rexb(rde), ModrmRm(rde));\n  } else {\n    return DisM(d, rde, p);\n  }\n}\n\nstatic char *DisEb(struct Dis *d, u64 rde, char *p) {\n  return DisE(d, rde, p, DisRegisterByte);\n}\n\nstatic char *DisEvqp(struct Dis *d, u64 rde, char *p) {\n  return DisE(d, rde, p, DisRegisterWord);\n}\n\nstatic char *DisRv(struct Dis *d, u64 rde, char *p) {\n  return DisRegister(p, kGreg[Osz(rde)][0][Rexb(rde)][ModrmRm(rde)]);\n}\n\nstatic char *DisRvqp(struct Dis *d, u64 rde, char *p) {\n  return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][Rexb(rde)][ModrmRm(rde)]);\n}\n\nstatic char *DisRdqp(struct Dis *d, u64 rde, char *p) {\n  return DisRegister(p, kGreg[0][Rexw(rde)][Rexb(rde)][ModrmRm(rde)]);\n}\n\nstatic char *DisEdqp(struct Dis *d, u64 rde, char *p) {\n  return DisRegMem(d, rde, p, DisRdqp);\n}\n\nstatic char *DisEv(struct Dis *d, u64 rde, char *p) {\n  return DisRegMem(d, rde, p, DisRv);\n}\n\nstatic char *DisGvq(struct Dis *d, u64 rde, char *p, int r) {\n  const char *s;\n  if (Mode(rde) == XED_MODE_LONG) {\n    s = kGreg[Osz(rde)][!Osz(rde)][Rexb(rde)][r];\n  } else {\n    s = kGreg[Osz(rde)][0][Rexb(rde)][r];\n  }\n  return DisRegister(p, s);\n}\n\nstatic char *DisZvq(struct Dis *d, u64 rde, char *p) {\n  return DisGvq(d, rde, p, ModrmSrm(rde));\n}\n\nstatic char *DisEvqReg(struct Dis *d, u64 rde, char *p) {\n  return DisGvq(d, rde, p, ModrmRm(rde));\n}\n\nstatic char *DisEvq(struct Dis *d, u64 rde, char *p) {\n  return DisRegMem(d, rde, p, DisEvqReg);\n}\n\nstatic char *DisEdReg(struct Dis *d, u64 rde, char *p) {\n  return DisRegister(p, kGreg[0][0][Rexb(rde)][ModrmRm(rde)]);\n}\n\nstatic char *DisEd(struct Dis *d, u64 rde, char *p) {\n  return DisRegMem(d, rde, p, DisEdReg);\n}\n\nstatic char *DisEqReg(struct Dis *d, u64 rde, char *p) {\n  const char *r;\n  if (Mode(rde) == XED_MODE_LONG) {\n    r = kGreg[0][1][Rexb(rde)][ModrmRm(rde)];\n  } else {\n    r = kGreg[Osz(rde)][0][Rexb(rde)][ModrmRm(rde)];\n  }\n  return DisRegister(p, r);\n}\n\nstatic char *DisEq(struct Dis *d, u64 rde, char *p) {\n  return DisRegMem(d, rde, p, DisEqReg);\n}\n\nstatic char *DisIndirEq(struct Dis *d, u64 rde, char *p) {\n  *p++ = '*';\n  return DisEq(d, rde, p);\n}\n\nstatic char *DisZvqp(struct Dis *d, u64 rde, char *p) {\n  return DisRegisterWord(d, rde, p, Rexb(rde), ModrmSrm(rde));\n}\n\nstatic char *DisZb(struct Dis *d, u64 rde, char *p) {\n  return DisRegisterByte(d, rde, p, Rexb(rde), ModrmSrm(rde));\n}\n\nstatic char *DisEax(struct Dis *d, u64 rde, char *p) {\n  return DisRegister(p, kGreg[Osz(rde)][0][0][0]);\n}\n\nstatic char *DisRax(struct Dis *d, u64 rde, char *p) {\n  return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][0][0]);\n}\n\nstatic char *DisRdx(struct Dis *d, u64 rde, char *p) {\n  return DisRegister(p, kGreg[Osz(rde)][Rexw(rde)][0][2]);\n}\n\nstatic char *DisPort(struct Dis *d, u64 rde, char *p) {\n  *p++ = '(';\n  p = DisRegister(p, kGreg[1][0][0][2]);\n  *p++ = ')';\n  *p = '\\0';\n  return p;\n}\n\nstatic char *DisCd(struct Dis *d, u64 rde, char *p) {\n  return DisRegister(p, kCtl[ModrmReg(rde)]);\n}\n\nstatic char *DisHd(struct Dis *d, u64 rde, char *p) {\n  return DisRegister(p, kGreg[0][Mode(rde) == XED_MODE_LONG][0][ModrmRm(rde)]);\n}\n\nstatic char *DisImm(struct Dis *d, u64 rde, char *p) {\n  return DisSymLiteral(d, rde, p, d->xedd->op.uimm0,\n                       ZeroExtend(rde, d->xedd->op.uimm0));\n}\n\nstatic char *DisIw(struct Dis *d, u64 rde, char *p) {\n  return DisSymLiteral(d, rde, p, d->xedd->op.uimm0 & 0xffff,\n                       d->xedd->op.uimm0 & 0xffff);\n}\n\nstatic char *DisEnterIb(struct Dis *d, u64 rde, char *p) {\n  return DisSymLiteral(d, rde, p, d->xedd->op.uimm0 >> 16 & 0xff,\n                       d->xedd->op.uimm0 >> 16 & 0xff);\n}\n\nstatic char *DisRvds(struct Dis *d, u64 rde, char *p) {\n  return DisSymLiteral(d, rde, p, d->xedd->op.disp, d->xedd->op.disp);\n}\n\nstatic char *DisKpvds(struct Dis *d, u64 rde, char *p, u64 x) {\n  *p++ = '$';\n  p = HighStart(p, g_high.literal);\n  p = DisInt(p, x);\n  p = HighEnd(p);\n  return p;\n}\n\nstatic char *DisKvds(struct Dis *d, u64 rde, char *p) {\n  return DisKpvds(d, rde, p, d->xedd->op.uimm0);\n}\n\nstatic char *DisPvds(struct Dis *d, u64 rde, char *p) {\n  return DisKpvds(d, rde, p,\n                  d->xedd->op.disp & (Osz(rde) ? 0xffff : 0xffffffff));\n}\n\nstatic char *DisOne(struct Dis *d, u64 rde, char *p) {\n  *p++ = '$';\n  p = HighStart(p, g_high.literal);\n  p = stpcpy(p, \"1\");\n  p = HighEnd(p);\n  return p;\n}\n\nstatic char *DisJbs(struct Dis *d, u64 rde, char *p) {\n  if (d->xedd->op.disp > 0) *p++ = '+';\n  p += snprintf(p, 32, \"%\" PRId64, d->xedd->op.disp);\n  return p;\n}\n\nstatic char *DisJb(struct Dis *d, u64 rde, char *p) {\n  if (d->xedd->op.disp > 0) *p++ = '+';\n  p += snprintf(p, 32, \"%d\", (int)(d->xedd->op.disp & 0xff));\n  return p;\n}\n\nstatic char *DisJvds(struct Dis *d, u64 rde, char *p) {\n  return DisSym(d, p, RipRelative(d, d->xedd->op.disp),\n                RipRelative(d, d->xedd->op.disp) - (d->m ? d->m->cs.base : 0));\n}\n\nstatic char *DisAbs(struct Dis *d, u64 rde, char *p) {\n  return DisSym(d, p, d->xedd->op.disp, d->xedd->op.disp);\n}\n\nstatic char *DisSw(struct Dis *d, u64 rde, char *p) {\n  if (kSeg[ModrmReg(rde)][0]) p = DisRegister(p, kSeg[ModrmReg(rde)]);\n  return p;\n}\n\nstatic char *DisSpecialAddr(struct Dis *d, u64 rde, char *p, int r) {\n  *p++ = '(';\n  p = DisRegister(p, GetAddrReg(d, rde, 0, r));\n  *p++ = ')';\n  *p = '\\0';\n  return p;\n}\n\nstatic char *DisY(struct Dis *d, u64 rde, char *p) {\n  return DisSpecialAddr(d, rde, p, 7);  // es:di\n}\n\nstatic char *DisX(struct Dis *d, u64 rde, char *p) {\n  p = DisSego(d, rde, p);\n  return DisSpecialAddr(d, rde, p, 6);  // ds:si\n}\n\nstatic char *DisBBb(struct Dis *d, u64 rde, char *p) {\n  p = DisSego(d, rde, p);\n  return DisSpecialAddr(d, rde, p, 3);  // ds:bx\n}\n\nstatic char *DisXmm(struct Dis *d, u64 rde, char *p, const char *s, int reg) {\n  p = HighStart(p, g_high.reg);\n  *p++ = '%';\n  p = stpcpy(p, s);\n  p += snprintf(p, 32, \"%u\", reg);\n  p = HighEnd(p);\n  return p;\n}\n\nstatic char *DisNq(struct Dis *d, u64 rde, char *p) {\n  return DisXmm(d, rde, p, \"mm\", ModrmRm(rde));\n}\n\nstatic char *DisPq(struct Dis *d, u64 rde, char *p) {\n  return DisXmm(d, rde, p, \"mm\", ModrmReg(rde));\n}\n\nstatic char *DisUq(struct Dis *d, u64 rde, char *p) {\n  return DisXmm(d, rde, p, \"xmm\", RexbRm(rde));\n}\n\nstatic char *DisUdq(struct Dis *d, u64 rde, char *p) {\n  return DisXmm(d, rde, p, \"xmm\", RexbRm(rde));\n}\n\nstatic char *DisVdq(struct Dis *d, u64 rde, char *p) {\n  return DisXmm(d, rde, p, \"xmm\", RexrReg(rde));\n}\n\nstatic char *DisQq(struct Dis *d, u64 rde, char *p) {\n  return DisRegMem(d, rde, p, DisNq);\n}\n\nstatic char *DisEst(struct Dis *d, u64 rde, char *p) {\n  p = DisRegister(p, \"st\");\n  if (ModrmRm(rde) != 0) {\n    *p++ = '(';\n    *p++ = '0' + ModrmRm(rde);\n    *p++ = ')';\n    *p = '\\0';\n  }\n  return p;\n}\n\nstatic char *DisEst1(struct Dis *d, u64 rde, char *p) {\n  if (ModrmRm(rde) != 1) {\n    p = DisEst(d, rde, p);\n  } else {\n    *p = '\\0';\n  }\n  return p;\n}\n\nstatic char *DisEssr(struct Dis *d, u64 rde, char *p) {\n  return DisRegMem(d, rde, p, DisEst);\n}\n\nstatic char *DisWps(struct Dis *d, u64 rde, char *p) {\n  return DisRegMem(d, rde, p, DisUdq);\n}\n\n#define DisEdr  DisM\n#define DisEqp  DisEq\n#define DisEsr  DisM\n#define DisGv   DisGvqp\n#define DisIb   DisImm\n#define DisIbs  DisImm\n#define DisIbss DisImm\n#define DisIvds DisImm\n#define DisIvqp DisImm\n#define DisIvs  DisImm\n#define DisMdi  DisM\n#define DisMdq  DisM\n#define DisMdqp DisM\n#define DisMdr  DisM\n#define DisMe   DisM\n#define DisMer  DisM\n#define DisMp   DisM\n#define DisMps  DisM\n#define DisMq   DisM\n#define DisMqi  DisM\n#define DisMs   DisM\n#define DisMsr  DisEssr\n#define DisMw   DisM\n#define DisMwi  DisM\n#define DisOb   DisAbs\n#define DisOvqp DisAbs\n#define DisPpi  DisPq\n#define DisQpi  DisQq\n#define DisVpd  DisVdq\n#define DisVps  DisVdq\n#define DisVq   DisVdq\n#define DisVsd  DisVdq\n#define DisVss  DisVdq\n#define DisWdq  DisWps\n#define DisWpd  DisWps\n#define DisWpsq DisWps\n#define DisWq   DisWps\n#define DisWsd  DisWps\n#define DisWss  DisWps\n#define DisXb   DisX\n#define DisXv   DisX\n#define DisXvqp DisX\n#define DisYb   DisY\n#define DisYv   DisY\n#define DisYvqp DisY\n#define DisZv   DisZvqp\n\nstatic const struct DisArg {\n  char s[8];\n  char *(*f)(struct Dis *, u64, char *);\n} kDisArgs[] = /* <sorted> */ {\n    {\"$1\", DisOne},       //\n    {\"%Bdqp\", DisBdqp},   //\n    {\"%Cd\", DisCd},       //\n    {\"%Gb\", DisGb},       //\n    {\"%Gdqp\", DisGdqp},   //\n    {\"%Gv\", DisGv},       //\n    {\"%Gvqp\", DisGvqp},   //\n    {\"%Hd\", DisHd},       //\n    {\"%Nq\", DisNq},       //\n    {\"%Ppi\", DisPpi},     //\n    {\"%Pq\", DisPq},       //\n    {\"%Rdqp\", DisRdqp},   //\n    {\"%Rvqp\", DisRvqp},   //\n    {\"%Sw\", DisSw},       //\n    {\"%Udq\", DisUdq},     //\n    {\"%Uq\", DisUq},       //\n    {\"%Vdq\", DisVdq},     //\n    {\"%Vpd\", DisVpd},     //\n    {\"%Vps\", DisVps},     //\n    {\"%Vq\", DisVq},       //\n    {\"%Vsd\", DisVsd},     //\n    {\"%Vss\", DisVss},     //\n    {\"%Zb\", DisZb},       //\n    {\"%Zv\", DisZv},       //\n    {\"%Zvq\", DisZvq},     //\n    {\"%Zvqp\", DisZvqp},   //\n    {\"%eAX\", DisEax},     //\n    {\"%rAX\", DisRax},     //\n    {\"%rDX\", DisRdx},     //\n    {\"*Eq\", DisIndirEq},  //\n    {\">Ib\", DisEnterIb},  //\n    {\"BBb\", DisBBb},      //\n    {\"DX\", DisPort},      //\n    {\"EST\", DisEst},      //\n    {\"EST1\", DisEst1},    //\n    {\"ESsr\", DisEssr},    //\n    {\"Eb\", DisEb},        //\n    {\"Ed\", DisEd},        //\n    {\"Edqp\", DisEdqp},    //\n    {\"Edr\", DisEdr},      //\n    {\"Eq\", DisEq},        //\n    {\"Eqp\", DisEqp},      //\n    {\"Esr\", DisEsr},      //\n    {\"Ev\", DisEv},        //\n    {\"Evq\", DisEvq},      //\n    {\"Evqp\", DisEvqp},    //\n    {\"Ew\", DisEvqp},      //\n    {\"Ib\", DisIb},        //\n    {\"Ibs\", DisIbs},      //\n    {\"Ibss\", DisIbss},    //\n    {\"Ivds\", DisIvds},    //\n    {\"Ivqp\", DisIvqp},    //\n    {\"Ivs\", DisIvs},      //\n    {\"Iw\", DisIw},        //\n    {\"Jb\", DisJb},        //\n    {\"Jbs\", DisJbs},      //\n    {\"Jvds\", DisJvds},    //\n    {\"Kvds\", DisKvds},    //\n    {\"M\", DisM},          //\n    {\"Mdi\", DisMdi},      //\n    {\"Mdq\", DisMdq},      //\n    {\"Mdqp\", DisMdqp},    //\n    {\"Mdr\", DisMdr},      //\n    {\"Me\", DisMe},        //\n    {\"Mer\", DisMer},      //\n    {\"Mp\", DisMp},        //\n    {\"Mps\", DisMps},      //\n    {\"Mq\", DisMq},        //\n    {\"Mqi\", DisMqi},      //\n    {\"Ms\", DisMs},        //\n    {\"Msr\", DisMsr},      //\n    {\"Mw\", DisMw},        //\n    {\"Mwi\", DisMwi},      //\n    {\"Ob\", DisOb},        //\n    {\"Ovqp\", DisOvqp},    //\n    {\"Pvds\", DisPvds},    //\n    {\"Qpi\", DisQpi},      //\n    {\"Qq\", DisQq},        //\n    {\"Rvds\", DisRvds},    //\n    {\"Wdq\", DisWdq},      //\n    {\"Wpd\", DisWpd},      //\n    {\"Wps\", DisWps},      //\n    {\"Wpsq\", DisWpsq},    //\n    {\"Wq\", DisWq},        //\n    {\"Wsd\", DisWsd},      //\n    {\"Wss\", DisWss},      //\n    {\"Xb\", DisXb},        //\n    {\"Xv\", DisXv},        //\n    {\"Xvqp\", DisXvqp},    //\n    {\"Yb\", DisYb},        //\n    {\"Yv\", DisYv},        //\n    {\"Yvqp\", DisYvqp},    //\n};\n\nstatic int CompareString8(const char a[8], const char b[8]) {\n  u64 x, y;\n  x = ((u64)(255 & a[0]) << 070 | (u64)(255 & a[1]) << 060 |\n       (u64)(255 & a[2]) << 050 | (u64)(255 & a[3]) << 040 |\n       (u64)(255 & a[4]) << 030 | (u64)(255 & a[5]) << 020 |\n       (u64)(255 & a[6]) << 010 | (u64)(255 & a[7]) << 000);\n  y = ((u64)(255 & b[0]) << 070 | (u64)(255 & b[1]) << 060 |\n       (u64)(255 & b[2]) << 050 | (u64)(255 & b[3]) << 040 |\n       (u64)(255 & b[4]) << 030 | (u64)(255 & b[5]) << 020 |\n       (u64)(255 & b[6]) << 010 | (u64)(255 & b[7]) << 000);\n  return x > y ? 1 : x < y ? -1 : 0;\n}\n\nchar *DisArg(struct Dis *d, char *p, const char *s) {\n  char key[8];\n  int c, m, l, r;\n  l = 0;\n  r = ARRAYLEN(kDisArgs) - 1;\n  memset(key, 0, sizeof(key));\n  memcpy(key, s, MIN(8, strlen(s)));\n  while (l <= r) {\n    m = (l + r) >> 1;\n    c = CompareString8(kDisArgs[m].s, key);\n    if (c < 0) {\n      l = m + 1;\n    } else if (c > 0) {\n      r = m - 1;\n    } else {\n      return kDisArgs[m].f(d, d->xedd->op.rde, p);\n    }\n  }\n  if (*s == '%') {\n    p = DisRegister(p, s + 1);\n  } else {\n    p = stpcpy(p, s);\n  }\n  return p;\n}\n"
  },
  {
    "path": "blink/diself.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/assert.h\"\n#include \"blink/dis.h\"\n#include \"blink/elf.h\"\n#include \"blink/endian.h\"\n#include \"blink/log.h\"\n#include \"blink/util.h\"\n\nstatic int DisSymCompare(const void *p1, const void *p2) {\n  const struct DisSym *a = (const struct DisSym *)p1;\n  const struct DisSym *b = (const struct DisSym *)p2;\n  if (a->addr != b->addr) {\n    if (a->addr < b->addr) return -1;\n    if (a->addr > b->addr) return +1;\n  }\n  if (a->rank != b->rank) {\n    if (a->rank > b->rank) return -1;\n    if (a->rank < b->rank) return +1;\n  }\n  if (a->unique != b->unique) {\n    if (a->unique < b->unique) return -1;\n    if (a->unique > b->unique) return +1;\n  }\n  return 0;\n}\n\nstatic void DisLoadElfLoads(struct Dis *d, Elf64_Ehdr_ *ehdr, size_t esize,\n                            i64 eskew) {\n  long i;\n  Elf64_Phdr_ *phdr;\n  for (i = 0; i < Read16(ehdr->phnum); ++i) {\n    phdr = GetElfProgramHeaderAddress(ehdr, esize, i);\n    if (Read32(phdr->type) != PT_LOAD_) continue;\n    if (d->loads.i == d->loads.n) {\n      d->loads.n += 2;\n      d->loads.n += d->loads.n >> 1;\n      unassert(d->loads.p = (struct DisLoad *)realloc(\n                   d->loads.p, d->loads.n * sizeof(*d->loads.p)));\n    }\n    d->loads.p[d->loads.i].addr = Read64(phdr->vaddr) + eskew;\n    d->loads.p[d->loads.i].size = Read64(phdr->memsz);\n    d->loads.p[d->loads.i].istext = (Read32(phdr->flags) & PF_X_) == PF_X_;\n    ++d->loads.i;\n  }\n}\n\nstatic void DisLoadElfSyms(struct Dis *d, Elf64_Ehdr_ *ehdr, size_t esize,\n                           i64 eskew) {\n  int n;\n  long i;\n  char *stab;\n  i64 stablen;\n  const Elf64_Sym_ *st;\n  bool isabs, isweak, islocal, isprotected, isfunc, isobject;\n  if ((stab = GetElfStringTable(ehdr, esize))) {\n    if ((st = GetElfSymbolTable(ehdr, esize, &n))) {\n      stablen = (uintptr_t)ehdr + esize - (uintptr_t)stab;\n      for (i = 0; i < n; ++i) {\n        if (ELF64_ST_TYPE_(st[i].info) == STT_SECTION_ ||\n            ELF64_ST_TYPE_(st[i].info) == STT_FILE_ || !Read32(st[i].name) ||\n            StartsWith(stab + Read32(st[i].name), \"v_\") ||\n            !(0 <= Read32(st[i].name) && Read32(st[i].name) < stablen) ||\n            !Read64(st[i].value) ||\n            !(-0x800000000000 <= (i64)Read64(st[i].value) &&\n              (i64)Read64(st[i].value) < 0x800000000000)) {\n          continue;\n        }\n        isabs = Read16(st[i].shndx) == SHN_ABS_;\n        isweak = ELF64_ST_BIND_(st[i].info) == STB_WEAK_;\n        islocal = ELF64_ST_BIND_(st[i].info) == STB_LOCAL_;\n        isprotected = st[i].other == STV_PROTECTED_;\n        isfunc = ELF64_ST_TYPE_(st[i].info) == STT_FUNC_;\n        isobject = ELF64_ST_TYPE_(st[i].info) == STT_OBJECT_;\n        if (d->syms.i == d->syms.n) {\n          d->syms.n += 2;\n          d->syms.n += d->syms.n >> 1;\n          unassert(d->syms.p = (struct DisSym *)realloc(\n                       d->syms.p, d->syms.n * sizeof(*d->syms.p)));\n        }\n        d->syms.p[d->syms.i].unique = i;\n        d->syms.p[d->syms.i].size = Read64(st[i].size);\n        unassert(d->syms.p[d->syms.i].name = strdup(stab + Read32(st[i].name)));\n        d->syms.p[d->syms.i].addr = Read64(st[i].value) + eskew;\n        d->syms.p[d->syms.i].rank =\n            -islocal + -isweak + -isabs + isprotected + isobject + isfunc;\n        d->syms.p[d->syms.i].iscode =\n            DisIsText(d, Read64(st[i].value)) ? !isobject : isfunc;\n        d->syms.p[d->syms.i].isabs = isabs;\n        ++d->syms.i;\n      }\n    } else {\n      LOGF(\"could not load elf symbol table\");\n    }\n  } else {\n    LOGF(\"could not load elf string table\");\n  }\n}\n\nstatic void DisSortSyms(struct Dis *d) {\n  qsort(d->syms.p, d->syms.i, sizeof(struct DisSym), DisSymCompare);\n}\n\nbool DisIsProg(struct Dis *d, i64 addr) {\n  long i;\n  for (i = 0; i < d->loads.i; ++i) {\n    if (addr >= d->loads.p[i].addr &&\n        addr < d->loads.p[i].addr + d->loads.p[i].size) {\n      return true;\n    }\n  }\n  return false;\n}\n\nbool DisIsText(struct Dis *d, i64 addr) {\n  long i;\n  for (i = 0; i < d->loads.i; ++i) {\n    if (addr >= d->loads.p[i].addr &&\n        addr < d->loads.p[i].addr + d->loads.p[i].size) {\n      return d->loads.p[i].istext;\n    }\n  }\n  return false;\n}\n\nlong DisFindSym(struct Dis *d, i64 addr) {\n  long l, r, m;\n  if (DisIsProg(d, addr)) {\n    l = 0;\n    r = d->syms.i;\n    while (l < r) {\n      m = (l + r) >> 1;\n      if (d->syms.p[m].addr > addr) {\n        r = m;\n      } else {\n        l = m + 1;\n      }\n    }\n    // TODO(jart): This was <256 but that broke SectorLISP debugging\n    //             Why did the Cosmo binbase bootloader need this?\n    if (r && d->syms.p[r - 1].addr < 32) {\n      return -1;\n    }\n    if (r && (addr == d->syms.p[r - 1].addr ||\n              (addr > d->syms.p[r - 1].addr &&\n               (addr <= d->syms.p[r - 1].addr + d->syms.p[r - 1].size ||\n                !d->syms.p[r - 1].size)))) {\n      return r - 1;\n    }\n  }\n  return -1;\n}\n\nlong DisFindSymByName(struct Dis *d, const char *s) {\n  long i;\n  for (i = 0; i < d->syms.i; ++i) {\n    if (strcmp(s, d->syms.p[i].name) == 0) {\n      return i;\n    }\n  }\n  return -1;\n}\n\nvoid DisLoadElf(struct Dis *d, Elf64_Ehdr_ *ehdr, size_t esize, i64 eskew) {\n  DisLoadElfLoads(d, ehdr, esize, eskew);\n  DisLoadElfSyms(d, ehdr, esize, eskew);\n  DisSortSyms(d);\n}\n"
  },
  {
    "path": "blink/disfree.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/dis.h\"\n\nvoid DisFreeOp(struct DisOp *o) {\n  free(o->s);\n}\n\nvoid DisFreeOps(struct DisOps *ops) {\n  long i;\n  for (i = 0; i < ops->i; ++i) {\n    DisFreeOp(&ops->p[i]);\n  }\n  free(ops->p);\n  memset(ops, 0, sizeof(*ops));\n}\n\nvoid DisFreeSyms(struct DisSyms *syms) {\n  long i;\n  for (i = 0; i < syms->i; ++i) {\n    free(syms->p[i].name);\n  }\n  free(syms->p);\n  memset(syms, 0, sizeof(*syms));\n}\n\nvoid DisFree(struct Dis *d) {\n  DisFreeOps(&d->ops);\n  DisFreeSyms(&d->syms);\n  free(d->edges.p);\n  free(d->loads.p);\n  memset(d, 0, sizeof(*d));\n}\n"
  },
  {
    "path": "blink/disinst.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/assert.h\"\n#include \"blink/dis.h\"\n#include \"blink/high.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n#include \"blink/util.h\"\n\nstatic const char kJcxz[3][6] = {\"jcxz\", \"jecxz\", \"jrcxz\"};\nstatic const char kAluOp[8][4] = {\"add\", \"or\",  \"adc\", \"sbb\",\n                                  \"and\", \"sub\", \"xor\", \"cmp\"};\nstatic const char kBitOp[8][4] = {\"rol\", \"ror\", \"rcl\", \"rcr\",\n                                  \"shl\", \"shr\", \"sal\", \"sar\"};\nstatic const char kCc[16][3] = {\"o\", \"no\", \"b\", \"ae\", \"e\", \"ne\", \"be\", \"a\",\n                                \"s\", \"ns\", \"p\", \"np\", \"l\", \"ge\", \"le\", \"g\"};\n\nstatic bool IsProbablyByteOp(struct XedDecodedInst *x) {\n  return !(Opcode(x->op.rde) & 1);\n}\n\nstatic int IsRepOpcode(struct Dis *d) {\n  switch (Opcode(d->xedd->op.rde) & ~1) {\n    case 0x6C: /* INS */\n      return 1;\n    case 0x6E: /* OUTS */\n      return 1;\n    case 0xA4: /* MOVS */\n      return 1;\n    case 0xAA: /* STOS */\n      return 1;\n    case 0xAC: /* LODS */\n      return 1;\n    case 0xA6: /* CMPS */\n      return 2;\n    case 0xAE: /* SCAS */\n      return 2;\n    default:\n      return 0;\n  }\n}\n\nstatic char *DisRepPrefix(struct Dis *d, char *p) {\n  if (Rep(d->xedd->op.rde) && Opmap(d->xedd->op.rde) == XED_ILD_MAP0) {\n    switch (IsRepOpcode(d)) {\n      case 0:\n        break;\n      case 1:\n        p = stpcpy(p, \"rep \");\n        break;\n      case 2:\n        p = stpcpy(p, Rep(d->xedd->op.rde) == 2 ? \"repnz \" : \"repz \");\n        break;\n      default:\n        break;\n    }\n  }\n  return p;\n}\n\nstatic char *DisName(struct Dis *d, char *bp, const char *name,\n                     bool ambiguous) {\n  u64 rde;\n  char *p;\n  const char *np;\n  bool notbyte, notlong, wantsuffix, wantsuffixsd;\n  p = bp;\n  rde = d->xedd->op.rde;\n  if (Lock(d->xedd->op.rde)) p = stpcpy(p, \"lock \");\n  p = DisRepPrefix(d, p);\n  if (strcmp(name, \"BIT\") == 0) {\n    p = stpcpy(p, kBitOp[ModrmReg(rde)]);\n  } else if (strcmp(name, \"nop\") == 0 && Rep(d->xedd->op.rde)) {\n    p = stpcpy(p, \"pause\");\n  } else if (strcmp(name, \"CALL\") == 0) {\n    p = stpcpy(p, \"call\");\n  } else if (strcmp(name, \"JMP\") == 0) {\n    p = stpcpy(p, \"jmp\");\n  } else if (strcmp(name, \"jcxz\") == 0) {\n    p = stpcpy(p, kJcxz[Eamode(rde)]);\n  } else if (strcmp(name, \"loop\") == 0 || strcmp(name, \"loope\") == 0 ||\n             strcmp(name, \"loopne\") == 0) {\n    p = stpcpy(p, name);\n    if (Eamode(rde) != Mode(rde)) {\n      *p++ = \"wl\"[Eamode(rde)];\n      *p = '\\0';\n    }\n  } else if (strcmp(name, \"cwtl\") == 0) {\n    if (Osz(rde)) name = \"cbtw\";\n    if (Rexw(rde)) name = \"cltq\";\n    p = stpcpy(p, name);\n  } else if (strcmp(name, \"cltd\") == 0) {\n    if (Osz(rde)) name = \"cwtd\";\n    if (Rexw(rde)) name = \"cqto\";\n    p = stpcpy(p, name);\n  } else {\n    notbyte = false;\n    notlong = false;\n    wantsuffix = false;\n    wantsuffixsd = false;\n    for (np = name; *np && (islower(*np) || isdigit(*np)); ++np) {\n      *p++ = *np;\n    }\n    if (strcmp(name, \"ALU\") == 0) {\n      p = stpcpy(p, kAluOp[(Opcode(rde) & 070) >> 3]);\n    } else if (strcmp(name, \"ALU2\") == 0) {\n      p = stpcpy(p, kAluOp[ModrmReg(rde)]);\n    } else if (strcmp(np, \"WLQ\") == 0) {\n      notbyte = true;\n      wantsuffix = true;\n    } else if (strcmp(np, \"CC\") == 0) {\n      p = stpcpy(p, kCc[Opcode(rde) & 15]);\n    } else if (strcmp(np, \"WQ\") == 0) {\n      notbyte = true;\n      notlong = Eamode(rde) != XED_MODE_REAL;\n      wantsuffix = true;\n    } else if (strcmp(np, \"LQ\") == 0 || strcmp(np, \"WL\") == 0) {\n      notbyte = true;\n      wantsuffix = true;\n    } else if (strcmp(np, \"SD\") == 0) {\n      notbyte = true;\n      wantsuffixsd = true;\n    } else if (strcmp(np, \"ABS\") == 0) {\n      if (Rexw(rde)) p = stpcpy(p, \"abs\");\n    }\n    if (wantsuffixsd) {\n      if (Osz(rde)) {\n        *p++ = 'd';\n      } else {\n        *p++ = 's';\n      }\n    } else if (wantsuffix || (ambiguous && !StartsWith(name, \"f\") &&\n                              !StartsWith(name, \"set\"))) {\n      if (Osz(rde)) {\n        if (ambiguous || Mode(rde) != XED_MODE_REAL) {\n          *p++ = 'w';\n        }\n      } else if (Rexw(rde)) {\n        *p++ = 'q';\n      } else if (ambiguous && !notbyte && IsProbablyByteOp(d->xedd)) {\n        *p++ = 'b';\n      } else if (!notlong) {\n        *p++ = 'l';\n      }\n    }\n  }\n  *p++ = ' ';\n  if (!d->notab) {\n    while (p - bp < 8) {\n      *p++ = ' ';\n    }\n  }\n  *p = '\\0';\n  return p;\n}\n\n/**\n * Disassembles instruction based on string spec.\n * @see DisSpec()\n */\nchar *DisInst(struct Dis *d, char *p, const char *spec) {\n  size_t m;\n  long i, n;\n  char sbuf[64];\n  char args[4][256];\n  char *s, *name, *state;\n  bool hasarg, hasmodrm, hasregister, hasmemory;\n  unassert(strlen(spec) < 128);\n  hasarg = false;\n  hasmodrm = d->xedd->op.has_modrm;\n  hasmemory = hasmodrm && !IsModrmRegister(d->xedd->op.rde);\n  hasregister = hasmodrm && IsModrmRegister(d->xedd->op.rde);\n  name = strtok_r(strcpy(sbuf, spec), \" \", &state);\n  for (n = 0; (s = strtok_r(NULL, \" \", &state)); ++n) {\n    hasarg = true;\n    hasregister |= *s == '%';\n    hasmemory |= *s == 'O';\n    m = DisArg(d, args[n], s) - args[n];\n    if (m >= sizeof(args[n])) Abort();\n  }\n  p = HighStart(p, g_high.keyword);\n  p = DisName(d, p, name, hasarg && !hasregister && hasmemory);\n  p = HighEnd(p);\n  for (i = 0; i < n; ++i) {\n    if (i && args[n - i][0]) {\n      *p++ = ',';\n    }\n    p = stpcpy(p, args[n - i - 1]);\n  }\n  return p;\n}\n"
  },
  {
    "path": "blink/disspec.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdbool.h>\n#include <string.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/case.h\"\n#include \"blink/rde.h\"\n#include \"blink/x86.h\"\n\n#define UNKNOWN     \"wut\"\n#define RCASE(x, y) CASE(x, return y)\n\nstatic const char kFpuName[][8][8] = {\n    {\"fadd\", \"fmul\", \"fcom\", \"fcomp\", \"fsub\", \"fsubr\", \"fdiv\", \"fdivr\"},\n    {\"fchs\", \"fabs\", UNKNOWN, UNKNOWN, \"ftst\", \"fxam\", UNKNOWN, UNKNOWN},\n    {\"fld1\", \"fldl2t\", \"fldl2e\", \"fldpi\", \"fldlg2\", \"fldln2\", \"fldz\"},\n    {\"f2xm1\", \"fyl2x\", \"fptan\", \"fpatan\", \"fxtract\", \"fprem1\", \"fdecstp\",\n     \"fincstp\"},\n    {\"fprem\", \"fyl2xp1\", \"fsqrt\", \"fsincos\", \"frndint\", \"fscale\", \"fsin\",\n     \"fcos\"},\n    {\"fneni\", \"fndisi\", \"fnclex\", \"fninit\", \"fnsetpm\"},\n};\n\nchar *DisOpFpu1(struct XedDecodedInst *x, char *p, const char *extra) {\n  stpcpy(stpcpy(p, kFpuName[0][ModrmReg(x->op.rde)]), extra);\n  return p;\n}\n\nchar *DisOp66(struct XedDecodedInst *x, char *p, const char *s, const char *a,\n              const char *b) {\n  stpcpy(stpcpy(p, s), !Osz(x->op.rde) ? a : b);\n  return p;\n}\n\nchar *DisOpVpsWpsVssWss(struct XedDecodedInst *x, char *p, const char *s) {\n  return DisOp66(x, p, s, \"ps %Vps Wps\", \"ss %Vss Wss\");\n}\n\nchar *DisOpVpdWpdVpsWps(struct XedDecodedInst *x, char *p, const char *s) {\n  return DisOp66(x, p, s, \"ps %Vps Wps\", \"pd %Vpd Wpd\");\n}\n\nchar *DisOpPqQqVdqWdq(struct XedDecodedInst *x, char *p, const char *s) {\n  return DisOp66(x, p, s, \" %Pq Qq\", \" %Vdq Wdq\");\n}\n\nchar *DisOpPqQqIbVdqWdqIb(struct XedDecodedInst *x, char *p, const char *s) {\n  return DisOp66(x, p, s, \" %Pq Qq Ib\", \" %Vdq Wdq Ib\");\n}\n\nchar *DisOpNqIbUdqIb(struct XedDecodedInst *x, char *p, const char *s) {\n  return DisOp66(x, p, s, \" %Nq Ib\", \" %Udq Ib\");\n}\n\nchar *DisOpVpsWpsVssWssVpdWpdVsdWsd(struct XedDecodedInst *x, char *p,\n                                    const char *s) {\n  char *q = stpcpy(p, s);\n  if (Rep(x->op.rde) == 3) {\n    stpcpy(q, \"ss %Vss Wss\");\n  } else if (Rep(x->op.rde) == 2) {\n    stpcpy(q, \"sd %Vsd Wsd\");\n  } else if (Osz(x->op.rde)) {\n    stpcpy(q, \"pd %Vpd Wpd\");\n  } else {\n    stpcpy(q, \"ps %Vps Wps\");\n  }\n  return p;\n}\n\nconst char *DisSpecFpu0(struct XedDecodedInst *x, int group) {\n  const char *s;\n  s = kFpuName[group][ModrmRm(x->op.rde)];\n  return *s ? s : UNKNOWN;\n}\n\nconst char *DisSpecRegMem(struct XedDecodedInst *x, const char *a,\n                          const char *b) {\n  if (IsModrmRegister(x->op.rde)) {\n    return a;\n  } else {\n    return b;\n  }\n}\n\nconst char *DisSpecRegMemFpu0(struct XedDecodedInst *x, int group,\n                              const char *b) {\n  return DisSpecRegMem(x, DisSpecFpu0(x, group), b);\n}\n\nconst char *DisSpecMap0(struct XedDecodedInst *x, char *p) {\n  switch (Opcode(x->op.rde)) {\n    RCASE(0x00, \"ALU Eb %Gb\");\n    RCASE(0x01, \"ALU Evqp %Gvqp\");\n    RCASE(0x02, \"ALU %Gb Eb\");\n    RCASE(0x03, \"ALU %Gvqp Evqp\");\n    RCASE(0x04, \"ALU %al Ib\");\n    RCASE(0x05, \"ALU %rAX Ivds\");\n    RCASE(0x06, \"push %es\");\n    RCASE(0x07, \"pop %es\");\n    RCASE(0x08, \"ALU Eb %Gb\");\n    RCASE(0x09, \"ALU Evqp %Gvqp\");\n    RCASE(0x0a, \"ALU %Gb Eb\");\n    RCASE(0x0b, \"ALU %Gvqp Evqp\");\n    RCASE(0x0c, \"ALU %al Ib\");\n    RCASE(0x0d, \"ALU %rAX Ivds\");\n    RCASE(0x0e, \"push %cs\");\n    RCASE(0x0f, \"pop %cs\");\n    RCASE(0x10, \"ALU Eb %Gb\");\n    RCASE(0x11, \"ALU Evqp %Gvqp\");\n    RCASE(0x12, \"ALU %Gb Eb\");\n    RCASE(0x13, \"ALU %Gvqp Evqp\");\n    RCASE(0x14, \"ALU %al Ib\");\n    RCASE(0x15, \"ALU %rAX Ivds\");\n    RCASE(0x16, \"push %ss\");\n    RCASE(0x17, \"pop %ss\");\n    RCASE(0x18, \"ALU Eb %Gb\");\n    RCASE(0x19, \"ALU Evqp %Gvqp\");\n    RCASE(0x1a, \"ALU %Gb Eb\");\n    RCASE(0x1b, \"ALU %Gvqp Evqp\");\n    RCASE(0x1c, \"ALU %al Ib\");\n    RCASE(0x1d, \"ALU %rAX Ivds\");\n    RCASE(0x1e, \"push %ds\");\n    RCASE(0x1f, \"pop %ds\");\n    RCASE(0x20, \"ALU Eb %Gb\");\n    RCASE(0x21, \"ALU Evqp %Gvqp\");\n    RCASE(0x22, \"ALU %Gb Eb\");\n    RCASE(0x23, \"ALU %Gvqp Evqp\");\n    RCASE(0x24, \"ALU %al Ib\");\n    RCASE(0x25, \"ALU %rAX Ivds\");\n    RCASE(0x26, \"push %es\");\n    RCASE(0x27, \"pop %es\");\n    RCASE(0x28, \"ALU Eb %Gb\");\n    RCASE(0x29, \"ALU Evqp %Gvqp\");\n    RCASE(0x2a, \"ALU %Gb Eb\");\n    RCASE(0x2b, \"ALU %Gvqp Evqp\");\n    RCASE(0x2c, \"ALU %al Ib\");\n    RCASE(0x2d, \"ALU %rAX Ivds\");\n    RCASE(0x2F, \"das\");\n    RCASE(0x30, \"ALU Eb %Gb\");\n    RCASE(0x31, \"ALU Evqp %Gvqp\");\n    RCASE(0x32, \"ALU %Gb Eb\");\n    RCASE(0x33, \"ALU %Gvqp Evqp\");\n    RCASE(0x34, \"ALU %al Ib\");\n    RCASE(0x35, \"ALU %rAX Ivds\");\n    RCASE(0x37, \"aaa\");\n    RCASE(0x38, \"ALU Eb %Gb\");\n    RCASE(0x39, \"ALU Evqp %Gvqp\");\n    RCASE(0x3A, \"ALU %Gb Eb\");\n    RCASE(0x3B, \"ALU %Gvqp Evqp\");\n    RCASE(0x3C, \"ALU %al Ib\");\n    RCASE(0x3D, \"ALU %rAX Ivds\");\n    RCASE(0x3F, \"aas\");\n    RCASE(0x60, \"pusha\");\n    RCASE(0x61, \"popa\");\n    RCASE(0x62, \"bound\");\n    RCASE(0x63, \"movslLQ %Gdqp Ed\");\n    RCASE(0x68, \"pushWQ Ivs\");\n    RCASE(0x69, \"imul %Gvqp Evqp Ivds\");\n    RCASE(0x6A, \"pushWQ Ibss\");\n    RCASE(0x6B, \"imul %Gvqp Evqp Ibs\");\n    RCASE(0x6C, \"insb Yb DX\");\n    RCASE(0x6D, \"insWL Yv DX\");\n    RCASE(0x6E, \"outsb DX Xb\");\n    RCASE(0x6F, \"outsWL DX Xv\");\n    RCASE(0x80, \"ALU2 Eb Ib\");\n    RCASE(0x81, \"ALU2 Evqp Ivds\");\n    RCASE(0x82, \"ALU2 Eb Ib\");\n    RCASE(0x83, \"ALU2 Evqp Ibs\");\n    RCASE(0x84, \"test Eb %Gb\");\n    RCASE(0x85, \"test %Gvqp Evqp\");\n    RCASE(0x86, \"xchg %Gb Eb\");\n    RCASE(0x87, \"xchg %Gvqp Evqp\");\n    RCASE(0x88, \"mov Eb %Gb\");\n    RCASE(0x89, \"mov Evqp %Gvqp\");\n    RCASE(0x8A, \"mov %Gb Eb\");\n    RCASE(0x8B, \"mov %Gvqp Evqp\");\n    RCASE(0x8C, \"mov Evqp %Sw\");\n    RCASE(0x8D, \"lea %Gvqp M\");\n    RCASE(0x8E, \"mov %Sw Evqp\");\n    RCASE(0x90, \"nop\");\n    RCASE(0x98, \"cwtl\");\n    RCASE(0x99, \"cltd\");\n    RCASE(0x9A, \"lcall Pvds Kvds\");\n    RCASE(0x9B, \"fwait\");\n    RCASE(0x9C, \"pushfWQ\");\n    RCASE(0x9D, \"popfWQ\");\n    RCASE(0x9E, \"sahf\");\n    RCASE(0x9F, \"lahf\");\n    RCASE(0xA0, \"movABS %al Ob\");\n    RCASE(0xA1, \"movABS %rAX Ovqp\");\n    RCASE(0xA2, \"movABS Ob %al\");\n    RCASE(0xA3, \"movABS Ovqp %rAX\");\n    RCASE(0xA4, \"movsb Yb Xb\");\n    RCASE(0xA5, \"movsWLQ Yvqp Xvqp\");\n    RCASE(0xA6, \"cmpsb Yb Xb\");\n    RCASE(0xA7, \"cmpsWLQ Yvqp Xvqp\");\n    RCASE(0xA8, \"test %al Ib\");\n    RCASE(0xA9, \"test %rAX Ivds\");\n    RCASE(0xAA, \"stosb Yb %al\");\n    RCASE(0xAB, \"stosWLQ Yvqp %rAX\");\n    RCASE(0xAC, \"lodsb %al Xb\");\n    RCASE(0xAD, \"lodsWLQ %rAX Xvqp\");\n    RCASE(0xAE, \"scasb %al Yb\");\n    RCASE(0xAF, \"scasWLQ %rAX Yvqp\");\n    RCASE(0xC0, \"BIT Eb Ib\");\n    RCASE(0xC1, \"BIT Evqp Ib\");\n    RCASE(0xC2, \"ret Iw\");\n    RCASE(0xC3, \"ret\");\n    RCASE(0xC4, \"les %Gv Mp\");\n    RCASE(0xC5, \"lds %Gv Mp\");\n    RCASE(0xC6, \"mov Eb Ib\");\n    RCASE(0xC7, \"mov Evqp Ivds\");\n    RCASE(0xC8, \"enter >Ib Iw\");\n    RCASE(0xC9, \"leave\");\n    RCASE(0xCA, \"lret Iw\");\n    RCASE(0xCB, \"lret\");\n    RCASE(0xCC, \"int3\");\n    RCASE(0xCD, \"int Ib\");\n    RCASE(0xCE, \"into\");\n    RCASE(0xCF, \"iret\");\n    RCASE(0xD0, \"BIT Eb\");\n    RCASE(0xD1, \"BIT Evqp\");\n    RCASE(0xD2, \"BIT Evqp %cl\");\n    RCASE(0xD3, \"BIT Evqp %cl\");\n    RCASE(0xD4, x->op.uimm0 == 0x0a ? \"aam\" : \"aam Ib\");\n    RCASE(0xD5, x->op.uimm0 == 0x0a ? \"aad\" : \"aad Ib\");\n    RCASE(0xD6, \"salc\");\n    RCASE(0xD7, \"xlat BBb\");\n    RCASE(0xE0, \"loopne Jbs\");\n    RCASE(0xE1, \"loope Jbs\");\n    RCASE(0xE2, \"loop Jbs\");\n    RCASE(0xE3, \"jcxz Jbs\");\n    RCASE(0xE4, \"in %al Ib\");\n    RCASE(0xE5, \"in %eAX Ib\");\n    RCASE(0xE6, \"out Ib %al\");\n    RCASE(0xE7, \"out Ib %eAX\");\n    RCASE(0xE8, \"call Jvds\");\n    RCASE(0xE9, \"jmp Jvds\");\n    RCASE(0xEA, \"ljmp Rvds Kvds\");\n    RCASE(0xEB, \"jmp Jbs\");\n    RCASE(0xEC, \"in %al DX\");\n    RCASE(0xED, \"in %eAX DX\");\n    RCASE(0xEE, \"out DX %al\");\n    RCASE(0xEF, \"out DX %eAX\");\n    RCASE(0xF1, \"int1\");\n    RCASE(0xF4, \"hlt\");\n    RCASE(0xF5, \"cmc\");\n    RCASE(0xF8, \"clc\");\n    RCASE(0xF9, \"stc\");\n    RCASE(0xFA, \"cli\");\n    RCASE(0xFB, \"sti\");\n    RCASE(0xFC, \"cld\");\n    RCASE(0xFD, \"std\");\n    case 0x40:\n    case 0x41:\n    case 0x42:\n    case 0x43:\n    case 0x44:\n    case 0x45:\n    case 0x46:\n    case 0x47:\n      return \"inc %Zv\";\n    case 0x48:\n    case 0x49:\n    case 0x4a:\n    case 0x4b:\n    case 0x4c:\n    case 0x4d:\n    case 0x4e:\n    case 0x4f:\n      return \"dec %Zv\";\n    case 0x50:\n    case 0x51:\n    case 0x52:\n    case 0x53:\n    case 0x54:\n    case 0x55:\n    case 0x56:\n    case 0x57:\n      return \"push %Zvq\";\n    case 0x58:\n    case 0x59:\n    case 0x5a:\n    case 0x5b:\n    case 0x5c:\n    case 0x5d:\n    case 0x5e:\n    case 0x5f:\n      return \"pop %Zvq\";\n    case 0x70:\n    case 0x71:\n    case 0x72:\n    case 0x73:\n    case 0x74:\n    case 0x75:\n    case 0x76:\n    case 0x77:\n    case 0x78:\n    case 0x79:\n    case 0x7a:\n    case 0x7b:\n    case 0x7c:\n    case 0x7d:\n    case 0x7e:\n    case 0x7f:\n      return \"jCC Jbs\";\n    case 0x91:\n    case 0x92:\n    case 0x93:\n    case 0x94:\n    case 0x95:\n    case 0x96:\n    case 0x97:\n      return \"xchg %Zvqp %rAX\";\n    case 0xB0:\n    case 0xb1:\n    case 0xb2:\n    case 0xb3:\n    case 0xb4:\n    case 0xb5:\n    case 0xb6:\n    case 0xb7:\n      return \"mov %Zb Ib\";\n    case 0xb8:\n    case 0xb9:\n    case 0xba:\n    case 0xbb:\n    case 0xbc:\n    case 0xbd:\n    case 0xbe:\n    case 0xbf:\n      return \"movABS %Zvqp Ivqp\";\n    case 0x8F:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(0, \"popWQ Evq\");\n        default:\n          break;\n      }\n      break;\n    case 0xD9:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(1, \"fxch EST1\");\n        RCASE(3, \"fstps Msr %st\");\n        RCASE(0, DisSpecRegMem(x, \"fld EST\", \"flds Msr\"));\n        RCASE(2, DisSpecRegMem(x, \"fnop\", \"fsts Msr %st\"));\n        RCASE(4, DisSpecRegMemFpu0(x, 1, \"fldenv Me\"));\n        RCASE(5, DisSpecRegMemFpu0(x, 2, \"fldcw Mw\"));\n        RCASE(6, DisSpecRegMemFpu0(x, 3, \"fnstenv M\"));\n        RCASE(7, DisSpecRegMemFpu0(x, 4, \"fnstcw Mw\"));\n      }\n      break;\n    case 0xDA:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(0, DisSpecRegMem(x, \"fcmovb %st EST\", \"fiaddl Mdi\"));\n        RCASE(1, DisSpecRegMem(x, \"fcmove %st EST\", \"fimull Mdi\"));\n        RCASE(2, DisSpecRegMem(x, \"fcmovbe %st EST\", \"ficoml Mdi\"));\n        RCASE(3, DisSpecRegMem(x, \"fcmovu %st EST\", \"ficompl Mdi\"));\n        RCASE(4, DisSpecRegMem(x, \"fisubr Mdi\", \"fisubl Mdi\"));\n        RCASE(5, DisSpecRegMem(x, \"fucompp\", \"fisubrl Mdi\"));\n        RCASE(6, DisSpecRegMem(x, \"fidivl Mdi\", \"UNKNOWN\"));\n        RCASE(7, DisSpecRegMem(x, \"fidivrl Mdi\", \"UNKNOWN\"));\n      }\n      break;\n    case 0xDB:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(0, DisSpecRegMem(x, \"fcmovnb %st EST\", \"fildl Mdi\"));\n        RCASE(1, DisSpecRegMem(x, \"fcmovne %st EST\", \"fisttpl Mdi\"));\n        RCASE(2, DisSpecRegMem(x, \"fcmovnbe %st EST\", \"fistl Mdi\"));\n        RCASE(3, DisSpecRegMem(x, \"fcmovnu %st EST\", \"fistpl Mdi\"));\n        RCASE(4, DisSpecFpu0(x, 5));\n        RCASE(5, DisSpecRegMem(x, \"fucomi %st EST\", \"fldt Mer\"));\n        RCASE(6, DisSpecRegMem(x, \"fcomi %st EST\", UNKNOWN));\n        RCASE(7, DisSpecRegMem(x, UNKNOWN, \"fstpt Mer\"));\n      }\n      break;\n    case 0xD8:\n      return DisOpFpu1(x, p, !IsModrmRegister(x->op.rde) ? \"s Msr\" : \" EST1\");\n    case 0xDC:\n      if (!IsModrmRegister(x->op.rde)) {\n        return DisOpFpu1(x, p, \"l Mdr\");\n      } else {\n        switch (ModrmReg(x->op.rde)) {\n          RCASE(0, \"fadd EST %st\");\n          RCASE(1, \"fmul EST %st\");\n          RCASE(2, \"fcom %st EST\");\n          RCASE(3, \"fcomp %st EST\");\n          RCASE(4, \"fsub EST %st\");\n          RCASE(5, \"fsubr EST %st\");\n          RCASE(6, \"fdiv EST %st\");\n          RCASE(7, \"fdivr EST %st\");\n        }\n      }\n      break;\n    case 0xDD:\n      if (!IsModrmRegister(x->op.rde)) {\n        switch (ModrmReg(x->op.rde)) {\n          RCASE(0, \"fldl Mdr\");\n          RCASE(1, \"fisttpll Mqi\");\n          RCASE(2, \"fstl Mdr\");\n          RCASE(3, \"fstpl Mdr\");\n          RCASE(4, \"frstor Mdr\");\n          RCASE(6, \"fnsave Mst\");\n          RCASE(7, \"fnstsw Mst\");\n        }\n      } else {\n        switch (ModrmReg(x->op.rde)) {\n          RCASE(0, \"ffree EST\");\n          RCASE(1, \"fxch EST\");\n          RCASE(2, \"fst EST\");\n          RCASE(3, \"fstp EST\");\n          RCASE(4, \"fucom EST1\");\n          RCASE(5, \"fucomp EST1\");\n        }\n      }\n      break;\n    case 0xDE:\n      if (!IsModrmRegister(x->op.rde)) {\n        switch (ModrmReg(x->op.rde)) {\n          RCASE(0, \"fiadds Mwi\");\n          RCASE(1, \"fimuls Mwi\");\n          RCASE(2, \"ficoms Mwi\");\n          RCASE(3, \"ficomps Mwi\");\n          RCASE(4, \"fisubs Mwi\");\n          RCASE(5, \"fisubrs Mwi\");\n          RCASE(6, \"fidivs Mwi\");\n          RCASE(7, \"fidivrs Mwi\");\n        }\n      } else {\n        switch (ModrmReg(x->op.rde)) {\n          RCASE(0, \"faddp EST1\");\n          RCASE(1, \"fmulp EST1\");\n          RCASE(2, \"fcomp EST1\");\n          RCASE(3, \"fcompp\");\n          RCASE(4, \"fsubp EST1\");\n          RCASE(5, \"fsubrp EST1\");\n          RCASE(6, \"fdivp EST1\");\n          RCASE(7, \"fdivrp EST1\");\n        }\n      }\n      break;\n    case 0xDF:\n      if (!IsModrmRegister(x->op.rde)) {\n        switch (ModrmReg(x->op.rde)) {\n          RCASE(0, \"filds Mwi\");\n          RCASE(1, \"fisttps Mwi\");\n          RCASE(2, \"fists Mwi\");\n          RCASE(3, \"fistps Mwi\");\n          RCASE(4, \"fbld\");\n          RCASE(5, \"fildll Mqi\");\n          RCASE(6, \"fbstp\");\n          RCASE(7, \"fistpll Mqi\");\n        }\n      } else {\n        switch (ModrmReg(x->op.rde)) {\n          RCASE(0, \"ffreep EST\");\n          RCASE(1, \"fxch\");\n          RCASE(2, \"fstp EST\");\n          RCASE(3, \"fstp EST\");\n          RCASE(4, \"fnstsw\");\n          RCASE(5, \"fucomip EST\");\n          RCASE(6, \"fcomip EST\");\n        }\n      }\n      break;\n    case 0xF6:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(0, \"test Eb Ib\");\n        RCASE(1, \"test Eb Ib\");\n        RCASE(2, \"not Eb\");\n        RCASE(3, \"neg Eb\");\n        RCASE(4, \"mulb Eb\");\n        RCASE(5, \"imulb Eb\");\n        RCASE(6, \"divb Eb\");\n        RCASE(7, \"idivb Eb\");\n      }\n      break;\n    case 0xF7:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(0, \"test Evqp Ivds\");\n        RCASE(1, \"test Evqp Ivds\");\n        RCASE(2, \"not Evqp\");\n        RCASE(3, \"neg Evqp\");\n        RCASE(4, \"mul Evqp\");\n        RCASE(5, \"imul Evqp\");\n        RCASE(6, \"div Evqp\");\n        RCASE(7, \"idiv Evqp\");\n      }\n      break;\n    case 0xFE:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(0, \"inc Eb\");\n        RCASE(1, \"dec Eb\");\n      }\n      break;\n    case 0xFF:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(0, \"inc Evqp\");\n        RCASE(1, \"dec Evqp\");\n        RCASE(2, \"CALL *Eq\");\n        RCASE(3, \"lcall *Eq\");\n        RCASE(4, \"JMP *Eq\");\n        RCASE(5, \"ljmp *Eq\");\n        RCASE(6, \"pushWQ Evq\");\n      }\n      break;\n  }\n  return UNKNOWN;\n}\n\nconst char *DisSpecMap1(struct XedDecodedInst *x, char *p) {\n  bool isreg;\n  isreg = IsModrmRegister(x->op.rde);\n  switch (Opcode(x->op.rde)) {\n    RCASE(0x02, \"lar %Gvqp Ev\");\n    RCASE(0x03, \"lsl %Gvqp Ev\");\n    RCASE(0x05, \"syscall\");\n    RCASE(0x06, \"clts\");\n    RCASE(0x09, \"wbinvd\");\n    RCASE(0x0B, \"ud2\");\n    RCASE(0x20, \"mov %Hd %Cd\");\n    RCASE(0x22, \"mov %Cd %Hd\");\n    RCASE(0x28, \"movapSD %Vps Wps\");\n    RCASE(0x29, \"movapSD Wps %Vps\");\n    RCASE(0x2B, \"movntpSD Mps %Vps\");\n    RCASE(0x2E, Osz(x->op.rde) ? \"ucomisd %Vsd Wsd\" : \"ucomiss %Vss Wss\");\n    RCASE(0x2F, Osz(x->op.rde) ? \"comisd %Vsd Wsd\" : \"comiss %Vss Wss\");\n    RCASE(0x30, \"wrmsr\");\n    RCASE(0x31, \"rdtsc\");\n    RCASE(0x32, \"rdmsr\");\n    RCASE(0x33, \"rdpmc\");\n    RCASE(0x34, \"sysenter\");\n    RCASE(0x35, \"sysexit\");\n    RCASE(0x50, Osz(x->op.rde) ? \"movmskpd %Gdqp %Udq\" : \"movmskps %Gdqp %Nq\");\n    RCASE(0x52, DisOpVpsWpsVssWss(x, p, \"rsqrt\"));\n    RCASE(0x53, DisOpVpsWpsVssWss(x, p, \"rcp\"));\n    RCASE(0x54, DisOpVpdWpdVpsWps(x, p, \"and\"));\n    RCASE(0x55, DisOpVpdWpdVpsWps(x, p, \"andn\"));\n    RCASE(0x56, DisOpVpdWpdVpsWps(x, p, \"or\"));\n    RCASE(0x57, DisOpVpdWpdVpsWps(x, p, \"xor\"));\n    RCASE(0x58, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, \"add\"));\n    RCASE(0x59, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, \"mul\"));\n    RCASE(0x5C, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, \"sub\"));\n    RCASE(0x5D, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, \"min\"));\n    RCASE(0x5E, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, \"div\"));\n    RCASE(0x5F, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, \"max\"));\n    RCASE(0x60, DisOpPqQqVdqWdq(x, p, \"punpcklbw\"));\n    RCASE(0x61, DisOpPqQqVdqWdq(x, p, \"punpcklwd\"));\n    RCASE(0x62, DisOpPqQqVdqWdq(x, p, \"punpckldq\"));\n    RCASE(0x63, DisOpPqQqVdqWdq(x, p, \"packsswb\"));\n    RCASE(0x64, DisOpPqQqVdqWdq(x, p, \"pcmpgtb\"));\n    RCASE(0x65, DisOpPqQqVdqWdq(x, p, \"pcmpgtw\"));\n    RCASE(0x66, DisOpPqQqVdqWdq(x, p, \"pcmpgtd\"));\n    RCASE(0x67, DisOpPqQqVdqWdq(x, p, \"packuswb\"));\n    RCASE(0x68, DisOpPqQqVdqWdq(x, p, \"punpckhbw\"));\n    RCASE(0x69, DisOpPqQqVdqWdq(x, p, \"punpckhwd\"));\n    RCASE(0x6A, DisOpPqQqVdqWdq(x, p, \"punpckhdq\"));\n    RCASE(0x6B, DisOpPqQqVdqWdq(x, p, \"packssdw\"));\n    RCASE(0x6C, DisOpPqQqVdqWdq(x, p, \"punpcklqdq\"));\n    RCASE(0x6D, DisOpPqQqVdqWdq(x, p, \"punpckhqdq\"));\n    RCASE(0x74, DisOpPqQqVdqWdq(x, p, \"pcmpeqb\"));\n    RCASE(0x75, DisOpPqQqVdqWdq(x, p, \"pcmpeqw\"));\n    RCASE(0x76, DisOpPqQqVdqWdq(x, p, \"pcmpeqd\"));\n    RCASE(0x77, \"emms\");\n    RCASE(0xA0, \"push %fs\");\n    RCASE(0xA1, \"pop %fs\");\n    RCASE(0xA2, \"cpuid\");\n    RCASE(0xA3, \"bt Evqp %Gvqp\");\n    RCASE(0xA4, \"shld Evqp %Gvqp Ib\");\n    RCASE(0xA5, \"shld Evqp %Gvqp %cl\");\n    RCASE(0xA8, \"push %gs\");\n    RCASE(0xA9, \"pop %gs\");\n    RCASE(0xAB, \"bts Evqp %Gvqp\");\n    RCASE(0xAC, \"shrd Evqp %Gvqp Ib\");\n    RCASE(0xAD, \"shrd Evqp %Gvqp %cl\");\n    RCASE(0xAF, \"imul %Gvqp Evqp\");\n    RCASE(0xB0, \"cmpxchg Eb %Gb\");\n    RCASE(0xB1, \"cmpxchg Evqp %Gvqp\");\n    RCASE(0xB2, \"lss %Gv Mp\");\n    RCASE(0xB3, \"btr Evqp %Gvqp\");\n    RCASE(0xB4, \"lfs %Gv Mp\");\n    RCASE(0xB5, \"lgs %Gv Mp\");\n    RCASE(0xB6, \"movzbWLQ %Gvqp Eb\");\n    RCASE(0xB7, \"movzwWLQ %Gvqp Ew\");\n    RCASE(0xB9, \"ud %Gvqp Evqp\");\n    RCASE(0xBB, \"btc Evqp %Gvqp\");\n    RCASE(0xBE, \"movsbWLQ %Gvqp Eb\");\n    RCASE(0xBF, \"movswWLQ %Gvqp Ew\");\n    RCASE(0xC0, \"xadd Eb %Gb\");\n    RCASE(0xC1, \"xadd Evqp %Gvqp\");\n    RCASE(0xC2, DisOpVpsWpsVssWssVpdWpdVsdWsd(x, p, \"cmp\"));\n    RCASE(0xC3, \"movnti Mdqp %Gdqp\");\n    RCASE(0xD1, DisOpPqQqVdqWdq(x, p, \"psrlw\"));\n    RCASE(0xD2, DisOpPqQqVdqWdq(x, p, \"psrld\"));\n    RCASE(0xD3, DisOpPqQqVdqWdq(x, p, \"psrlq\"));\n    RCASE(0xD4, DisOpPqQqVdqWdq(x, p, \"paddq\"));\n    RCASE(0xD5, DisOpPqQqVdqWdq(x, p, \"pmullw\"));\n    RCASE(0xD7, Osz(x->op.rde) ? \"pmovmskb %Gdqp %Udq\" : \"pmovmskb %Gdqp %Nq\");\n    RCASE(0xD8, DisOpPqQqVdqWdq(x, p, \"psubusb\"));\n    RCASE(0xD9, DisOpPqQqVdqWdq(x, p, \"psubusw\"));\n    RCASE(0xDA, DisOpPqQqVdqWdq(x, p, \"pminub\"));\n    RCASE(0xDB, DisOpPqQqVdqWdq(x, p, \"pand\"));\n    RCASE(0xDC, DisOpPqQqVdqWdq(x, p, \"paddusb\"));\n    RCASE(0xDD, DisOpPqQqVdqWdq(x, p, \"paddusw\"));\n    RCASE(0xDE, DisOpPqQqVdqWdq(x, p, \"pmaxub\"));\n    RCASE(0xDF, DisOpPqQqVdqWdq(x, p, \"pandn\"));\n    RCASE(0xE0, DisOpPqQqVdqWdq(x, p, \"pavgb\"));\n    RCASE(0xE1, DisOpPqQqVdqWdq(x, p, \"psrawv\"));\n    RCASE(0xE2, DisOpPqQqVdqWdq(x, p, \"psradv\"));\n    RCASE(0xE3, DisOpPqQqVdqWdq(x, p, \"pavgw\"));\n    RCASE(0xE4, DisOpPqQqVdqWdq(x, p, \"pmulhuw\"));\n    RCASE(0xE5, DisOpPqQqVdqWdq(x, p, \"pmulhw\"));\n    RCASE(0xE7, Osz(x->op.rde) ? \"movntdq Mdq %Vdq\" : \"movntq Mq %Pq\");\n    RCASE(0xE8, DisOpPqQqVdqWdq(x, p, \"psubsb\"));\n    RCASE(0xE9, DisOpPqQqVdqWdq(x, p, \"psubsw\"));\n    RCASE(0xEA, DisOpPqQqVdqWdq(x, p, \"pminsw\"));\n    RCASE(0xEB, DisOpPqQqVdqWdq(x, p, \"por\"));\n    RCASE(0xEC, DisOpPqQqVdqWdq(x, p, \"paddsb\"));\n    RCASE(0xED, DisOpPqQqVdqWdq(x, p, \"paddsw\"));\n    RCASE(0xEE, DisOpPqQqVdqWdq(x, p, \"pmaxsw\"));\n    RCASE(0xEF, DisOpPqQqVdqWdq(x, p, \"pxor\"));\n    RCASE(0xF0, \"lddqu %Vdq Mdq\");\n    RCASE(0xF1, DisOpPqQqVdqWdq(x, p, \"psllwv\"));\n    RCASE(0xF2, DisOpPqQqVdqWdq(x, p, \"pslldv\"));\n    RCASE(0xF3, DisOpPqQqVdqWdq(x, p, \"psllqv\"));\n    RCASE(0xF4, DisOpPqQqVdqWdq(x, p, \"pmuludq\"));\n    RCASE(0xF5, DisOpPqQqVdqWdq(x, p, \"pmaddwd\"));\n    RCASE(0xF6, DisOpPqQqVdqWdq(x, p, \"psadbw\"));\n    RCASE(0xF8, DisOpPqQqVdqWdq(x, p, \"psubb\"));\n    RCASE(0xF9, DisOpPqQqVdqWdq(x, p, \"psubw\"));\n    RCASE(0xFA, DisOpPqQqVdqWdq(x, p, \"psubd\"));\n    RCASE(0xFB, DisOpPqQqVdqWdq(x, p, \"psubq\"));\n    RCASE(0xFC, DisOpPqQqVdqWdq(x, p, \"paddb\"));\n    RCASE(0xFD, DisOpPqQqVdqWdq(x, p, \"paddw\"));\n    RCASE(0xFE, DisOpPqQqVdqWdq(x, p, \"paddd\"));\n    case 0x0D:\n    case 0x18:\n    case 0x19:\n    case 0x1A:\n    case 0x1B:\n    case 0x1C:\n    case 0x1D:\n    case 0x1E:\n      return \"nop Ev\";\n    case 0x40:\n    case 0x41:\n    case 0x42:\n    case 0x43:\n    case 0x44:\n    case 0x45:\n    case 0x46:\n    case 0x47:\n    case 0x48:\n    case 0x49:\n    case 0x4a:\n    case 0x4b:\n    case 0x4c:\n    case 0x4d:\n    case 0x4e:\n    case 0x4f:\n      return \"cmovCC %Gvqp Evqp\";\n    case 0x80:\n    case 0x81:\n    case 0x82:\n    case 0x83:\n    case 0x84:\n    case 0x85:\n    case 0x86:\n    case 0x87:\n    case 0x88:\n    case 0x89:\n    case 0x8a:\n    case 0x8b:\n    case 0x8c:\n    case 0x8d:\n    case 0x8e:\n    case 0x8f:\n      return \"jCC Jvds\";\n    case 0x90:\n    case 0x91:\n    case 0x92:\n    case 0x93:\n    case 0x94:\n    case 0x95:\n    case 0x96:\n    case 0x97:\n    case 0x98:\n    case 0x99:\n    case 0x9a:\n    case 0x9b:\n    case 0x9c:\n    case 0x9d:\n    case 0x9e:\n    case 0x9f:\n      return \"setCC Eb\";\n    case 0xC8:\n    case 0xc9:\n    case 0xca:\n    case 0xcb:\n    case 0xcc:\n    case 0xcd:\n    case 0xce:\n    case 0xcf:\n      return \"bswap %Zvqp\";\n    case 0xBC:\n      if (Rep(x->op.rde) == 3) {\n        return \"tzcnt %Gvqp Evqp\";\n      } else {\n        return \"bsf %Gvqp Evqp\";\n      }\n    case 0xBD:\n      if (Rep(x->op.rde) == 3) {\n        return \"lzcnt %Gvqp Evqp\";\n      } else {\n        return \"bsr %Gvqp Evqp\";\n      }\n    case 0x00:\n      switch (ModrmReg(x->op.rde)) {\n        case 0:\n          return \"sldt Ew\";\n        case 1:\n          return \"str Ew\";\n        case 2:\n          return \"lldt Ew\";\n        case 3:\n          return \"ltr Ew\";\n        case 4:\n          return \"verr Ew\";\n        case 5:\n          return \"verw Ew\";\n        default:\n          return UNKNOWN;\n      }\n    case 0x01:\n      switch (ModrmReg(x->op.rde)) {\n        case 0:\n          if (!isreg) {\n            return \"sgdt Ms\";\n          } else {\n            switch (ModrmRm(x->op.rde)) {\n              case 1:\n                return \"vmcall\";\n              case 2:\n                return \"vmlaunch\";\n              case 3:\n                return \"vmresume\";\n              case 4:\n                return \"vmxoff\";\n              default:\n                return UNKNOWN;\n            }\n          }\n          break;\n        case 1:\n          if (!isreg) {\n            return \"sidt Ms\";\n          } else {\n            switch (ModrmRm(x->op.rde)) {\n              case 0:\n                return \"monitor\";\n              case 1:\n                return \"mwait\";\n              default:\n                return UNKNOWN;\n            }\n          }\n          break;\n        case 2:\n          if (!isreg) {\n            return \"lgdt Ms\";\n          } else if (ModrmRm(x->op.rde) == 0) {\n            return \"xgetbv\";\n          } else if (ModrmRm(x->op.rde) == 1) {\n            return \"xsetbv\";\n          } else {\n            return UNKNOWN;\n          }\n          break;\n        case 3:\n          if (!isreg) {\n            return \"lidt Ms\";\n          } else {\n            return UNKNOWN;\n          }\n        case 4:\n          return \"smsw Ew\";\n        case 6:\n          return \"lmsw Ew\";\n        case 7:\n          if (!isreg) {\n            return \"invlpg M\";\n          } else {\n            switch (ModrmRm(x->op.rde)) {\n              case 0:\n                return \"swapgs\";\n              case 1:\n                return \"rdtscp\";\n              default:\n                return UNKNOWN;\n            }\n          }\n        default:\n          return UNKNOWN;\n      }\n    case 0x1F:\n      if (ModrmMod(x->op.rde) == 1 && ModrmReg(x->op.rde) == 0 &&\n          ModrmRm(x->op.rde) == 5) {\n        return \"bofram Jb\";\n      } else {\n        return \"nop Ev\";\n      }\n      break;\n    case 0x70:\n      switch (Rep(x->op.rde) | Osz(x->op.rde)) {\n        RCASE(0, \"pshufw %Pq Qq Ib\");\n        RCASE(1, \"pshufd %Vdq Wdq Ib\");\n        RCASE(2, \"pshuflw %Vdq Wdq Ib\");\n        RCASE(3, \"pshufhw %Vdq Wdq Ib\");\n      }\n      break;\n    case 0x71:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(2, DisOpNqIbUdqIb(x, p, \"psrlw\"));\n        RCASE(4, DisOpNqIbUdqIb(x, p, \"psraw\"));\n        RCASE(6, DisOpNqIbUdqIb(x, p, \"psllw\"));\n      }\n      break;\n    case 0x72:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(2, DisOpNqIbUdqIb(x, p, \"psrld\"));\n        RCASE(4, DisOpNqIbUdqIb(x, p, \"psrad\"));\n        RCASE(6, DisOpNqIbUdqIb(x, p, \"pslld\"));\n      }\n      break;\n    case 0x73:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(2, DisOpNqIbUdqIb(x, p, \"psrlq\"));\n        RCASE(3, DisOpNqIbUdqIb(x, p, \"psrldq\"));\n        RCASE(6, DisOpNqIbUdqIb(x, p, \"psllq\"));\n        RCASE(7, DisOpNqIbUdqIb(x, p, \"pslldq\"));\n      }\n      break;\n    case 0xAE:\n      switch (ModrmReg(x->op.rde)) {\n        case 0:\n          if (isreg) {\n            return \"rdfsbase %Rdqp\";\n          } else {\n            return \"fxsave M\";\n          }\n        case 1:\n          if (isreg) {\n            return \"rdgsbase %Rdqp\";\n          } else {\n            return \"fxrstor M\";\n          }\n        case 2:\n          if (isreg) {\n            return \"wrfsbase %Rdqp\";\n          } else {\n            return \"ldmxcsr Md\";\n          }\n        case 3:\n          if (isreg) {\n            return \"wrgsbase %Rdqp\";\n          } else {\n            return \"stmxcsr Md\";\n          }\n        case 4:\n          if (isreg) {\n            return UNKNOWN;\n          } else {\n            return \"xsave M %edx %eax\";\n          }\n        case 5:\n          return \"lfence\";\n        case 6:\n          return \"mfence\";\n        case 7:\n          if (isreg && ModrmReg(x->op.rde) == 7) {\n            return \"sfence\";\n          } else {\n            return \"clflush\";\n          }\n      }\n      break;\n    case 0xBA:\n      switch (ModrmReg(x->op.rde)) {\n        RCASE(4, \"btWLQ Evqp Ib\");\n        RCASE(5, \"btsWLQ Evqp Ib\");\n        RCASE(6, \"btrWLQ Evqp Ib\");\n        RCASE(7, \"btcWLQ Evqp Ib\");\n      }\n      break;\n    case 0x10:\n      if (Rep(x->op.rde) == 3) {\n        return \"movss %Vss Wss\";\n      } else if (Rep(x->op.rde) == 2) {\n        return \"movsd %Vsd Wsd\";\n      } else if (Osz(x->op.rde)) {\n        return \"movupd %Vpd Wpd\";\n      } else {\n        return \"movups %Vps Wps\";\n      }\n      break;\n    case 0x11:\n      if (Rep(x->op.rde) == 3) {\n        return \"movss Wss %Vss\";\n      } else if (Rep(x->op.rde) == 2) {\n        return \"movsd Wsd %Vsd\";\n      } else if (Osz(x->op.rde)) {\n        return \"movupd Wpd %Vpd\";\n      } else {\n        return \"movups Wps %Vps\";\n      }\n      break;\n    case 0xC4:\n      if (!Osz(x->op.rde)) {\n        if (isreg) {\n          return \"pinsrw %Pq %Rdqp Ib\";\n        } else {\n          return \"pinsrw %Pq Mw Ib\";\n        }\n      } else {\n        if (isreg) {\n          return \"pinsrw %Vdq %Rdqp Ib\";\n        } else {\n          return \"pinsrw %Vdq Mw Ib\";\n        }\n      }\n      break;\n    case 0xC5:\n      if (!Osz(x->op.rde)) {\n        return \"pextrw %Gdqp %Nq Ib\";\n      } else {\n        return \"pextrw %Gdqp %Udq Ib\";\n      }\n      break;\n    case 0xC6:\n      if (!Osz(x->op.rde)) {\n        return \"shufps %Vps Wps Ib\";\n      } else {\n        return \"shufpd %Vpd Wpd Ib\";\n      }\n      break;\n    case 0xC7:\n      switch (ModrmReg(x->op.rde)) {\n        case 1:\n          if (!isreg) {\n            if (Rexw(x->op.rde)) {\n              return \"cmpxchg16b Mdq\";\n            } else {\n              return \"cmpxchg8b Mq\";\n            }\n          } else {\n            return UNKNOWN;\n          }\n          break;\n        case 6:\n          if (isreg) {\n            return \"rdrand %Rdqp\";\n          } else {\n            return UNKNOWN;\n          }\n          break;\n        case 7:\n          if (isreg) {\n            if (Rep(x->op.rde) == 3) {\n              return \"rdpid %Rdqp\";\n            } else {\n              return \"rdseed %Rdqp\";\n            }\n          } else {\n            return UNKNOWN;\n          }\n          break;\n        default:\n          return UNKNOWN;\n      }\n      break;\n    case 0xD6:\n      if (Osz(x->op.rde)) {\n        return \"movq Wq %Vq\";\n      } else if (Rep(x->op.rde) == 3) {\n        return \"movq2dq %Vdq %Nq\";\n      } else if (Rep(x->op.rde) == 2) {\n        return \"movq2dq %Pq %Uq\";\n      }\n      break;\n    case 0x12:\n      switch (Rep(x->op.rde) | Osz(x->op.rde)) {\n        case 0:\n          if (isreg) {\n            return \"movhlps %Vq %Uq\";\n          } else {\n            return \"movlps %Vq Mq\";\n          }\n          break;\n        case 1:\n          return \"movlpd %Vq Mq\";\n        case 2:\n          return \"movddup %Vq Wq\";\n        case 3:\n          return \"movsldup %Vq Wq\";\n        default:\n          __builtin_unreachable();\n      }\n      break;\n    case 0x13:\n      if (Osz(x->op.rde)) {\n        return \"movlpd Mq %Vq\";\n      } else {\n        return \"movlps Mq %Vq\";\n      }\n      break;\n    case 0x16:\n      switch (Rep(x->op.rde) | Osz(x->op.rde)) {\n        case 0:\n          if (isreg) {\n            return \"movlhps %Vq %Uq\";\n          } else {\n            return \"movhps %Vq Mq\";\n          }\n          break;\n        case 1:\n          return \"movhpd %Vq Mq\";\n        case 3:\n          return \"movshdup %Vq Wq\";\n        default:\n          break;\n      }\n      break;\n    case 0x17:\n      if (Osz(x->op.rde)) {\n        return \"movhpd Mq %Vq\";\n      } else {\n        return \"movhps Mq %Vq\";\n      }\n      break;\n    case 0x2A:\n      if (Rep(x->op.rde) == 3) {\n        return \"cvtsi2ss %Vss Edqp\";\n      } else if (Rep(x->op.rde) == 2) {\n        return \"cvtsi2sd %Vsd Edqp\";\n      } else if (Osz(x->op.rde)) {\n        return \"cvtpi2pd %Vpd Qpi\";\n      } else {\n        return \"cvtpi2ps %Vps Qpi\";\n      }\n      break;\n    case 0x2C:\n      if (Rep(x->op.rde) == 3) {\n        return \"cvttss2si %Gdqp Wss\";\n      } else if (Rep(x->op.rde) == 2) {\n        return \"cvttsd2si %Gdqp Wsd\";\n      } else if (Osz(x->op.rde)) {\n        return \"cvttpd2pi %Ppi Wpd\";\n      } else {\n        return \"cvttps2pi %Ppi Wpsq\";\n      }\n      break;\n    case 0x2D:\n      if (Rep(x->op.rde) == 3) {\n        return \"cvtss2si %Gdqp Wss\";\n      } else if (Rep(x->op.rde) == 2) {\n        return \"cvtsd2si %Gdqp Wsd\";\n      } else if (Osz(x->op.rde)) {\n        return \"cvtpd2pi %Ppi Wpd\";\n      } else {\n        return \"cvtps2pi %Ppi Wpsq\";\n      }\n      break;\n    case 0x5a:\n      if (Rep(x->op.rde) == 3) {\n        return \"cvtss2sd %Vsd Wss\";\n      } else if (Rep(x->op.rde) == 2) {\n        return \"cvtsd2ss %Vss Wsd\";\n      } else if (Osz(x->op.rde)) {\n        return \"cvtpd2ps %Vps Wpd\";\n      } else {\n        return \"cvtps2pd %Vpd Wps\";\n      }\n      break;\n    case 0x5b:\n      if (Rep(x->op.rde) == 3) {\n        return \"cvttps2dq %Vdq Wps\";\n      } else if (Osz(x->op.rde)) {\n        return \"cvtps2dq %Vdq Wps\";\n      } else {\n        return \"cvtdq2ps %Vps Wdq\";\n      }\n      break;\n    case 0x51:\n      if (Rep(x->op.rde) == 3) {\n        return \"sqrtss %Vss Wss\";\n      } else if (Rep(x->op.rde) == 2) {\n        return \"sqrtsd %Vsd Wsd\";\n      } else if (Osz(x->op.rde)) {\n        return \"sqrtpd %Vpd Wpd\";\n      } else {\n        return \"sqrtps %Vps Wps\";\n      }\n      break;\n    case 0x6E:\n      if (Osz(x->op.rde)) {\n        if (Rexw(x->op.rde)) {\n          return \"movq %Vdq Eqp\";\n        } else {\n          return \"movd %Vdq Ed\";\n        }\n      } else {\n        if (Rexw(x->op.rde)) {\n          return \"movq %Pq Eqp\";\n        } else {\n          return \"movd %Pq Ed\";\n        }\n      }\n      break;\n    case 0x6F:\n      if (Rep(x->op.rde) == 3) {\n        return \"movdqu %Vdq Wdq\";\n      } else if (Osz(x->op.rde)) {\n        return \"movdqa %Vdq Wdq\";\n      } else {\n        return \"movq %Pq Qq\";\n      }\n      break;\n    case 0x7E:\n      if (Rep(x->op.rde) == 3) {\n        return \"movq %Vq Wq\";\n      } else if (Osz(x->op.rde)) {\n        if (Rexw(x->op.rde)) {\n          return \"movq Eqp %Vdq\";\n        } else {\n          return \"movd Ed %Vdq\";\n        }\n      } else {\n        if (Rexw(x->op.rde)) {\n          return \"movq Eqp %Pq\";\n        } else {\n          return \"movd Ed %Pq\";\n        }\n      }\n      break;\n    case 0x7F:\n      if (Rep(x->op.rde) == 3) {\n        return \"movdqu Wdq %Vdq\";\n      } else if (Osz(x->op.rde)) {\n        return \"movdqa Wdq %Vdq\";\n      } else {\n        return \"movq Qq %Pq\";\n      }\n      break;\n    case 0xE6:\n      if (Rep(x->op.rde) == 2) {\n        return \"cvtpd2dq %Vdq Wpd\";\n      } else if (Osz(x->op.rde)) {\n        return \"cvttpd2dq %Vdq Wpd\";\n      } else if (Rep(x->op.rde) == 3) {\n        return \"cvtdq2pd %Vpd Wdq\";\n      }\n      break;\n    case 0xFF:\n      switch (Rep(x->op.rde) << 9 | ModrmMod(x->op.rde) << 6 |\n              ModrmReg(x->op.rde) << 3 | ModrmRm(x->op.rde)) {\n        case 00067:\n        case 00167:\n        case 00267:\n          return \"hvtailcall Ovqp\";\n        case 00077:\n        case 00177:\n        case 00277:\n          return \"hvcall Ovqp\";\n        default:\n          return \"ud0 %Gvqp Evqp\";\n      }\n  }\n  return UNKNOWN;\n}\n\nconst char *DisSpecMap2(struct XedDecodedInst *x, char *p) {\n  switch (Opcode(x->op.rde)) {\n    RCASE(0x00, DisOpPqQqVdqWdq(x, p, \"pshufb\"));\n    RCASE(0x01, DisOpPqQqVdqWdq(x, p, \"phaddw\"));\n    RCASE(0x02, DisOpPqQqVdqWdq(x, p, \"phaddd\"));\n    RCASE(0x03, DisOpPqQqVdqWdq(x, p, \"phaddsw\"));\n    RCASE(0x04, DisOpPqQqVdqWdq(x, p, \"pmaddubsw\"));\n    RCASE(0x05, DisOpPqQqVdqWdq(x, p, \"phsubw\"));\n    RCASE(0x06, DisOpPqQqVdqWdq(x, p, \"phsubd\"));\n    RCASE(0x07, DisOpPqQqVdqWdq(x, p, \"phsubsw\"));\n    RCASE(0x08, DisOpPqQqVdqWdq(x, p, \"psignb\"));\n    RCASE(0x09, DisOpPqQqVdqWdq(x, p, \"psignw\"));\n    RCASE(0x0A, DisOpPqQqVdqWdq(x, p, \"psignd\"));\n    RCASE(0x0B, DisOpPqQqVdqWdq(x, p, \"pmulhrsw\"));\n    RCASE(0x10, \"pblendvb %Vdq Wdq\");\n    RCASE(0x14, \"blendvps Vps Wps\");\n    RCASE(0x15, \"blendvpd Vpd Wpd\");\n    RCASE(0x17, \"ptest %Vdq Wdq\");\n    RCASE(0x1C, DisOpPqQqVdqWdq(x, p, \"pabsb\"));\n    RCASE(0x1D, DisOpPqQqVdqWdq(x, p, \"pabsw\"));\n    RCASE(0x1E, DisOpPqQqVdqWdq(x, p, \"pabsd\"));\n    RCASE(0x20, \"pmovsxbw %Vdq Mq\");\n    RCASE(0x21, \"pmovsxbd %Vdq Md\");\n    RCASE(0x22, \"pmovsxbq %Vdq Mw\");\n    RCASE(0x23, \"pmovsxwd %Vdq Mq\");\n    RCASE(0x24, \"pmovsxwq %Vdq Md\");\n    RCASE(0x25, \"pmovsxdq %Vdq Mq\");\n    RCASE(0x28, \"pmuldq %Vdq Wdq\");\n    RCASE(0x29, \"pcmpeqq %Vdq Wdq\");\n    RCASE(0x2A, \"movntdqa %Vdq Mdq\");\n    RCASE(0x2B, \"packusdw %Vdq Wdq\");\n    RCASE(0x30, \"pmovzxbw %Vdq Mq\");\n    RCASE(0x31, \"pmovzxbd %Vdq Md\");\n    RCASE(0x32, \"pmovzxbq %Vdq Mw\");\n    RCASE(0x33, \"pmovzxwd %Vdq Mq\");\n    RCASE(0x34, \"pmovzxwq %Vdq Md\");\n    RCASE(0x35, \"pmovzxdq %Vdq Mq\");\n    RCASE(0x37, \"pcmpgtq %Vdq Wdq\");\n    RCASE(0x38, \"pminsb %Vdq Wdq\");\n    RCASE(0x39, \"pminsd %Vdq Wdq\");\n    RCASE(0x3A, \"pminuw %Vdq Wdq\");\n    RCASE(0x3B, \"pminud %Vdq Wdq\");\n    RCASE(0x3C, \"pmaxsb %Vdq Wdq\");\n    RCASE(0x3D, \"pmaxsd %Vdq Wdq\");\n    RCASE(0x3E, \"pmaxuw %Vdq Wdq\");\n    RCASE(0x3F, \"pmaxud %Vdq Wdq\");\n    RCASE(0x40, \"pmulld %Vdq Wdq\");\n    RCASE(0x41, \"phminposuw %Vdq Wdq\");\n    RCASE(0x80, \"invept %Gq Mdq\");\n    RCASE(0x81, \"invvpid %Gq Mdq\");\n    case 0xF0:\n      if (Rep(x->op.rde) == 2) {\n        return \"crc32 %Gvqp Eb\";\n      } else {\n        return \"movbe %Gvqp M\";\n      }\n      break;\n    case 0xF1:\n      if (Rep(x->op.rde) == 2) {\n        return \"crc32 %Gvqp Evqp\";\n      } else {\n        return \"movbe M %Gvqp\";\n      }\n      break;\n    case 0xF5:\n      if (Rep(x->op.rde) == 2) {\n        return \"pdep %Gdqp %Bdqp Edqp\";\n      } else if (Rep(x->op.rde) == 3) {\n        return \"pext %Gdqp %Bdqp Edqp\";\n      } else if (!Osz(x->op.rde)) {\n        return \"bzhi %Gdqp %Bdqp Edqp\";\n      } else {\n        return \"wut\";\n      }\n    case 0xF6:\n      if (Osz(x->op.rde)) {\n        return \"adcx %Gdqp Edqp\";\n      } else if (Rep(x->op.rde) == 2) {\n        return \"mulx %Gdqp %Bdqp Edqp\";\n      } else if (Rep(x->op.rde) == 3) {\n        return \"adox %Gdqp Edqp\";\n      } else {\n        return \"wut\";\n      }\n    case 0xF7:\n      if (Osz(x->op.rde)) {\n        return \"shlx %Gdqp %Bdqp Edqp\";\n      } else if (Rep(x->op.rde) == 2) {\n        return \"shrx %Gdqp %Bdqp Edqp\";\n      } else if (Rep(x->op.rde) == 3) {\n        return \"sarx %Gdqp %Bdqp Edqp\";\n      } else {\n        return \"wut\";\n      }\n    default:\n      return UNKNOWN;\n  }\n}\n\nconst char *DisSpecMap3(struct XedDecodedInst *x, char *p) {\n  switch (Opcode(x->op.rde)) {\n    RCASE(0x0F, DisOpPqQqIbVdqWdqIb(x, p, \"palignr\"));\n    RCASE(0xF0, \"rorx %Gdqp Edqp Ib\");\n    case 0x44:  // pclmulqdq\n      if (Osz(x->op.rde)) {\n        switch (x->op.uimm0) {\n          case 0x00:\n            return \"pclmullqlqdq Wdq %Vdq\";\n          case 0x01:\n            return \"pclmulhqlqdq Wdq %Vdq\";\n          case 0x10:\n            return \"pclmullqhqdq Wdq %Vdq\";\n          case 0x11:\n            return \"pclmulhqhqdq Wdq %Vdq\";\n          default:\n            return \"wut\";\n        }\n      } else {\n        return \"wut\";\n      }\n    default:\n      return UNKNOWN;\n  }\n}\n\nconst char *DisSpec(struct XedDecodedInst *x, char *p) {\n  switch (Opmap(x->op.rde)) {\n    case XED_ILD_MAP0:\n      return DisSpecMap0(x, p);\n    case XED_ILD_MAP1:\n      return DisSpecMap1(x, p);\n    case XED_ILD_MAP2:\n      return DisSpecMap2(x, p);\n    case XED_ILD_MAP3:\n      return DisSpecMap3(x, p);\n    default:\n      return UNKNOWN;\n  }\n}\n"
  },
  {
    "path": "blink/divmul.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <limits.h>\n\n#include \"blink/alu.h\"\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n\nstruct Dubble {\n  u64 lo;\n  u64 hi;\n};\n\nstatic inline struct Dubble DubbleNeg(struct Dubble x) {\n  struct Dubble d;\n  d.lo = -x.lo;\n  d.hi = ~(x.hi - (x.lo - 1 > x.lo));\n  return d;\n}\n\nstatic inline struct Dubble DubbleShl(struct Dubble x) {\n  struct Dubble d;\n  d.lo = x.lo << 1;\n  d.hi = x.hi << 1 | x.lo >> 63;\n  return d;\n}\n\nstatic inline struct Dubble DubbleShr(struct Dubble x) {\n  struct Dubble d;\n  d.lo = x.lo >> 1 | x.hi << 63;\n  d.hi = x.hi >> 1;\n  return d;\n}\n\nstatic inline unsigned DubbleLte(struct Dubble a, struct Dubble b) {\n  return a.hi == b.hi ? a.lo <= b.lo : a.hi <= b.hi;\n}\n\nstatic struct Dubble DubbleMul(u64 a, u64 b) {\n  u64 x, y, t;\n  struct Dubble d;\n  x = (a & 0xffffffff) * (b & 0xffffffff);\n  t = x >> 32;\n  x &= 0xffffffff;\n  t += (a >> 32) * (b & 0xffffffff);\n  x += (t & 0xffffffff) << 32;\n  y = t >> 32;\n  t = x >> 32;\n  x &= 0xffffffff;\n  t += (b >> 32) * (a & 0xffffffff);\n  x += (t & 0xffffffff) << 32;\n  y += t >> 32;\n  y += (a >> 32) * (b >> 32);\n  d.lo = x;\n  d.hi = y;\n  return d;\n}\n\nstatic struct Dubble DubbleImul(u64 a, u64 b) {\n  unsigned s, t;\n  struct Dubble p;\n  if ((s = a >> 63)) a = -a;\n  if ((t = b >> 63)) b = -b;\n  p = DubbleMul(a, b);\n  return s ^ t ? DubbleNeg(p) : p;\n}\n\nstatic struct Dubble DubbleDiv(struct Dubble a, u64 b, u64 *r) {\n  u64 s;\n  int n, c;\n  struct Dubble d, q, t;\n  d.lo = b, d.hi = 0;\n  q.lo = 0, q.hi = 0;\n  for (n = 0; DubbleLte(d, a) && n < 128; ++n) {\n    d = DubbleShl(d);\n  }\n  for (; n > 0; --n) {\n    t = a;\n    d = DubbleShr(d);\n    q = DubbleShl(q);\n    s = a.lo, a.lo -= d.lo + 0, c = a.lo > s;\n    s = a.hi, a.hi -= d.hi + c, c = a.hi > s;\n    if (c) {\n      a = t;\n    } else {\n      q.lo++;\n    }\n  }\n  *r = a.lo;\n  return q;\n}\n\nstatic struct Dubble DubbleIdiv(struct Dubble a, u64 b, u64 *r) {\n  unsigned s, t;\n  struct Dubble q;\n  if ((s = a.hi >> 63)) a = DubbleNeg(a);\n  if ((t = b >> 63)) b = -b;\n  q = DubbleDiv(a, b, r);\n  if (s ^ t) q = DubbleNeg(q);\n  if (s) *r = -*r;\n  return q;\n}\n\nvoid OpDivAlAhAxEbSigned(P) {\n  i8 y, r;\n  i16 x, q;\n  x = Get16(m->ax);\n  y = Load8(GetModrmRegisterBytePointerRead1(A));\n  if (!y) RaiseDivideError(m);\n  if (x == INT16_MIN) RaiseDivideError(m);\n  q = x / y;\n  r = x % y;\n  if (q != (i8)q) RaiseDivideError(m);\n  m->al = q & 0xff;\n  m->ah = r & 0xff;\n}\n\nvoid OpDivAlAhAxEbUnsigned(P) {\n  u8 y, r;\n  u16 x, q;\n  x = Get16(m->ax);\n  y = Load8(GetModrmRegisterBytePointerRead1(A));\n  if (!y) RaiseDivideError(m);\n  q = x / y;\n  r = x % y;\n  if (q > UINT8_MAX) RaiseDivideError(m);\n  m->al = q & 0xff;\n  m->ah = r & 0xff;\n}\n\nstatic void OpDivRdxRaxEvqpSigned64(P, u8 *p) {\n#ifdef HAVE_INT128\n  i64 y, r;\n  __int128 x, q;\n  x = (unsigned __int128)Get64(m->dx) << 64 | Get64(m->ax);\n  y = Load64(p);\n  if (!y) RaiseDivideError(m);\n  if (x == (unsigned __int128)UINT64_C(0x8000000000000000) << 64) {\n    RaiseDivideError(m);\n  }\n  q = x / y;\n  r = x % y;\n  if (q != (i64)q) RaiseDivideError(m);\n  Put64(m->ax, q);\n  Put64(m->dx, r);\n#else\n  u64 d, r;\n  struct Dubble q;\n  q.lo = Get64(m->ax);\n  q.hi = Get64(m->dx);\n  d = Load64(p);\n  if (!d) RaiseDivideError(m);\n  if (!q.lo && q.hi == 0x8000000000000000) RaiseDivideError(m);\n  q = DubbleIdiv(q, d, &r);\n  if ((i64)q.lo < 0 && (i64)q.hi != -1) RaiseDivideError(m);\n  if ((i64)q.lo >= 0 && q.hi) RaiseDivideError(m);\n  Put64(m->ax, q.lo);\n  Put64(m->dx, r);\n#endif\n}\n\nstatic void OpDivRdxRaxEvqpSigned32(P, u8 *p) {\n  i32 y, r;\n  i64 x, q;\n  x = (u64)Get32(m->dx) << 32 | Get32(m->ax);\n  y = Load32(p);\n  if (!y) RaiseDivideError(m);\n  if (x == INT64_MIN) RaiseDivideError(m);\n  q = x / y;\n  r = x % y;\n  if (q != (i32)q) RaiseDivideError(m);\n  Put64(m->ax, (u32)q);\n  Put64(m->dx, (u32)r);\n}\n\nstatic void OpDivRdxRaxEvqpSigned16(P, u8 *p) {\n  i16 y, r;\n  i32 x, q;\n  x = (u32)Get16(m->dx) << 16 | Get16(m->ax);\n  y = Load16(p);\n  if (!y) RaiseDivideError(m);\n  if (x == INT32_MIN) RaiseDivideError(m);\n  q = x / y;\n  r = x % y;\n  if (q != (i16)q) RaiseDivideError(m);\n  Put16(m->ax, q);\n  Put16(m->dx, r);\n}\n\nstatic void OpDivRdxRaxEvqpUnsigned16(P, u8 *p) {\n  u16 y, r;\n  u32 x, q;\n  x = (u32)Get16(m->dx) << 16 | Get16(m->ax);\n  y = Load16(p);\n  if (!y) RaiseDivideError(m);\n  q = x / y;\n  r = x % y;\n  if (q > UINT16_MAX) RaiseDivideError(m);\n  Put16(m->ax, q);\n  Put16(m->dx, r);\n}\n\nstatic void OpDivRdxRaxEvqpUnsigned32(P, u8 *p) {\n  u32 y, r;\n  u64 x, q;\n  x = (u64)Get32(m->dx) << 32 | Get32(m->ax);\n  y = Load32(p);\n  if (!y) RaiseDivideError(m);\n  q = x / y;\n  r = x % y;\n  if (q > UINT32_MAX) RaiseDivideError(m);\n  Put64(m->ax, (u32)q);\n  Put64(m->dx, (u32)r);\n}\n\nstatic void OpDivRdxRaxEvqpUnsigned64(P, u8 *p) {\n#ifdef HAVE_INT128\n  u64 y, r;\n  unsigned __int128 x, q;\n  x = (unsigned __int128)Get64(m->dx) << 64 | Get64(m->ax);\n  y = Load64(p);\n  if (!y) RaiseDivideError(m);\n  q = x / y;\n  r = x % y;\n  if (q > UINT64_MAX) RaiseDivideError(m);\n  Put64(m->ax, q);\n  Put64(m->dx, r);\n#else\n  u64 d, r;\n  struct Dubble q;\n  q.lo = Get64(m->ax);\n  q.hi = Get64(m->dx);\n  d = Load64(p);\n  if (!d) RaiseDivideError(m);\n  q = DubbleDiv(q, d, &r);\n  if (q.hi) RaiseDivideError(m);\n  Put64(m->ax, q.lo);\n  Put64(m->dx, r);\n#endif\n}\n\nvoid OpDivRdxRaxEvqpSigned(P) {\n  u8 *p = GetModrmRegisterWordPointerReadOszRexw(A);\n  if (Rexw(rde)) {\n    OpDivRdxRaxEvqpSigned64(A, p);\n  } else if (!Osz(rde)) {\n    OpDivRdxRaxEvqpSigned32(A, p);\n  } else {\n    OpDivRdxRaxEvqpSigned16(A, p);\n  }\n}\n\nvoid OpDivRdxRaxEvqpUnsigned(P) {\n  u8 *p = GetModrmRegisterWordPointerReadOszRexw(A);\n  if (Rexw(rde)) {\n    OpDivRdxRaxEvqpUnsigned64(A, p);\n  } else if (!Osz(rde)) {\n    OpDivRdxRaxEvqpUnsigned32(A, p);\n  } else {\n    OpDivRdxRaxEvqpUnsigned16(A, p);\n  }\n}\n\nvoid OpMulAxAlEbSigned(P) {\n  u8 *p;\n  i16 ax;\n  unsigned of;\n  p = GetModrmRegisterBytePointerRead1(A);\n  ax = (i8)Get8(m->ax) * (i8)Load8(p);\n  of = ax != (i8)ax;\n  m->flags = SetFlag(m->flags, FLAGS_CF, of);\n  m->flags = SetFlag(m->flags, FLAGS_OF, of);\n  Put16(m->ax, ax);\n}\n\nvoid OpMulAxAlEbUnsigned(P) {\n  u8 *p;\n  int ax;\n  unsigned of;\n  p = GetModrmRegisterBytePointerRead1(A);\n  ax = Get8(m->ax) * Load8(p);\n  of = ax != (u8)ax;\n  m->flags = SetFlag(m->flags, FLAGS_CF, of);\n  m->flags = SetFlag(m->flags, FLAGS_OF, of);\n  Put16(m->ax, ax);\n}\n\nstatic void OpMulRdxRaxEvqpSigned64(struct Machine *m, i64 x) {\n#ifdef HAVE_INT128\n  __int128 rdxrax = (__int128)(i64)Get64(m->ax) * x;\n  unsigned of = rdxrax != (i64)rdxrax;\n  Put64(m->ax, rdxrax);\n  Put64(m->dx, rdxrax >> 64);\n#else\n  struct Dubble rdxrax = DubbleImul(Get64(m->ax), x);\n  unsigned of = !!(rdxrax.hi + (rdxrax.lo >> 63));\n  Put64(m->ax, rdxrax.lo);\n  Put64(m->dx, rdxrax.hi);\n#endif\n  m->flags = SetFlag(m->flags, FLAGS_CF, of);\n  m->flags = SetFlag(m->flags, FLAGS_OF, of);\n}\n\nvoid OpMulRdxRaxEvqpSigned(P) {\n  u8 *p = GetModrmRegisterWordPointerReadOszRexw(A);\n  if (Rexw(rde)) {\n    OpMulRdxRaxEvqpSigned64(m, Load64(p));\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"B\"      // res0 = GetRegOrMem(RexbRm)\n             \"r0a1=\"  // arg1 = res0\n             \"q\"      // arg0 = sav0\n             \"c\",     // call function\n             OpMulRdxRaxEvqpSigned64);\n    }\n  } else if (!Osz(rde)) {\n    i64 edxeax = (i64)(i32)Get32(m->ax) * (i32)Load32(p);\n    unsigned of = edxeax != (i32)edxeax;\n    Put64(m->ax, (u32)edxeax);\n    Put64(m->dx, edxeax >> 32);\n    m->flags = SetFlag(m->flags, FLAGS_CF, of);\n    m->flags = SetFlag(m->flags, FLAGS_OF, of);\n  } else {\n    i32 dxax = (i32)(i16)Get16(m->ax) * (i16)Load16(p);\n    unsigned of = dxax != (i16)dxax;\n    Put16(m->ax, dxax);\n    Put16(m->dx, dxax >> 16);\n    m->flags = SetFlag(m->flags, FLAGS_CF, of);\n    m->flags = SetFlag(m->flags, FLAGS_OF, of);\n  }\n}\n\nstatic void OpMulRdxRaxEvqpUnsigned64(struct Machine *m, u64 x) {\n#ifdef HAVE_INT128\n  unsigned __int128 rdxrax = (unsigned __int128)Get64(m->ax) * x;\n  unsigned of = (u64)rdxrax != rdxrax;\n  Put64(m->ax, rdxrax);\n  Put64(m->dx, rdxrax >> 64);\n#else\n  struct Dubble rdxrax = DubbleMul(Get64(m->ax), x);\n  unsigned of = !!rdxrax.hi;\n  Put64(m->ax, rdxrax.lo);\n  Put64(m->dx, rdxrax.hi);\n#endif\n  m->flags = SetFlag(m->flags, FLAGS_CF, of);\n  m->flags = SetFlag(m->flags, FLAGS_OF, of);\n}\n\nstatic void OpMulRdxRaxEvqpUnsigned32(struct Machine *m, u64 x) {\n  u64 edxeax;\n  unsigned of;\n  edxeax = (u64)Get32(m->ax) * x;\n  of = (u32)edxeax != edxeax;\n  Put64(m->ax, (u32)edxeax);\n  Put64(m->dx, edxeax >> 32);\n  m->flags = SetFlag(m->flags, FLAGS_CF, of);\n  m->flags = SetFlag(m->flags, FLAGS_OF, of);\n}\n\nvoid OpMulRdxRaxEvqpUnsigned(P) {\n  u8 *p;\n  u32 dxax;\n  unsigned of;\n  p = GetModrmRegisterWordPointerReadOszRexw(A);\n  if (Rexw(rde)) {\n    OpMulRdxRaxEvqpUnsigned64(m, Load64(p));\n    if (IsMakingPath(m)) {\n#ifdef HAVE_INT128\n      Jitter(A,\n             \"z3B\"    // res0 = GetRegOrMem[force64bit](RexbRm)\n             \"s0a1=\"  // arg1 = machine\n             \"t\"      // arg0 = res0\n             \"m\",     // call micro-op\n             !GetNeededFlags(m, m->ip, CF | OF) ? (u64)(uintptr_t)JustMulAxDx\n                                                : (u64)(uintptr_t)MulAxDx);\n#else\n      Jitter(A,\n             \"B\"      // res0 = GetRegOrMem(RexbRm)\n             \"r0a1=\"  // arg1 = res0\n             \"q\"      // arg0 = sav0\n             \"c\",     // call function\n             OpMulRdxRaxEvqpUnsigned64);\n#endif\n    }\n  } else if (!Osz(rde)) {\n    OpMulRdxRaxEvqpUnsigned32(m, Load32(p));\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"B\"      // res0 = GetRegOrMem(RexbRm)\n             \"r0a1=\"  // arg1 = res0\n             \"q\"      // arg0 = sav0\n             \"c\",     // call function\n             OpMulRdxRaxEvqpUnsigned32);\n    }\n  } else {\n    dxax = (u32)(u16)Get16(m->ax) * (u16)Load16(p);\n    of = (u16)dxax != dxax;\n    Put16(m->ax, dxax);\n    Put16(m->dx, dxax >> 16);\n    m->flags = SetFlag(m->flags, FLAGS_CF, of);\n    m->flags = SetFlag(m->flags, FLAGS_OF, of);\n  }\n}\n\nstatic void AluImul(P, u8 *a, u8 *b) {\n  unsigned of;\n  if (Rexw(rde)) {\n#ifdef HAVE_INT128\n    __int128 z;\n    z = (__int128)(i64)Get64(a) * (i64)Load64(b);\n    of = z != (i64)z;\n    Put64(RegRexrReg(m, rde), z);\n#else\n    struct Dubble p;\n    p = DubbleImul(Get64(a), Load64(b));\n    of = !!(p.hi + (p.lo >> 63));\n    Put64(RegRexrReg(m, rde), p.lo);\n#endif\n  } else if (!Osz(rde)) {\n    i64 z;\n    z = (i64)(i32)Get32(a) * (i32)Load32(b);\n    of = z != (i32)z;\n    Put64(RegRexrReg(m, rde), (u32)z);\n  } else {\n    i32 z;\n    z = (i32)(i16)Get16(a) * (i16)Load16(b);\n    of = z != (i16)z;\n    Put16(RegRexrReg(m, rde), z);\n  }\n  m->flags = SetFlag(m->flags, FLAGS_CF, of);\n  m->flags = SetFlag(m->flags, FLAGS_OF, of);\n}\n\nvoid OpImulGvqpEvqp(P) {\n  AluImul(A, RegRexrReg(m, rde), GetModrmRegisterWordPointerReadOszRexw(A));\n#ifdef HAVE_INT128\n  if (IsMakingPath(m) && Rexw(rde)) {\n    Jitter(A,\n           \"z3A\"     // res0 = GetReg[force64bit](RexrReg)\n           \"r0s1=\"   // sav1 = res0\n           \"z3B\"     // res0 = GetRegOrMem[force64bit](RexbRm)\n           \"s0a2=\"   // arg2 = machine\n           \"s1a1=\"   // arg1 = sav1\n           \"t\"       // arg0 = res0\n           \"m\"       // res0 = Imul64(arg0, arg1, machine)\n           \"r0z3C\",  // PutReg[force64bit](RexrReg, res0)\n           !GetNeededFlags(m, m->ip, CF | OF) ? (u64)(uintptr_t)JustMul64\n                                              : (u64)(uintptr_t)Imul64);\n  }\n#endif\n  if (IsMakingPath(m) && !Rexw(rde) && !Osz(rde)) {\n    Jitter(A,\n           \"z2A\"     // res0 = GetReg[force32bit](RexrReg)\n           \"r0s1=\"   // sav1 = res0\n           \"z2B\"     // res0 = GetRegOrMem[force32bit](RexbRm)\n           \"s0a2=\"   // arg2 = machine\n           \"s1a1=\"   // arg1 = sav1\n           \"t\"       // arg0 = res0\n           \"m\"       // res0 = Imul32(arg0, arg1, machine)\n           \"r0z2C\",  // PutReg[force32bit](RexrReg, res0)\n           !GetNeededFlags(m, m->ip, CF | OF) ? (u64)(uintptr_t)JustMul32\n                                              : (u64)(uintptr_t)Imul32);\n  }\n}\n\nvoid OpImulGvqpEvqpImm(P) {\n  u8 b[8];\n  Put64(b, uimm0);\n  AluImul(A, GetModrmRegisterWordPointerReadOszRexw(A), b);\n#ifdef HAVE_INT128\n  if (IsMakingPath(m) && Rexw(rde)) {\n    Jitter(A,\n           \"z3B\"     // res0 = GetRegOrMem[force64bit](RexbRm)\n           \"s0a2=\"   // arg2 = machine\n           \"a1i\"     // arg1 = uimm0\n           \"t\"       // arg0 = res0\n           \"m\"       // res0 = Imul64(arg0, arg1, machine)\n           \"r0z3C\",  // PutReg[force64bit](RexrReg, res0)\n           uimm0,\n           !GetNeededFlags(m, m->ip, CF | OF) ? (u64)(uintptr_t)JustMul64\n                                              : (u64)(uintptr_t)Imul64);\n  }\n#endif\n  if (IsMakingPath(m) && !Rexw(rde) && !Osz(rde)) {\n    Jitter(A,\n           \"z2B\"     // res0 = GetRegOrMem[force32bit](RexbRm)\n           \"s0a2=\"   // arg2 = machine\n           \"a1i\"     // arg1 = uimm0\n           \"t\"       // arg0 = res0\n           \"m\"       // res0 = Imul32(arg0, arg1, machine)\n           \"r0z2C\",  // PutReg[force32bit](RexrReg, res0)\n           uimm0,\n           !GetNeededFlags(m, m->ip, CF | OF) ? (u64)(uintptr_t)JustMul32\n                                              : (u64)(uintptr_t)Imul32);\n  }\n}\n\n#ifndef DISABLE_BMI2\n\nstatic void OpAdx(P, i64 op64(u64, u64, struct Machine *),\n                  i64 op32(u64, u64, struct Machine *)) {\n  if (Rexw(rde)) {\n    Put64(RegRexrReg(m, rde),\n          op64(Get64(RegRexrReg(m, rde)),\n               Load64(GetModrmRegisterWordPointerRead8(A)), m));\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"z3B\"     // res0 = GetRegOrMem[force32bit](RexbRm)\n             \"r0s1=\"   // sav1 = res0\n             \"z3A\"     // res0 = GetReg[force32bit](RexrReg)\n             \"s0a2=\"   // arg2 = machine\n             \"s1a1=\"   // arg1 = sav1\n             \"t\"       // arg0 = res0\n             \"m\"       // call micro-op\n             \"r0z3C\",  // PutReg(RexrReg, <pop>)\n             op64);\n    }\n  } else {\n    Put64(RegRexrReg(m, rde),\n          (u32)op32(Get32(RegRexrReg(m, rde)),\n                    Load32(GetModrmRegisterWordPointerRead4(A)), m));\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"z2B\"     // res0 = GetRegOrMem[force32bit](RexbRm)\n             \"r0s1=\"   // sav1 = res0\n             \"z2A\"     // res0 = GetReg[force32bit](RexrReg)\n             \"s0a2=\"   // arg2 = machine\n             \"s1a1=\"   // arg1 = sav1\n             \"t\"       // arg0 = res0\n             \"m\"       // call micro-op\n             \"r0z2C\",  // PutReg(RexrReg, <pop>)\n             op32);\n    }\n  }\n}\n\nstatic void OpMulx(P) {\n  if (Rexw(rde)) {\n    u64 x, y;\n    x = Load64(GetModrmRegisterWordPointerRead8(A));\n    y = Get64(m->dx);\n#ifdef HAVE_INT128\n    unsigned __int128 z = (unsigned __int128)y * x;\n    Put64(RegVreg(m, rde), z);\n    Put64(RegRexrReg(m, rde), z >> 64);\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"z3B\"    // res0 = GetRegOrMem[force64bit](RexbRm)\n             \"a3i\"    // arg3 = rexrreg\n             \"a2i\"    // arg2 = vreg\n             \"s0a1=\"  // arg1 = sav0 (machine)\n             \"t\"      // arg0 = res0\n             \"m\",     // call micro-op\n             RexrReg(rde), Vreg(rde), Mulx64);\n    }\n#else\n    struct Dubble z = DubbleMul(y, x);\n    Put64(RegVreg(m, rde), z.lo);\n    Put64(RegRexrReg(m, rde), z.hi);\n#endif\n  } else {\n    u64 x;\n    x = Load32(GetModrmRegisterWordPointerRead4(A));\n    x *= Get32(m->dx);\n    Put64(RegVreg(m, rde), (u32)x);\n    Put64(RegRexrReg(m, rde), x >> 32);\n  }\n}\n\nvoid Op2f6(P) {\n  if (Osz(rde)) {\n    OpAdx(A, Adcx64, Adcx32);\n  } else if (Rep(rde) == 3) {\n    OpAdx(A, Adox64, Adox32);\n  } else if (Rep(rde) == 2) {\n    OpMulx(A);\n  } else {\n    OpUdImpl(m);\n  }\n}\n\n#endif /* DISABLE_BMI2 */\n"
  },
  {
    "path": "blink/dll.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/dll.h\"\n\n/**\n * Makes `succ` and its successors come after `elem`.\n *\n * It's required that `elem` and `succ` aren't part of the same list.\n */\nvoid dll_splice_after(struct Dll *elem, struct Dll *succ) {\n  struct Dll *tmp1, *tmp2;\n  tmp1 = elem->next;\n  tmp2 = succ->prev;\n  elem->next = succ;\n  succ->prev = elem;\n  tmp2->next = tmp1;\n  tmp1->prev = tmp2;\n}\n\n/**\n * Removes item from doubly-linked list.\n *\n * @param list is a doubly-linked list, where `!*list` means empty\n */\nvoid dll_remove(struct Dll **list, struct Dll *elem) {\n  if (*list == elem) {\n    if ((*list)->prev == *list) {\n      *list = 0;\n    } else {\n      *list = (*list)->prev;\n    }\n  }\n  elem->next->prev = elem->prev;\n  elem->prev->next = elem->next;\n  elem->next = elem;\n  elem->prev = elem;\n}\n\n/**\n * Inserts items into list, at the beginning.\n *\n * The resulting list will start with `elem`, followed by other items in\n * `elem`, followed by the items previously in `*list`.\n *\n * @param list is a doubly-linked list, where `!*list` means empty\n * @param elem must not be a member of `list`, or null for no-op\n */\nvoid dll_make_first(struct Dll **list, struct Dll *elem) {\n  if (elem) {\n    if (!*list) {\n      *list = elem->prev;\n    } else {\n      dll_splice_after(*list, elem);\n    }\n  }\n}\n\n/**\n * Inserts items into list, at the end.\n *\n * The resulting `*list` will end with `elem`, preceded by the other\n * items in `elem`, preceded by the items previously in `*list`.\n *\n * @param list is a doubly-linked list, where `!*list` means empty\n * @param elem must not be a member of `list`, or null for no-op\n */\nvoid dll_make_last(struct Dll **list, struct Dll *elem) {\n  if (elem) {\n    dll_make_first(list, elem->next);\n    *list = elem;\n  }\n}\n"
  },
  {
    "path": "blink/dll.h",
    "content": "#ifndef BLINK_DLL_H_\n#define BLINK_DLL_H_\n#include <stddef.h>\n\n#define DLL_CONTAINER(t, f, p) ((t *)(((char *)(p)) - offsetof(t, f)))\n\nstruct Dll {\n  struct Dll *next;\n  struct Dll *prev;\n};\n\nstatic inline void dll_init(struct Dll *e) {\n  e->next = e;\n  e->prev = e;\n}\n\nstatic inline int dll_is_empty(struct Dll *list) {\n  return !list;\n}\n\nstatic inline struct Dll *dll_last(struct Dll *list) {\n  return list;\n}\n\nstatic inline struct Dll *dll_first(struct Dll *list) {\n  struct Dll *first = 0;\n  if (list) first = list->next;\n  return first;\n}\n\nstatic inline struct Dll *dll_next(struct Dll *list, struct Dll *e) {\n  struct Dll *next = 0;\n  if (e != list) next = e->next;\n  return next;\n}\n\nstatic inline struct Dll *dll_prev(struct Dll *list, struct Dll *e) {\n  struct Dll *prev = 0;\n  if (e != list->next) prev = e->prev;\n  return prev;\n}\n\nvoid dll_make_first(struct Dll **, struct Dll *);\nvoid dll_make_last(struct Dll **, struct Dll *);\nvoid dll_remove(struct Dll **, struct Dll *);\nvoid dll_splice_after(struct Dll *, struct Dll *);\n\n#endif /* BLINK_DLL_H_ */\n"
  },
  {
    "path": "blink/doublenul.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n\n#include \"blink/util.h\"\n\nconst char *doublenul(const char *s, unsigned i) {\n  size_t n;\n  while (i--) {\n    if ((n = strlen(s))) {\n      s += n + 1;\n    } else {\n      return 0;\n    }\n  }\n  return s;\n}\n"
  },
  {
    "path": "blink/elf.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/elf.h\"\n\n#include <inttypes.h>\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/checked.h\"\n#include \"blink/endian.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/util.h\"\n\ni64 GetElfMemorySize(const Elf64_Ehdr_ *ehdr, size_t size, i64 *base) {\n  size_t off;\n  unsigned i;\n  i64 x, y, lo, hi, res;\n  const Elf64_Phdr_ *phdr;\n  lo = INT64_MAX;\n  hi = INT64_MIN;\n  if (Read64(ehdr->phoff) < size) {\n    for (i = 0; i < Read16(ehdr->phnum); ++i) {\n      off = Read64(ehdr->phoff) + Read16(ehdr->phentsize) * i;\n      if (off + Read16(ehdr->phentsize) > size) return -1;\n      phdr = (const Elf64_Phdr_ *)((const u8 *)ehdr + off);\n      if (Read32(phdr->type) == PT_LOAD_) {\n        x = Read64(phdr->vaddr);\n        if (ckd_add(&y, x, (i64)Read64(phdr->memsz))) return -1;\n        lo = MIN(x, lo);\n        hi = MAX(y, hi);\n      }\n    }\n  }\n  lo &= -FLAG_pagesize;\n  if (ckd_sub(&res, hi, lo)) return -1;\n  *base = lo;\n  return res;\n}\n\nchar *GetElfString(const Elf64_Ehdr_ *elf,  // validated\n                   size_t mapsize,          // validated\n                   const char *strtab,      // validated\n                   size_t rva) {            // foreign\n  if (!strtab) return 0;\n  if (rva >= mapsize) return 0;\n  const char *addr = strtab + rva;\n  if (!memchr(addr, 0, mapsize - rva)) return 0;\n  return (char *)addr;\n}\n\nElf64_Phdr_ *GetElfProgramHeaderAddress(const Elf64_Ehdr_ *elf,  //\n                                        size_t mapsize,          //\n                                        u16 i) {                 //\n  uint64_t off;\n  if (i >= Read16(elf->phnum)) return 0;\n  if (Read64(elf->phoff) <= 0) return 0;\n  if (Read64(elf->phoff) >= mapsize) return 0;\n  if (Read16(elf->phentsize) < sizeof(Elf64_Phdr_)) return 0;\n  off = Read64(elf->phoff) + (unsigned)i * Read16(elf->phentsize);\n  if (off > mapsize) return 0;\n  return (Elf64_Phdr_ *)((char *)elf + off);\n}\n\nElf64_Shdr_ *GetElfSectionHeaderAddress(const Elf64_Ehdr_ *elf,  //\n                                        size_t mapsize,          //\n                                        u16 i) {                 //\n  uint64_t off;\n  if (i >= Read16(elf->shnum)) return 0;\n  if (Read64(elf->shoff) <= 0) return 0;\n  if (Read64(elf->shoff) >= mapsize) return 0;\n  if (Read16(elf->shentsize) < sizeof(Elf64_Shdr_)) return 0;\n  off = Read64(elf->shoff) + (unsigned)i * Read16(elf->shentsize);\n  if (off > mapsize) return 0;\n  return (Elf64_Shdr_ *)((char *)elf + off);\n}\n\n// note: should not be used on bss section\nvoid *GetElfSectionAddress(const Elf64_Ehdr_ *elf,     // validated\n                           size_t mapsize,             // validated\n                           const Elf64_Shdr_ *shdr) {  // foreign\n  uint64_t last;\n  if (!shdr) return 0;\n  if (!Read64(shdr->size)) return 0;\n  if (ckd_add(&last, Read64(shdr->offset), Read64(shdr->size))) return 0;\n  if (last > mapsize) return 0;\n  return (char *)elf + Read64(shdr->offset);\n}\n\nchar *GetElfSectionNameStringTable(const Elf64_Ehdr_ *elf,  //\n                                   size_t mapsize) {        //\n  return (char *)GetElfSectionAddress(\n      elf, mapsize,\n      GetElfSectionHeaderAddress(elf, mapsize, Read16(elf->shstrndx)));\n}\n\nconst char *GetElfSectionName(const Elf64_Ehdr_ *elf,  //\n                              size_t mapsize,          //\n                              Elf64_Shdr_ *shdr) {     //\n  if (!shdr) return 0;\n  return GetElfString(elf, mapsize, GetElfSectionNameStringTable(elf, mapsize),\n                      Read32(shdr->name));\n}\n\nstatic char *GetElfStringTableImpl(const Elf64_Ehdr_ *elf,  //\n                                   size_t mapsize,          //\n                                   const char *kind) {      //\n  int i;\n  const char *name;\n  Elf64_Shdr_ *shdr;\n  for (i = 0; i < Read16(elf->shnum); ++i) {\n    if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i)) &&\n        Read32(shdr->type) == SHT_STRTAB_ &&\n        (name = GetElfSectionName(elf, mapsize, shdr)) && !strcmp(name, kind)) {\n      return (char *)GetElfSectionAddress(elf, mapsize, shdr);\n    }\n  }\n  return 0;\n}\n\nchar *GetElfStringTable(const Elf64_Ehdr_ *elf, size_t mapsize) {\n  char *res;\n  if (!(res = GetElfStringTableImpl(elf, mapsize, \".strtab\"))) {\n    res = GetElfStringTableImpl(elf, mapsize, \".dynstr\");\n  }\n  return res;\n}\n\nstatic Elf64_Sym_ *GetElfSymbolTableImpl(const Elf64_Ehdr_ *elf,  //\n                                         size_t mapsize,          //\n                                         int *out_count,          //\n                                         u32 kind) {              //\n  int i;\n  Elf64_Shdr_ *shdr;\n  for (i = Read16(elf->shnum); i > 0; --i) {\n    if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i - 1)) &&\n        Read64(shdr->entsize) == sizeof(Elf64_Sym_) &&\n        Read32(shdr->type) == kind) {\n      if (out_count) {\n        *out_count = Read64(shdr->size) / sizeof(Elf64_Sym_);\n      }\n      return (Elf64_Sym_ *)GetElfSectionAddress(elf, mapsize, shdr);\n    }\n  }\n  return 0;\n}\n\nElf64_Sym_ *GetElfSymbolTable(const Elf64_Ehdr_ *elf,  //\n                              size_t mapsize,          //\n                              int *out_count) {        //\n  Elf64_Sym_ *res;\n  if (!(res = GetElfSymbolTableImpl(elf, mapsize, out_count, SHT_SYMTAB_))) {\n    res = GetElfSymbolTableImpl(elf, mapsize, out_count, SHT_DYNSYM_);\n  }\n  return res;\n}\n"
  },
  {
    "path": "blink/elf.h",
    "content": "#ifndef BLINK_ELF_H_\n#define BLINK_ELF_H_\n#include <stddef.h>\n\n#include \"blink/types.h\"\n\n/**\n * @fileoverview Executable and Linkable Format Definitions.\n */\n\n#define EI_MAG0_   0\n#define EI_MAG1_   1\n#define EI_MAG2_   2\n#define EI_MAG3_   3\n#define EI_NIDENT_ 16\n\n#define ELFMAG_  \"\\177ELF\"\n#define ELFMAG0_ 0x7f\n#define ELFMAG1_ 'E'\n#define ELFMAG2_ 'L'\n#define ELFMAG3_ 'F'\n#define SELFMAG_ 4\n\n#define EI_CLASS_     4\n#define ELFCLASSNONE_ 0\n#define ELFCLASS32_   1\n#define ELFCLASS64_   2\n#define ELFCLASSNUM_  3\n\n#define EI_DATA_     5\n#define ELFDATANONE_ 0\n#define ELFDATA2LSB_ 1\n#define ELFDATA2MSB_ 2\n#define ELFDATANUM_  3\n\n#define EI_VERSION_ 6\n\n#define EI_OSABI_            7\n#define ELFOSABI_NONE_       0\n#define ELFOSABI_SYSV_       0\n#define ELFOSABI_HPUX_       1\n#define ELFOSABI_NETBSD_     2\n#define ELFOSABI_LINUX_      3\n#define ELFOSABI_GNU_        3\n#define ELFOSABI_SOLARIS_    6\n#define ELFOSABI_AIX_        7\n#define ELFOSABI_IRIX_       8\n#define ELFOSABI_FREEBSD_    9\n#define ELFOSABI_TRU64_      10\n#define ELFOSABI_MODESTO_    11\n#define ELFOSABI_OPENBSD_    12\n#define ELFOSABI_ARM_        97\n#define ELFOSABI_STANDALONE_ 255\n\n#define EI_ABIVERSION_ 8\n\n#define EI_PAD_ 9\n\n#define ET_NONE_   0\n#define ET_REL_    1\n#define ET_EXEC_   2\n#define ET_DYN_    3\n#define ET_CORE_   4\n#define ET_NUM_    5\n#define ET_LOOS_   0xfe00\n#define ET_HIOS_   0xfeff\n#define ET_LOPROC_ 0xff00\n#define ET_HIPROC_ 0xffff\n\n#define EM_NONE_      0\n#define EM_M32_       1\n#define EM_386_       3\n#define EM_S390_      22\n#define EM_ARM_       40\n#define EM_NEXGEN32E_ 62\n#define EM_X86_64_    EM_NEXGEN32E\n#define EM_IA32E_     EM_NEXGEN32E\n#define EM_AMD64_     EM_NEXGEN32E\n#define EM_PDP11_     65\n#define EM_CRAYNV2_   172\n#define EM_L10M_      180\n#define EM_K10M_      181\n#define EM_AARCH64_   183\n#define EM_CUDA_      190\n#define EM_Z80_       220\n#define EM_RISCV_     243\n#define EM_BPF_       247\n\n#define GRP_COMDAT_ 0x1\n#define STN_UNDEF_  0\n\n#define EV_NONE_    0\n#define EV_CURRENT_ 1\n#define EV_NUM_     2\n\n#define SYMINFO_NONE_          0\n#define SYMINFO_CURRENT_       1\n#define SYMINFO_NUM_           2\n#define SYMINFO_BT_SELF_       0xffff\n#define SYMINFO_BT_PARENT_     0xfffe\n#define SYMINFO_BT_LOWRESERVE_ 0xff00\n#define SYMINFO_FLG_DIRECT_    0x0001\n#define SYMINFO_FLG_PASSTHRU_  0x0002\n#define SYMINFO_FLG_COPY_      0x0004\n#define SYMINFO_FLG_LAZYLOAD_  0x0008\n\n#define PT_NULL_              0\n#define PT_LOAD_              1\n#define PT_DYNAMIC_           2\n#define PT_INTERP_            3\n#define PT_NOTE_              4\n#define PT_SHLIB_             5\n#define PT_PHDR_              6\n#define PT_TLS_               7\n#define PT_NUM_               8\n#define PT_LOOS_              0x60000000\n#define PT_GNU_EH_FRAME_      0x6474e550\n#define PT_GNU_STACK_         0x6474e551\n#define PT_GNU_RELRO_         0x6474e552\n#define PT_OPENBSD_RANDOMIZE_ 0x65a3dbe6\n#define PT_LOSUNW_            0x6ffffffa\n#define PT_SUNWBSS_           0x6ffffffa\n#define PT_SUNWSTACK_         0x6ffffffb\n#define PT_HISUNW_            0x6fffffff\n#define PT_HIOS_              0x6fffffff\n#define PT_LOPROC_            0x70000000\n#define PT_HIPROC_            0x7fffffff\n\n#define PN_XNUM_ 0xffff\n\n#define PF_X_        1\n#define PF_W_        2\n#define PF_R_        4\n#define PF_MASKOS_   0x0ff00000\n#define PF_MASKPROC_ 0xf0000000\n\n#define R_X86_64_NONE_            0\n#define R_X86_64_64_              1\n#define R_X86_64_PC32_            2\n#define R_X86_64_GOT32_           3\n#define R_X86_64_PLT32_           4\n#define R_X86_64_COPY_            5\n#define R_X86_64_GLOB_DAT_        6\n#define R_X86_64_JUMP_SLOT_       7\n#define R_X86_64_RELATIVE_        8\n#define R_X86_64_GOTPCREL_        9\n#define R_X86_64_32_              10\n#define R_X86_64_32S_             11\n#define R_X86_64_16_              12\n#define R_X86_64_PC16_            13\n#define R_X86_64_8_               14\n#define R_X86_64_PC8_             15\n#define R_X86_64_DTPMOD64_        16\n#define R_X86_64_DTPOFF64_        17\n#define R_X86_64_TPOFF64_         18\n#define R_X86_64_TLSGD_           19\n#define R_X86_64_TLSLD_           20\n#define R_X86_64_DTPOFF32_        21\n#define R_X86_64_GOTTPOFF_        22\n#define R_X86_64_TPOFF32_         23\n#define R_X86_64_PC64_            24\n#define R_X86_64_GOTOFF64_        25\n#define R_X86_64_GOTPC32_         26\n#define R_X86_64_GOT64_           27\n#define R_X86_64_GOTPCREL64_      28\n#define R_X86_64_GOTPC64_         29\n#define R_X86_64_GOTPLT64_        30\n#define R_X86_64_PLTOFF64_        31\n#define R_X86_64_SIZE32_          32\n#define R_X86_64_SIZE64_          33\n#define R_X86_64_GOTPC32_TLSDESC_ 34\n#define R_X86_64_TLSDESC_CALL_    35\n#define R_X86_64_TLSDESC_         36\n#define R_X86_64_IRELATIVE_       37\n#define R_X86_64_RELATIVE64_      38\n#define R_X86_64_GOTPCRELX_       41  // 6 bytes\n#define R_X86_64_REX_GOTPCRELX_   42  // 7 bytes\n#define R_X86_64_NUM_             43\n\n#define STB_LOCAL_      0\n#define STB_GLOBAL_     1\n#define STB_WEAK_       2\n#define STB_NUM_        3\n#define STB_LOOS_       10\n#define STB_GNU_UNIQUE_ 10\n#define STB_HIOS_       12\n#define STB_LOPROC_     13\n#define STB_HIPROC_     15\n\n#define STT_NOTYPE_    0\n#define STT_OBJECT_    1\n#define STT_FUNC_      2\n#define STT_SECTION_   3\n#define STT_FILE_      4\n#define STT_COMMON_    5\n#define STT_TLS_       6\n#define STT_NUM_       7\n#define STT_LOOS_      10\n#define STT_GNU_IFUNC_ 10\n#define STT_HIOS_      12\n#define STT_LOPROC_    13\n#define STT_HIPROC_    15\n\n#define STV_DEFAULT_   0\n#define STV_INTERNAL_  1\n#define STV_HIDDEN_    2\n#define STV_PROTECTED_ 3\n\n#define SHN_UNDEF_     0\n#define SHN_LORESERVE_ 0xff00\n#define SHN_LOPROC_    0xff00\n#define SHN_BEFORE_    0xff00\n#define SHN_AFTER_     0xff01\n#define SHN_HIPROC_    0xff1f\n#define SHN_LOOS_      0xff20\n#define SHN_HIOS_      0xff3f\n#define SHN_ABS_       0xfff1\n#define SHN_COMMON_    0xfff2\n#define SHN_XINDEX_    0xffff\n#define SHN_HIRESERVE_ 0xffff\n\n#define SHF_WRITE_            (1 << 0)\n#define SHF_ALLOC_            (1 << 1)\n#define SHF_EXECINSTR_        (1 << 2)\n#define SHF_MERGE_            (1 << 4)\n#define SHF_STRINGS_          (1 << 5)\n#define SHF_INFO_LINK_        (1 << 6)\n#define SHF_LINK_ORDER_       (1 << 7)\n#define SHF_OS_NONCONFORMING_ (1 << 8)\n#define SHF_GROUP_            (1 << 9)\n#define SHF_TLS_              (1 << 10)\n#define SHF_COMPRESSED_       (1 << 11)\n#define SHF_MASKOS_           0x0ff00000\n#define SHF_MASKPROC_         0xf0000000\n#define SHF_ORDERED_          (1 << 30)\n#define SHF_EXCLUDE_          (1U << 31)\n\n#define ELFCOMPRESS_ZLIB_   1\n#define ELFCOMPRESS_LOOS_   0x60000000\n#define ELFCOMPRESS_HIOS_   0x6fffffff\n#define ELFCOMPRESS_LOPROC_ 0x70000000\n#define ELFCOMPRESS_HIPROC_ 0x7fffffff\n\n#define SHT_NULL_           0\n#define SHT_PROGBITS_       1\n#define SHT_SYMTAB_         2\n#define SHT_STRTAB_         3\n#define SHT_RELA_           4\n#define SHT_HASH_           5\n#define SHT_DYNAMIC_        6\n#define SHT_NOTE_           7\n#define SHT_NOBITS_         8\n#define SHT_REL_            9\n#define SHT_SHLIB_          10\n#define SHT_DYNSYM_         11\n#define SHT_INIT_ARRAY_     14\n#define SHT_FINI_ARRAY_     15\n#define SHT_PREINIT_ARRAY_  16\n#define SHT_GROUP_          17\n#define SHT_SYMTAB_SHNDX_   18\n#define SHT_NUM_            19\n#define SHT_LOOS_           0x60000000\n#define SHT_GNU_ATTRIBUTES_ 0x6ffffff5\n#define SHT_GNU_HASH_       0x6ffffff6\n#define SHT_GNU_LIBLIST_    0x6ffffff7\n#define SHT_CHECKSUM_       0x6ffffff8\n#define SHT_LOSUNW_         0x6ffffffa\n#define SHT_SUNW_move_      0x6ffffffa\n#define SHT_SUNW_COMDAT_    0x6ffffffb\n#define SHT_SUNW_syminfo_   0x6ffffffc\n#define SHT_GNU_verdef_     0x6ffffffd\n#define SHT_GNU_verneed_    0x6ffffffe\n#define SHT_GNU_versym_     0x6fffffff\n#define SHT_HISUNW_         0x6fffffff\n#define SHT_HIOS_           0x6fffffff\n#define SHT_LOPROC_         0x70000000\n#define SHT_HIPROC_         0x7fffffff\n#define SHT_LOUSER_         0x80000000\n#define SHT_HIUSER_         0x8fffffff\n\n#define DT_NULL_               0\n#define DT_NEEDED_             1\n#define DT_PLTRELSZ_           2\n#define DT_PLTGOT_             3\n#define DT_HASH_               4\n#define DT_STRTAB_             5\n#define DT_SYMTAB_             6\n#define DT_RELA_               7\n#define DT_RELASZ_             8\n#define DT_RELAENT_            9\n#define DT_STRSZ_              10\n#define DT_SYMENT_             11\n#define DT_INIT_               12\n#define DT_FINI_               13\n#define DT_SONAME_             14\n#define DT_RPATH_              15\n#define DT_SYMBOLIC_           16\n#define DT_REL_                17\n#define DT_RELSZ_              18\n#define DT_RELENT_             19\n#define DT_PLTREL_             20\n#define DT_DEBUG_              21\n#define DT_TEXTREL_            22\n#define DT_JMPREL_             23\n#define DT_BIND_NOW_           24\n#define DT_INIT_ARRAY_         25\n#define DT_FINI_ARRAY_         26\n#define DT_INIT_ARRAYSZ_       27\n#define DT_FINI_ARRAYSZ_       28\n#define DT_RUNPATH_            29\n#define DT_FLAGS_              30\n#define DT_ENCODING_           32\n#define DT_PREINIT_ARRAY_      32\n#define DT_PREINIT_ARRAYSZ_    33\n#define DT_SYMTAB_SHNDX_       34\n#define DT_NUM_                35\n#define DT_LOOS_               0x6000000d\n#define DT_HIOS_               0x6ffff000\n#define DT_LOPROC_             0x70000000\n#define DT_HIPROC_             0x7fffffff\n#define DT_VALRNGLO_           0x6ffffd00\n#define DT_GNU_PRELINKED_      0x6ffffdf5\n#define DT_GNU_CONFLICTSZ_     0x6ffffdf6\n#define DT_GNU_LIBLISTSZ_      0x6ffffdf7\n#define DT_CHECKSUM_           0x6ffffdf8\n#define DT_PLTPADSZ_           0x6ffffdf9\n#define DT_MOVEENT_            0x6ffffdfa\n#define DT_MOVESZ_             0x6ffffdfb\n#define DT_FEATURE_1_          0x6ffffdfc\n#define DT_POSFLAG_1_          0x6ffffdfd\n#define DT_SYMINSZ_            0x6ffffdfe\n#define DT_SYMINENT_           0x6ffffdff\n#define DT_VALRNGHI_           0x6ffffdff\n#define DT_VALTAGIDX_(tag)     (DT_VALRNGHI - (tag))\n#define DT_VALNUM_             12\n#define DT_ADDRRNGLO_          0x6ffffe00\n#define DT_GNU_HASH_           0x6ffffef5\n#define DT_TLSDESC_PLT_        0x6ffffef6\n#define DT_TLSDESC_GOT_        0x6ffffef7\n#define DT_GNU_CONFLICT_       0x6ffffef8\n#define DT_GNU_LIBLIST_        0x6ffffef9\n#define DT_CONFIG_             0x6ffffefa\n#define DT_DEPAUDIT_           0x6ffffefb\n#define DT_AUDIT_              0x6ffffefc\n#define DT_PLTPAD_             0x6ffffefd\n#define DT_MOVETAB_            0x6ffffefe\n#define DT_SYMINFO_            0x6ffffeff\n#define DT_ADDRRNGHI_          0x6ffffeff\n#define DT_ADDRTAGIDX_(tag)    (DT_ADDRRNGHI - (tag))\n#define DT_ADDRNUM_            11\n#define DT_VERSYM_             0x6ffffff0\n#define DT_RELACOUNT_          0x6ffffff9\n#define DT_RELCOUNT_           0x6ffffffa\n#define DT_FLAGS_1_            0x6ffffffb\n#define DT_VERDEF_             0x6ffffffc\n#define DT_VERDEFNUM_          0x6ffffffd\n#define DT_VERNEED_            0x6ffffffe\n#define DT_VERNEEDNUM_         0x6fffffff\n#define DT_VERSIONTAGIDX_(tag) (DT_VERNEEDNUM - (tag))\n#define DT_VERSIONTAGNUM_      16\n#define DT_AUXILIARY_          0x7ffffffd\n#define DT_FILTER_             0x7fffffff\n#define DT_EXTRATAGIDX_(tag)   ((Elf32_Word) - ((Elf32_Sword)(tag) << 1 >> 1) - 1)\n#define DT_EXTRANUM_           3\n\n#define VER_NEED_NONE_    0\n#define VER_NEED_CURRENT_ 1\n#define VER_NEED_NUM_     2\n#define VER_FLG_WEAK_     0x2\n\n#define ELF_NOTE_SOLARIS_       \"SUNW Solaris\"\n#define ELF_NOTE_GNU_           \"GNU\"\n#define ELF_NOTE_PAGESIZE_HINT_ 1\n#define ELF_NOTE_ABI_           NT_GNU_ABI_TAG\n#define ELF_NOTE_OS_LINUX_      0\n#define ELF_NOTE_OS_GNU_        1\n#define ELF_NOTE_OS_SOLARIS2_   2\n#define ELF_NOTE_OS_FREEBSD_    3\n\n#define NT_GNU_ABI_TAG_      1\n#define NT_GNU_BUILD_ID_     3\n#define NT_GNU_GOLD_VERSION_ 4\n\n#define EF_CPU32_ 0x00810000\n\n#define DF_ORIGIN_       0x00000001\n#define DF_SYMBOLIC_     0x00000002\n#define DF_TEXTREL_      0x00000004\n#define DF_BIND_NOW_     0x00000008\n#define DF_STATIC_TLS_   0x00000010\n#define DF_1_NOW_        0x00000001\n#define DF_1_GLOBAL_     0x00000002\n#define DF_1_GROUP_      0x00000004\n#define DF_1_NODELETE_   0x00000008\n#define DF_1_LOADFLTR_   0x00000010\n#define DF_1_INITFIRST_  0x00000020\n#define DF_1_NOOPEN_     0x00000040\n#define DF_1_ORIGIN_     0x00000080\n#define DF_1_DIRECT_     0x00000100\n#define DF_1_TRANS_      0x00000200\n#define DF_1_INTERPOSE_  0x00000400\n#define DF_1_NODEFLIB_   0x00000800\n#define DF_1_NODUMP_     0x00001000\n#define DF_1_CONFALT_    0x00002000\n#define DF_1_ENDFILTEE_  0x00004000\n#define DF_1_DISPRELDNE_ 0x00008000\n#define DF_1_DISPRELPND_ 0x00010000\n#define DF_1_NODIRECT_   0x00020000\n#define DF_1_IGNMULDEF_  0x00040000\n#define DF_1_NOKSYMS_    0x00080000\n#define DF_1_NOHDR_      0x00100000\n#define DF_1_EDITED_     0x00200000\n#define DF_1_NORELOC_    0x00400000\n#define DF_1_SYMINTPOSE_ 0x00800000\n#define DF_1_GLOBAUDIT_  0x01000000\n#define DF_1_SINGLETON_  0x02000000\n#define DF_1_STUB_       0x04000000\n#define DF_1_PIE_        0x08000000\n#define DTF_1_PARINIT_   0x00000001\n#define DTF_1_CONFEXP_   0x00000002\n#define DF_P1_LAZYLOAD_  0x00000001\n#define DF_P1_GROUPPERM_ 0x00000002\n\n#define ELF64_ST_BIND_(val)        (((u8)(val)) >> 4)\n#define ELF64_ST_TYPE_(val)        ((val)&0xf)\n#define ELF64_ST_INFO_(bind, type) (((bind) << 4) + ((type)&0xf))\n#define ELF64_ST_VISIBILITY_(o)    ((o)&0x03)\n\n#define ELF64_R_SYM_(i)          ((i) >> 32)\n#define ELF64_R_TYPE_(i)         ((i)&0xffffffff)\n#define ELF64_R_INFO_(sym, type) ((((u64)(sym)) << 32) + (type))\n\n#define ELF64_M_SYM_(info)       ((info) >> 8)\n#define ELF64_M_SIZE_(info)      ((u8)(info))\n#define ELF64_M_INFO_(sym, size) (((sym) << 8) + (u8)(size))\n\n#define NT_PRSTATUS_         1\n#define NT_PRFPREG_          2\n#define NT_FPREGSET_         2\n#define NT_PRPSINFO_         3\n#define NT_PRXREG_           4\n#define NT_TASKSTRUCT_       4\n#define NT_PLATFORM_         5\n#define NT_AUXV_             6\n#define NT_GWINDOWS_         7\n#define NT_ASRS_             8\n#define NT_PSTATUS_          10\n#define NT_PSINFO_           13\n#define NT_PRCRED_           14\n#define NT_UTSNAME_          15\n#define NT_LWPSTATUS_        16\n#define NT_LWPSINFO_         17\n#define NT_PRFPXREG_         20\n#define NT_SIGINFO_          0x53494749\n#define NT_FILE_             0x46494c45\n#define NT_PRXFPREG_         0x46e62b7f\n#define NT_PPC_VMX_          0x100\n#define NT_PPC_SPE_          0x101\n#define NT_PPC_VSX_          0x102\n#define NT_PPC_TAR_          0x103\n#define NT_PPC_PPR_          0x104\n#define NT_PPC_DSCR_         0x105\n#define NT_PPC_EBB_          0x106\n#define NT_PPC_PMU_          0x107\n#define NT_PPC_TM_CGPR_      0x108\n#define NT_PPC_TM_CFPR_      0x109\n#define NT_PPC_TM_CVMX_      0x10a\n#define NT_PPC_TM_CVSX_      0x10b\n#define NT_PPC_TM_SPR_       0x10c\n#define NT_PPC_TM_CTAR_      0x10d\n#define NT_PPC_TM_CPPR_      0x10e\n#define NT_PPC_TM_CDSCR_     0x10f\n#define NT_X86_XSTATE_       0x202\n#define NT_S390_HIGH_GPRS_   0x300\n#define NT_S390_TIMER_       0x301\n#define NT_S390_TODCMP_      0x302\n#define NT_S390_TODPREG_     0x303\n#define NT_S390_CTRS_        0x304\n#define NT_S390_PREFIX_      0x305\n#define NT_S390_LAST_BREAK_  0x306\n#define NT_S390_SYSTEM_CALL_ 0x307\n#define NT_S390_TDB_         0x308\n#define NT_S390_VXRS_LOW_    0x309\n#define NT_S390_VXRS_HIGH_   0x30a\n#define NT_S390_GS_CB_       0x30b\n#define NT_S390_GS_BC_       0x30c\n#define NT_S390_RI_CB_       0x30d\n#define NT_ARM_VFP_          0x400\n#define NT_ARM_TLS_          0x401\n#define NT_ARM_HW_BREAK_     0x402\n#define NT_ARM_HW_WATCH_     0x403\n#define NT_ARM_SYSTEM_CALL_  0x404\n#define NT_ARM_SVE_          0x405\n#define NT_ARM_PAC_MASK_     0x406\n#define NT_METAG_CBUF_       0x500\n#define NT_METAG_RPIPE_      0x501\n#define NT_METAG_TLS_        0x502\n#define NT_ARC_V2_           0x600\n#define NT_VMCOREDD_         0x700\n#define NT_VERSION_          1\n\n#define VER_DEF_NONE_      0\n#define VER_DEF_CURRENT_   1\n#define VER_DEF_NUM_       2\n#define VER_FLG_BASE_      0x1\n#define VER_FLG_WEAK_      0x2\n#define VER_NDX_LOCAL_     0\n#define VER_NDX_GLOBAL_    1\n#define VER_NDX_LORESERVE_ 0xff00\n#define VER_NDX_ELIMINATE_ 0xff01\n\n#define LL_NONE_           0\n#define LL_EXACT_MATCH_    (1 << 0)\n#define LL_IGNORE_INT_VER_ (1 << 1)\n#define LL_REQUIRE_MINOR_  (1 << 2)\n#define LL_EXPORTS_        (1 << 3)\n#define LL_DELAY_LOAD_     (1 << 4)\n#define LL_DELTA_          (1 << 5)\n\n#define R_BPF_NONE_   0\n#define R_BPF_MAP_FD_ 1\n\ntypedef struct Elf64_Ehdr_ {\n  u8 ident[EI_NIDENT_];\n  u8 type[2];       // u16\n  u8 machine[2];    // u16\n  u8 version[4];    // u32\n  u8 entry[8];      // u64\n  u8 phoff[8];      // u64\n  u8 shoff[8];      // u64\n  u8 flags[4];      // u32\n  u8 ehsize[2];     // u16\n  u8 phentsize[2];  // u16\n  u8 phnum[2];      // u16\n  u8 shentsize[2];  // u16\n  u8 shnum[2];      // u16\n  u8 shstrndx[2];   // u16\n} Elf64_Ehdr_;\n\ntypedef struct Elf64_Phdr_ {\n  u8 type[4];    // u32\n  u8 flags[4];   // u32\n  u8 offset[8];  // u64\n  u8 vaddr[8];   // u64\n  u8 paddr[8];   // u64\n  u8 filesz[8];  // u64\n  u8 memsz[8];   // u64\n  u8 align[8];   // u64\n} Elf64_Phdr_;\n\ntypedef struct Elf64_Shdr_ {\n  u8 name[4];       // u32\n  u8 type[4];       // u32\n  u8 flags[8];      // u64\n  u8 addr[8];       // u64\n  u8 offset[8];     // u64\n  u8 size[8];       // u64\n  u8 link[4];       // u32\n  u8 info[4];       // u32\n  u8 addralign[8];  // u64\n  u8 entsize[8];    // u64\n} Elf64_Shdr_;\n\ntypedef struct Elf64_Rel_ {\n  u8 offset[8];  // u64\n  u8 info[8];    // u64\n} Elf64_Rel_;\n\ntypedef struct Elf64_Rela_ {\n  u8 offset[8];  // u64\n  u8 info[8];    // u64\n  u8 addend[8];  // i64\n} Elf64_Rela_;\n\ntypedef struct Elf64_Sym_ {\n  u8 name[4];  // u32\n  u8 info;\n  u8 other;\n  u8 shndx[2];  // u16\n  u8 value[8];  // u64\n  u8 size[8];   // u64\n} Elf64_Sym_;\n\ntypedef struct Elf64_Syminfo_ {\n  u8 boundto[2];  // u16\n  u8 flags[2];    // u16\n} Elf64_Syminfo_;\n\ntypedef struct Elf64_Chdr_ {\n  u8 type[4];       // u32\n  u8 reserved[4];   // u32\n  u8 size[8];       // u64\n  u8 addralign[8];  // u64\n} Elf64_Chdr_;\n\ntypedef struct Elf64_Dyn_ {\n  u8 tag[8];  // i64\n  u8 val[8];  // u64\n} Elf64_Dyn_;\n\ntypedef struct Elf64_Lib_ {\n  u8 name[4];        // u32\n  u8 time_stamp[4];  // u32\n  u8 checksum[4];    // u32\n  u8 version[4];     // u32\n  u8 flags[4];       // u32\n} Elf64_Lib_;\n\ntypedef struct Elf64_Move_ {\n  u8 value[8];    // u64\n  u8 info[8];     // u64\n  u8 poffset[8];  // u64\n  u8 repeat[2];   // u16\n  u8 stride[2];   // u16\n} Elf64_Move_;\n\ntypedef struct Elf64_Nhdr_ {\n  u8 namesz[4];  // u32\n  u8 descsz[4];  // u32\n  u8 type[4];    // u32\n} Elf64_Nhdr_;\n\nElf64_Phdr_ *GetElfProgramHeaderAddress(const Elf64_Ehdr_ *, size_t, u16);\nchar *GetElfStringTable(const Elf64_Ehdr_ *, size_t);\nElf64_Shdr_ *GetElfSectionHeaderAddress(const Elf64_Ehdr_ *, size_t, u16);\nconst char *GetElfSectionName(const Elf64_Ehdr_ *, size_t, Elf64_Shdr_ *);\nchar *GetElfString(const Elf64_Ehdr_ *, size_t, const char *, size_t);\nchar *GetElfSectionNameStringTable(const Elf64_Ehdr_ *, size_t);\nvoid *GetElfSectionAddress(const Elf64_Ehdr_ *, size_t, const Elf64_Shdr_ *);\nElf64_Sym_ *GetElfSymbolTable(const Elf64_Ehdr_ *, size_t, int *);\ni64 GetElfMemorySize(const Elf64_Ehdr_ *, size_t, i64 *);\n\n#endif /* BLINK_ELF_H_ */\n"
  },
  {
    "path": "blink/end.h",
    "content": "#ifndef BLINK_END_H_\n#define BLINK_END_H_\n#include \"blink/flag.h\"\n\n// many platforms complain about `end` / `_end` so we'll just pick some\n// arbitarry variable in the .bss section, which should be close enough\n#define IMAGE_END ((u8 *)&FLAG_noconnect)\n\n#endif /* BLINK_END_H_ */\n"
  },
  {
    "path": "blink/endian.h",
    "content": "#ifndef BLINK_ENDIAN_H_\n#define BLINK_ENDIAN_H_\n#include \"blink/builtin.h\"\n#include \"blink/swap.h\"\n#include \"blink/types.h\"\n\nMICRO_OP_SAFE u8 Little8(u8 x) {\n  return x;\n}\n\nMICRO_OP_SAFE u16 Little16(u16 x) {\n#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n  return SWAP16(x);\n#else\n  return x;\n#endif\n}\n\nMICRO_OP_SAFE u32 Little32(u32 x) {\n#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n  return SWAP32(x);\n#else\n  return x;\n#endif\n}\n\nMICRO_OP_SAFE u64 Little64(u64 x) {\n#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n  return SWAP64(x);\n#else\n  return x;\n#endif\n}\n\nMICRO_OP_SAFE u8 Get8(const u8 *p) {\n  return *p;\n}\n\nMICRO_OP_SAFE u16 Get16(const u8 *p) {\n#ifdef __OPTIMIZE__\n  u16 x;\n  __builtin_memcpy(&x, p, 16 / 8);\n  return Little16(x);\n#else\n  return p[1] << 8 | p[0];\n#endif\n}\n\nMICRO_OP_SAFE u32 Get32(const u8 *p) {\n#ifdef __OPTIMIZE__\n  u32 x;\n  __builtin_memcpy(&x, p, 32 / 8);\n  return Little32(x);\n#else\n  return ((u32)p[0] << 000 |  //\n          (u32)p[1] << 010 |  //\n          (u32)p[2] << 020 |  //\n          (u32)p[3] << 030);\n#endif\n}\n\nMICRO_OP_SAFE u64 Get64(const u8 *p) {\n#ifdef __OPTIMIZE__\n  u64 x;\n  __builtin_memcpy(&x, p, 64 / 8);\n  return Little64(x);\n#else\n  return ((u64)p[0] << 000 |  //\n          (u64)p[1] << 010 |  //\n          (u64)p[2] << 020 |  //\n          (u64)p[3] << 030 |  //\n          (u64)p[4] << 040 |  //\n          (u64)p[5] << 050 |  //\n          (u64)p[6] << 060 |  //\n          (u64)p[7] << 070);\n#endif\n}\n\nMICRO_OP_SAFE void Put8(u8 *p, u8 v) {\n  *p = v;\n}\n\nMICRO_OP_SAFE void Put16(u8 *p, u16 v) {\n#ifdef __OPTIMIZE__\n  v = Little16(v);\n  __builtin_memcpy(p, &v, 16 / 8);\n#else\n  p[0] = v >> 000;\n  p[1] = v >> 010;\n#endif\n}\n\nMICRO_OP_SAFE void Put32(u8 *p, u32 v) {\n#ifdef __OPTIMIZE__\n  v = Little32(v);\n  __builtin_memcpy(p, &v, 32 / 8);\n#else\n  p[0] = v >> 000;\n  p[1] = v >> 010;\n  p[2] = v >> 020;\n  p[3] = v >> 030;\n#endif\n}\n\nMICRO_OP_SAFE void Put64(u8 *p, u64 v) {\n#ifdef __OPTIMIZE__\n  v = Little64(v);\n  __builtin_memcpy(p, &v, 64 / 8);\n#else\n  p[0] = v >> 000;\n  p[1] = v >> 010;\n  p[2] = v >> 020;\n  p[3] = v >> 030;\n  p[4] = v >> 040;\n  p[5] = v >> 050;\n  p[6] = v >> 060;\n  p[7] = v >> 070;\n#endif\n}\n\n#define Read8  Get8\n#define Read16 Get16\n#define Read32 Get32\n#define Read64 Get64\n\n#define Write8  Put8\n#define Write16 Put16\n#define Write32 Put32\n#define Write64 Put64\n\n#endif /* BLINK_ENDIAN_H_ */\n"
  },
  {
    "path": "blink/endswith.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n\n#include \"blink/util.h\"\n\nbool EndsWith(const char *s, const char *suffix) {\n  size_t n, m;\n  n = strlen(s);\n  m = strlen(suffix);\n  if (m > n) return false;\n  return !memcmp(s + n - m, suffix, m);\n}\n"
  },
  {
    "path": "blink/errfd.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/log.h\"\n#include \"blink/thread.h\"\n#include \"blink/tunables.h\"\n\n#define EXIT_FAILURE_ERRFD_INIT 200\n\nstatic int g_errfd;\n\nint WriteErrorString(const char *buf) {\n  return WriteError(0, buf, strlen(buf));\n}\n\nint WriteError(int fd, const char *buf, int len) {\n  int rc, cs;\n#ifdef HAVE_PTHREAD_SETCANCELSTATE\n  unassert(!pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs));\n#endif\n  do rc = write(fd > 0 ? fd : g_errfd, buf, len);\n  while (rc == -1 && errno == EINTR);\n#ifdef HAVE_PTHREAD_SETCANCELSTATE\n  unassert(!pthread_setcancelstate(cs, 0));\n#endif\n  return rc;\n}\n\nvoid WriteErrorInit(void) {\n  if (g_errfd) return;\n  g_errfd = fcntl(2, F_DUPFD_CLOEXEC, kMinBlinkFd);\n  if (g_errfd == -1) exit(EXIT_FAILURE_ERRFD_INIT);\n}\n"
  },
  {
    "path": "blink/errno.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/errno.h\"\n\n#include <errno.h>\n\n#include \"blink/builtin.h\"\n\nstatic dontinline long ReturnErrno(int e) {\n  errno = e;\n  return -1;\n}\n\nlong ebadf(void) {\n  return ReturnErrno(EBADF);\n}\n\nlong einval(void) {\n  return ReturnErrno(EINVAL);\n}\n\nlong eagain(void) {\n  return ReturnErrno(EAGAIN);\n}\n\nlong enomem(void) {\n  return ReturnErrno(ENOMEM);\n}\n\nlong enosys(void) {\n  return ReturnErrno(ENOSYS);\n}\n\nlong emfile(void) {\n  return ReturnErrno(EMFILE);\n}\n\nlong efault(void) {\n  return ReturnErrno(EFAULT);\n}\n\nvoid *efault0(void) {\n  efault();\n  return 0;\n}\n\nlong eintr(void) {\n  return ReturnErrno(EINTR);\n}\n\nlong eoverflow(void) {\n  return ReturnErrno(EOVERFLOW);\n}\n\nlong enfile(void) {\n  return ReturnErrno(ENFILE);\n}\n\nlong esrch(void) {\n  return ReturnErrno(ESRCH);\n}\n\nlong eperm(void) {\n  return ReturnErrno(EPERM);\n}\n\nlong enotsup(void) {\n  return ReturnErrno(ENOTSUP);\n}\n\nlong enoent(void) {\n  return ReturnErrno(ENOENT);\n}\n\nlong enotdir(void) {\n  return ReturnErrno(ENOTDIR);\n}\n\nlong erange(void) {\n  return ReturnErrno(ERANGE);\n}\n\nlong eopnotsupp(void) {\n  return ReturnErrno(EOPNOTSUPP);\n}\n\nlong enodev(void) {\n  return ReturnErrno(ENODEV);\n}\n\nlong eacces(void) {\n  return ReturnErrno(EACCES);\n}\n\nlong eisdir(void) {\n  return ReturnErrno(EISDIR);\n}\n\nlong eexist(void) {\n  return ReturnErrno(EEXIST);\n}\n\nlong eloop(void) {\n  return ReturnErrno(ELOOP);\n}\n\nlong exdev(void) {\n  return ReturnErrno(EXDEV);\n}\n\nlong enametoolong(void) {\n  return ReturnErrno(ENAMETOOLONG);\n}\n"
  },
  {
    "path": "blink/errno.h",
    "content": "#ifndef BLINK_ERRNO_H_\n#define BLINK_ERRNO_H_\n\nlong eagain(void);\nlong ebadf(void);\nlong efault(void);\nvoid *efault0(void);\nlong eintr(void);\nlong einval(void);\nlong enfile(void);\nlong enoent(void);\nlong enomem(void);\nlong enosys(void);\nlong emfile(void);\nlong enotdir(void);\nlong enotsup(void);\nlong eoverflow(void);\nlong eopnotsupp(void);\nlong erange(void);\nlong eperm(void);\nlong esrch(void);\nlong enodev(void);\nlong eacces(void);\nlong eisdir(void);\nlong eexist(void);\nlong eloop(void);\nlong exdev(void);\nlong enametoolong(void);\n\n#endif /* BLINK_ERRNO_H_ */\n"
  },
  {
    "path": "blink/fds.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/fds.h\"\n\n#include <fcntl.h>\n#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/errno.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/thread.h\"\n#include \"blink/vfs.h\"\n\nvoid InitFds(struct Fds *fds) {\n  fds->list = 0;\n  unassert(!pthread_mutex_init(&fds->lock, 0));\n}\n\nstruct Fd *AddFd(struct Fds *fds, int fildes, int oflags) {\n  struct Fd *fd;\n  if (fildes >= 0) {\n    if ((fd = (struct Fd *)calloc(1, sizeof(*fd)))) {\n      dll_init(&fd->elem);\n      fd->cb = &kFdCbHost;\n      fd->fildes = fildes;\n      fd->oflags = oflags;\n      unassert(!pthread_mutex_init(&fd->lock, 0));\n      dll_make_first(&fds->list, &fd->elem);\n    }\n    return fd;\n  } else {\n    einval();\n    return 0;\n  }\n}\n\nstruct Fd *ForkFd(struct Fds *fds, struct Fd *fd, int fildes, int oflags) {\n  struct Fd *fd2;\n  if ((fd2 = AddFd(fds, fildes, oflags))) {\n    if (fd) {\n      fd2->path = fd->path ? strdup(fd->path) : 0;\n      fd2->socktype = fd->socktype;\n      fd2->norestart = fd->norestart;\n      memcpy(&fd2->saddr, &fd->saddr, sizeof(fd->saddr));\n    }\n  }\n  return fd2;\n}\n\nstruct Fd *GetFd(struct Fds *fds, int fildes) {\n  bool lru;\n  struct Dll *e;\n  if (fildes >= 0) {\n    lru = false;\n    for (e = dll_first(fds->list); e; e = dll_next(fds->list, e)) {\n      if (FD_CONTAINER(e)->fildes == fildes) {\n        if (lru) {\n          dll_remove(&fds->list, e);\n          dll_make_first(&fds->list, e);\n        }\n        return FD_CONTAINER(e);\n      }\n      lru = true;\n    }\n  }\n  ebadf();\n  return 0;\n}\n\nvoid LockFd(struct Fd *fd) {\n  LOCK(&fd->lock);\n}\n\nvoid UnlockFd(struct Fd *fd) {\n  UNLOCK(&fd->lock);\n}\n\nint CountFds(struct Fds *fds) {\n  int n = 0;\n  struct Dll *e;\n  for (e = dll_first(fds->list); e; e = dll_next(fds->list, e)) {\n    ++n;\n  }\n  return n;\n}\n\nvoid FreeFd(struct Fd *fd) {\n  if (fd) {\n    unassert(!pthread_mutex_destroy(&fd->lock));\n    free(fd->path);\n    free(fd);\n  }\n}\n\nvoid DestroyFds(struct Fds *fds) {\n  struct Dll *e, *e2;\n  for (e = dll_first(fds->list); e; e = e2) {\n    e2 = dll_next(fds->list, e);\n    dll_remove(&fds->list, e);\n    FreeFd(FD_CONTAINER(e));\n  }\n  unassert(!fds->list);\n  unassert(!pthread_mutex_destroy(&fds->lock));\n}\n\nstatic int GetFdSocketType(int fildes, int *type) {\n  socklen_t len = sizeof(*type);\n  return VfsGetsockopt(fildes, SOL_SOCKET, SO_TYPE, type, &len);\n}\n\nstatic bool IsNoRestartSocket(int fildes) {\n  struct timeval tv = {0};\n  socklen_t len = sizeof(tv);\n  VfsGetsockopt(fildes, SOL_SOCKET, SO_RCVTIMEO, &tv, &len);\n  return tv.tv_sec || tv.tv_usec;\n}\n\nvoid InheritFd(struct Fd *fd) {\n#ifndef DISABLE_SOCKETS\n  socklen_t addrlen;\n  if (!fd) return;\n  if (!GetFdSocketType(fd->fildes, &fd->socktype)) {\n    fd->norestart = IsNoRestartSocket(fd->fildes);\n    addrlen = sizeof(fd->saddr);\n    VfsGetsockname(fd->fildes, (struct sockaddr *)&fd->saddr, &addrlen);\n  }\n#endif\n}\n\nvoid AddStdFd(struct Fds *fds, int fildes) {\n  int flags;\n  if ((flags = VfsFcntl(fildes, F_GETFL, 0)) >= 0) {\n    InheritFd(AddFd(fds, fildes, flags));\n  }\n}\n"
  },
  {
    "path": "blink/fds.h",
    "content": "#ifndef BLINK_FDS_H_\n#define BLINK_FDS_H_\n#include <dirent.h>\n#include <limits.h>\n#include <netinet/in.h>\n#include <poll.h>\n#include <stdbool.h>\n#include <sys/socket.h>\n#include <sys/uio.h>\n#include <termios.h>\n\n#include \"blink/dll.h\"\n#include \"blink/thread.h\"\n#include \"blink/types.h\"\n\n#define FD_CONTAINER(e) DLL_CONTAINER(struct Fd, elem, e)\n\nstruct winsize;\n\nstruct FdCb {\n  int (*close)(int);\n  ssize_t (*readv)(int, const struct iovec *, int);\n  ssize_t (*writev)(int, const struct iovec *, int);\n  int (*poll)(struct pollfd *, nfds_t, int);\n  int (*tcgetattr)(int, struct termios *);\n  int (*tcsetattr)(int, int, const struct termios *);\n  int (*tcgetwinsize)(int, struct winsize *);\n  int (*tcsetwinsize)(int, const struct winsize *);\n};\n\nstruct Fd {\n  int fildes;      // file descriptor\n  int oflags;      // host O_XXX constants\n  int socktype;    // host SOCK_XXX constants\n  bool norestart;  // is SO_RCVTIMEO in play?\n  DIR *dirstream;  // for getdents() lazilly\n  struct Dll elem;\n  pthread_mutex_t_ lock;\n  const struct FdCb *cb;\n  char *path;\n  union {\n    struct sockaddr sa;\n    struct sockaddr_in sin;\n    struct sockaddr_in6 sin6;\n  } saddr;\n};\n\nstruct Fds {\n  struct Dll *list;\n  pthread_mutex_t_ lock;\n};\n\nextern const struct FdCb kFdCbHost;\n\nvoid InitFds(struct Fds *);\nstruct Fd *AddFd(struct Fds *, int, int);\nstruct Fd *ForkFd(struct Fds *, struct Fd *, int, int);\nstruct Fd *GetFd(struct Fds *, int);\nvoid LockFd(struct Fd *);\nvoid UnlockFd(struct Fd *);\nint CountFds(struct Fds *);\nvoid FreeFd(struct Fd *);\nvoid DestroyFds(struct Fds *);\nvoid InheritFd(struct Fd *);\n\n#endif /* BLINK_FDS_H_ */\n"
  },
  {
    "path": "blink/flag.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/flag.h\"\n\n#include \"blink/builtin.h\"\n\nbool FLAG_zero;\nbool FLAG_wantjit;\nbool FLAG_nolinear;\nbool FLAG_noconnect;\nbool FLAG_nologstderr;\nbool FLAG_alsologtostderr;\n\nint FLAG_strace;\nint FLAG_vabits;\n\nlong FLAG_pagesize;\n\nu64 FLAG_skew;\nu64 FLAG_vaspace;\nu64 FLAG_aslrmask;\nu64 FLAG_stacktop;\nu64 FLAG_imagestart;\ni64 FLAG_automapend;\ni64 FLAG_automapstart;\nu64 FLAG_dyninterpaddr;\n\nconst char *FLAG_logpath;\n\n#ifndef DISABLE_OVERLAYS\nconst char *FLAG_overlays;\n#endif\n#ifndef DISABLE_VFS\nconst char *FLAG_prefix;\n#endif\nconst char *FLAG_bios;\n"
  },
  {
    "path": "blink/flag.h",
    "content": "#ifndef BLINK_FLAG_H_\n#define BLINK_FLAG_H_\n#include <stdbool.h>\n\n#include \"blink/types.h\"\n\nextern bool FLAG_zero;\nextern bool FLAG_wantjit;\nextern bool FLAG_nolinear;\nextern bool FLAG_noconnect;\nextern bool FLAG_nologstderr;\nextern bool FLAG_alsologtostderr;\n\nextern int FLAG_strace;\nextern int FLAG_vabits;\n\nextern long FLAG_pagesize;\n\nextern u64 FLAG_skew;\nextern u64 FLAG_vaspace;\nextern u64 FLAG_stacktop;\nextern u64 FLAG_aslrmask;\nextern u64 FLAG_imagestart;\nextern i64 FLAG_automapend;\nextern i64 FLAG_automapstart;\nextern u64 FLAG_dyninterpaddr;\n\nextern const char *FLAG_logpath;\nextern const char *FLAG_overlays;\nextern const char *FLAG_prefix;\nextern const char *FLAG_bios;\n\n#endif /* BLINK_FLAG_H_ */\n"
  },
  {
    "path": "blink/flags.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/flags.h\"\n\n#include \"blink/builtin.h\"\n#include \"blink/debug.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/rde.h\"\n#include \"blink/stats.h\"\n#include \"blink/x86.h\"\n\nbool GetParity(u8 b) {\n  b ^= b >> 4;\n  b ^= b >> 2;\n  b ^= b >> 1;\n  return ~b & 1;\n}\n\nvoid ImportFlags(struct Machine *m, u64 flags) {\n  u64 mask = 0;\n  mask |= 1 << FLAGS_CF;\n  mask |= 1 << FLAGS_PF;\n  mask |= 1 << FLAGS_AF;\n  mask |= 1 << FLAGS_ZF;\n  mask |= 1 << FLAGS_SF;\n  mask |= 1 << FLAGS_TF;\n  mask |= 1 << FLAGS_IF;\n  mask |= 1 << FLAGS_DF;\n  mask |= 1 << FLAGS_OF;\n  mask |= 1 << FLAGS_NT;\n  mask |= 1 << FLAGS_AC;\n  mask |= 1 << FLAGS_ID;\n  m->flags = (flags & mask) | (m->flags & ~mask);\n  m->flags = SetFlag(m->flags, FLAGS_RF, false);\n  m->flags = SetLazyParityByte(m->flags, !((m->flags >> FLAGS_PF) & 1));\n}\n\nu64 ExportFlags(u64 flags) {\n  flags = SetFlag(flags, FLAGS_IOPL, 3);\n  flags = SetFlag(flags, FLAGS_F1, true);\n  flags = SetFlag(flags, FLAGS_F0, false);\n  flags = flags & ~((u64)1 << FLAGS_PF);\n  flags |= GetLazyParityBool(flags) << FLAGS_PF;\n  return flags;\n}\n"
  },
  {
    "path": "blink/flags.h",
    "content": "#ifndef BLINK_FLAGS_H_\n#define BLINK_FLAGS_H_\n#include \"blink/builtin.h\"\n#include \"blink/machine.h\"\n\n#define FLAGS_CF   0   // carry flag\n#define FLAGS_VF   1   // always 1\n#define FLAGS_PF   2   // parity flag\n#define FLAGS_F1   3   // always 0\n#define FLAGS_AF   4   // auxiliary carry flag\n#define FLAGS_KF   5   // always 0\n#define FLAGS_ZF   6   // zero flag\n#define FLAGS_SF   7   // sign flag\n#define FLAGS_TF   8   // trap flag\n#define FLAGS_IF   9   // interrupt enable flag\n#define FLAGS_DF   10  // direction flag\n#define FLAGS_OF   11  // overflow flag\n#define FLAGS_IOPL 12  // [12,13] i/o privilege level\n#define FLAGS_NT   14  // nested task\n#define FLAGS_F0   15  // always 0\n#define FLAGS_RF   16  // resume flag\n#define FLAGS_VM   17  // virtual-8086 mode\n#define FLAGS_AC   18  // access control / alignment check\n#define FLAGS_VIF  19  // virtual interrupt flag\n#define FLAGS_VIP  20  // virtual interrupt pending\n#define FLAGS_ID   21  // id flag\n#define FLAGS_LP   24  // [24,31] low bits of last alu result (supposed to be 0)\n\n#define CF (1 << FLAGS_CF)\n#define PF (1 << FLAGS_PF)\n#define AF (1 << FLAGS_AF)\n#define ZF (1 << FLAGS_ZF)\n#define SF (1 << FLAGS_SF)\n#define OF (1 << FLAGS_OF)\n#define DF (1 << FLAGS_DF)\n#define RF (1 << FLAGS_RF)\n#define AC (1 << FLAGS_AC)\n#define ID (1 << FLAGS_ID)\n\n#define GetLazyParityBool(f)    GetParity((0xff000000 & (f)) >> FLAGS_LP)\n#define SetLazyParityByte(f, x) ((0x00ffffff & (f)) | (255 & (x)) << FLAGS_LP)\n\nu64 ExportFlags(u64);\nbool GetParity(u8) pureconst;\nvoid ImportFlags(struct Machine *, u64);\nint GetFlagDeps(u64) pureconst;\nint GetFlagClobbers(u64) pureconst;\nint GetNeededFlags(struct Machine *, i64, int);\n\nstatic inline bool GetFlag(u32 f, int b) {\n  switch (b) {\n    case FLAGS_PF:\n      return GetLazyParityBool(f);\n    default:\n      return (f >> b) & 1;\n  }\n}\n\nstatic inline u32 SetFlag(u32 f, int b, bool v) {\n  switch (b) {\n    case FLAGS_PF:\n      return SetLazyParityByte(f, !v);\n    default:\n      return (f & ~(1u << b)) | v << b;\n  }\n}\n\nMICRO_OP_SAFE bool IsParity(struct Machine *m) {\n  return GetFlag(m->flags, FLAGS_PF);\n}\n\nMICRO_OP_SAFE bool IsBelowOrEqual(struct Machine *m) {  // CF || ZF\n  return ((m->flags >> 6) | m->flags) & 1;\n}\n\nMICRO_OP_SAFE bool IsAbove(struct Machine *m) {  // !CF && ~ZF\n  return ((~m->flags >> 6) & ~m->flags) & 1;\n}\n\nMICRO_OP_SAFE bool IsLess(struct Machine *m) {  // SF != OF\n  return (i8)(m->flags ^ (m->flags >> 4)) < 0;\n}\n\nMICRO_OP_SAFE bool IsGreaterOrEqual(struct Machine *m) {  // SF == OF\n  return (i8)(~(m->flags ^ (m->flags >> 4))) < 0;\n}\n\nMICRO_OP_SAFE bool IsLessOrEqual(struct Machine *m) {  // ZF || SF != OF\n  return (i8)((m->flags ^ (m->flags >> 4)) | (m->flags << 1)) < 0;\n}\n\nMICRO_OP_SAFE bool IsGreater(struct Machine *m) {  // !ZF && SF == OF\n  return (i8)(~(m->flags ^ (m->flags >> 4)) & ~(m->flags << 1)) < 0;\n}\n\n#endif /* BLINK_FLAGS_H_ */\n"
  },
  {
    "path": "blink/formatint64.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2021 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/builtin.h\"\n#include \"blink/util.h\"\n\n/**\n * Converts unsigned 64-bit integer to string.\n *\n * @param p needs at least 21 bytes\n * @return pointer to nul byte\n */\ndontinline char *FormatUint64(char *p, uint64_t x) {\n  char t;\n  size_t i, a, b;\n  i = 0;\n  do {\n    p[i++] = x % 10 + '0';\n    x = x / 10;\n  } while (x > 0);\n  p[i] = '\\0';\n  if (i) {\n    for (a = 0, b = i - 1; a < b; ++a, --b) {\n      t = p[a];\n      p[a] = p[b];\n      p[b] = t;\n    }\n  }\n  return p + i;\n}\n\n/**\n * Converts signed 64-bit integer to string.\n *\n * @param p needs at least 21 bytes\n * @return pointer to nul byte\n */\nchar *FormatInt64(char *p, int64_t x) {\n  if (x < 0) *p++ = '-', x = -(uint64_t)x;\n  return FormatUint64(p, x);\n}\n"
  },
  {
    "path": "blink/formatint64thousands.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2021 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/builtin.h\"\n#include \"blink/util.h\"\n\n/**\n * Converts unsigned 64-bit integer to string w/ commas.\n *\n * @param p needs at least 27 bytes\n * @return pointer to nul byte\n */\ndontinline char *FormatUint64Thousands(char *p, uint64_t x) {\n  size_t i;\n  char m[26];\n  i = 0;\n  do {\n    m[i++] = x % 10 + '0';\n    x = x / 10;\n  } while (x);\n  for (;;) {\n    *p++ = m[--i];\n    if (!i) break;\n    if (!(i % 3)) *p++ = ',';\n  }\n  *p = '\\0';\n  return p;\n}\n\n/**\n * Converts 64-bit integer to string w/ commas.\n *\n * @param p needs at least 27 bytes\n * @return pointer to nul byte\n */\nchar *FormatInt64Thousands(char *p, int64_t x) {\n  if (x < 0) *p++ = '-', x = -(uint64_t)x;\n  return FormatUint64Thousands(p, x);\n}\n"
  },
  {
    "path": "blink/formatsize.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/macros.h\"\n#include \"blink/util.h\"\n\n/**\n * Represents size as readable string.\n *\n * @param p is output buffer\n * @param b should be 1024 or 1000\n * @return pointer to nul byte\n */\nchar *FormatSize(char *p, uint64_t x, uint64_t b) {\n  int i, suffix;\n  struct {\n    char suffix;\n    uint64_t size;\n  } kUnits[] = {\n      {'e', b * b * b * b * b * b},\n      {'p', b * b * b * b * b},\n      {'t', b * b * b * b},\n      {'g', b * b * b},\n      {'m', b * b},\n      {'k', b},\n  };\n  for (suffix = i = 0; i < ARRAYLEN(kUnits); ++i) {\n    if (x >= kUnits[i].size * 9) {\n      x = (x + kUnits[i].size / 2) / kUnits[i].size;\n      suffix = kUnits[i].suffix;\n      break;\n    }\n  }\n  p = FormatUint64(p, x);\n  if (suffix) *p++ = suffix;\n  *p = 0;\n  return p;\n}\n"
  },
  {
    "path": "blink/fpu.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/fpu.h\"\n\n#include <math.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/case.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/ldbl.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/modrm.h\"\n#include \"blink/pun.h\"\n#include \"blink/rde.h\"\n\n#define FPUREG 0\n#define MEMORY 1\n\n#define DISP(x, y, z) ((7 & (x)) << 4 | (y) << 3 | (u32)(z))\n\nstatic i16 FpuGetMemoryShort(struct Machine *m) {\n  u8 b[2];\n  return Read16(Load(m, m->fpu.dp, 2, b));\n}\n\nstatic void FpuSetMemoryShort(struct Machine *m, i16 i) {\n  void *p[2];\n  u8 b[2];\n  Write16(BeginStore(m, m->fpu.dp, 2, p, b), i);\n  EndStore(m, m->fpu.dp, 2, p, b);\n}\n\nstatic void OpFstcw(struct Machine *m) {\n  FpuSetMemoryShort(m, m->fpu.cw);\n}\n\nstatic void OpFldcw(struct Machine *m) {\n  m->fpu.cw = FpuGetMemoryShort(m);\n}\n\n#ifndef DISABLE_X87\n\nstatic void OnFpuStackOverflow(struct Machine *m) {\n  m->fpu.sw |= kFpuSwIe | kFpuSwC1 | kFpuSwSf;\n}\n\nstatic double OnFpuStackUnderflow(struct Machine *m) {\n  m->fpu.sw |= kFpuSwIe | kFpuSwSf;\n  m->fpu.sw &= ~kFpuSwC1;\n  return -NAN;\n}\n\nstatic double St(struct Machine *m, int i) {\n  if (FpuGetTag(m, i) == kFpuTagEmpty) OnFpuStackUnderflow(m);\n  return *FpuSt(m, i);\n}\n\nstatic double St0(struct Machine *m) {\n  return St(m, 0);\n}\n\nstatic double St1(struct Machine *m) {\n  return St(m, 1);\n}\n\nstatic double StRm(struct Machine *m, u64 rde) {\n  return St(m, ModrmRm(rde));\n}\n\nstatic void FpuClearRoundup(struct Machine *m) {\n  m->fpu.sw &= ~kFpuSwC1;\n}\n\nstatic void FpuClearOutOfRangeIndicator(struct Machine *m) {\n  m->fpu.sw &= ~kFpuSwC2;\n}\n\nstatic void FpuSetSt0(struct Machine *m, double x) {\n  *FpuSt(m, 0) = x;\n}\n\nstatic void FpuSetStRm(struct Machine *m, u64 rde, double x) {\n  *FpuSt(m, ModrmRm(rde)) = x;\n}\n\nstatic void FpuSetStPop(struct Machine *m, int i, double x) {\n  *FpuSt(m, i) = x;\n  FpuPop(m);\n}\n\nstatic void FpuSetStRmPop(struct Machine *m, u64 rde, double x) {\n  FpuSetStPop(m, ModrmRm(rde), x);\n}\n\nstatic i32 FpuGetMemoryInt(struct Machine *m) {\n  u8 b[4];\n  return Read32(Load(m, m->fpu.dp, 4, b));\n}\n\nstatic i64 FpuGetMemoryLong(struct Machine *m) {\n  u8 b[8];\n  return Read64(Load(m, m->fpu.dp, 8, b));\n}\n\nstatic float FpuGetMemoryFloat(struct Machine *m) {\n  union FloatPun u;\n  u.i = FpuGetMemoryInt(m);\n  return u.f;\n}\n\nstatic double FpuGetMemoryDouble(struct Machine *m) {\n  union DoublePun u;\n  u.i = FpuGetMemoryLong(m);\n  return u.f;\n}\n\nstatic void FpuSetMemoryInt(struct Machine *m, i32 i) {\n  void *p[2];\n  u8 b[4];\n  Write32(BeginStore(m, m->fpu.dp, 4, p, b), i);\n  EndStore(m, m->fpu.dp, 4, p, b);\n}\n\nstatic void FpuSetMemoryLong(struct Machine *m, i64 i) {\n  void *p[2];\n  u8 b[8];\n  Write64(BeginStore(m, m->fpu.dp, 8, p, b), i);\n  EndStore(m, m->fpu.dp, 8, p, b);\n}\n\nstatic void FpuSetMemoryFloat(struct Machine *m, float f) {\n  union FloatPun u = {f};\n  FpuSetMemoryInt(m, u.i);\n}\n\nstatic void FpuSetMemoryDouble(struct Machine *m, double f) {\n  union DoublePun u = {f};\n  FpuSetMemoryLong(m, u.i);\n}\n\nstatic double FpuGetMemoryLdbl(struct Machine *m) {\n  u8 b[10];\n  return DeserializeLdbl(Load(m, m->fpu.dp, 10, b));\n}\n\nstatic void FpuSetMemoryLdbl(struct Machine *m, double f) {\n  void *p[2];\n  u8 b[10], t[10];\n  SerializeLdbl(b, f);\n  memcpy(BeginStore(m, m->fpu.dp, 10, p, t), b, 10);\n  EndStore(m, m->fpu.dp, 10, p, t);\n}\n\nstatic double f2xm1(double x) {\n  return exp2(x) - 1;\n}\n\nstatic double fyl2x(double x, double y) {\n  return y * log2(x);\n}\n\nstatic double fyl2xp1(double x, double y) {\n  return y * log2(x + 1);\n}\n\nstatic double fscale(double significand, double exponent) {\n  if (isunordered(significand, exponent)) return NAN;\n  return ldexp(significand, exponent);\n}\n\nstatic double x87remainder(double x, double y, u32 *sw,\n                           double rem(double, double), double rnd(double)) {\n  int s;\n  long q;\n  double r;\n  s = 0;\n  r = rem(x, y);\n  q = rnd(x / y);\n  s &= ~kFpuSwC2; /* ty libm */\n  if (q & 1) s |= kFpuSwC1;\n  if (q & 2) s |= kFpuSwC3;\n  if (q & 4) s |= kFpuSwC0;\n  if (sw) *sw = s | (*sw & ~(kFpuSwC0 | kFpuSwC1 | kFpuSwC2 | kFpuSwC3));\n  return r;\n}\n\nstatic double fprem(double dividend, double modulus, u32 *sw) {\n  return x87remainder(dividend, modulus, sw, fmod, trunc);\n}\n\nstatic double fprem1(double dividend, double modulus, u32 *sw) {\n  return x87remainder(dividend, modulus, sw, remainder, rint);\n}\n\nstatic double FpuAdd(struct Machine *m, double x, double y) {\n  if (!isunordered(x, y)) {\n    switch (isinf(y) << 1 | isinf(x)) {\n      case 0:\n        return x + y;\n      case 1:\n        return x;\n      case 2:\n        return y;\n      case 3:\n        if (signbit(x) == signbit(y)) {\n          return x;\n        } else {\n          m->fpu.sw |= kFpuSwIe;\n          return copysign(NAN, x);\n        }\n      default:\n        __builtin_unreachable();\n    }\n  } else {\n    return NAN;\n  }\n}\n\nstatic double FpuSub(struct Machine *m, double x, double y) {\n  if (!isunordered(x, y)) {\n    switch (isinf(y) << 1 | isinf(x)) {\n      case 0:\n        return x - y;\n      case 1:\n        return -x;\n      case 2:\n        return y;\n      case 3:\n        if (signbit(x) == signbit(y)) {\n          m->fpu.sw |= kFpuSwIe;\n          return copysign(NAN, x);\n        } else {\n          return y;\n        }\n      default:\n        __builtin_unreachable();\n    }\n  } else {\n    return NAN;\n  }\n}\n\nstatic double FpuMul(struct Machine *m, double x, double y) {\n  if (!isunordered(x, y)) {\n    if (!((isinf(x) && !y) || (isinf(y) && !x))) {\n      return x * y;\n    } else {\n      m->fpu.sw |= kFpuSwIe;\n      return -NAN;\n    }\n  } else {\n    return NAN;\n  }\n}\n\nstatic double FpuDiv(struct Machine *m, double x, double y) {\n  if (!isunordered(x, y)) {\n    if (x || y) {\n      if (y) {\n        return x / y;\n      } else {\n        m->fpu.sw |= kFpuSwZe;\n        return copysign(INFINITY, x);\n      }\n    } else {\n      m->fpu.sw |= kFpuSwIe;\n      return copysign(NAN, x);\n    }\n  } else {\n    return NAN;\n  }\n}\n\nstatic double FpuRound(struct Machine *m, double x) {\n  switch ((m->fpu.cw & kFpuCwRc) >> 10) {\n    case 0:\n      return rint(x);\n    case 1:\n      return floor(x);\n    case 2:\n      return ceil(x);\n    case 3:\n      return trunc(x);\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic void FpuCompare(struct Machine *m, double y) {\n  double x = St0(m);\n  m->fpu.sw &= ~(kFpuSwC0 | kFpuSwC1 | kFpuSwC2 | kFpuSwC3);\n  if (!isunordered(x, y)) {\n    if (x < y) m->fpu.sw |= kFpuSwC0;\n    if (x == y) m->fpu.sw |= kFpuSwC3;\n  } else {\n    m->fpu.sw |= kFpuSwC0 | kFpuSwC2 | kFpuSwC3 | kFpuSwIe;\n  }\n}\n\nstatic void OpFxam(struct Machine *m) {\n  double x;\n  x = *FpuSt(m, 0);\n  m->fpu.sw &= ~(kFpuSwC0 | kFpuSwC1 | kFpuSwC2 | kFpuSwC3);\n  if (signbit(x)) m->fpu.sw |= kFpuSwC1;\n  if (FpuGetTag(m, 0) == kFpuTagEmpty) {\n    m->fpu.sw |= kFpuSwC0 | kFpuSwC3;\n  } else {\n    switch (fpclassify(x)) {\n      case FP_NAN:\n        m->fpu.sw |= kFpuSwC0;\n        break;\n      case FP_INFINITE:\n        m->fpu.sw |= kFpuSwC0 | kFpuSwC2;\n        break;\n      case FP_ZERO:\n        m->fpu.sw |= kFpuSwC3;\n        break;\n      case FP_SUBNORMAL:\n        m->fpu.sw |= kFpuSwC2 | kFpuSwC3;\n        break;\n      case FP_NORMAL:\n        m->fpu.sw |= kFpuSwC2;\n        break;\n      default:\n        __builtin_unreachable();\n    }\n  }\n}\n\nstatic void OpFtst(struct Machine *m) {\n  FpuCompare(m, 0);\n}\n\nstatic void OpFcmovb(struct Machine *m, u64 rde) {\n  if (GetFlag(m->flags, FLAGS_CF)) {\n    FpuSetSt0(m, StRm(m, rde));\n  }\n}\n\nstatic void OpFcmove(struct Machine *m, u64 rde) {\n  if (GetFlag(m->flags, FLAGS_ZF)) {\n    FpuSetSt0(m, StRm(m, rde));\n  }\n}\n\nstatic void OpFcmovbe(struct Machine *m, u64 rde) {\n  if (GetFlag(m->flags, FLAGS_CF) || GetFlag(m->flags, FLAGS_ZF)) {\n    FpuSetSt0(m, StRm(m, rde));\n  }\n}\n\nstatic void OpFcmovu(struct Machine *m, u64 rde) {\n  if (GetFlag(m->flags, FLAGS_PF)) {\n    FpuSetSt0(m, StRm(m, rde));\n  }\n}\n\nstatic void OpFcmovnb(struct Machine *m, u64 rde) {\n  if (!GetFlag(m->flags, FLAGS_CF)) {\n    FpuSetSt0(m, StRm(m, rde));\n  }\n}\n\nstatic void OpFcmovne(struct Machine *m, u64 rde) {\n  if (!GetFlag(m->flags, FLAGS_ZF)) {\n    FpuSetSt0(m, StRm(m, rde));\n  }\n}\n\nstatic void OpFcmovnbe(struct Machine *m, u64 rde) {\n  if (!(GetFlag(m->flags, FLAGS_CF) || GetFlag(m->flags, FLAGS_ZF))) {\n    FpuSetSt0(m, StRm(m, rde));\n  }\n}\n\nstatic void OpFcmovnu(struct Machine *m, u64 rde) {\n  if (!GetFlag(m->flags, FLAGS_PF)) {\n    FpuSetSt0(m, StRm(m, rde));\n  }\n}\n\nstatic void OpFchs(struct Machine *m) {\n  FpuSetSt0(m, -St0(m));\n}\n\nstatic void OpFabs(struct Machine *m) {\n  FpuSetSt0(m, fabs(St0(m)));\n}\n\nstatic void OpF2xm1(struct Machine *m) {\n  FpuSetSt0(m, f2xm1(St0(m)));\n}\n\nstatic void OpFyl2x(struct Machine *m) {\n  FpuSetStPop(m, 1, fyl2x(St0(m), St1(m)));\n}\n\nstatic void OpFyl2xp1(struct Machine *m) {\n  FpuSetStPop(m, 1, fyl2xp1(St0(m), St1(m)));\n}\n\nstatic void OpFcos(struct Machine *m) {\n  FpuClearOutOfRangeIndicator(m);\n  FpuSetSt0(m, cos(St0(m)));\n}\n\nstatic void OpFsin(struct Machine *m) {\n  FpuClearOutOfRangeIndicator(m);\n  FpuSetSt0(m, sin(St0(m)));\n}\n\nstatic void OpFptan(struct Machine *m) {\n  FpuClearOutOfRangeIndicator(m);\n  FpuSetSt0(m, tan(St0(m)));\n  FpuPush(m, 1);\n}\n\nstatic void OpFsincos(struct Machine *m) {\n  double tsin, tcos;\n  FpuClearOutOfRangeIndicator(m);\n  tsin = sin(St0(m));\n  tcos = cos(St0(m));\n  FpuSetSt0(m, tsin);\n  FpuPush(m, tcos);\n}\n\nstatic void OpFpatan(struct Machine *m) {\n  FpuClearRoundup(m);\n  FpuSetStPop(m, 1, atan2(St1(m), St0(m)));\n}\n\nstatic void OpFcom(struct Machine *m, u64 rde) {\n  FpuCompare(m, StRm(m, rde));\n}\n\nstatic void OpFcomp(struct Machine *m, u64 rde) {\n  FpuCompare(m, StRm(m, rde));\n  FpuPop(m);\n}\n\nstatic void OpFaddStEst(struct Machine *m, u64 rde) {\n  FpuSetSt0(m, FpuAdd(m, St0(m), StRm(m, rde)));\n}\n\nstatic void OpFmulStEst(struct Machine *m, u64 rde) {\n  FpuSetSt0(m, FpuMul(m, St0(m), StRm(m, rde)));\n}\n\nstatic void OpFsubStEst(struct Machine *m, u64 rde) {\n  FpuSetSt0(m, FpuSub(m, St0(m), StRm(m, rde)));\n}\n\nstatic void OpFsubrStEst(struct Machine *m, u64 rde) {\n  FpuSetSt0(m, FpuSub(m, StRm(m, rde), St0(m)));\n}\n\nstatic void OpFdivStEst(struct Machine *m, u64 rde) {\n  FpuSetSt0(m, FpuDiv(m, St0(m), StRm(m, rde)));\n}\n\nstatic void OpFdivrStEst(struct Machine *m, u64 rde) {\n  FpuSetSt0(m, FpuDiv(m, StRm(m, rde), St0(m)));\n}\n\nstatic void OpFaddEstSt(struct Machine *m, u64 rde) {\n  FpuSetStRm(m, rde, FpuAdd(m, StRm(m, rde), St0(m)));\n}\n\nstatic void OpFmulEstSt(struct Machine *m, u64 rde) {\n  FpuSetStRm(m, rde, FpuMul(m, StRm(m, rde), St0(m)));\n}\n\nstatic void OpFsubEstSt(struct Machine *m, u64 rde) {\n  FpuSetStRm(m, rde, FpuSub(m, St0(m), StRm(m, rde)));\n}\n\nstatic void OpFsubrEstSt(struct Machine *m, u64 rde) {\n  FpuSetStRm(m, rde, FpuSub(m, StRm(m, rde), St0(m)));\n}\n\nstatic void OpFdivEstSt(struct Machine *m, u64 rde) {\n  FpuSetStRm(m, rde, FpuDiv(m, StRm(m, rde), St0(m)));\n}\n\nstatic void OpFdivrEstSt(struct Machine *m, u64 rde) {\n  FpuSetStRm(m, rde, FpuDiv(m, St0(m), StRm(m, rde)));\n}\n\nstatic void OpFaddp(struct Machine *m, u64 rde) {\n  FpuSetStRmPop(m, rde, FpuAdd(m, St0(m), StRm(m, rde)));\n}\n\nstatic void OpFmulp(struct Machine *m, u64 rde) {\n  FpuSetStRmPop(m, rde, FpuMul(m, St0(m), StRm(m, rde)));\n}\n\nstatic void OpFcompp(struct Machine *m, u64 rde) {\n  OpFcomp(m, rde);\n  FpuPop(m);\n}\n\nstatic void OpFsubp(struct Machine *m, u64 rde) {\n  FpuSetStRmPop(m, rde, FpuSub(m, St0(m), StRm(m, rde)));\n}\n\nstatic void OpFsubrp(struct Machine *m, u64 rde) {\n  FpuSetStPop(m, 1, FpuSub(m, StRm(m, rde), St0(m)));\n}\n\nstatic void OpFdivp(struct Machine *m, u64 rde) {\n  FpuSetStRmPop(m, rde, FpuDiv(m, St0(m), StRm(m, rde)));\n}\n\nstatic void OpFdivrp(struct Machine *m, u64 rde) {\n  FpuSetStRmPop(m, rde, FpuDiv(m, StRm(m, rde), St0(m)));\n}\n\nstatic void OpFadds(struct Machine *m, u64 rde) {\n  FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryFloat(m)));\n}\n\nstatic void OpFmuls(struct Machine *m, u64 rde) {\n  FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryFloat(m)));\n}\n\nstatic void OpFcoms(struct Machine *m) {\n  FpuCompare(m, FpuGetMemoryFloat(m));\n}\n\nstatic void OpFcomps(struct Machine *m) {\n  OpFcoms(m);\n  FpuPop(m);\n}\n\nstatic void OpFsubs(struct Machine *m) {\n  FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryFloat(m)));\n}\n\nstatic void OpFsubrs(struct Machine *m) {\n  FpuSetSt0(m, FpuSub(m, FpuGetMemoryFloat(m), St0(m)));\n}\n\nstatic void OpFdivs(struct Machine *m) {\n  FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryFloat(m)));\n}\n\nstatic void OpFdivrs(struct Machine *m) {\n  FpuSetSt0(m, FpuDiv(m, FpuGetMemoryFloat(m), St0(m)));\n}\n\nstatic void OpFaddl(struct Machine *m) {\n  FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryDouble(m)));\n}\n\nstatic void OpFmull(struct Machine *m) {\n  FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryDouble(m)));\n}\n\nstatic void OpFcoml(struct Machine *m) {\n  FpuCompare(m, FpuGetMemoryDouble(m));\n}\n\nstatic void OpFcompl(struct Machine *m) {\n  FpuCompare(m, FpuGetMemoryDouble(m));\n  FpuPop(m);\n}\n\nstatic void OpFsubl(struct Machine *m) {\n  FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryDouble(m)));\n}\n\nstatic void OpFsubrl(struct Machine *m) {\n  FpuSetSt0(m, FpuSub(m, FpuGetMemoryDouble(m), St0(m)));\n}\n\nstatic void OpFdivl(struct Machine *m) {\n  FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryDouble(m)));\n}\n\nstatic void OpFdivrl(struct Machine *m) {\n  FpuSetSt0(m, FpuDiv(m, FpuGetMemoryDouble(m), St0(m)));\n}\n\nstatic void OpFiaddl(struct Machine *m) {\n  FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryInt(m)));\n}\n\nstatic void OpFimull(struct Machine *m) {\n  FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryInt(m)));\n}\n\nstatic void OpFicoml(struct Machine *m) {\n  FpuCompare(m, FpuGetMemoryInt(m));\n}\n\nstatic void OpFicompl(struct Machine *m) {\n  OpFicoml(m);\n  FpuPop(m);\n}\n\nstatic void OpFisubl(struct Machine *m) {\n  FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryInt(m)));\n}\n\nstatic void OpFisubrl(struct Machine *m) {\n  FpuSetSt0(m, FpuSub(m, FpuGetMemoryInt(m), St0(m)));\n}\n\nstatic void OpFidivl(struct Machine *m) {\n  FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryInt(m)));\n}\n\nstatic void OpFidivrl(struct Machine *m) {\n  FpuSetSt0(m, FpuDiv(m, FpuGetMemoryInt(m), St0(m)));\n}\n\nstatic void OpFiadds(struct Machine *m) {\n  FpuSetSt0(m, FpuAdd(m, St0(m), FpuGetMemoryShort(m)));\n}\n\nstatic void OpFimuls(struct Machine *m) {\n  FpuSetSt0(m, FpuMul(m, St0(m), FpuGetMemoryShort(m)));\n}\n\nstatic void OpFicoms(struct Machine *m) {\n  FpuCompare(m, FpuGetMemoryShort(m));\n}\n\nstatic void OpFicomps(struct Machine *m) {\n  OpFicoms(m);\n  FpuPop(m);\n}\n\nstatic void OpFisubs(struct Machine *m) {\n  FpuSetSt0(m, FpuSub(m, St0(m), FpuGetMemoryShort(m)));\n}\n\nstatic void OpFisubrs(struct Machine *m) {\n  FpuSetSt0(m, FpuSub(m, FpuGetMemoryShort(m), St0(m)));\n}\n\nstatic void OpFidivs(struct Machine *m) {\n  FpuSetSt0(m, FpuDiv(m, St0(m), FpuGetMemoryShort(m)));\n}\n\nstatic void OpFidivrs(struct Machine *m) {\n  FpuSetSt0(m, FpuDiv(m, FpuGetMemoryShort(m), St0(m)));\n}\n\nstatic void OpFsqrt(struct Machine *m) {\n  FpuClearRoundup(m);\n  FpuSetSt0(m, sqrt(St0(m)));\n}\n\nstatic void OpFrndint(struct Machine *m) {\n  FpuSetSt0(m, FpuRound(m, St0(m)));\n}\n\nstatic void OpFscale(struct Machine *m) {\n  FpuClearRoundup(m);\n  FpuSetSt0(m, fscale(St0(m), St1(m)));\n}\n\nstatic void OpFprem(struct Machine *m) {\n  FpuSetSt0(m, fprem(St0(m), St1(m), &m->fpu.sw));\n}\n\nstatic void OpFprem1(struct Machine *m) {\n  FpuSetSt0(m, fprem1(St0(m), St1(m), &m->fpu.sw));\n}\n\nstatic void OpFdecstp(struct Machine *m) {\n  m->fpu.sw = (m->fpu.sw & ~kFpuSwSp) | ((m->fpu.sw - (1 << 11)) & kFpuSwSp);\n}\n\nstatic void OpFincstp(struct Machine *m) {\n  m->fpu.sw = (m->fpu.sw & ~kFpuSwSp) | ((m->fpu.sw + (1 << 11)) & kFpuSwSp);\n}\n\nstatic void OpFxtract(struct Machine *m) {\n  double x = St0(m);\n  FpuSetSt0(m, logb(x));\n  FpuPush(m, ldexp(x, -ilogb(x)));\n}\n\nstatic void OpFld(struct Machine *m, u64 rde) {\n  FpuPush(m, StRm(m, rde));\n}\n\nstatic void OpFlds(struct Machine *m) {\n  FpuPush(m, FpuGetMemoryFloat(m));\n}\n\nstatic void OpFsts(struct Machine *m) {\n  FpuSetMemoryFloat(m, St0(m));\n}\n\nstatic void OpFstps(struct Machine *m) {\n  OpFsts(m);\n  FpuPop(m);\n}\n\nstatic void OpFstpt(struct Machine *m) {\n  FpuSetMemoryLdbl(m, FpuPop(m));\n}\n\nstatic void OpFstl(struct Machine *m) {\n  FpuSetMemoryDouble(m, St0(m));\n}\n\nstatic void OpFstpl(struct Machine *m) {\n  OpFstl(m);\n  FpuPop(m);\n}\n\nstatic void OpFst(struct Machine *m, u64 rde) {\n  FpuSetStRm(m, rde, St0(m));\n}\n\nstatic void OpFstp(struct Machine *m, u64 rde) {\n  FpuSetStRmPop(m, rde, St0(m));\n}\n\nstatic void OpFxch(struct Machine *m, u64 rde) {\n  double t = StRm(m, rde);\n  FpuSetStRm(m, rde, St0(m));\n  FpuSetSt0(m, t);\n}\n\nstatic void OpFldt(struct Machine *m) {\n  FpuPush(m, FpuGetMemoryLdbl(m));\n}\n\nstatic void OpFldl(struct Machine *m) {\n  FpuPush(m, FpuGetMemoryDouble(m));\n}\n\nstatic double Fld1(void) {\n  return 1;\n}\n\nstatic double Fldl2t(void) {\n  return 0xd.49a784bcd1b8afep-2L; /* log₂10 */\n}\n\nstatic double Fldl2e(void) {\n  return 0xb.8aa3b295c17f0bcp-3L; /* log₂𝑒 */\n}\n\nstatic double Fldpi(void) {\n  return 0x1.921fb54442d1846ap+1L; /* π */\n}\n\nstatic double Fldlg2(void) {\n  return 0x9.a209a84fbcff799p-5L; /* log₁₀2 */\n}\n\nstatic double Fldln2(void) {\n  return 0xb.17217f7d1cf79acp-4L; /* logₑ2 */\n}\n\nstatic double Fldz(void) {\n  return 0;\n}\n\nstatic void OpFldConstant(struct Machine *m, u64 rde) {\n  double x;\n  switch (ModrmRm(rde)) {\n    CASE(0, x = Fld1());\n    CASE(1, x = Fldl2t());\n    CASE(2, x = Fldl2e());\n    CASE(3, x = Fldpi());\n    CASE(4, x = Fldlg2());\n    CASE(5, x = Fldln2());\n    CASE(6, x = Fldz());\n    default:\n      OpUdImpl(m);\n  }\n  FpuPush(m, x);\n}\n\nstatic void OpFilds(struct Machine *m) {\n  FpuPush(m, FpuGetMemoryShort(m));\n}\n\nstatic void OpFildl(struct Machine *m) {\n  FpuPush(m, FpuGetMemoryInt(m));\n}\n\nstatic void OpFildll(struct Machine *m) {\n  FpuPush(m, FpuGetMemoryLong(m));\n}\n\nstatic void OpFisttpl(struct Machine *m) {\n  FpuSetMemoryInt(m, FpuPop(m));\n}\n\nstatic void OpFisttpll(struct Machine *m) {\n  FpuSetMemoryLong(m, FpuPop(m));\n}\n\nstatic void OpFisttps(struct Machine *m) {\n  FpuSetMemoryShort(m, FpuPop(m));\n}\n\nstatic void OpFists(struct Machine *m) {\n  FpuSetMemoryShort(m, FpuRound(m, St0(m)));\n}\n\nstatic void OpFistl(struct Machine *m) {\n  FpuSetMemoryInt(m, FpuRound(m, St0(m)));\n}\n\nstatic void OpFistll(struct Machine *m) {\n  FpuSetMemoryLong(m, FpuRound(m, St0(m)));\n}\n\nstatic void OpFistpl(struct Machine *m) {\n  OpFistl(m);\n  FpuPop(m);\n}\n\nstatic void OpFistpll(struct Machine *m) {\n  OpFistll(m);\n  FpuPop(m);\n}\n\nstatic void OpFistps(struct Machine *m) {\n  OpFists(m);\n  FpuPop(m);\n}\n\nstatic void OpFcomi(struct Machine *m, u64 rde) {\n  double x, y;\n  x = St0(m);\n  y = StRm(m, rde);\n  if (!isunordered(x, y)) {\n    m->flags = SetFlag(m->flags, FLAGS_ZF, x == y);\n    m->flags = SetFlag(m->flags, FLAGS_CF, x < y);\n    m->flags = SetFlag(m->flags, FLAGS_PF, false);\n  } else {\n    m->fpu.sw |= kFpuSwIe;\n    m->flags = SetFlag(m->flags, FLAGS_ZF, true);\n    m->flags = SetFlag(m->flags, FLAGS_CF, true);\n    m->flags = SetFlag(m->flags, FLAGS_PF, true);\n  }\n}\n\nstatic void OpFucom(struct Machine *m, u64 rde) {\n  FpuCompare(m, StRm(m, rde));\n}\n\nstatic void OpFucomp(struct Machine *m, u64 rde) {\n  FpuCompare(m, StRm(m, rde));\n  FpuPop(m);\n}\n\nstatic void OpFcomip(struct Machine *m, u64 rde) {\n  OpFcomi(m, rde);\n  FpuPop(m);\n}\n\nstatic void OpFucomi(struct Machine *m, u64 rde) {\n  OpFcomi(m, rde);\n}\n\nstatic void OpFucomip(struct Machine *m, u64 rde) {\n  OpFcomip(m, rde);\n}\n\nstatic void OpFfree(struct Machine *m, u64 rde) {\n  FpuSetTag(m, ModrmRm(rde), kFpuTagEmpty);\n}\n\nstatic void OpFfreep(struct Machine *m, u64 rde) {\n  if (ModrmRm(rde)) OpFfree(m, rde);\n  FpuPop(m);\n}\n\nstatic void OpFstswMw(struct Machine *m) {\n  FpuSetMemoryShort(m, m->fpu.sw);\n}\n\nstatic void OpFstswAx(struct Machine *m) {\n  Write16(m->ax, m->fpu.sw);\n}\n\nstatic void SetFpuEnv(struct Machine *m, u8 p[28]) {\n  Write16(p + 0, m->fpu.cw);\n  Write16(p + 4, m->fpu.sw);\n  Write16(p + 8, m->fpu.tw);\n  Write64(p + 12, m->fpu.ip);\n  Write16(p + 18, m->fpu.op);\n  Write64(p + 20, m->fpu.dp);\n}\n\nstatic void GetFpuEnv(struct Machine *m, u8 p[28]) {\n  m->fpu.cw = Read16(p + 0);\n  m->fpu.sw = Read16(p + 4);\n  m->fpu.tw = Read16(p + 8);\n}\n\nstatic void OpFstenv(struct Machine *m) {\n  void *p[2];\n  u8 b[28];\n  SetFpuEnv(m, BeginStore(m, m->fpu.dp, sizeof(b), p, b));\n  EndStore(m, m->fpu.dp, sizeof(b), p, b);\n}\n\nstatic void OpFldenv(struct Machine *m) {\n  u8 b[28];\n  GetFpuEnv(m, Load(m, m->fpu.dp, sizeof(b), b));\n}\n\nstatic void OpFsave(struct Machine *m) {\n  int i;\n  void *p[2];\n  u8 *a, b[108], t[16];\n  a = BeginStore(m, m->fpu.dp, sizeof(b), p, b);\n  SetFpuEnv(m, a);\n  memset(t, 0, sizeof(t));\n  for (i = 0; i < 8; ++i) {\n    SerializeLdbl(a + 28 + i * 10, *FpuSt(m, i));\n  }\n  EndStore(m, m->fpu.dp, sizeof(b), p, b);\n  OpFinit(m);\n}\n\nstatic void OpFrstor(struct Machine *m) {\n  int i;\n  u8 *a, b[108];\n  a = Load(m, m->fpu.dp, sizeof(b), b);\n  GetFpuEnv(m, a);\n  for (i = 0; i < 8; ++i) {\n    *FpuSt(m, i) = DeserializeLdbl(a + 28 + i * 10);\n  }\n}\n\nstatic void OpFnclex(struct Machine *m) {\n  m->fpu.sw &= ~(kFpuSwIe | kFpuSwDe | kFpuSwZe | kFpuSwOe | kFpuSwUe |\n                 kFpuSwPe | kFpuSwEs | kFpuSwSf | kFpuSwBf);\n}\n\nstatic void OpFnop(struct Machine *m) {\n  /* do nothing */\n}\n\nvoid OpFinit(struct Machine *m) {\n  m->fpu.cw = 0x037f;\n  m->fpu.sw = 0;\n  m->fpu.tw = -1;\n}\n\nvoid OpFwait(P) {\n  int sw, cw;\n  sw = m->fpu.sw;\n  cw = m->fpu.cw;\n  if (((sw & kFpuSwIe) && !(cw & kFpuCwIm)) ||\n      ((sw & kFpuSwDe) && !(cw & kFpuCwDm)) ||\n      ((sw & kFpuSwZe) && !(cw & kFpuCwZm)) ||\n      ((sw & kFpuSwOe) && !(cw & kFpuCwOm)) ||\n      ((sw & kFpuSwUe) && !(cw & kFpuCwUm)) ||\n      ((sw & kFpuSwPe) && !(cw & kFpuCwPm)) ||\n      ((sw & kFpuSwSf) && !(cw & kFpuCwIm))) {\n    HaltMachine(m, kMachineFpuException);\n  }\n}\n\nint FpuGetTag(struct Machine *m, unsigned i) {\n  unsigned t;\n  t = m->fpu.tw;\n  i += (m->fpu.sw & kFpuSwSp) >> 11;\n  i &= 7;\n  i *= 2;\n  t &= 3 << i;\n  t >>= i;\n  return t;\n}\n\nvoid FpuSetTag(struct Machine *m, unsigned i, unsigned t) {\n  i += (m->fpu.sw & kFpuSwSp) >> 11;\n  t &= 3;\n  i &= 7;\n  i *= 2;\n  m->fpu.tw &= ~(3 << i);\n  m->fpu.tw |= t << i;\n}\n\nvoid FpuPush(struct Machine *m, double x) {\n  if (FpuGetTag(m, -1) != kFpuTagEmpty) OnFpuStackOverflow(m);\n  m->fpu.sw = (m->fpu.sw & ~kFpuSwSp) | ((m->fpu.sw - (1 << 11)) & kFpuSwSp);\n  *FpuSt(m, 0) = x;\n  FpuSetTag(m, 0, kFpuTagValid);\n}\n\ndouble FpuPop(struct Machine *m) {\n  double x;\n  if (FpuGetTag(m, 0) != kFpuTagEmpty) {\n    x = *FpuSt(m, 0);\n    FpuSetTag(m, 0, kFpuTagEmpty);\n  } else {\n    x = OnFpuStackUnderflow(m);\n  }\n  m->fpu.sw = (m->fpu.sw & ~kFpuSwSp) | ((m->fpu.sw + (1 << 11)) & kFpuSwSp);\n  return x;\n}\n\nvoid OpFpu(P) {\n  unsigned op;\n  bool ismemory;\n  op = Opcode(rde) & 7;\n  ismemory = ModrmMod(rde) != 3;\n  m->fpu.ip = MaskAddress(m->mode.omode, m->ip - Oplength(rde));\n  m->fpu.op = op << 8 | ModrmMod(rde) << 6 | ModrmReg(rde) << 3 | ModrmRm(rde);\n  m->fpu.dp = ismemory ? ComputeAddress(A) : 0;\n  switch (DISP(op, ismemory, ModrmReg(rde))) {\n    CASE(DISP(0xD8, FPUREG, 0), OpFaddStEst(m, rde));\n    CASE(DISP(0xD8, FPUREG, 1), OpFmulStEst(m, rde));\n    CASE(DISP(0xD8, FPUREG, 2), OpFcom(m, rde));\n    CASE(DISP(0xD8, FPUREG, 3), OpFcomp(m, rde));\n    CASE(DISP(0xD8, FPUREG, 4), OpFsubStEst(m, rde));\n    CASE(DISP(0xD8, FPUREG, 5), OpFsubrStEst(m, rde));\n    CASE(DISP(0xD8, FPUREG, 6), OpFdivStEst(m, rde));\n    CASE(DISP(0xD8, FPUREG, 7), OpFdivrStEst(m, rde));\n    CASE(DISP(0xD8, MEMORY, 0), OpFadds(m, rde));\n    CASE(DISP(0xD8, MEMORY, 1), OpFmuls(m, rde));\n    CASE(DISP(0xD8, MEMORY, 2), OpFcoms(m));\n    CASE(DISP(0xD8, MEMORY, 3), OpFcomps(m));\n    CASE(DISP(0xD8, MEMORY, 4), OpFsubs(m));\n    CASE(DISP(0xD8, MEMORY, 5), OpFsubrs(m));\n    CASE(DISP(0xD8, MEMORY, 6), OpFdivs(m));\n    CASE(DISP(0xD8, MEMORY, 7), OpFdivrs(m));\n    CASE(DISP(0xD9, FPUREG, 0), OpFld(m, rde));\n    CASE(DISP(0xD9, FPUREG, 1), OpFxch(m, rde));\n    CASE(DISP(0xD9, FPUREG, 2), OpFnop(m));\n    CASE(DISP(0xD9, FPUREG, 3), OpFstp(m, rde));\n    CASE(DISP(0xD9, FPUREG, 5), OpFldConstant(m, rde));\n    CASE(DISP(0xD9, MEMORY, 0), OpFlds(m));\n    CASE(DISP(0xD9, MEMORY, 2), OpFsts(m));\n    CASE(DISP(0xD9, MEMORY, 3), OpFstps(m));\n    CASE(DISP(0xD9, MEMORY, 4), OpFldenv(m));\n    CASE(DISP(0xD9, MEMORY, 5), OpFldcw(m));\n    CASE(DISP(0xD9, MEMORY, 6), OpFstenv(m));\n    CASE(DISP(0xD9, MEMORY, 7), OpFstcw(m));\n    CASE(DISP(0xDA, FPUREG, 0), OpFcmovb(m, rde));\n    CASE(DISP(0xDA, FPUREG, 1), OpFcmove(m, rde));\n    CASE(DISP(0xDA, FPUREG, 2), OpFcmovbe(m, rde));\n    CASE(DISP(0xDA, FPUREG, 3), OpFcmovu(m, rde));\n    CASE(DISP(0xDA, MEMORY, 0), OpFiaddl(m));\n    CASE(DISP(0xDA, MEMORY, 1), OpFimull(m));\n    CASE(DISP(0xDA, MEMORY, 2), OpFicoml(m));\n    CASE(DISP(0xDA, MEMORY, 3), OpFicompl(m));\n    CASE(DISP(0xDA, MEMORY, 4), OpFisubl(m));\n    CASE(DISP(0xDA, MEMORY, 5), OpFisubrl(m));\n    CASE(DISP(0xDA, MEMORY, 6), OpFidivl(m));\n    CASE(DISP(0xDA, MEMORY, 7), OpFidivrl(m));\n    CASE(DISP(0xDB, FPUREG, 0), OpFcmovnb(m, rde));\n    CASE(DISP(0xDB, FPUREG, 1), OpFcmovne(m, rde));\n    CASE(DISP(0xDB, FPUREG, 2), OpFcmovnbe(m, rde));\n    CASE(DISP(0xDB, FPUREG, 3), OpFcmovnu(m, rde));\n    CASE(DISP(0xDB, FPUREG, 5), OpFucomi(m, rde));\n    CASE(DISP(0xDB, FPUREG, 6), OpFcomi(m, rde));\n    CASE(DISP(0xDB, MEMORY, 0), OpFildl(m));\n    CASE(DISP(0xDB, MEMORY, 1), OpFisttpl(m));\n    CASE(DISP(0xDB, MEMORY, 2), OpFistl(m));\n    CASE(DISP(0xDB, MEMORY, 3), OpFistpl(m));\n    CASE(DISP(0xDB, MEMORY, 5), OpFldt(m));\n    CASE(DISP(0xDB, MEMORY, 7), OpFstpt(m));\n    CASE(DISP(0xDC, FPUREG, 0), OpFaddEstSt(m, rde));\n    CASE(DISP(0xDC, FPUREG, 1), OpFmulEstSt(m, rde));\n    CASE(DISP(0xDC, FPUREG, 2), OpFcom(m, rde));\n    CASE(DISP(0xDC, FPUREG, 3), OpFcomp(m, rde));\n    CASE(DISP(0xDC, FPUREG, 4), OpFsubEstSt(m, rde));\n    CASE(DISP(0xDC, FPUREG, 5), OpFsubrEstSt(m, rde));\n    CASE(DISP(0xDC, FPUREG, 6), OpFdivEstSt(m, rde));\n    CASE(DISP(0xDC, FPUREG, 7), OpFdivrEstSt(m, rde));\n    CASE(DISP(0xDC, MEMORY, 0), OpFaddl(m));\n    CASE(DISP(0xDC, MEMORY, 1), OpFmull(m));\n    CASE(DISP(0xDC, MEMORY, 2), OpFcoml(m));\n    CASE(DISP(0xDC, MEMORY, 3), OpFcompl(m));\n    CASE(DISP(0xDC, MEMORY, 4), OpFsubl(m));\n    CASE(DISP(0xDC, MEMORY, 5), OpFsubrl(m));\n    CASE(DISP(0xDC, MEMORY, 6), OpFdivl(m));\n    CASE(DISP(0xDC, MEMORY, 7), OpFdivrl(m));\n    CASE(DISP(0xDD, FPUREG, 0), OpFfree(m, rde));\n    CASE(DISP(0xDD, FPUREG, 1), OpFxch(m, rde));\n    CASE(DISP(0xDD, FPUREG, 2), OpFst(m, rde));\n    CASE(DISP(0xDD, FPUREG, 3), OpFstp(m, rde));\n    CASE(DISP(0xDD, FPUREG, 4), OpFucom(m, rde));\n    CASE(DISP(0xDD, FPUREG, 5), OpFucomp(m, rde));\n    CASE(DISP(0xDD, MEMORY, 0), OpFldl(m));\n    CASE(DISP(0xDD, MEMORY, 1), OpFisttpll(m));\n    CASE(DISP(0xDD, MEMORY, 2), OpFstl(m));\n    CASE(DISP(0xDD, MEMORY, 3), OpFstpl(m));\n    CASE(DISP(0xDD, MEMORY, 4), OpFrstor(m));\n    CASE(DISP(0xDD, MEMORY, 6), OpFsave(m));\n    CASE(DISP(0xDD, MEMORY, 7), OpFstswMw(m));\n    CASE(DISP(0xDE, FPUREG, 0), OpFaddp(m, rde));\n    CASE(DISP(0xDE, FPUREG, 1), OpFmulp(m, rde));\n    CASE(DISP(0xDE, FPUREG, 2), OpFcomp(m, rde));\n    CASE(DISP(0xDE, FPUREG, 3), OpFcompp(m, rde));\n    CASE(DISP(0xDE, FPUREG, 4), OpFsubp(m, rde));\n    CASE(DISP(0xDE, FPUREG, 5), OpFsubrp(m, rde));\n    CASE(DISP(0xDE, FPUREG, 6), OpFdivp(m, rde));\n    CASE(DISP(0xDE, FPUREG, 7), OpFdivrp(m, rde));\n    CASE(DISP(0xDE, MEMORY, 0), OpFiadds(m));\n    CASE(DISP(0xDE, MEMORY, 1), OpFimuls(m));\n    CASE(DISP(0xDE, MEMORY, 2), OpFicoms(m));\n    CASE(DISP(0xDE, MEMORY, 3), OpFicomps(m));\n    CASE(DISP(0xDE, MEMORY, 4), OpFisubs(m));\n    CASE(DISP(0xDE, MEMORY, 5), OpFisubrs(m));\n    CASE(DISP(0xDE, MEMORY, 6), OpFidivs(m));\n    CASE(DISP(0xDE, MEMORY, 7), OpFidivrs(m));\n    CASE(DISP(0xDF, FPUREG, 0), OpFfreep(m, rde));\n    CASE(DISP(0xDF, FPUREG, 1), OpFxch(m, rde));\n    CASE(DISP(0xDF, FPUREG, 2), OpFstp(m, rde));\n    CASE(DISP(0xDF, FPUREG, 3), OpFstp(m, rde));\n    CASE(DISP(0xDF, FPUREG, 4), OpFstswAx(m));\n    CASE(DISP(0xDF, FPUREG, 5), OpFucomip(m, rde));\n    CASE(DISP(0xDF, FPUREG, 6), OpFcomip(m, rde));\n    CASE(DISP(0xDF, MEMORY, 0), OpFilds(m));\n    CASE(DISP(0xDF, MEMORY, 1), OpFisttps(m));\n    CASE(DISP(0xDF, MEMORY, 2), OpFists(m));\n    CASE(DISP(0xDF, MEMORY, 3), OpFistps(m));\n    CASE(DISP(0xDF, MEMORY, 5), OpFildll(m));\n    CASE(DISP(0xDF, MEMORY, 7), OpFistpll(m));\n    case DISP(0xD9, FPUREG, 4):\n      switch (ModrmRm(rde)) {\n        CASE(0, OpFchs(m));\n        CASE(1, OpFabs(m));\n        CASE(4, OpFtst(m));\n        CASE(5, OpFxam(m));\n        default:\n          OpUdImpl(m);\n      }\n      break;\n    case DISP(0xD9, FPUREG, 6):\n      switch (ModrmRm(rde)) {\n        CASE(0, OpF2xm1(m));\n        CASE(1, OpFyl2x(m));\n        CASE(2, OpFptan(m));\n        CASE(3, OpFpatan(m));\n        CASE(4, OpFxtract(m));\n        CASE(5, OpFprem1(m));\n        CASE(6, OpFdecstp(m));\n        CASE(7, OpFincstp(m));\n        default:\n          __builtin_unreachable();\n      }\n      break;\n    case DISP(0xD9, FPUREG, 7):\n      switch (ModrmRm(rde)) {\n        CASE(0, OpFprem(m));\n        CASE(1, OpFyl2xp1(m));\n        CASE(2, OpFsqrt(m));\n        CASE(3, OpFsincos(m));\n        CASE(4, OpFrndint(m));\n        CASE(5, OpFscale(m));\n        CASE(6, OpFsin(m));\n        CASE(7, OpFcos(m));\n        default:\n          __builtin_unreachable();\n      }\n      break;\n    case DISP(0xDb, FPUREG, 4):\n      switch (ModrmRm(rde)) {\n        CASE(2, OpFnclex(m));\n        CASE(3, OpFinit(m));\n        default:\n          OpUdImpl(m);\n      }\n      break;\n    default:\n      OpUdImpl(m);\n  }\n}\n\n#else /* DISABLE_X87 */\n\nvoid(OpFpu)(P) {\n  unsigned op;\n  bool ismemory;\n  op = Opcode(rde) & 7;\n  ismemory = ModrmMod(rde) != 3;\n  m->fpu.dp = ismemory ? ComputeAddress(A) : 0;\n  switch (DISP(op, ismemory, ModrmReg(rde))) {\n    CASE(DISP(0xD9, MEMORY, 5), OpFldcw(m));\n    CASE(DISP(0xD9, MEMORY, 7), OpFstcw(m));\n    default:\n      OpUdImpl(m);\n  }\n}\n\n#endif /* DISABLE_X87 */\n"
  },
  {
    "path": "blink/fpu.h",
    "content": "#ifndef BLINK_FPU_H_\n#define BLINK_FPU_H_\n#include \"blink/machine.h\"\n\n#define kFpuTagValid   0\n#define kFpuTagZero    1\n#define kFpuTagSpecial 2\n#define kFpuTagEmpty   3\n\n#define kFpuCwIm 0x0001 /* invalid operation mask */\n#define kFpuCwDm 0x0002 /* denormal operand mask */\n#define kFpuCwZm 0x0004 /* zero divide mask */\n#define kFpuCwOm 0x0008 /* overflow mask */\n#define kFpuCwUm 0x0010 /* underflow mask */\n#define kFpuCwPm 0x0020 /* precision mask */\n#define kFpuCwPc 0x0300 /* precision: 32,∅,64,80 */\n#define kFpuCwRc 0x0c00 /* rounding: even,→-∞,→+∞,→0 */\n\n#define kFpuSwIe 0x0001 /* invalid operation */\n#define kFpuSwDe 0x0002 /* denormalized operand */\n#define kFpuSwZe 0x0004 /* zero divide */\n#define kFpuSwOe 0x0008 /* overflow */\n#define kFpuSwUe 0x0010 /* underflow */\n#define kFpuSwPe 0x0020 /* precision */\n#define kFpuSwSf 0x0040 /* stack fault */\n#define kFpuSwEs 0x0080 /* exception summary status */\n#define kFpuSwC0 0x0100 /* condition 0 */\n#define kFpuSwC1 0x0200 /* condition 1 */\n#define kFpuSwC2 0x0400 /* condition 2 */\n#define kFpuSwSp 0x3800 /* top stack */\n#define kFpuSwC3 0x4000 /* condition 3 */\n#define kFpuSwBf 0x8000 /* busy flag */\n\n#define kMxcsrIe  0x0001 /* invalid operation flag */\n#define kMxcsrDe  0x0002 /* denormal flag */\n#define kMxcsrZe  0x0004 /* divide by zero flag */\n#define kMxcsrOe  0x0008 /* overflow flag */\n#define kMxcsrUe  0x0010 /* underflow flag */\n#define kMxcsrPe  0x0020 /* precision flag */\n#define kMxcsrDaz 0x0040 /* denormals are zeros */\n#define kMxcsrIm  0x0080 /* invalid operation mask */\n#define kMxcsrDm  0x0100 /* denormal mask */\n#define kMxcsrZm  0x0200 /* divide by zero mask */\n#define kMxcsrOm  0x0400 /* overflow mask */\n#define kMxcsrUm  0x0800 /* underflow mask */\n#define kMxcsrPm  0x1000 /* precision mask */\n#define kMxcsrRc  0x6000 /* rounding control */\n#define kMxcsrFtz 0x8000 /* flush to zero */\n\n#define FpuSt(m, i) ((m)->fpu.st + (((i) + ((m->fpu.sw & kFpuSwSp) >> 11)) & 7))\n\ndouble FpuPop(struct Machine *);\nint FpuGetTag(struct Machine *, unsigned);\nvoid FpuPush(struct Machine *, double);\nvoid FpuSetTag(struct Machine *, unsigned, unsigned);\nvoid OpFinit(struct Machine *);\nvoid OpFpu(P);\nvoid OpFwait(P);\n\n#endif /* BLINK_FPU_H_ */\n"
  },
  {
    "path": "blink/fspath.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/fspath.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\nchar *JoinPath(const char *x, const char *y) {\n  char *z, *p;\n  size_t n, m;\n  if (!y || !*y) {\n    return x ? strdup(x) : 0;\n  }\n  if (!x || !*x || *y == '/' || (*x == '.' && !x[1])) {\n    return strdup(y);\n  }\n  n = strlen(x);\n  m = strlen(y);\n  if (!(z = (char *)malloc(n + 1 + m + 1))) return 0;\n  memcpy(z, x, n);\n  p = z + n;\n  if (x[n - 1] != '/') {\n    *p++ = '/';\n  }\n  memcpy(p, y, m + 1);\n  return z;\n}\n\nchar *ExpandUser(const char *path) {\n  const char *home;\n  if (path[0] == '~' && path[1] == '/' && (home = getenv(\"HOME\"))) {\n    return JoinPath(home, &path[2]);\n  } else {\n    return strdup(path);\n  }\n}\n"
  },
  {
    "path": "blink/fspath.h",
    "content": "#ifndef BLINK_FSPATH_H_\n#define BLINK_FSPATH_H_\n\nchar *JoinPath(const char *, const char *);\nchar *ExpandUser(const char *);\n\n#endif /* BLINK_FSPATH_H_ */\n"
  },
  {
    "path": "blink/fusion.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/debug.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/machine.h\"\n#include \"blink/rde.h\"\n#include \"blink/stats.h\"\n\n/**\n * @fileoverview Branch Micro-Op Fusion.\n */\n\nbool FuseBranchTest(P) {\n#ifdef HAVE_JIT\n  i64 bdisp;\n  u8 *p, jcc, jlen;\n  if (RegLog2(rde) < 2) {\n    LogCodOp(m, \"can't fuse test: byte/word fuse unimplemented\");\n    return false;\n  }\n  if (4096 - (m->ip & 4095) < 6) {\n    LogCodOp(m, \"can't fuse test: too close to the edge\");\n    return false;\n  }\n  if (RexrReg(rde) != RexbRm(rde)) {\n    LogCodOp(m, \"can't fuse test: different operands unimplemented\");\n    return false;\n  }\n  if (!(p = GetAddress(m, m->ip))) {\n    LogCodOp(m, \"can't fuse test: null address\");\n    return false;\n  }\n  if ((p[0] & 0xf0) == 0x70) {  // Jcc Jbs\n    jlen = 2;\n    jcc = p[0] & 0x0f;\n    bdisp = (i8)Read8(p + 1);\n  } else if (p[0] == 0x0f && (p[1] & 0xf0) == 0x80) {  // Jcc Jvds\n    jlen = 6;\n    jcc = p[1] & 0x0f;\n    bdisp = (i32)Read32(p + 2);\n  } else {\n    LogCodOp(m, \"can't fuse test: not followed by jump\");\n    return false;\n  }\n#ifndef __x86_64__\n  switch (jcc) {\n    case 0x04:  // jz\n      break;\n    case 0x05:  // jnz\n      break;\n    default:\n      LogCodOp(m, \"can't fuse test: unsupported jump operation\");\n      return false;\n  }\n#endif\n  if (GetNeededFlags(m, m->ip + jlen + bdisp, CF | ZF | SF | OF | AF | PF)) {\n    LogCodOp(m, \"can't fuse test: loop carries\");\n    return false;\n  }\n  if (GetNeededFlags(m, m->ip + jlen, CF | ZF | SF | OF | AF | PF)) {\n    LogCodOp(m, \"can't fuse test: loop exit carries\");\n    return false;\n  }\n#if LOG_CPU\n  LogCpu(m);\n#endif\n  FlushCod(m->path.jb);\n  WriteCod(\"/\\tfusing branch test+jcc\\n\");\n  BeginCod(m, m->ip);\n#if LOG_JIX\n  Jitter(A,\n         \"a1i\"  // arg1 = ip\n         \"c\"    // call function\n         \"q\",   // arg0 = machine\n         m->ip, FuseOp);\n#endif\n  Jitter(A,\n         \"a1i\"  // arg1 = skew + jlen\n         \"m\",   // call micro-op\n         m->path.skew + jlen, AdvanceIp);\n  m->path.skew = 0;\n#ifdef __x86_64__\n  Jitter(A, \"A\"    // res0 = GetReg(RexrReg)\n            \"q\");  // arg0 = machine\n  if (!Rexw(rde)) {\n    AlignJit(m->path.jb, 8, 4);\n  } else {\n    AlignJit(m->path.jb, 8, 3);\n    AppendJit(m->path.jb, (u8[]){0x48}, 1);  // rex.w\n  }\n  u8 code[] = {\n      0x85, 0300 | kJitRes0 << 3 | kJitRes0,  // test %eax,%eax\n      (u8)(0x70 | jcc), 5,                    // jz/jnz +5\n  };\n#elif defined(__aarch64__)\n  Jitter(A, \"A\"      // res0 = GetReg(RexrReg)\n            \"r0a1=\"  // arg1 = res0\n            \"q\");    // arg0 = machine\n  u32 code[] = {\n      // b4000042 cbz  x2, #8\n      // 34000042 cbz  w2, #8\n      // b5000042 cbnz x2, #8\n      // 35000042 cbnz w2, #8\n      Rexw(rde) << 31 | 0x30000000 | jcc << 24 | (8 / 4) << 5 | kJitArg1,\n  };\n#else\n#error \"architecture not implemented\"\n#endif\n  AppendJit(m->path.jb, code, sizeof(code));\n  Connect(A, m->ip + jlen, true);\n  Jitter(A,\n         \"a1i\"  // arg1 = disp\n         \"m\"    // call micro-op\n         \"q\",   // arg0 = machine\n         bdisp, AdvanceIp);\n  AlignJit(m->path.jb, 8, 0);\n  Connect(A, m->ip + jlen + bdisp, false);\n  FinishPath(m);\n  m->path.skip = 1;\n  STATISTIC(++fused_branches);\n  return true;\n#else\n  return false;\n#endif\n}\n\nbool FuseBranchCmp(P, bool imm) {\n#ifdef HAVE_JIT\n  i64 bdisp;\n  u8 *p, jcc, jlen;\n  if (RegLog2(rde) < 2) {\n    LogCodOp(m, \"can't fuse cmp: byte/word fuse unimplemented\");\n    return false;\n  }\n  if (4096 - (m->ip & 4095) < 6) {\n    LogCodOp(m, \"can't fuse cmp: too close to the edge\");\n    return false;\n  }\n  if (!(p = GetAddress(m, m->ip))) {\n    LogCodOp(m, \"can't fuse cmp: null address\");\n    return false;\n  }\n  if ((p[0] & 0xf0) == 0x70) {  // Jcc Jbs\n    jlen = 2;\n    jcc = p[0] & 0x0f;\n    bdisp = (i8)Read8(p + 1);\n  } else if (p[0] == 0x0f && (p[1] & 0xf0) == 0x80) {  // Jcc Jvds\n    jlen = 6;\n    jcc = p[1] & 0x0f;\n    bdisp = (i32)Read32(p + 2);\n  } else {\n    LogCodOp(m, \"can't fuse cmp: not followed by jump\");\n    return false;\n  }\n#ifndef __x86_64__\n  switch (jcc) {\n    case 0x0:  // jo\n      break;\n    case 0x1:  // jno\n      break;\n    case 0x2:  // jb\n      break;\n    case 0x3:  // jae\n      break;\n    case 0x4:  // je\n      break;\n    case 0x5:  // jne\n      break;\n    case 0x6:  // jbe\n      break;\n    case 0x7:  // ja\n      break;\n    case 0xC:  // jl\n      break;\n    case 0xD:  // jge\n      break;\n    case 0xE:  // jle\n      break;\n    case 0xF:  // jg\n      break;\n    default:\n      LogCodOp(m, \"can't fuse cmp: unsupported jump operation\");\n      return false;\n  }\n#endif\n  if (GetNeededFlags(m, m->ip + jlen + bdisp, CF | ZF | SF | OF | AF | PF)) {\n    LogCodOp(m, \"can't fuse cmp: loop carries\");\n    return false;\n  }\n  if (GetNeededFlags(m, m->ip + jlen, CF | ZF | SF | OF | AF | PF)) {\n    LogCodOp(m, \"can't fuse cmp: loop exit carries\");\n    return false;\n  }\n#if LOG_CPU\n  LogCpu(m);\n#endif\n  FlushCod(m->path.jb);\n  WriteCod(\"/\\tfusing branch cmp+jcc\\n\");\n  BeginCod(m, m->ip);\n#if LOG_JIX\n  Jitter(A,\n         \"a1i\"  // arg1 = ip\n         \"c\"    // call function\n         \"q\",   // arg0 = machine\n         m->ip, FuseOp);\n#endif\n  if (IsModrmRegister(rde)) {\n    Jitter(A,\n           \"a1i\"  // arg1 = skew + jlen\n           \"m\",   // call micro-op\n           m->path.skew + jlen, AdvanceIp);\n  } else {\n    Jitter(A,\n           \"a2i\"  // arg2 = delta\n           \"a1i\"  // arg1 = oplen\n           \"m\",   // call micro-op\n           m->path.skew + jlen, Oplength(rde) + jlen, SkewIp);\n  }\n  m->path.skew = 0;\n  if (imm) {\n    Jitter(A, \"s1i\", uimm0);\n  } else {\n    Jitter(A, \"A\"        // res0 = GetReg(RexrReg)\n              \"r0s1=\");  // sav1 = res0\n  }\n#ifdef __x86_64__\n  Jitter(A, \"B\"    // res0 = GetRegOrMem(RexbRm)\n            \"q\");  // arg0 = machine\n  AlignJit(m->path.jb, 8, 3);\n  u8 code[] = {\n      // cmp %r12,%rax\n      (u8)((Rexw(rde) ? kAmdRexw : 0) | (kJitSav1 > 7 ? kAmdRexr : 0)),\n      0x39,\n      0300 | (kJitSav1 & 7) << 3 | kJitRes0,\n      // jz/jnz +5\n      (u8)(0x70 | jcc),\n      5,\n  };\n#elif defined(__aarch64__)\n  Jitter(A, \"B\"      // res0 = GetRegOrMem(RexbRm)\n            \"r0a1=\"  // arg1 = res0\n            \"q\");    // arg0 = machine\n  // 54000000 b.eq #0 equal\n  // 54000001 b.ne #0 not equal\n  // 54000002 b.cs #0 carry set\n  // 54000003 b.cc #0 carry clear\n  // 54000004 b.mi #0 less than\n  // 54000005 b.pl #0 positive or zero\n  // 54000006 b.vs #0 signed overflow\n  // 54000007 b.vc #0 no signed overflow\n  // 54000008 b.hi #0 greater than (unsigned)\n  // 54000009 b.ls #0 less than or equal to (unsigned)\n  // 5400000a b.ge #0 greater than or equal to (signed)\n  // 5400000b b.lt #0 less than (signed)\n  // 5400000c b.gt #0 greater than (signed)\n  // 5400000d b.le #0 less than or equal to (signed)\n  switch (jcc) {\n    case 0x0:  // jo → b.vs\n      jcc = 0x6;\n      break;\n    case 0x1:  // jno → b.vc\n      jcc = 0x7;\n      break;\n    case 0x2:  // jb → b.cc\n      jcc = 0x3;\n      break;\n    case 0x3:  // jae → b.cs\n      jcc = 0x2;\n      break;\n    case 0x4:  // je → b.eq\n      jcc = 0x0;\n      break;\n    case 0x5:  // jne → b.ne\n      jcc = 0x1;\n      break;\n    case 0x6:  // jbe → b.ls\n      jcc = 0x9;\n      break;\n    case 0x7:  // ja → b.hi\n      jcc = 0x8;\n      break;\n    case 0xC:  // jl → b.lt\n      jcc = 0xB;\n      break;\n    case 0xD:  // jge → b.ge\n      jcc = 0xA;\n      break;\n    case 0xE:  // jle → b.le\n      jcc = 0xD;\n      break;\n    case 0xF:  // jg → b.gt\n      jcc = 0xC;\n      break;\n    default:\n      __builtin_unreachable();\n  }\n  u32 code[] = {\n      // 6b07007f cmp w3, w7\n      // eb07007f cmp x3, x7\n      Rexw(rde) << 31 | 0x6b00001f | kJitSav1 << 16 | kJitArg1 << 5,\n      // 54000000 b.xx\n      0x54000000 | (8 / 4) << 5 | jcc,\n  };\n#else\n#error \"architecture not implemented\"\n#endif\n  AppendJit(m->path.jb, code, sizeof(code));\n  Connect(A, m->ip + jlen, true);\n  Jitter(A,\n         \"a1i\"  // arg1 = disp\n         \"m\"    // call micro-op\n         \"q\",   // arg0 = machine\n         bdisp, AdvanceIp);\n  AlignJit(m->path.jb, 8, 0);\n  Connect(A, m->ip + jlen + bdisp, false);\n  FinishPath(m);\n  m->path.skip = 1;\n  STATISTIC(++fused_branches);\n  return true;\n#else\n  return false;\n#endif\n}\n"
  },
  {
    "path": "blink/getopt.c",
    "content": "/*\t$NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $\t*/\n/*\n * Copyright (c) 1987, 1993, 1994\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * @(#)getopt.c\t8.3 (Berkeley) 4/27/95\n * $FreeBSD: src/lib/libc/stdlib/getopt.c,v 1.8 2007/01/09 00:28:10 imp Exp $\n * $DragonFly: src/lib/libc/stdlib/getopt.c,v 1.7 2005/11/20 12:37:48 swildner\n */\n#include <string.h>\n#include <unistd.h>\n\n/**\n * @fileoverview Command Line Argument Parser\n *\n * We vendor this ancient NetBSD getopt() implementation because:\n *\n * 1. We want the non-GNU behavior where flags must come before the\n *    first argument. GNU systems permit flags to come after arguments,\n *    which isn't a great fit for commands like `blink` whose arguments\n *    are mostly just passed along to a sub-command.\n *\n * 2. We've modified it by hand to have a tiny transitive footprint. The\n *    `blink` command can't depend on beefy libc functions like printf()\n *    or even snprintf().\n */\n\n#define BADCH  '?'\n#define BADARG ':'\n\nint optind_;\nchar *optarg_;\n\nstatic char *getopt_place;\nstatic char getopt_emsg[1];\n\nstatic void getopt_print_badch(int argc, char *const argv[], int optopt,\n                               const char *s) {\n  long i = 0;\n  char b[256], *t;\n  if (argc > 0 && (t = argv[0])) {\n    while (*t && i < sizeof(b) - 64) b[i++] = *t++;\n    b[i++] = ':';\n    b[i++] = ' ';\n  }\n  while (*s) b[i++] = *s++;\n  b[i + 0] = ' ';\n  b[i + 1] = '-';\n  b[i + 2] = '-';\n  b[i + 3] = ' ';\n  b[i + 4] = optopt;\n  b[i + 5] = '\\n';\n  (void)!write(2, b, i + 6);\n}\n\n/**\n * Parses argc/argv argument vector, e.g.\n *\n *     while ((opt = getopt(argc, argv, \"hvx:\")) != -1) {\n *       switch (opt) {\n *         case 'x':\n *           x = atoi(optarg_);\n *           break;\n *         case 'v':\n *           ++verbose;\n *           break;\n *         case 'h':\n *           PrintUsage(EXIT_SUCCESS, stdout);\n *         default:\n *           PrintUsage(EX_USAGE, stderr);\n *       }\n *     }\n *\n * @see optind_\n * @see optarg_\n */\nint GetOpt(int nargc, char *const nargv[], const char *ostr) {\n  int optopt;\n  const char *oli; /* option letter list index */\n  if (!optind_) optind_ = 1;\n  if (!getopt_place) getopt_place = getopt_emsg;\n  if (!*getopt_place) { /* update scanning pointer */\n    getopt_place = nargv[optind_];\n    if (optind_ >= nargc || *getopt_place++ != '-') {\n      /* Argument is absent or is not an option */\n      getopt_place = getopt_emsg;\n      return -1;\n    }\n    optopt = *getopt_place++;\n    if (optopt == '-' && *getopt_place == 0) {\n      /* \"--\" => end of options */\n      ++optind_;\n      getopt_place = getopt_emsg;\n      return -1;\n    }\n    if (optopt == 0) {\n      /* Solitary '-', treat as a '-' option\n         if the program (eg su) is looking for it. */\n      getopt_place = getopt_emsg;\n      if (!strchr(ostr, '-')) return -1;\n      optopt = '-';\n    }\n  } else {\n    optopt = *getopt_place++;\n  }\n  /* See if option letter is one the caller wanted... */\n  if (optopt == ':' || !(oli = strchr(ostr, optopt))) {\n    if (*getopt_place == 0) ++optind_;\n    if (*ostr != ':')\n      getopt_print_badch(nargc, nargv, optopt, \"illegal option\");\n    return BADCH;\n  }\n  /* Does this option need an argument? */\n  if (oli[1] != ':') {\n    /* don't need argument */\n    optarg_ = 0;\n    if (*getopt_place == 0) ++optind_;\n  } else {\n    /* Option-argument is either the rest of this argument or the\n       entire next argument. */\n    if (*getopt_place) {\n      optarg_ = getopt_place;\n    } else if (nargc > ++optind_) {\n      optarg_ = nargv[optind_ & 0xffffffff];\n    } else {\n      /* option-argument absent */\n      getopt_place = getopt_emsg;\n      if (*ostr == ':') return BADARG;\n      getopt_print_badch(nargc, nargv, optopt, \"option requires an argument\");\n      return BADCH;\n    }\n    getopt_place = getopt_emsg;\n    ++optind_;\n  }\n  return optopt; /* return option letter */\n}\n"
  },
  {
    "path": "blink/hex.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <ctype.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n#include \"blink/debug.h\"\n#include \"blink/log.h\"\n#include \"blink/tsan.h\"\n\n#define APPEND(...) oi += snprintf(ob + oi, oi > on ? 0 : on - oi, __VA_ARGS__)\n\nvoid DumpHex(u8 *p, size_t n) {\n  int oi = 0;\n  int on = n * 100;\n  char *ob = (char *)malloc(on);\n  size_t i, j;\n  IGNORE_RACES_START();\n  for (i = 0; i < n; i += 16) {\n    APPEND(\"\\n\\t%04zx:\", i);\n    for (j = 0; j < 16; ++j) {\n      if (i + j < n) {\n        APPEND(\" %02x\", p[i + j]);\n      } else {\n        APPEND(\"   \");\n      }\n    }\n    APPEND(\" \");\n    for (j = 0; j < 16 && i + j < n; ++j) {\n      APPEND(\"%c\", isprint(p[i + j]) ? p[i + j] : '.');\n    }\n  }\n  IGNORE_RACES_END();\n  LOGF(\"hex dump%s\", ob);\n  free(ob);\n}\n"
  },
  {
    "path": "blink/high.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/high.h\"\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"blink/builtin.h\"\n\nstruct High g_high = {\n    .enabled = true,\n    .active = true,\n#ifdef __APPLE__\n    .keyword = 40,\n#else\n    .keyword = 155,\n#endif\n    .reg = 215,\n    .literal = 182,\n    .label = 221,\n    .comment = 112,\n    .quote = 215,\n};\n\nchar *HighStart(char *p, int h) {\n  if (g_high.enabled) {\n    if (h) {\n      p = stpcpy(p, \"\\033[38;5;\");\n      p += snprintf(p, 12, \"%u\", h);\n      p = stpcpy(p, \"m\");\n      g_high.active = true;\n    }\n  }\n  return p;\n}\n\nchar *HighEnd(char *p) {\n  if (g_high.enabled) {\n    if (g_high.active) {\n      p = stpcpy(p, \"\\033[39m\");\n      g_high.active = false;\n    }\n  }\n  return p;\n}\n"
  },
  {
    "path": "blink/high.h",
    "content": "#ifndef BLINK_HIGH_H_\n#define BLINK_HIGH_H_\n#include <stdbool.h>\n\n#include \"blink/types.h\"\n\n#define DISABLE_HIGHLIGHT_BEGIN \\\n  {                             \\\n    bool high_;                 \\\n    high_ = g_high.enabled;     \\\n    g_high.enabled = false\n#define DISABLE_HIGHLIGHT_END \\\n  g_high.enabled = high_;     \\\n  }\n\nstruct High {\n  bool enabled;\n  bool active;\n  u8 keyword;\n  u8 reg;\n  u8 literal;\n  u8 label;\n  u8 comment;\n  u8 quote;\n};\n\nextern struct High g_high;\n\nchar *HighStart(char *, int);\nchar *HighEnd(char *);\n\n#endif /* BLINK_HIGH_H_ */\n"
  },
  {
    "path": "blink/hostfs.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Trung Nguyen                                                  │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/hostfs.h\"\n\n#include <errno.h>\n#include <fcntl.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/file.h>\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#include <sys/types.h>\n\n#include \"blink/assert.h\"\n#include \"blink/errno.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/syscall.h\"\n#include \"blink/vfs.h\"\n\n#ifndef DISABLE_VFS\n\nstruct HostfsDevice {\n  const char *source;\n  size_t sourcelen;\n};\n\nstatic u64 HostfsHash(u64 parent, const char *data, size_t size) {\n  u64 hash;\n  if (data == NULL) {\n    efault();\n    return 0;\n  }\n  hash = parent;\n  while (size--) {\n    hash = *data++ + (hash << 6) + (hash << 16) - hash;\n  }\n  return hash;\n}\n\nint HostfsInit(const char *source, u64 flags, const void *data,\n               struct VfsDevice **device, struct VfsMount **mount) {\n  struct HostfsDevice *hostdevice;\n  struct HostfsInfo *hostfsrootinfo;\n  struct stat st;\n  if (source == NULL) {\n    return efault();\n  }\n  if (stat(source, &st) == -1) {\n    return -1;\n  }\n  if (!S_ISDIR(st.st_mode)) {\n    return enotdir();\n  }\n  hostdevice = NULL;\n  hostfsrootinfo = NULL;\n  *device = NULL;\n  *mount = NULL;\n  hostdevice = (struct HostfsDevice *)malloc(sizeof(struct HostfsDevice));\n  if (hostdevice == NULL) {\n    return enomem();\n  }\n  hostdevice->source = realpath(source, NULL);\n  if (hostdevice->source == NULL) {\n    goto cleananddie;\n  }\n  hostdevice->sourcelen = strlen(hostdevice->source);\n  if (hostdevice->source[hostdevice->sourcelen - 1] == '/') {\n    hostdevice->sourcelen--;\n  }\n  if (VfsCreateDevice(device) == -1) {\n    goto cleananddie;\n  }\n  (*device)->data = hostdevice;\n  (*device)->ops = &g_hostfs.ops;\n  *mount = (struct VfsMount *)malloc(sizeof(struct VfsMount));\n  if (*mount == NULL) {\n    goto cleananddie;\n  }\n  if (VfsCreateInfo(&(*mount)->root) == -1) {\n    goto cleananddie;\n  }\n  unassert(!VfsAcquireDevice(*device, &(*mount)->root->device));\n  if (HostfsCreateInfo(&hostfsrootinfo) == -1) {\n    goto cleananddie;\n  }\n  (*mount)->root->data = hostfsrootinfo;\n  hostfsrootinfo->mode = st.st_mode;\n  (*mount)->root->mode = st.st_mode;\n  (*mount)->root->ino =\n      HostfsHash(st.st_dev, (const char *)&st.st_ino, sizeof(st.st_ino));\n  // Weak reference.\n  (*device)->root = (*mount)->root;\n  VFS_LOGF(\"Mounted a hostfs device for \\\"%s\\\"\", source);\n  return 0;\ncleananddie:\n  if (*device) {\n    unassert(!VfsFreeDevice(*device));\n  } else {\n    if (hostdevice) {\n      free((void *)hostdevice->source);\n      free(hostdevice);\n    }\n  }\n  if (*mount) {\n    if ((*mount)->root) {\n      unassert(!VfsFreeInfo((*mount)->root));\n    } else {\n      free(hostfsrootinfo);\n    }\n    free(*mount);\n  }\n  return -1;\n}\n\nint HostfsReadmountentry(struct VfsDevice *device, char **spec, char **type,\n                         char **mntops) {\n  struct HostfsDevice *hostfsdevice = (struct HostfsDevice *)device->data;\n  *spec = strdup(hostfsdevice->source);\n  if (*spec == NULL) {\n    return enomem();\n  }\n  *type = strdup(\"hostfs\");\n  if (*type == NULL) {\n    free(*spec);\n    return enomem();\n  }\n  *mntops = NULL;\n  return 0;\n}\n\nint HostfsFreeInfo(void *info) {\n  struct HostfsInfo *hostfsinfo = (struct HostfsInfo *)info;\n  if (info == NULL) {\n    return 0;\n  }\n  VFS_LOGF(\"HostfsFreeInfo(%p)\", info);\n  if (S_ISDIR(hostfsinfo->mode)) {\n    if (hostfsinfo->dirstream) {\n      unassert(!closedir(hostfsinfo->dirstream));\n    } else if (hostfsinfo->filefd != -1) {\n      unassert(!close(hostfsinfo->filefd));\n    }\n  } else if (S_ISSOCK(hostfsinfo->mode)) {\n    if (hostfsinfo->filefd != -1) {\n      unassert(!close(hostfsinfo->filefd));\n    }\n    free(hostfsinfo->socketaddr);\n    free(hostfsinfo->socketpeeraddr);\n  } else {\n    if (hostfsinfo->filefd != -1) {\n      unassert(!close(hostfsinfo->filefd));\n    }\n  }\n  free(info);\n  return 0;\n}\n\nint HostfsFreeDevice(void *device) {\n  struct HostfsDevice *hostfsdevice = (struct HostfsDevice *)device;\n  if (device == NULL) {\n    return 0;\n  }\n  VFS_LOGF(\"HostfsFreeDevice(%p)\", device);\n  free((void *)hostfsdevice->source);\n  free(hostfsdevice);\n  return 0;\n}\n\nint HostfsCreateInfo(struct HostfsInfo **output) {\n  *output = (struct HostfsInfo *)malloc(sizeof(struct HostfsInfo));\n  if (!*output) {\n    return 0;\n  }\n  (*output)->mode = 0;\n  (*output)->socketfamily = 0;\n  (*output)->filefd = -1;\n  (*output)->dirstream = NULL;\n  (*output)->socketaddr = NULL;\n  (*output)->socketaddrlen = 0;\n  (*output)->socketpeeraddr = NULL;\n  (*output)->socketpeeraddrlen = 0;\n  return 0;\n}\n\nstatic ssize_t HostfsGetHostPath(struct VfsInfo *info,\n                                 char output[VFS_PATH_MAX]) {\n  struct HostfsDevice *hostfsdevice;\n  ssize_t ret = -1;\n  size_t pathlen, sourcelen;\n  if (info == NULL) {\n    efault();\n    return -1;\n  }\n  hostfsdevice = (struct HostfsDevice *)info->device->data;\n  if ((pathlen = VfsPathBuild(info, info->device->root, true, output)) == -1) {\n    return -1;\n  }\n  sourcelen = hostfsdevice->sourcelen;\n  if (sourcelen && hostfsdevice->source[sourcelen - 1] == '/') {\n    --sourcelen;\n  }\n  pathlen += sourcelen;\n  if (pathlen + 1 >= VFS_PATH_MAX) {\n    ret = enametoolong();\n  } else {\n    memmove(output + sourcelen, output, pathlen - sourcelen);\n    memcpy(output, hostfsdevice->source, sourcelen);\n    output[pathlen] = '\\0';\n    ret = pathlen;\n  }\n  return ret;\n}\n\nstatic ssize_t HostfsGetOptimalDirFdName(struct VfsInfo *dir, const char *name,\n                                         int *hostfd,\n                                         char hostpath[VFS_PATH_MAX]) {\n  struct VfsInfo *currentdir;\n  struct HostfsDevice *hostdevice;\n  int ret = -1;\n  ssize_t len1, len2;\n  VFS_LOGF(\"HostfsGetOptimalDirFdName(%p, \\\"%s\\\", %p, %p)\", dir, name, hostfd,\n           hostpath);\n  if (!S_ISDIR(dir->mode)) {\n    enotdir();\n    return -1;\n  }\n  currentdir = dir;\n  if (!strcmp(name, \"/\")) {\n    name = \".\";\n  }\n  while (currentdir && currentdir->dev == dir->dev) {\n    if (currentdir->data &&\n        ((struct HostfsInfo *)currentdir->data)->filefd != -1) {\n      *hostfd = ((struct HostfsInfo *)currentdir->data)->filefd;\n      if (dir != currentdir) {\n        if ((len1 = VfsPathBuild(dir, currentdir, false, hostpath)) == -1) {\n          ret = -1;\n        }\n        len2 = strlen(name);\n        if (hostpath[len1 - 1] == '/') {\n          --len1;\n        }\n        if (len1 + 1 + len2 >= VFS_PATH_MAX) {\n          ret = enametoolong();\n        } else {\n          hostpath[len1] = '/';\n          memcpy(hostpath + len1 + 1, name, len2);\n          hostpath[len1 + 1 + len2] = '\\0';\n          ret = len1 + 1 + len2;\n        }\n        break;\n      } else {\n        len1 = strlen(name);\n        if (len1 >= VFS_PATH_MAX) {\n          ret = enametoolong();\n        } else {\n          memcpy(hostpath, name, len1 + 1);\n          ret = len1;\n        }\n        break;\n      }\n    }\n    currentdir = currentdir->parent;\n  }\n  if (ret == -1 && (!currentdir || currentdir->dev != dir->dev)) {\n    *hostfd = AT_FDCWD;\n    if ((len1 = VfsPathBuild(dir, dir->device->root, true, hostpath)) == -1) {\n      ret = -1;\n    } else {\n      len2 = strlen(name);\n      hostdevice = (struct HostfsDevice *)dir->device->data;\n      ret = hostdevice->sourcelen + len1 +\n            // add a slash if the host path doesn't end with one\n            ((len2 == 0) ? 0 : len2 + (hostpath[len1 - 1] != '/'));\n      if (ret + 1 >= VFS_PATH_MAX) {\n        ret = enametoolong();\n      } else {\n        memmove(hostpath + hostdevice->sourcelen, hostpath, len1);\n        memcpy(hostpath, hostdevice->source, hostdevice->sourcelen);\n        if (len2 != 0) {\n          if (hostpath[hostdevice->sourcelen + len1 - 1] != '/') {\n            hostpath[hostdevice->sourcelen + len1] = '/';\n            ++len1;\n          }\n          memcpy(hostpath + hostdevice->sourcelen + len1, name, len2 + 1);\n        }\n        hostpath[ret] = '\\0';\n      }\n    }\n  }\n  VFS_LOGF(\"HostfsGetOptimalDirFdName: output=\\\"%s\\\"\", hostpath);\n  return ret;\n}\n\nint HostfsFinddir(struct VfsInfo *parent, const char *name,\n                  struct VfsInfo **output) {\n  struct HostfsInfo *outputinfo;\n  struct stat st;\n  int hostfd;\n  char hostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsFinddir(%p, \\\"%s\\\", %p)\", parent, name, output);\n  if (parent == NULL || name == NULL || output == NULL) {\n    efault();\n    return -1;\n  }\n  if (!S_ISDIR(parent->mode)) {\n    enotdir();\n    return -1;\n  }\n  *output = NULL;\n  outputinfo = NULL;\n  if (HostfsGetOptimalDirFdName(parent, name, &hostfd, hostname) == -1) {\n    return -1;\n  }\n  if (fstatat(hostfd, hostname, &st, AT_SYMLINK_NOFOLLOW) == -1) {\n    VFS_LOGF(\"HostfsFinddir: fstatat(%d, \\\"%s\\\", %p, AT_SYMLINK_NOFOLLOW) \"\n             \"failed (%d)\",\n             hostfd, hostname, &st, errno);\n    goto cleananddie;\n  }\n  if (HostfsCreateInfo(&outputinfo) == -1) {\n    goto cleananddie;\n  }\n  outputinfo->mode = st.st_mode;\n  outputinfo->filefd = -1;\n  if (VfsCreateInfo(output) == -1) {\n    goto cleananddie;\n  }\n  (*output)->name = strdup(name);\n  if ((*output)->name == NULL) {\n    enomem();\n    goto cleananddie;\n  }\n  (*output)->namelen = strlen(name);\n  (*output)->data = outputinfo;\n  unassert(!VfsAcquireDevice(parent->device, &(*output)->device));\n  (*output)->dev = parent->dev;\n  (*output)->ino =\n      HostfsHash(st.st_dev, (const char *)&st.st_ino, sizeof(st.st_ino));\n  (*output)->mode = st.st_mode;\n  (*output)->refcount = 1;\n  unassert(!VfsAcquireInfo(parent, &(*output)->parent));\n  return 0;\ncleananddie:\n  if (*output) {\n    unassert(!VfsFreeInfo(*output));\n  } else {\n    unassert(!HostfsFreeInfo(outputinfo));\n  }\n  return -1;\n}\n\nint HostfsTraverse(struct VfsInfo **dir, const char **path,\n                   struct VfsInfo *root) {\n  char hostpath[VFS_PATH_MAX];\n  struct VfsInfo *next, *original;\n  struct HostfsInfo *nexthost;\n  const char *currentpath = *path, *nextpath;\n  struct stat st;\n  ssize_t hostpathlen, currentnamelen;\n  u32 currentdev;\n  int hostfd;\n  VFS_LOGF(\"HostfsTraverse(%s, \\\"%s\\\", %p)\", (*dir)->name, *path, root);\n  if ((hostpathlen = HostfsGetOptimalDirFdName(*dir, \"\", &hostfd, hostpath)) ==\n      -1) {\n    return -1;\n  }\n  if (hostpathlen > 0 && hostpath[hostpathlen - 1] != '/') {\n    if (hostpathlen + 1 >= VFS_PATH_MAX) {\n      return enametoolong();\n    }\n    hostpath[hostpathlen] = '/';\n    ++hostpathlen;\n  }\n  VFS_LOGF(\"HostfsTraverse: hostpath=\\\"%s\\\", hostfd=%d\", hostpath, hostfd);\n  original = *dir;\n  next = NULL;\n  nexthost = NULL;\n  currentdev = (*dir)->dev;\n  while (*currentpath) {\n    while (*currentpath == '/') {\n      ++currentpath;\n    }\n    nextpath = currentpath;\n    while (*nextpath && *nextpath != '/') {\n      ++nextpath;\n    }\n    if (nextpath == currentpath) {\n      break;\n    }\n    if (!strcmp(currentpath, \".\")) {\n      currentpath = nextpath;\n      continue;\n    } else if (!strcmp(currentpath, \"..\")) {\n      currentpath = nextpath;\n      if (*dir == root || (*dir)->parent == NULL) {\n        continue;\n      }\n      unassert(!VfsAcquireInfo((*dir)->parent, &next));\n      unassert(!VfsFreeInfo(*dir));\n      *dir = next;\n      if (next->dev != currentdev) {\n        *path = currentpath;\n        return 0;\n      }\n      if (hostpathlen > 0) {\n        --hostpathlen;\n        while (hostpathlen > 0 && hostpath[hostpathlen - 1] != '/') {\n          --hostpathlen;\n        }\n        hostpath[hostpathlen] = '\\0';\n      }\n      continue;\n    }\n    currentnamelen = nextpath - currentpath;\n    if (currentnamelen >= VFS_NAME_MAX) {\n      enametoolong();\n      goto cleananddie;\n    }\n    if (currentnamelen + hostpathlen + 1 >= VFS_PATH_MAX) {\n      enametoolong();\n      goto cleananddie;\n    }\n    memcpy(hostpath + hostpathlen, currentpath, currentnamelen);\n    hostpath[hostpathlen + currentnamelen] = '\\0';\n    VFS_LOGF(\"HostfsTraverse: fstatat(%d, \\\"%s\\\", %p, AT_SYMLINK_NOFOLLOW)\",\n             hostfd, hostpath, &st);\n    if (fstatat(hostfd, hostpath, &st, AT_SYMLINK_NOFOLLOW) == -1) {\n      if (original != *dir) {\n        *path = currentpath;\n        return 0;\n      } else {\n        return enoent();\n      }\n    }\n    hostpath[hostpathlen + currentnamelen] = '/';\n    hostpath[hostpathlen + currentnamelen + 1] = '\\0';\n    hostpathlen += currentnamelen + 1;\n    if (HostfsCreateInfo(&nexthost) == -1) {\n      goto cleananddie;\n    }\n    nexthost->mode = st.st_mode;\n    nexthost->filefd = -1;\n    if (VfsCreateInfo(&next) == -1) {\n      unassert(!HostfsFreeInfo(nexthost));\n      goto cleananddie;\n    }\n    next->name = strndup(currentpath, currentnamelen);\n    if (next->name == NULL) {\n      unassert(!VfsFreeInfo(next));\n      unassert(!HostfsFreeInfo(nexthost));\n      enomem();\n      goto cleananddie;\n    }\n    next->namelen = currentnamelen;\n    next->data = nexthost;\n    unassert(!VfsAcquireDevice((*dir)->device, &next->device));\n    next->dev = currentdev;\n    next->ino =\n        HostfsHash(st.st_dev, (const char *)&st.st_ino, sizeof(st.st_ino));\n    next->mode = st.st_mode;\n    next->refcount = 1;\n    next->parent = *dir;\n    *dir = next;\n    currentpath = nextpath;\n    VFS_LOGF(\"HostfsTraverse: Changed current path to \\\"%s\\\"\", currentpath);\n    if (!S_ISDIR(st.st_mode)) {\n      break;\n    }\n  }\n  *path = currentpath;\n  return 0;\ncleananddie:\n  while (original != *dir) {\n    unassert(!VfsAcquireInfo((*dir)->parent, &next));\n    unassert(!VfsFreeInfo(*dir));\n    *dir = next;\n  }\n  return -1;\n}\n\nssize_t HostfsReadlink(struct VfsInfo *info, char **output) {\n  struct HostfsInfo *hostinfo;\n  char *buf;\n  char name[VFS_PATH_MAX];\n  ssize_t len, reallen;\n  int fd;\n  VFS_LOGF(\"HostfsReadlink(%p, %p)\", info, output);\n  if (info == NULL || output == NULL) {\n    efault();\n    return -1;\n  }\n  if (!S_ISLNK(info->mode)) {\n    einval();\n    return -1;\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (hostinfo->filefd != -1) {\n    fd = hostinfo->filefd;\n    name[0] = '\\0';\n  } else {\n    fd = -1;\n    if (HostfsGetHostPath(info, name) == -1) {\n      return -1;\n    }\n  }\n  len = VFS_PATH_MAX;\n  buf = (char *)malloc(len);\n  if (buf == NULL) {\n    enomem();\n    goto cleananddie;\n  }\n  while (true) {\n    reallen = readlinkat(fd, name, buf, len);\n    if (reallen == -1) {\n      goto cleananddie;\n    }\n    if (reallen < len) {\n      break;\n    }\n    len *= 2;\n    buf = (char *)realloc(buf, len);\n    if (buf == NULL) {\n      enomem();\n      goto cleananddie;\n    }\n  }\n  buf[reallen] = '\\0';\n  *output = buf;\n  if (fd != -1) {\n    unassert(!close(fd));\n  }\n  return reallen;\ncleananddie:\n  if (fd != -1) {\n    unassert(!close(fd));\n  }\n  free(buf);\n  return -1;\n}\n\nint HostfsMkdir(struct VfsInfo *parent, const char *name, mode_t mode) {\n  int hostfd;\n  char hostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsMkdir(%p, \\\"%s\\\", %d)\", parent, name, mode);\n  if (HostfsGetOptimalDirFdName(parent, name, &hostfd, hostname) == -1) {\n    return -1;\n  }\n  return mkdirat(hostfd, hostname, mode);\n}\n\nint HostfsMkfifo(struct VfsInfo *parent, const char *name, mode_t mode) {\n  int hostfd;\n  char hostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsMkfifo(%p, \\\"%s\\\", %d)\", parent, name, mode);\n  if (HostfsGetOptimalDirFdName(parent, name, &hostfd, hostname) == -1) {\n    return -1;\n  }\n  return mkfifoat(hostfd, hostname, mode);\n}\n\nint HostfsOpen(struct VfsInfo *parent, const char *name, int flags, int mode,\n               struct VfsInfo **output) {\n  struct HostfsInfo *outputinfo;\n  struct stat st;\n  int hostfd;\n  char hostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsOpen(%p, \\\"%s\\\", %d, %d, %p)\", parent, name, flags, mode,\n           output);\n  if (parent == NULL || name == NULL || output == NULL) {\n    return efault();\n  }\n  if (!S_ISDIR(parent->mode)) {\n    return enotdir();\n  }\n  *output = NULL;\n  outputinfo = NULL;\n  if (HostfsGetOptimalDirFdName(parent, name, &hostfd, hostname) == -1) {\n    return -1;\n  }\n  if (HostfsCreateInfo(&outputinfo) == -1) {\n    goto cleananddie;\n  }\n  outputinfo->filefd = openat(hostfd, hostname, flags, mode);\n  VFS_LOGF(\"HostfsOpen: openat(%d, \\\"%s\\\", %d, %d) -> %d, %s\", hostfd, hostname,\n           flags, mode, outputinfo->filefd, strerror(errno));\n  if (outputinfo->filefd == -1) {\n    goto cleananddie;\n  }\n  unassert(fstat(outputinfo->filefd, &st) != -1);\n  outputinfo->mode = st.st_mode;\n  if (VfsCreateInfo(output) == -1) {\n    goto cleananddie;\n  }\n  (*output)->data = outputinfo;\n  (*output)->name = strdup(name);\n  if ((*output)->name == NULL) {\n    enomem();\n    goto cleananddie;\n  }\n  (*output)->namelen = strlen(name);\n  unassert(!VfsAcquireDevice(parent->device, &(*output)->device));\n  (*output)->dev = parent->dev;\n  (*output)->ino =\n      HostfsHash(st.st_dev, (const char *)&st.st_ino, sizeof(st.st_ino));\n  (*output)->mode = outputinfo->mode;\n  (*output)->refcount = 1;\n  unassert(!VfsAcquireInfo(parent, &(*output)->parent));\n  return 0;\ncleananddie:\n  if (*output) {\n    unassert(!VfsFreeInfo(*output));\n  } else {\n    unassert(!HostfsFreeInfo(outputinfo));\n  }\n  return -1;\n}\n\nint HostfsAccess(struct VfsInfo *parent, const char *name, mode_t mode,\n                 int flags) {\n  int hostfd;\n  char hostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsAccess(%p, \\\"%s\\\", %d, %d)\", parent, name, mode, flags);\n  if (HostfsGetOptimalDirFdName(parent, name, &hostfd, hostname) == -1) {\n    return -1;\n  }\n  return faccessat(hostfd, hostname, mode, flags);\n}\n\nint HostfsStat(struct VfsInfo *parent, const char *name, struct stat *st,\n               int flags) {\n  int hostfd, ret;\n  char hostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsStat(%p, \\\"%s\\\", %p, %d)\", parent, name, st, flags);\n  if (HostfsGetOptimalDirFdName(parent, name, &hostfd, hostname) == -1) {\n    return -1;\n  }\n  ret = fstatat(hostfd, hostname, st, flags);\n  if (ret != -1) {\n    st->st_ino =\n        HostfsHash(st->st_dev, (const char *)&st->st_ino, sizeof(st->st_ino));\n    st->st_dev = parent->dev;\n  }\n  return ret;\n}\n\nint HostfsFstat(struct VfsInfo *info, struct stat *st) {\n  struct HostfsInfo *hostinfo;\n  int ret;\n  VFS_LOGF(\"HostfsFstat(%p, %p)\", info, st);\n  if (info == NULL || st == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  ret = fstat(hostinfo->filefd, st);\n  if (ret != -1) {\n    st->st_ino =\n        HostfsHash(st->st_dev, (const char *)&st->st_ino, sizeof(st->st_ino));\n    st->st_dev = info->dev;\n  }\n  return ret;\n}\n\nint HostfsChmod(struct VfsInfo *parent, const char *name, mode_t mode,\n                int flags) {\n  int hostfd;\n  char hostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsChmod(%p, \\\"%s\\\", %d)\", parent, name, mode);\n  if (HostfsGetOptimalDirFdName(parent, name, &hostfd, hostname) == -1) {\n    return -1;\n  }\n  return fchmodat(hostfd, hostname, mode, flags);\n}\n\nint HostfsFchmod(struct VfsInfo *info, mode_t mode) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsFchmod(%p, %d)\", info, mode);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return fchmod(hostinfo->filefd, mode);\n}\n\nint HostfsChown(struct VfsInfo *parent, const char *name, uid_t uid, gid_t gid,\n                int flags) {\n  int hostfd;\n  char hostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsChown(%p, \\\"%s\\\", %d, %d)\", parent, name, uid, gid);\n  if (HostfsGetOptimalDirFdName(parent, name, &hostfd, hostname) == -1) {\n    return -1;\n  }\n  return fchownat(hostfd, hostname, uid, gid, flags);\n}\n\nint HostfsFchown(struct VfsInfo *info, uid_t uid, gid_t gid) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsFchown(%p, %d, %d)\", info, uid, gid);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return fchown(hostinfo->filefd, uid, gid);\n}\n\nint HostfsFtruncate(struct VfsInfo *info, off_t length) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsFtruncate(%p, %ld)\", info, length);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return ftruncate(hostinfo->filefd, length);\n}\n\nint HostfsClose(struct VfsInfo *info) {\n  struct HostfsInfo *hostinfo;\n  int ret;\n  VFS_LOGF(\"HostfsClose(%p)\", info);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  ret = close(hostinfo->filefd);\n  hostinfo->filefd = -1;\n  return ret;\n}\n\nint HostfsLink(struct VfsInfo *oldparent, const char *oldname,\n               struct VfsInfo *newparent, const char *newname, int flags) {\n  int oldhostfd, newhostfd;\n  char oldhostname[VFS_PATH_MAX], newhostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsLink(%p, \\\"%s\\\", %p, \\\"%s\\\")\", oldparent, oldname, newparent,\n           newname);\n  if (HostfsGetOptimalDirFdName(oldparent, oldname, &oldhostfd, oldhostname) ==\n      -1) {\n    return -1;\n  }\n  if (HostfsGetOptimalDirFdName(newparent, newname, &newhostfd, newhostname) ==\n      -1) {\n    return -1;\n  }\n  return linkat(oldhostfd, oldhostname, newhostfd, newhostname, flags);\n}\n\nint HostfsUnlink(struct VfsInfo *parent, const char *name, int flags) {\n  int hostfd;\n  char hostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsUnlink(%p, \\\"%s\\\")\", parent, name);\n  if (HostfsGetOptimalDirFdName(parent, name, &hostfd, hostname) == -1) {\n    return -1;\n  }\n  return unlinkat(hostfd, hostname, flags);\n}\n\nssize_t HostfsRead(struct VfsInfo *info, void *buf, size_t size) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsRead(%p, %p, %ld)\", info, buf, size);\n  if (info == NULL || buf == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return read(hostinfo->filefd, buf, size);\n}\n\nssize_t HostfsWrite(struct VfsInfo *info, const void *buf, size_t size) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsWrite(%p, %p, %ld)\", info, buf, size);\n  if (info == NULL || buf == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return write(hostinfo->filefd, buf, size);\n}\n\nssize_t HostfsPread(struct VfsInfo *info, void *buf, size_t size,\n                    off_t offset) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsPread(%p, %p, %ld, %ld)\", info, buf, size, offset);\n  if (info == NULL || buf == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return pread(hostinfo->filefd, buf, size, offset);\n}\n\nssize_t HostfsPwrite(struct VfsInfo *info, const void *buf, size_t size,\n                     off_t offset) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsPwrite(%p, %p, %ld, %ld)\", info, buf, size, offset);\n  if (info == NULL || buf == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return pwrite(hostinfo->filefd, buf, size, offset);\n}\n\nssize_t HostfsReadv(struct VfsInfo *info, const struct iovec *iov, int iovcnt) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsReadv(%p, %p, %d)\", info, iov, iovcnt);\n  if (info == NULL || iov == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return readv(hostinfo->filefd, iov, iovcnt);\n}\n\nssize_t HostfsWritev(struct VfsInfo *info, const struct iovec *iov,\n                     int iovcnt) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsWritev(%p, %p, %d)\", info, iov, iovcnt);\n  if (info == NULL || iov == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return writev(hostinfo->filefd, iov, iovcnt);\n}\n\nssize_t HostfsPreadv(struct VfsInfo *info, const struct iovec *iov, int iovcnt,\n                     off_t offset) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsPreadv(%p, %p, %d, %ld)\", info, iov, iovcnt, offset);\n  if (info == NULL || iov == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return preadv(hostinfo->filefd, iov, iovcnt, offset);\n}\n\nssize_t HostfsPwritev(struct VfsInfo *info, const struct iovec *iov, int iovcnt,\n                      off_t offset) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsPwritev(%p, %p, %d, %ld)\", info, iov, iovcnt, offset);\n  if (info == NULL || iov == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return pwritev(hostinfo->filefd, iov, iovcnt, offset);\n}\n\noff_t HostfsSeek(struct VfsInfo *info, off_t offset, int whence) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsLseek(%p, %ld, %d)\", info, offset, whence);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return lseek(hostinfo->filefd, offset, whence);\n}\n\nint HostfsFsync(struct VfsInfo *info) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsFsync(%p)\", info);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return fsync(hostinfo->filefd);\n}\n\nint HostfsFdatasync(struct VfsInfo *info) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsFdatasync(%p)\", info);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n#ifdef HAVE_FDATASYNC\n  return fdatasync(hostinfo->filefd);\n#else\n  return fsync(hostinfo->filefd);\n#endif\n}\n\nint HostfsFlock(struct VfsInfo *info, int operation) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsFlock(%p, %d)\", info, operation);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return flock(hostinfo->filefd, operation);\n}\n\nint HostfsFcntl(struct VfsInfo *info, int cmd, va_list args) {\n  struct HostfsInfo *hostinfo;\n  int rc;\n  VFS_LOGF(\"HostfsFcntl(%p, %d, ...)\", info, cmd);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (hostinfo == NULL) {\n    return enoent();\n  }\n  if (cmd == F_GETFD || cmd == F_GETFL || cmd == F_GETOWN\n#ifdef F_GETSIG\n      || cmd == F_GETSIG\n#endif\n#ifdef F_GETLEASE\n      || cmd == F_GETLEASE\n#endif\n#ifdef F_GETPIPE_SZ\n      || cmd == F_GETPIPE_SZ\n#endif\n#ifdef F_GET_SEALS\n      || cmd == F_GET_SEALS\n#endif\n  ) {\n    rc = fcntl(hostinfo->filefd, cmd);\n  } else if (cmd == F_SETFD || cmd == F_SETFL || cmd == F_SETOWN\n#ifdef F_SETSIG\n             || cmd == F_SETSIG\n#endif\n#ifdef F_SETLEASE\n             || cmd == F_SETLEASE\n#endif\n#ifdef F_NOTIFY\n             || cmd == F_NOTIFY\n#endif\n#ifdef F_SETPIPE_SZ\n             || cmd == F_SETPIPE_SZ\n#endif\n#ifdef F_ADD_SEALS\n             || cmd == F_ADD_SEALS\n#endif\n  ) {\n    rc = fcntl(hostinfo->filefd, cmd, va_arg(args, int));\n  } else if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK\n#ifdef F_OFD_SETLK\n             || cmd == F_OFD_SETLK || cmd == F_OFD_SETLKW || cmd == F_OFD_GETLK\n#endif\n  ) {\n    rc = fcntl(hostinfo->filefd, cmd, va_arg(args, struct flock *));\n#ifdef F_GETOWN_EX\n  } else if (cmd == F_GETOWN_EX || cmd == F_SETOWN_EX) {\n    rc = fcntl(hostinfo->filefd, cmd, va_arg(args, struct f_owner_ex *));\n#endif\n#ifdef F_GET_RW_HINT\n  } else if (cmd == F_GET_RW_HINT || cmd == F_SET_RW_HINT ||\n             cmd == F_GET_FILE_RW_HINT || cmd == F_SET_FILE_RW_HINT) {\n    rc = fcntl(hostinfo->filefd, cmd, va_arg(args, uint64_t *));\n#endif\n  } else {\n    rc = einval();\n  }\n\n  return rc;\n}\n\nint HostfsIoctl(struct VfsInfo *info, unsigned long request, const void *arg) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsIoctl(%p, %lu, %p)\", info, request, arg);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return ioctl(hostinfo->filefd, request, arg);\n}\n\nint HostfsDup(struct VfsInfo *info, struct VfsInfo **newinfo) {\n  struct HostfsInfo *hostinfo, *newhostinfo;\n  VFS_LOGF(\"HostfsDup(%p, %p)\", info, newinfo);\n  if (info == NULL || newinfo == NULL) {\n    return efault();\n  }\n  *newinfo = NULL;\n  newhostinfo = NULL;\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (hostinfo == NULL) {\n    return enoent();\n  }\n  if (HostfsCreateInfo(&newhostinfo) == -1) {\n    return -1;\n  }\n  newhostinfo->filefd = dup(hostinfo->filefd);\n  if (newhostinfo->filefd == -1) {\n    goto cleananddie;\n  }\n  newhostinfo->mode = hostinfo->mode;\n  if (S_ISSOCK(hostinfo->mode) && hostinfo->socketaddr != NULL) {\n    newhostinfo->socketaddr =\n        (struct sockaddr *)malloc(hostinfo->socketaddrlen);\n    if (newhostinfo->socketaddr != NULL) {\n      memcpy(newhostinfo->socketaddr, hostinfo->socketaddr,\n             hostinfo->socketaddrlen);\n      newhostinfo->socketaddrlen = hostinfo->socketaddrlen;\n    }\n  } else if (S_ISDIR(hostinfo->mode) && hostinfo->dirstream != NULL) {\n    newhostinfo->dirstream = fdopendir(newhostinfo->filefd);\n    if (newhostinfo->dirstream == NULL) {\n      goto cleananddie;\n    }\n  }\n  if (VfsCreateInfo(newinfo) == -1) {\n    goto cleananddie;\n  }\n  if (info->name != NULL) {\n    (*newinfo)->name = strdup(info->name);\n    if ((*newinfo)->name == NULL) {\n      goto cleananddie;\n    }\n    (*newinfo)->namelen = info->namelen;\n  }\n  (*newinfo)->data = newhostinfo;\n  (*newinfo)->dev = info->dev;\n  unassert(!VfsAcquireDevice(info->device, &(*newinfo)->device));\n  (*newinfo)->ino = info->ino;\n  (*newinfo)->mode = info->mode;\n  unassert(!VfsAcquireInfo(info->parent, &(*newinfo)->parent));\n  (*newinfo)->refcount = 1;\n  return 0;\ncleananddie:\n  unassert(!HostfsFreeInfo(newhostinfo));\n  unassert(!VfsFreeInfo(*newinfo));\n  return -1;\n}\n\n#ifdef HAVE_DUP3\nint HostfsDup3(struct VfsInfo *info, struct VfsInfo **newinfo, int flags) {\n  struct HostfsInfo *hostinfo, *newhostinfo;\n  VFS_LOGF(\"HostfsDup3(%p, %p, %i)\", info, newinfo, flags);\n  if (info == NULL || newinfo == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (hostinfo == NULL) {\n    return enoent();\n  }\n  if (HostfsCreateInfo(&newhostinfo) == -1) {\n    return -1;\n  }\n  newhostinfo->filefd =\n      dup3(hostinfo->filefd, open(\"/dev/null\", O_RDONLY), flags);\n  if (newhostinfo->filefd == -1) {\n    goto cleananddie;\n  }\n  if (VfsCreateInfo(newinfo) == -1) {\n    goto cleananddie;\n  }\n  if (info->name != NULL) {\n    (*newinfo)->name = strdup(info->name);\n    if ((*newinfo)->name == NULL) {\n      goto cleananddie;\n    }\n    (*newinfo)->namelen = info->namelen;\n  }\n  if (VfsCreateInfo(newinfo) == -1) {\n    goto cleananddie;\n  }\n  (*newinfo)->data = newhostinfo;\n  (*newinfo)->dev = info->dev;\n  unassert(!VfsAcquireDevice(info->device, &(*newinfo)->device));\n  (*newinfo)->ino = info->ino;\n  (*newinfo)->mode = info->mode;\n  unassert(!VfsAcquireInfo(info->parent, &(*newinfo)->parent));\n  (*newinfo)->refcount = 1;\n  return 0;\ncleananddie:\n  unassert(!HostfsFreeInfo(newhostinfo));\n  unassert(!VfsFreeInfo(*newinfo));\n  return -1;\n}\n#endif\n\nint HostfsPoll(struct VfsInfo **infos, struct pollfd *fds, nfds_t nfds,\n               int timeout) {\n  int rc;\n  int oldfd;\n  VFS_LOGF(\"HostfsPoll(%p, %lli, %i)\", infos, (long long)nfds, timeout);\n  if (infos == NULL) {\n    return efault();\n  }\n  // Same reason as in VfsPoll above\n  unassert(nfds == 1);\n  oldfd = fds->fd;\n  fds->fd = ((struct HostfsInfo *)infos[0]->data)->filefd;\n  rc = poll(fds, nfds, timeout);\n  fds->fd = oldfd;\n  return rc;\n}\n\nint HostfsOpendir(struct VfsInfo *info, struct VfsInfo **output) {\n  struct HostfsInfo *hostinfo;\n  DIR *dirstream;\n  VFS_LOGF(\"HostfsOpendir(%p)\", info);\n  if (info == NULL || output == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  unassert(hostinfo->filefd != -1);\n  dirstream = fdopendir(hostinfo->filefd);\n  if (dirstream == NULL) {\n    return -1;\n  }\n  hostinfo->dirstream = dirstream;\n  unassert(!VfsAcquireInfo(info, output));\n  return 0;\n}\n\n#ifdef HAVE_SEEKDIR\nvoid HostfsSeekdir(struct VfsInfo *info, long loc) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsSeekdir(%p, %ld)\", info, loc);\n  if (info == NULL) {\n    efault();\n    return;\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return seekdir(hostinfo->dirstream, loc);\n}\n\nlong HostfsTelldir(struct VfsInfo *info) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsTelldir(%p)\", info);\n  if (info == NULL) {\n    efault();\n    return -1;\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return telldir(hostinfo->dirstream);\n}\n#endif\n\nstruct dirent *HostfsReaddir(struct VfsInfo *info) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsReaddir(%p)\", info);\n  if (info == NULL) {\n    efault();\n    return NULL;\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return readdir(hostinfo->dirstream);\n}\n\nvoid HostfsRewinddir(struct VfsInfo *info) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsRewinddir(%p)\", info);\n  if (info == NULL) {\n    efault();\n    return;\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return rewinddir(hostinfo->dirstream);\n}\n\nint HostfsClosedir(struct VfsInfo *info) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsClosedir(%p)\", info);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (closedir(hostinfo->dirstream) == -1) {\n    return -1;\n  }\n  hostinfo->dirstream = NULL;\n  hostinfo->filefd = -1;\n  unassert(!VfsFreeInfo(info));\n  return 0;\n}\n\nint HostfsBind(struct VfsInfo *info, const struct sockaddr *addr,\n               socklen_t addrlen) {\n  struct HostfsInfo *hostinfo;\n  struct sockaddr_un *hostun;\n  struct stat st;\n  char hostpath[VFS_PATH_MAX];\n  size_t len;\n  int ret;\n  VFS_LOGF(\"HostfsBind(%p, %p, %i)\", info, addr, addrlen);\n  if (info == NULL || addr == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (addr->sa_family != AF_UNIX) {\n    ret = bind(hostinfo->filefd, addr, addrlen);\n    if (ret == 0) {\n      hostinfo->socketfamily = addr->sa_family;\n    }\n  } else {\n    if (HostfsGetHostPath(info, hostpath) == -1) {\n      ret = -1;\n    } else {\n      len = strlen(hostpath) + 1 + offsetof(struct sockaddr_un, sun_path);\n      hostun = (struct sockaddr_un *)malloc(len);\n      if (hostun == NULL) {\n        ret = -1;\n      } else {\n        hostun->sun_family = AF_UNIX;\n        strcpy(hostun->sun_path, hostpath);\n        ret = bind(hostinfo->filefd, (struct sockaddr *)hostun, len);\n        if (ret == 0) {\n          hostinfo->socketfamily = AF_UNIX;\n          unassert(!fstat(hostinfo->filefd, &st));\n          info->dev = info->parent->dev;\n          info->ino = HostfsHash(st.st_dev, (const char *)&st.st_ino,\n                                 sizeof(st.st_ino));\n          info->mode = st.st_mode;\n          hostinfo->socketaddr = (struct sockaddr *)malloc(addrlen);\n          if (hostinfo->socketaddr != NULL) {\n            memcpy(hostinfo->socketaddr, addr, addrlen);\n            hostinfo->socketaddrlen = addrlen;\n          }\n        }\n        free(hostun);\n      }\n    }\n  }\n  return ret;\n}\n\nint HostfsConnect(struct VfsInfo *info, const struct sockaddr *addr,\n                  socklen_t addrlen) {\n  struct HostfsInfo *hostinfo;\n  int ret;\n  VFS_LOGF(\"HostfsConnect(%p, %p, %i)\", info, addr, addrlen);\n  if (info == NULL || addr == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  ret = connect(hostinfo->filefd, addr, addrlen);\n  if (ret == 0) {\n    hostinfo->socketfamily = addr->sa_family;\n  }\n  return ret;\n}\n\nint HostfsConnectUnix(struct VfsInfo *sock, struct VfsInfo *info,\n                      const struct sockaddr_un *addr, socklen_t addrlen) {\n  struct HostfsInfo *hostinfo;\n  struct sockaddr_un *hostun;\n  socklen_t hostlen;\n  char hostpath[VFS_PATH_MAX];\n  size_t hostpathlen;\n  int ret;\n  VFS_LOGF(\"HostfsConnectUnix(%p, %p, %p, %i)\", sock, info, addr, addrlen);\n  if (sock == NULL || info == NULL || addr == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (HostfsGetHostPath(sock, hostpath) == -1) {\n    return -1;\n  }\n  hostpathlen = strlen(hostpath);\n  hostlen = hostpathlen + 1 + offsetof(struct sockaddr_un, sun_path);\n  hostun = (struct sockaddr_un *)malloc(hostlen);\n  if (hostun == NULL) {\n    return enomem();\n  }\n  hostun->sun_family = AF_UNIX;\n  memcpy(hostun->sun_path, hostpath, hostpathlen + 1);\n  ret = connect(hostinfo->filefd, (struct sockaddr *)hostun, hostlen);\n  free(hostun);\n  if (ret != -1) {\n    hostinfo->socketpeeraddr = (struct sockaddr *)malloc(addrlen);\n    if (hostinfo->socketpeeraddr != NULL) {\n      memcpy(hostinfo->socketpeeraddr, addr, addrlen);\n      hostinfo->socketpeeraddrlen = addrlen;\n    }\n  }\n  return ret;\n}\n\nint HostfsAccept(struct VfsInfo *info, struct sockaddr *addr,\n                 socklen_t *addrlen, struct VfsInfo **output) {\n  struct HostfsInfo *hostinfo, *newhostinfo;\n  int ret;\n  VFS_LOGF(\"HostfsAccept(%p, %p, %p)\", info, addr, addrlen);\n  if (info == NULL || output == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (HostfsCreateInfo(&newhostinfo) == -1) {\n    return -1;\n  }\n  if (VfsCreateInfo(output) == -1) {\n    unassert(!HostfsFreeInfo(newhostinfo));\n    return -1;\n  }\n  (*output)->data = newhostinfo;\n  unassert(!VfsAcquireDevice(info->device, &(*output)->device));\n  ret = accept(hostinfo->filefd, addr, addrlen);\n  if (ret != -1) {\n    newhostinfo->filefd = ret;\n    newhostinfo->socketfamily = hostinfo->socketfamily;\n    (*output)->ino = info->ino;\n    (*output)->dev = info->dev;\n    (*output)->mode = info->mode;\n    unassert(!VfsFreeInfo((*output)->parent));\n    unassert(!VfsAcquireInfo(info->parent, &(*output)->parent));\n    (*output)->refcount = 1;\n    ret = 0;\n  } else {\n    unassert(!VfsFreeInfo(*output));\n  }\n  return ret;\n}\n\nint HostfsListen(struct VfsInfo *info, int backlog) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsListen(%p, %i)\", info, backlog);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return listen(hostinfo->filefd, backlog);\n}\n\nint HostfsShutdown(struct VfsInfo *info, int how) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsShutdown(%p, %i)\", info, how);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return shutdown(hostinfo->filefd, how);\n}\n\nssize_t HostfsRecvmsg(struct VfsInfo *info, struct msghdr *msg, int flags) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsRecvmsg(%p, %p, %i)\", info, msg, flags);\n  if (info == NULL || msg == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return recvmsg(hostinfo->filefd, msg, flags);\n}\n\nssize_t HostfsSendmsg(struct VfsInfo *info, const struct msghdr *msg,\n                      int flags) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsSendmsg(%p, %p, %i)\", info, msg, flags);\n  if (info == NULL || msg == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return sendmsg(hostinfo->filefd, msg, flags);\n}\n\nssize_t HostfsRecvmsgUnix(struct VfsInfo *sock, struct VfsInfo *info,\n                          struct msghdr *msg, int flags) {\n  struct HostfsInfo *hostinfo;\n  struct sockaddr_un *hostun, *oldun;\n  socklen_t hostlen, oldlen;\n  char hostpath[VFS_PATH_MAX];\n  size_t hostpathlen;\n  int ret;\n  VFS_LOGF(\"HostfsRecvmsgUnix(%p, %p, %p, %i)\", sock, info, msg, flags);\n  if (sock == NULL || info == NULL || msg == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (HostfsGetHostPath(sock, hostpath) == -1) {\n    return -1;\n  }\n  hostpathlen = strlen(hostpath);\n  hostlen = hostpathlen + 1 + offsetof(struct sockaddr_un, sun_path);\n  hostun = (struct sockaddr_un *)malloc(hostlen);\n  if (hostun == NULL) {\n    return enomem();\n  }\n  hostun->sun_family = AF_UNIX;\n  memcpy(hostun->sun_path, hostpath, hostpathlen + 1);\n  oldun = (struct sockaddr_un *)msg->msg_name;\n  oldlen = msg->msg_namelen;\n  msg->msg_name = hostun;\n  msg->msg_namelen = hostlen;\n  ret = recvmsg(hostinfo->filefd, msg, flags);\n  free(hostun);\n  msg->msg_name = oldun;\n  msg->msg_namelen = oldlen;\n  return ret;\n}\n\nssize_t HostfsSendmsgUnix(struct VfsInfo *sock, struct VfsInfo *info,\n                          const struct msghdr *msg, int flags) {\n  struct HostfsInfo *hostinfo;\n  struct msghdr newmsg;\n  struct sockaddr_un *hostun;\n  socklen_t hostlen;\n  char hostpath[VFS_PATH_MAX];\n  size_t hostpathlen;\n  int ret;\n  VFS_LOGF(\"HostfsSendmsgUnix(%p, %p, %p, %i)\", sock, info, msg, flags);\n  if (sock == NULL || info == NULL || msg == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (HostfsGetHostPath(sock, hostpath) == -1) {\n    return -1;\n  }\n  hostpathlen = strlen(hostpath);\n  hostlen = hostpathlen + 1 + offsetof(struct sockaddr_un, sun_path);\n  hostun = (struct sockaddr_un *)malloc(hostlen);\n  if (hostun == NULL) {\n    return enomem();\n  }\n  hostun->sun_family = AF_UNIX;\n  memcpy(hostun->sun_path, hostpath, hostpathlen + 1);\n  memcpy(&newmsg, msg, sizeof(struct msghdr));\n  newmsg.msg_name = hostun;\n  newmsg.msg_namelen = hostlen;\n  ret = sendmsg(hostinfo->filefd, &newmsg, flags);\n  free(hostun);\n  return ret;\n}\n\nint HostfsGetsockopt(struct VfsInfo *info, int level, int optname, void *optval,\n                     socklen_t *optlen) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsGetsockopt(%p, %i, %i, %p, %p)\", info, level, optname, optval,\n           optlen);\n  if (info == NULL || optval == NULL || optlen == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return getsockopt(hostinfo->filefd, level, optname, optval, optlen);\n}\n\nint HostfsSetsockopt(struct VfsInfo *info, int level, int optname,\n                     const void *optval, socklen_t optlen) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsSetsockopt(%p, %i, %i, %p, %i)\", info, level, optname, optval,\n           optlen);\n  if (info == NULL || optval == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return setsockopt(hostinfo->filefd, level, optname, optval, optlen);\n}\n\nint HostfsGetsockname(struct VfsInfo *info, struct sockaddr *addr,\n                      socklen_t *addrlen) {\n  struct HostfsInfo *hostinfo;\n  struct sockaddr_un *un;\n  char *path;\n  VFS_LOGF(\"HostfsGetsockname(%p, %p, %p)\", info, addr, addrlen);\n  if (info == NULL || addr == NULL || addrlen == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (hostinfo->socketfamily != AF_UNIX) {\n    return getsockname(hostinfo->filefd, addr, addrlen);\n  }\n  if (hostinfo->socketaddr) {\n    memcpy(addr, hostinfo->socketaddr, MIN(*addrlen, hostinfo->socketaddrlen));\n    *addrlen = hostinfo->socketaddrlen;\n  } else {\n    if (info->parent == NULL) {\n      return getsockname(hostinfo->filefd, addr, addrlen);\n    }\n    un = (struct sockaddr_un *)addr;\n    if (VfsPathBuildFull(info, NULL, &path) == -1) {\n      return -1;\n    }\n    un->sun_family = AF_UNIX;\n    strncpy(un->sun_path, path,\n            *addrlen - offsetof(struct sockaddr_un, sun_path));\n    *addrlen = strlen(path) + offsetof(struct sockaddr_un, sun_path);\n  }\n  return 0;\n}\n\nint HostfsGetpeername(struct VfsInfo *info, struct sockaddr *addr,\n                      socklen_t *addrlen) {\n  struct HostfsInfo *hostinfo;\n  struct sockaddr_un *hostun;\n  socklen_t hostlen = sizeof(*hostun);\n  char *s;\n  VFS_LOGF(\"HostfsGetpeername(%p, %p, %p)\", info, addr, addrlen);\n  if (info == NULL || addr == NULL || addrlen == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (hostinfo->socketfamily != AF_UNIX) {\n    return getpeername(hostinfo->filefd, addr, addrlen);\n  } else {\n    if (hostinfo->socketpeeraddr) {\n      memcpy(addr, hostinfo->socketpeeraddr,\n             MIN(*addrlen, hostinfo->socketpeeraddrlen));\n      *addrlen = hostinfo->socketpeeraddrlen;\n      return 0;\n    }\n    hostun = (struct sockaddr_un *)malloc(hostlen + 1);\n    if (hostun == NULL) {\n      return enomem();\n    }\n    memset(hostun, 0, hostlen + 1);\n    if (getpeername(hostinfo->filefd, (struct sockaddr *)hostun, &hostlen) ==\n        -1) {\n      return -1;\n    } else {\n      // As we don't manage the socket connections, this is the best we can do.\n      // For relative names we don't know where it's relative from, and for\n      // absolute names we don't know which device it lives on.\n      // VFS_SYSTEM_ROOT_MOUNT may have been unmounted by the user.\n      if (hostun->sun_path[0] == '/') {\n        s = (char *)malloc(sizeof(VFS_SYSTEM_ROOT_MOUNT) + hostlen -\n                           offsetof(struct sockaddr_un, sun_path));\n        if (s == NULL) {\n          free(hostun);\n          return enomem();\n        }\n        strcpy(s, VFS_SYSTEM_ROOT_MOUNT);\n        strncat(s, hostun->sun_path,\n                hostlen - offsetof(struct sockaddr_un, sun_path));\n        addr->sa_family = AF_UNIX;\n        strncpy(addr->sa_data, s,\n                *addrlen - offsetof(struct sockaddr_un, sun_path));\n        *addrlen = strlen(s) + offsetof(struct sockaddr_un, sun_path);\n        free(s);\n      } else {\n        // This also includes abstract names, where sun_path[0] == '\\0'.\n        addr->sa_family = AF_UNIX;\n        strncpy(addr->sa_data, hostun->sun_path,\n                *addrlen - offsetof(struct sockaddr_un, sun_path));\n        *addrlen =\n            strlen(hostun->sun_path) + offsetof(struct sockaddr_un, sun_path);\n      }\n      free(hostun);\n      return 0;\n    }\n  }\n}\n\nint HostfsRename(struct VfsInfo *oldinfo, const char *oldname,\n                 struct VfsInfo *newinfo, const char *newname) {\n  int oldhostfd, newhostfd;\n  char oldhostname[VFS_PATH_MAX], newhostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsRename(%p, %s, %p, %s)\", oldinfo, oldname, newinfo, newname);\n  if (HostfsGetOptimalDirFdName(oldinfo, oldname, &oldhostfd, oldhostname) ==\n      -1) {\n    return -1;\n  }\n  if (HostfsGetOptimalDirFdName(newinfo, newname, &newhostfd, newhostname) ==\n      -1) {\n    unassert(!close(oldhostfd));\n    return -1;\n  }\n  return renameat(oldhostfd, oldhostname, newhostfd, newhostname);\n}\n\nint HostfsUtime(struct VfsInfo *info, const char *name,\n                const struct timespec times[2], int flags) {\n  int hostfd;\n  char hostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsUtime(%p, %s, %p, %d)\", info, name, times, flags);\n  if (HostfsGetOptimalDirFdName(info, name, &hostfd, hostname) == -1) {\n    return -1;\n  }\n  return utimensat(hostfd, hostname, times, flags);\n}\n\nint HostfsFutime(struct VfsInfo *info, const struct timespec times[2]) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsFutime(%p, %p)\", info, times);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  if (futimens(hostinfo->filefd, times) == -1) {\n    return -1;\n  }\n  return 0;\n}\n\nint HostfsSymlink(const char *target, struct VfsInfo *info, const char *name) {\n  int hostfd;\n  char hostname[VFS_PATH_MAX];\n  VFS_LOGF(\"HostfsSymlink(%s, %p, %s)\", target, info, name);\n  if (HostfsGetOptimalDirFdName(info, name, &hostfd, hostname) == -1) {\n    return -1;\n  }\n  return symlinkat(target, hostfd, hostname);\n}\n\nvoid *HostfsMmap(struct VfsInfo *info, void *addr, size_t len, int prot,\n                 int flags, off_t offset) {\n#ifdef __CYGWIN__\n  struct stat st;\n#endif\n  void *ret;\n  int fd;\n  VFS_LOGF(\"HostfsMmap(%p, %p, %zu, %d, %d, %zd)\", info, addr, len, prot, flags,\n           offset);\n  if (info == NULL) {\n    efault();\n    return MAP_FAILED;\n  }\n  fd = ((struct HostfsInfo *)info->data)->filefd;\n#ifdef __CYGWIN__\n  if (fstat(fd, &st) != -1) {\n    if (offset >= st.st_size) {\n      // Cygwin doesn't like mapping files with offset past the end.\n      fd = -1;\n      flags |= MAP_ANONYMOUS;\n      offset = 0;\n    }\n  }\n#endif\n  ret = mmap(addr, len, prot, flags, fd, offset);\n  VFS_LOGF(\"mmap(%p, %zu, %d, %d, %d, %zd) -> %p\", addr, len, prot, flags, fd,\n           offset, ret);\n  return ret;\n}\n\nint HostfsMunmap(struct VfsInfo *info, void *addr, size_t len) {\n  VFS_LOGF(\"HostfsMunmap(%p, %p, %zu)\", info, addr, len);\n  // Do nothing. The host should handle all the cleanup.\n  return 0;\n}\n\nint HostfsMprotect(struct VfsInfo *info, void *addr, size_t len, int prot) {\n  VFS_LOGF(\"HostfsMprotect(%p, %p, %zu, %d)\", info, addr, len, prot);\n  // Do nothing, as the host should handle the protection details.\n  return 0;\n}\n\nint HostfsMsync(struct VfsInfo *info, void *addr, size_t len, int flags) {\n  VFS_LOGF(\"HostfsMsync(%p, %p, %zu, %d)\", info, addr, len, flags);\n  // Do nothing, as the host should handle the syncing.\n  return 0;\n}\n\nint HostfsTcgetattr(struct VfsInfo *info, struct termios *termios) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsTcgetattr(%p, %p)\", info, termios);\n  if (info == NULL || termios == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return tcgetattr(hostinfo->filefd, termios);\n}\n\nint HostfsTcsetattr(struct VfsInfo *info, int optional_actions,\n                    const struct termios *termios) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsTcsetattr(%p, %d, %p)\", info, optional_actions, termios);\n  if (info == NULL || termios == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return tcsetattr(hostinfo->filefd, optional_actions, termios);\n}\n\nint HostfsTcflush(struct VfsInfo *info, int queue_selector) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsTcflush(%p, %d)\", info, queue_selector);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return tcflush(hostinfo->filefd, queue_selector);\n}\n\nint HostfsTcdrain(struct VfsInfo *info) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsTcdrain(%p)\", info);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return tcdrain(hostinfo->filefd);\n}\n\nint HostfsTcsendbreak(struct VfsInfo *info, int duration) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsTcsendbreak(%p, %d)\", info, duration);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return tcsendbreak(hostinfo->filefd, duration);\n}\n\nint HostfsTcflow(struct VfsInfo *info, int action) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsTcflow(%p, %d)\", info, action);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return tcflow(hostinfo->filefd, action);\n}\n\npid_t HostfsTcgetsid(struct VfsInfo *info) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsTcgetsid(%p)\", info);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return tcgetsid(hostinfo->filefd);\n}\n\npid_t HostfsTcgetpgrp(struct VfsInfo *info) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsTcgetpgrp(%p)\", info);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return tcgetpgrp(hostinfo->filefd);\n}\n\nint HostfsTcsetpgrp(struct VfsInfo *info, pid_t pgrp) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsTcsetpgrp(%p, %d)\", info, pgrp);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return tcsetpgrp(hostinfo->filefd, pgrp);\n}\n\n#ifdef HAVE_SOCKATMARK\nint HostfsSockatmark(struct VfsInfo *info) {\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsSockatmark(%p)\", info);\n  if (info == NULL) {\n    return efault();\n  }\n  hostinfo = (struct HostfsInfo *)info->data;\n  return sockatmark(hostinfo->filefd);\n}\n#endif\n\nint HostfsPipe(struct VfsInfo *infos[2]) {\n  int i;\n  int fds[2];\n  VFS_LOGF(\"HostfsPipe(%p)\", infos);\n  if (infos == NULL) {\n    return efault();\n  }\n  fds[0] = fds[1] = -1;\n  infos[0] = infos[1] = NULL;\n  if (pipe(fds) == -1) {\n    return -1;\n  }\n  for (i = 0; i < 2; ++i) {\n    if (HostfsWrapFd(fds[i], false, &infos[i]) == -1) {\n      goto cleananddie;\n    }\n  }\n  return 0;\ncleananddie:\n  for (i = 0; i < 2; ++i) {\n    if (infos[i] != NULL) {\n      unassert(!VfsFreeInfo(infos[i]));\n    } else if (fds[i] != -1) {\n      unassert(!close(fds[i]));\n    }\n  }\n  return -1;\n}\n\n// TODO(trungnt): pipe2() should be polyfilled not partially disabled\n#ifdef HAVE_PIPE2\nint HostfsPipe2(struct VfsInfo *infos[2], int flags) {\n  int i;\n  int fds[2];\n  VFS_LOGF(\"HostfsPipe2(%p, %d)\", infos, flags);\n  if (infos == NULL) {\n    return efault();\n  }\n  fds[0] = fds[1] = -1;\n  infos[0] = infos[1] = NULL;\n  if (pipe2(fds, flags) == -1) {\n    return -1;\n  }\n  for (i = 0; i < 2; ++i) {\n    if (HostfsWrapFd(fds[i], false, &infos[i]) == -1) {\n      goto cleananddie;\n    }\n  }\n  return 0;\ncleananddie:\n  for (i = 0; i < 2; ++i) {\n    if (infos[i] != NULL) {\n      unassert(!VfsFreeInfo(infos[i]));\n    } else if (fds[i] != -1) {\n      unassert(!close(fds[i]));\n    }\n  }\n  return -1;\n}\n#endif\n\nint HostfsSocket(int domain, int type, int protocol, struct VfsInfo **output) {\n  int fd;\n  VFS_LOGF(\"HostfsSocket(%d, %d, %d, %p)\", domain, type, protocol, output);\n  if (output == NULL) {\n    return efault();\n  }\n  fd = -1;\n  *output = NULL;\n  fd = socket(domain, type, protocol);\n  if (fd == -1) {\n    goto cleananddie;\n  }\n  if (HostfsWrapFd(fd, false, output) == -1) {\n    goto cleananddie;\n  }\n  ((struct HostfsInfo *)(*output)->data)->socketfamily = domain;\n  return 0;\ncleananddie:\n  if (*output != NULL) {\n    unassert(!VfsFreeInfo(*output));\n  } else if (fd != -1) {\n    unassert(!close(fd));\n  }\n  return -1;\n}\n\nint HostfsSocketpair(int domain, int type, int protocol,\n                     struct VfsInfo *infos[2]) {\n  int i;\n  int fds[2];\n  VFS_LOGF(\"HostfsSocketpair(%d, %d, %d, %p)\", domain, type, protocol, infos);\n  if (infos == NULL) {\n    return efault();\n  }\n  fds[0] = fds[1] = -1;\n  infos[0] = infos[1] = NULL;\n  if (socketpair(domain, type, protocol, fds) == -1) {\n    return -1;\n  }\n  for (i = 0; i < 2; ++i) {\n    if (HostfsWrapFd(fds[i], false, &infos[i]) == -1) {\n      goto cleananddie;\n    }\n    ((struct HostfsInfo *)infos[i]->data)->socketfamily = domain;\n  }\n  return 0;\ncleananddie:\n  for (i = 0; i < 2; ++i) {\n    if (infos[i] != NULL) {\n      unassert(!VfsFreeInfo(infos[i]));\n    } else if (fds[i] != -1) {\n      unassert(!close(fds[i]));\n    }\n  }\n  return -1;\n}\n\nint HostfsFexecve(struct VfsInfo *info, char *const *argv, char *const *envp) {\n#ifndef HAVE_FEXECVE\n  char path[VFS_PATH_MAX];\n#endif\n  VFS_LOGF(\"HostfsFexecve(%p, %p, %p)\", info, argv, envp);\n#ifdef HAVE_FEXECVE\n  if (info == NULL) {\n    return efault();\n  }\n  struct HostfsInfo *hostinfo;\n  hostinfo = (struct HostfsInfo *)info->data;\n  return fexecve(hostinfo->filefd, argv, envp);\n#else\n  if (HostfsGetHostPath(info, path) == -1) {\n    return -1;\n  }\n  return execve(path, argv, envp);\n#endif\n}\n\nstruct VfsDevice g_anondevice = {\n    .mounts = NULL,\n    .ops = &g_hostfs.ops,\n    .data = NULL,\n    .dev = -1u,\n    .refcount = 1u,\n};\n\nint HostfsWrapFd(int fd, bool dodup, struct VfsInfo **output) {\n  struct stat st;\n  struct HostfsInfo *hostinfo;\n  VFS_LOGF(\"HostfsWrapFd(%d, %p)\", fd, output);\n  if (output == NULL) {\n    return efault();\n  }\n  hostinfo = NULL;\n  *output = NULL;\n  if (dodup) {\n    fd = dup(fd);\n    if (fd == -1) {\n      return -1;\n    }\n  }\n  if (fstat(fd, &st) == -1) {\n    goto cleananddie;\n  }\n  if (HostfsCreateInfo(&hostinfo) == -1) {\n    goto cleananddie;\n  }\n  hostinfo->filefd = fd;\n  hostinfo->mode = st.st_mode;\n  if (VfsCreateInfo(output) == -1) {\n    goto cleananddie;\n  }\n  (*output)->data = hostinfo;\n  (*output)->parent = NULL;\n  (*output)->dev = -1;\n  (*output)->ino =\n      HostfsHash(st.st_dev, (const char *)&st.st_ino, sizeof(st.st_ino));\n  (*output)->mode = st.st_mode;\n  (*output)->refcount = 1;\n  unassert(!VfsAcquireDevice(&g_anondevice, &(*output)->device));\n  return 0;\ncleananddie:\n  if (*output != NULL) {\n    unassert(!VfsFreeInfo(*output));\n  } else if (hostinfo != NULL) {\n    unassert(!HostfsFreeInfo(hostinfo));\n  } else if (dodup && fd != -1) {\n    unassert(!close(fd));\n  }\n  return -1;\n}\n\nstruct VfsSystem g_hostfs = {.name = \"hostfs\",\n                             .nodev = true,\n                             .ops = {\n                                 .Init = HostfsInit,\n                                 .Freeinfo = HostfsFreeInfo,\n                                 .Freedevice = HostfsFreeDevice,\n                                 .Readmountentry = HostfsReadmountentry,\n                                 .Finddir = HostfsFinddir,\n                                 .Traverse = HostfsTraverse,\n                                 .Readlink = HostfsReadlink,\n                                 .Mkdir = HostfsMkdir,\n                                 .Mkfifo = HostfsMkfifo,\n                                 .Open = HostfsOpen,\n                                 .Access = HostfsAccess,\n                                 .Stat = HostfsStat,\n                                 .Fstat = HostfsFstat,\n                                 .Chmod = HostfsChmod,\n                                 .Fchmod = HostfsFchmod,\n                                 .Chown = HostfsChown,\n                                 .Fchown = HostfsFchown,\n                                 .Ftruncate = HostfsFtruncate,\n                                 .Close = HostfsClose,\n                                 .Link = HostfsLink,\n                                 .Unlink = HostfsUnlink,\n                                 .Read = HostfsRead,\n                                 .Write = HostfsWrite,\n                                 .Pread = HostfsPread,\n                                 .Pwrite = HostfsPwrite,\n                                 .Readv = HostfsReadv,\n                                 .Writev = HostfsWritev,\n                                 .Preadv = HostfsPreadv,\n                                 .Pwritev = HostfsPwritev,\n                                 .Seek = HostfsSeek,\n                                 .Fsync = HostfsFsync,\n                                 .Fdatasync = HostfsFdatasync,\n                                 .Flock = HostfsFlock,\n                                 .Fcntl = HostfsFcntl,\n                                 .Ioctl = HostfsIoctl,\n                                 .Dup = HostfsDup,\n#ifdef HAVE_DUP3\n                                 .Dup3 = HostfsDup3,\n#endif\n                                 .Poll = HostfsPoll,\n                                 .Opendir = HostfsOpendir,\n#ifdef HAVE_SEEKDIR\n                                 .Seekdir = HostfsSeekdir,\n                                 .Telldir = HostfsTelldir,\n#endif\n                                 .Readdir = HostfsReaddir,\n                                 .Rewinddir = HostfsRewinddir,\n                                 .Closedir = HostfsClosedir,\n                                 .Bind = HostfsBind,\n                                 .Connect = HostfsConnect,\n                                 .Connectunix = HostfsConnectUnix,\n                                 .Accept = HostfsAccept,\n                                 .Listen = HostfsListen,\n                                 .Shutdown = HostfsShutdown,\n                                 .Recvmsg = HostfsRecvmsg,\n                                 .Sendmsg = HostfsSendmsg,\n                                 .Recvmsgunix = HostfsRecvmsgUnix,\n                                 .Sendmsgunix = HostfsSendmsgUnix,\n                                 .Getsockopt = HostfsGetsockopt,\n                                 .Setsockopt = HostfsSetsockopt,\n                                 .Getsockname = HostfsGetsockname,\n                                 .Getpeername = HostfsGetpeername,\n                                 .Rename = HostfsRename,\n                                 .Utime = HostfsUtime,\n                                 .Futime = HostfsFutime,\n                                 .Symlink = HostfsSymlink,\n                                 .Mmap = HostfsMmap,\n                                 .Munmap = HostfsMunmap,\n                                 .Mprotect = HostfsMprotect,\n                                 .Msync = HostfsMsync,\n                                 .Pipe = HostfsPipe,\n#ifdef HAVE_PIPE2\n                                 .Pipe2 = HostfsPipe2,\n#endif\n                                 .Socket = HostfsSocket,\n                                 .Socketpair = HostfsSocketpair,\n                                 .Tcgetattr = HostfsTcgetattr,\n                                 .Tcsetattr = HostfsTcsetattr,\n                                 .Tcflush = HostfsTcflush,\n                                 .Tcdrain = HostfsTcdrain,\n                                 .Tcsendbreak = HostfsTcsendbreak,\n                                 .Tcflow = HostfsTcflow,\n                                 .Tcgetsid = HostfsTcgetsid,\n                                 .Tcgetpgrp = HostfsTcgetpgrp,\n                                 .Tcsetpgrp = HostfsTcsetpgrp,\n#ifdef HAVE_SOCKATMARK\n                                 .Sockatmark = HostfsSockatmark,\n#endif\n                                 .Fexecve = HostfsFexecve,\n                             }};\n\n#endif /* DISABLE_VFS */\n"
  },
  {
    "path": "blink/hostfs.h",
    "content": "#ifndef BLINK_HOSTFS_H_\n#define BLINK_HOSTFS_H_\n\n#include <sys/types.h>\n#include <sys/un.h>\n\n#include \"blink/vfs.h\"\n\nstruct HostfsInfo {\n  int mode;\n  int filefd;\n  int socketfamily;\n  union {\n    DIR *dirstream;\n    struct sockaddr *socketaddr;\n  };\n  socklen_t socketaddrlen;\n  struct sockaddr *socketpeeraddr;\n  socklen_t socketpeeraddrlen;\n};\n\nint HostfsInit(const char *, u64, const void *, struct VfsDevice **,\n               struct VfsMount **);\nint HostfsCreateInfo(struct HostfsInfo **);\nint HostfsFreeInfo(void *);\nint HostfsFreeDevice(void *);\nint HostfsFinddir(struct VfsInfo *, const char *, struct VfsInfo **);\nint HostfsTraverse(struct VfsInfo **dir, const char **path,\n                   struct VfsInfo *root);\nssize_t HostfsReadlink(struct VfsInfo *, char **);\nint HostfsMkdir(struct VfsInfo *, const char *, mode_t);\nint HostfsMkfifo(struct VfsInfo *, const char *, mode_t);\nint HostfsOpen(struct VfsInfo *, const char *, int, int, struct VfsInfo **);\nint HostfsAccess(struct VfsInfo *, const char *, mode_t, int);\nint HostfsStat(struct VfsInfo *, const char *, struct stat *, int);\nint HostfsFstat(struct VfsInfo *, struct stat *);\nint HostfsChmod(struct VfsInfo *, const char *, mode_t, int);\nint HostfsFchmod(struct VfsInfo *, mode_t);\nint HostfsChown(struct VfsInfo *, const char *, uid_t, gid_t, int);\nint HostfsFchown(struct VfsInfo *, uid_t, gid_t);\nint HostfsFtruncate(struct VfsInfo *, off_t);\nint HostfsClose(struct VfsInfo *);\nint HostfsLink(struct VfsInfo *, const char *, struct VfsInfo *, const char *,\n               int);\nint HostfsUnlink(struct VfsInfo *, const char *, int);\nssize_t HostfsRead(struct VfsInfo *, void *, size_t);\nssize_t HostfsWrite(struct VfsInfo *, const void *, size_t);\nssize_t HostfsPread(struct VfsInfo *, void *, size_t, off_t);\nssize_t HostfsPwrite(struct VfsInfo *, const void *, size_t, off_t);\nssize_t HostfsReadv(struct VfsInfo *, const struct iovec *, int);\nssize_t HostfsWritev(struct VfsInfo *, const struct iovec *, int);\nssize_t HostfsPreadv(struct VfsInfo *, const struct iovec *, int, off_t);\nssize_t HostfsPwritev(struct VfsInfo *, const struct iovec *, int, off_t);\noff_t HostfsSeek(struct VfsInfo *, off_t, int);\nint HostfsFsync(struct VfsInfo *);\nint HostfsFdatasync(struct VfsInfo *);\nint HostfsFlock(struct VfsInfo *, int);\nint HostfsFcntl(struct VfsInfo *, int, va_list);\nint HostfsIoctl(struct VfsInfo *, unsigned long, const void *);\nint HostfsDup(struct VfsInfo *, struct VfsInfo **);\n#ifdef HAVE_DUP3\nint HostfsDup3(struct VfsInfo *, struct VfsInfo **, int);\n#endif\nint HostfsPoll(struct VfsInfo **, struct pollfd *, nfds_t, int);\nint HostfsOpendir(struct VfsInfo *, struct VfsInfo **);\n#ifdef HAVE_SEEKDIR\nvoid HostfsSeekdir(struct VfsInfo *, long);\nlong HostfsTelldir(struct VfsInfo *);\n#endif\nstruct dirent *HostfsReaddir(struct VfsInfo *);\nvoid HostfsRewinddir(struct VfsInfo *);\nint HostfsClosedir(struct VfsInfo *);\nint HostfsBind(struct VfsInfo *, const struct sockaddr *, socklen_t);\nint HostfsConnect(struct VfsInfo *, const struct sockaddr *, socklen_t);\nint HostfsConnectUnix(struct VfsInfo *, struct VfsInfo *,\n                      const struct sockaddr_un *, socklen_t);\nint HostfsAccept(struct VfsInfo *, struct sockaddr *, socklen_t *,\n                 struct VfsInfo **);\nint HostfsListen(struct VfsInfo *, int);\nint HostfsShutdown(struct VfsInfo *, int);\nssize_t HostfsRecvmsg(struct VfsInfo *, struct msghdr *, int);\nssize_t HostfsSendmsg(struct VfsInfo *, const struct msghdr *, int);\nssize_t HostfsRecvmsgUnix(struct VfsInfo *, struct VfsInfo *, struct msghdr *,\n                          int);\nssize_t HostfsSendmsgUnix(struct VfsInfo *, struct VfsInfo *,\n                          const struct msghdr *, int);\nint HostfsGetsockopt(struct VfsInfo *, int, int, void *, socklen_t *);\nint HostfsSetsockopt(struct VfsInfo *, int, int, const void *, socklen_t);\nint HostfsGetsockname(struct VfsInfo *, struct sockaddr *, socklen_t *);\nint HostfsGetpeername(struct VfsInfo *, struct sockaddr *, socklen_t *);\nint HostfsRename(struct VfsInfo *, const char *, struct VfsInfo *,\n                 const char *);\nint HostfsUtime(struct VfsInfo *, const char *, const struct timespec[2], int);\nint HostfsFutime(struct VfsInfo *, const struct timespec[2]);\nint HostfsSymlink(const char *, struct VfsInfo *, const char *);\n\nvoid *HostfsMmap(struct VfsInfo *, void *, size_t, int, int, off_t);\nint HostfsMunmap(struct VfsInfo *, void *, size_t);\nint HostfsMprotect(struct VfsInfo *, void *, size_t, int);\nint HostfsMsync(struct VfsInfo *, void *, size_t, int);\n\nint HostfsPipe(struct VfsInfo *[2]);\nint HostfsPipe2(struct VfsInfo *[2], int);\nint HostfsSocket(int, int, int, struct VfsInfo **);\nint HostfsSocketpair(int, int, int, struct VfsInfo *[2]);\n\nint HostfsTcgetattr(struct VfsInfo *, struct termios *);\nint HostfsTcsetattr(struct VfsInfo *, int, const struct termios *);\nint HostfsTcflush(struct VfsInfo *, int);\nint HostfsTcdrain(struct VfsInfo *);\nint HostfsTcsendbreak(struct VfsInfo *, int);\nint HostfsTcflow(struct VfsInfo *, int);\npid_t HostfsTcgetsid(struct VfsInfo *);\npid_t HostfsTcgetpgrp(struct VfsInfo *);\nint HostfsTcsetpgrp(struct VfsInfo *, pid_t);\n#ifdef HAVE_SOCKATMARK\nint HostfsSockatmark(struct VfsInfo *);\n#endif\nint HostfsFexecve(struct VfsInfo *, char *const *, char *const *);\n\nint HostfsWrapFd(int fd, bool dodup, struct VfsInfo **output);\n\nextern struct VfsSystem g_hostfs;\n\n#endif  // BLINK_HOSTFS_H_\n"
  },
  {
    "path": "blink/instruction.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n\n#include \"blink/assert.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/endian.h\"\n#include \"blink/linux.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/stats.h\"\n#include \"blink/x86.h\"\n\nstatic bool IsOpcodeEqual(struct XedDecodedInst *xedd, u8 *a) {\n  int n;\n  u64 w;\n  if ((n = xedd->length)) {\n    unassert(n <= 15);\n    if (n <= 7) {\n      w = Read64(a) ^ Read64(xedd->bytes);\n      return !w || (bsf(w) >> 3) >= n;\n    } else {\n      return !memcmp(a, xedd->bytes, n);\n    }\n  } else {\n    return false;\n  }\n}\n\nstatic int ReadInstruction(struct Machine *m, u8 *p, unsigned n) {\n  struct XedDecodedInst xedd[1];\n  STATISTIC(++instructions_decoded);\n  if (!DecodeInstruction(xedd, p, n, m->mode.omode)) {\n    memcpy(m->xedd, xedd, kInstructionBytes);\n    return 0;\n  } else {\n    return kMachineDecodeError;\n  }\n}\n\nstatic int LoadInstructionSlow(struct Machine *m, u64 ip) {\n  u8 *addr;\n  unsigned i;\n  u8 copy[15], *toil;\n  i = 4096 - (ip & 4095);\n  STATISTIC(++page_overlaps);\n  if ((addr = LookupAddress2(m, ip, PAGE_XD, 0))) {\n    if ((toil = LookupAddress2(m, ip + i, PAGE_XD, 0))) {\n      memcpy(copy, addr, i);\n      memcpy(copy + i, toil, 15 - i);\n      return ReadInstruction(m, copy, 15);\n    } else {\n      return ReadInstruction(m, addr, i);\n    }\n  } else {\n    return kMachineSegmentationFault;\n  }\n}\n\nint LoadInstruction2(struct Machine *m, u64 pc) {\n  unsigned key;\n  u8 *addr, *page;\n  if (atomic_load_explicit(&m->opcache->invalidated, memory_order_acquire)) {\n    ResetInstructionCache(m);\n    atomic_store_explicit(&m->opcache->invalidated, false,\n                          memory_order_relaxed);\n  }\n  key = pc & (ARRAYLEN(m->opcache->icache) - 1);\n  m->xedd = (struct XedDecodedInst *)m->opcache->icache[key];\n  if ((pc & 4095) + 15 <= 4096) {\n    if (pc - (pc & 4095) == m->opcache->codevirt && m->opcache->codehost) {\n      addr = m->opcache->codehost + (pc & 4095);\n    } else if ((page = LookupAddress2(m, pc - (pc & 4095), PAGE_XD, 0))) {\n      m->opcache->codevirt = pc - (pc & 4095);\n      m->opcache->codehost = page;\n      addr = page + (pc & 4095);\n    } else {\n      return kMachineSegmentationFault;\n    }\n    if (IsOpcodeEqual(m->xedd, addr)) {\n      STATISTIC(++instructions_cached);\n      return 0;\n    } else {\n      return ReadInstruction(m, addr, 15);\n    }\n  } else {\n    return LoadInstructionSlow(m, pc);\n  }\n}\n\nvoid LoadInstruction(struct Machine *m, u64 pc) {\n  int rc;\n  switch ((rc = LoadInstruction2(m, pc))) {\n    case 0:\n      break;\n    case kMachineSegmentationFault:\n      m->faultaddr = pc;\n      HaltMachine(m, rc);\n    case kMachineDecodeError:\n      HaltMachine(m, rc);\n    default:\n      HaltMachine(m, rc);\n  }\n}\n"
  },
  {
    "path": "blink/intrin.h",
    "content": "#ifndef BLINK_INTRIN_H_\n#define BLINK_INTRIN_H_\n\n#if defined(__x86_64__) && defined(__GNUC__) && __GNUC__ >= 6\n#define X86_INTRINSICS 1\ntypedef char char_xmmu_t __attribute__((__vector_size__(16), __may_alias__));\ntypedef char char_xmma_t\n    __attribute__((__vector_size__(16), __aligned__(16), __may_alias__));\n#else\n#define X86_INTRINSICS 0\n#endif\n#if defined(__aarch64__) && defined(__GNUC__)\n#define ARM_INTRINSICS 1\n#else\n#define ARM_INTRINSICS 0\n#endif\n\n#endif /* BLINK_INTRIN_H_ */\n"
  },
  {
    "path": "blink/ioctl.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <fcntl.h>\n#include <net/if.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#include <sys/socket.h>\n#include <termios.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/errno.h\"\n#include \"blink/fds.h\"\n#include \"blink/linux.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/ndelay.h\"\n#include \"blink/syscall.h\"\n#include \"blink/thread.h\"\n#include \"blink/types.h\"\n#include \"blink/vfs.h\"\n#include \"blink/xlat.h\"\n\n#ifdef __HAIKU__\n#include <OS.h>\n#include <sys/sockio.h>\n#endif\n\nstatic int IoctlTiocgwinsz(struct Machine *m, int fd, i64 addr,\n                           int fn(int, struct winsize *)) {\n  int rc;\n  struct winsize ws;\n  struct winsize_linux gws;\n  if ((rc = fn(fd, &ws)) != -1) {\n    XlatWinsizeToLinux(&gws, &ws);\n    if (CopyToUserWrite(m, addr, &gws, sizeof(gws)) == -1) rc = -1;\n  }\n  return rc;\n}\n\nstatic int IoctlTiocswinsz(struct Machine *m, int fd, i64 addr,\n                           int fn(int, const struct winsize *)) {\n  struct winsize ws;\n  struct winsize_linux gws;\n  if (CopyFromUserRead(m, &gws, addr, sizeof(gws)) == -1) return -1;\n  XlatWinsizeToHost(&ws, &gws);\n  return fn(fd, &ws);\n}\n\nstatic int IoctlTcgets(struct Machine *m, int fd, i64 addr,\n                       int fn(int, struct termios *)) {\n  int rc;\n  struct termios tio;\n  struct termios_linux gtio;\n  if ((rc = fn(fd, &tio)) != -1) {\n    XlatTermiosToLinux(&gtio, &tio);\n    if (CopyToUserWrite(m, addr, &gtio, sizeof(gtio)) == -1) rc = -1;\n  }\n  return rc;\n}\n\nstatic int IoctlTcsets(struct Machine *m, int fd, int request, i64 addr,\n                       int fn(int, int, const struct termios *)) {\n  struct termios tio;\n  struct termios_linux gtio;\n  if (CopyFromUserRead(m, &gtio, addr, sizeof(gtio)) == -1) return -1;\n  XlatLinuxToTermios(&tio, &gtio);\n  return fn(fd, request, &tio);\n}\n\nstatic int IoctlTiocgpgrp(struct Machine *m, int fd, i64 addr) {\n  int rc;\n  u8 *pgrp;\n#ifdef __EMSCRIPTEN__\n  // Force shells to disable job control in emscripten\n  errno = ENOTTY;\n  return -1;\n#endif\n  if (!(pgrp = (u8 *)SchlepW(m, addr, 4))) return -1;\n  if ((rc = VfsTcgetpgrp(fd)) == -1) return -1;\n  Write32(pgrp, rc);\n  return 0;\n}\n\nstatic int IoctlTiocspgrp(struct Machine *m, int fd, i64 addr) {\n  u8 *pgrp;\n  if (!(pgrp = (u8 *)SchlepR(m, addr, 4))) return -1;\n  return VfsTcsetpgrp(fd, Read32(pgrp));\n}\n\n#ifdef HAVE_SIOCGIFCONF\n\nstatic int IoctlSiocgifconf(struct Machine *m, int systemfd, i64 ifconf_addr) {\n  size_t i;\n  char *buf;\n  size_t len;\n  size_t bufsize;\n  char *buf_linux;\n  size_t len_linux;\n  struct ifreq *ifreq;\n  struct ifconf ifconf;\n  struct ifreq_linux ifreq_linux;\n  struct ifconf_linux ifconf_linux;\n  const struct ifconf_linux *ifconf_linuxp;\n  memset(&ifreq_linux, 0, sizeof(ifreq_linux));\n  if (!(ifconf_linuxp = (const struct ifconf_linux *)SchlepRW(\n            m, ifconf_addr, sizeof(*ifconf_linuxp))) ||\n      !IsValidMemory(m, Read64(ifconf_linuxp->buf), Read32(ifconf_linuxp->len),\n                     PROT_WRITE)) {\n    return efault();\n  }\n  bufsize = MIN(16384, Read32(ifconf_linuxp->len));\n  if (!(buf = (char *)AddToFreeList(m, malloc(bufsize)))) return -1;\n  if (!(buf_linux = (char *)AddToFreeList(m, malloc(bufsize)))) return -1;\n  ifconf.ifc_len = bufsize;\n  ifconf.ifc_buf = buf;\n  if (VfsIoctl(systemfd, SIOCGIFCONF, &ifconf)) return -1;\n  len_linux = 0;\n  ifreq = ifconf.ifc_req;\n  for (i = 0; i < ifconf.ifc_len;) {\n    if (len_linux + sizeof(ifreq_linux) > bufsize) break;\n#ifdef HAVE_SA_LEN\n    len = IFNAMSIZ + ifreq->ifr_addr.sa_len;\n#else\n    len = sizeof(*ifreq);\n#endif\n    if (ifreq->ifr_addr.sa_family == AF_INET) {\n      memset(ifreq_linux.name, 0, sizeof(ifreq_linux.name));\n      memcpy(ifreq_linux.name, ifreq->ifr_name,\n             MIN(sizeof(ifreq_linux.name) - 1, sizeof(ifreq->ifr_name)));\n      unassert(XlatSockaddrToLinux(\n                   (struct sockaddr_storage_linux *)&ifreq_linux.addr,\n                   (const struct sockaddr *)&ifreq->ifr_addr,\n                   sizeof(ifreq->ifr_addr)) ==\n               sizeof(struct sockaddr_in_linux));\n      memcpy(buf_linux + len_linux, &ifreq_linux, sizeof(ifreq_linux));\n      len_linux += sizeof(ifreq_linux);\n    }\n    ifreq = (struct ifreq *)((char *)ifreq + len);\n    i += len;\n  }\n  Write32(ifconf_linux.len, len_linux);\n  Write32(ifconf_linux.pad, 0);\n  Write64(ifconf_linux.buf, Read64(ifconf_linuxp->buf));\n  CopyToUserWrite(m, Read64(ifconf_linux.buf), buf_linux, len_linux);\n  CopyToUserWrite(m, ifconf_addr, &ifconf_linux, sizeof(ifconf_linux));\n  return 0;\n}\n\nstatic int IoctlSiocgifaddr(struct Machine *m, int systemfd, i64 ifreq_addr,\n                            unsigned long kind) {\n  struct ifreq ifreq;\n  struct ifreq_linux ifreq_linux;\n  if (!IsValidMemory(m, ifreq_addr, sizeof(ifreq_linux),\n                     PROT_READ | PROT_WRITE)) {\n    return efault();\n  }\n  CopyFromUserRead(m, &ifreq_linux, ifreq_addr, sizeof(ifreq_linux));\n  memset(ifreq.ifr_name, 0, sizeof(ifreq.ifr_name));\n  memcpy(ifreq.ifr_name, ifreq_linux.name,\n         MIN(sizeof(ifreq_linux.name) - 1, sizeof(ifreq.ifr_name)));\n  if (Read16(ifreq_linux.addr.family) != AF_INET_LINUX) return einval();\n  unassert(XlatSockaddrToHost((struct sockaddr_storage *)&ifreq.ifr_addr,\n                              (const struct sockaddr_linux *)&ifreq_linux.addr,\n                              sizeof(struct sockaddr_in_linux)) ==\n           sizeof(struct sockaddr_in));\n  if (VfsIoctl(systemfd, kind, &ifreq)) return -1;\n  memset(ifreq_linux.name, 0, sizeof(ifreq_linux.name));\n  memcpy(ifreq_linux.name, ifreq.ifr_name,\n         MIN(sizeof(ifreq_linux.name) - 1, sizeof(ifreq.ifr_name)));\n  unassert(XlatSockaddrToLinux(\n               (struct sockaddr_storage_linux *)&ifreq_linux.addr,\n               (struct sockaddr *)&ifreq.ifr_addr,\n               sizeof(ifreq.ifr_addr)) == sizeof(struct sockaddr_in_linux));\n  CopyToUserWrite(m, ifreq_addr, &ifreq_linux, sizeof(ifreq_linux));\n  return 0;\n}\n\n#endif /* HAVE_SIOCGIFCONF */\n\nstatic int IoctlFionbio(struct Machine *m, int fildes) {\n  int oflags;\n  if ((oflags = GetOflags(m, fildes)) == -1) return -1;\n  return VfsFcntl(fildes, F_SETFL, (oflags & SETFL_FLAGS) | O_NDELAY);\n}\n\nstatic int IoctlFioclex(struct Machine *m, int fildes) {\n  return VfsFcntl(fildes, F_SETFD, FD_CLOEXEC);\n}\n\nstatic int IoctlFionclex(struct Machine *m, int fildes) {\n  return VfsFcntl(fildes, F_SETFD, 0);\n}\n\nstatic int IoctlTcsbrk(struct Machine *m, int fildes, int drain) {\n  int rc;\n  if (drain) {\n    RESTARTABLE(rc = VfsTcdrain(fildes));\n  } else {\n    rc = VfsTcsendbreak(fildes, 0);\n  }\n  return rc;\n}\n\nstatic int IoctlTcxonc(struct Machine *m, int fildes, int arg) {\n  return VfsTcflow(fildes, arg);\n}\n\nstatic int IoctlTiocgsid(struct Machine *m, int fildes, i64 addr) {\n  int rc;\n  u8 *sid;\n  if (!(sid = (u8 *)SchlepW(m, addr, 4))) return -1;\n  if ((rc = VfsTcgetsid(fildes)) != -1) {\n    Write32(sid, rc);\n    rc = 0;\n  }\n  return rc;\n}\n\nstatic int XlatFlushQueue(int queue) {\n  switch (queue) {\n    case TCIFLUSH_LINUX:\n      return TCIFLUSH;\n    case TCOFLUSH_LINUX:\n      return TCOFLUSH;\n    case TCIOFLUSH_LINUX:\n      return TCIOFLUSH;\n    default:\n      return einval();\n  }\n}\n\nstatic int IoctlTcflsh(struct Machine *m, int fildes, int queue) {\n  if ((queue = XlatFlushQueue(queue)) == -1) return -1;\n  return VfsTcflush(fildes, queue);\n}\n\n#ifdef HAVE_SOCKATMARK\nstatic int IoctlSiocatmark(struct Machine *m, int fildes, i64 addr) {\n  u8 *p;\n  int rc;\n  if (!(p = (u8 *)SchlepW(m, addr, 4))) return -1;\n  if ((rc = VfsSockatmark(fildes)) != -1) {\n    Write32(p, rc);\n    rc = 0;\n  }\n  return rc;\n}\n#endif\n\nstatic int IoctlGetInt32(struct Machine *m, int fildes, unsigned long cmd,\n                         i64 addr) {\n  u8 *p;\n  int rc, val;\n  if (!(p = (u8 *)SchlepW(m, addr, 4))) return -1;\n  if ((rc = VfsIoctl(fildes, cmd, &val)) != -1) {\n    Write32(p, val);\n  }\n  return rc;\n}\n\nstatic int IoctlSetInt32(struct Machine *m, int fildes, unsigned long cmd,\n                         i64 addr) {\n  int val;\n  const u8 *p;\n  if (!(p = (const u8 *)SchlepR(m, addr, 4))) return -1;\n  val = Read32(p);\n  return VfsIoctl(fildes, cmd, &val);\n}\n\n#ifdef TIOCSTI\nstatic int IoctlTiocsti(struct Machine *m, int fildes, i64 addr) {\n  const u8 *bytep;\n  if (!(bytep = LookupAddress(m, addr))) return efault();\n  return VfsIoctl(fildes, TIOCSTI, (void *)bytep);\n}\n#endif\n\nint SysIoctl(struct Machine *m, int fildes, u64 request, i64 addr) {\n  struct Fd *fd;\n  int (*tcgetattr_impl)(int, struct termios *);\n  int (*tcsetattr_impl)(int, int, const struct termios *);\n  int (*tcgetwinsize_impl)(int, struct winsize *);\n  int (*tcsetwinsize_impl)(int, const struct winsize *);\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    unassert(fd->cb);\n    unassert(tcgetattr_impl = fd->cb->tcgetattr);\n    unassert(tcsetattr_impl = fd->cb->tcsetattr);\n    unassert(tcgetwinsize_impl = fd->cb->tcgetwinsize);\n    unassert(tcsetwinsize_impl = fd->cb->tcsetwinsize);\n  } else {\n    tcsetattr_impl = 0;\n    tcgetattr_impl = 0;\n    tcgetwinsize_impl = 0;\n    tcsetwinsize_impl = 0;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!fd) return -1;\n  switch (request) {\n    case TIOCGWINSZ_LINUX:\n      return IoctlTiocgwinsz(m, fildes, addr, tcgetwinsize_impl);\n    case TIOCSWINSZ_LINUX:\n      return IoctlTiocswinsz(m, fildes, addr, tcsetwinsize_impl);\n    case TCGETS_LINUX:\n      return IoctlTcgets(m, fildes, addr, tcgetattr_impl);\n    case TCSETS_LINUX:\n      return IoctlTcsets(m, fildes, TCSANOW, addr, tcsetattr_impl);\n    case TCSETSW_LINUX:\n      return IoctlTcsets(m, fildes, TCSADRAIN, addr, tcsetattr_impl);\n    case TCSETSF_LINUX:\n      return IoctlTcsets(m, fildes, TCSAFLUSH, addr, tcsetattr_impl);\n    case TIOCGPGRP_LINUX:\n      return IoctlTiocgpgrp(m, fildes, addr);\n    case TIOCSPGRP_LINUX:\n      return IoctlTiocspgrp(m, fildes, addr);\n#ifndef DISABLE_NONPOSIX\n    case FIONBIO_LINUX:\n      return IoctlFionbio(m, fildes);\n    case FIOCLEX_LINUX:\n      return IoctlFioclex(m, fildes);\n    case FIONCLEX_LINUX:\n      return IoctlFionclex(m, fildes);\n#endif\n    case TCSBRK_LINUX:\n      return IoctlTcsbrk(m, fildes, addr);\n    case TCXONC_LINUX:\n      return IoctlTcxonc(m, fildes, addr);\n    case TIOCGSID_LINUX:\n      return IoctlTiocgsid(m, fildes, addr);\n    case TCFLSH_LINUX:\n      return IoctlTcflsh(m, fildes, addr);\n#ifdef HAVE_SOCKATMARK\n#ifndef DISABLE_SOCKETS\n    case SIOCATMARK_LINUX:\n      return IoctlSiocatmark(m, fildes, addr);\n#endif\n#endif\n#ifdef FIONREAD\n    case FIONREAD_LINUX:\n      return IoctlGetInt32(m, fildes, FIONREAD, addr);\n#endif\n#ifdef TIOCOUTQ\n    case TIOCOUTQ_LINUX:\n      return IoctlGetInt32(m, fildes, TIOCOUTQ, addr);\n#endif\n#ifdef TIOCSTI\n    case TIOCSTI_LINUX:\n      return IoctlTiocsti(m, fildes, addr);\n#endif\n#ifdef FIOGETOWN\n    case FIOGETOWN_LINUX:\n      return IoctlGetInt32(m, fildes, FIOGETOWN, addr);\n#endif\n#ifdef FIOSETOWN\n    case FIOSETOWN_LINUX:\n      return IoctlSetInt32(m, fildes, FIOSETOWN, addr);\n#endif\n#ifdef SIOCSPGRP\n    case SIOCSPGRP_LINUX:\n      return IoctlSetInt32(m, fildes, SIOCSPGRP, addr);\n#endif\n#ifdef SIOCGPGRP\n    case SIOCGPGRP_LINUX:\n      return IoctlGetInt32(m, fildes, SIOCGPGRP, addr);\n#endif\n#ifdef HAVE_SIOCGIFCONF\n#ifndef DISABLE_SOCKETS\n#ifndef DISABLE_NONPOSIX\n    case SIOCGIFCONF_LINUX:\n      return IoctlSiocgifconf(m, fildes, addr);\n    case SIOCGIFADDR_LINUX:\n      return IoctlSiocgifaddr(m, fildes, addr, SIOCGIFADDR);\n    case SIOCGIFNETMASK_LINUX:\n      return IoctlSiocgifaddr(m, fildes, addr, SIOCGIFNETMASK);\n    case SIOCGIFBRDADDR_LINUX:\n      return IoctlSiocgifaddr(m, fildes, addr, SIOCGIFBRDADDR);\n    case SIOCGIFDSTADDR_LINUX:\n      return IoctlSiocgifaddr(m, fildes, addr, SIOCGIFDSTADDR);\n#endif /* DISABLE_NONPOSIX */\n#endif /* DISABLE_SOCKETS */\n#endif /* HAVE_SIOCGIFCONF */\n    default:\n      LOGF(\"missing ioctl %#\" PRIx64, request);\n      return einval();\n  }\n}\n"
  },
  {
    "path": "blink/ioports.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <poll.h>\n#include <sys/uio.h>\n\n#include \"blink/debug.h\"\n#include \"blink/machine.h\"\n#include \"blink/syscall.h\"\n#include \"blink/thread.h\"\n#include \"blink/uart.h\"\n\n#ifndef DISABLE_METAL\n\nstatic int OpE9Read(struct Machine *m) {\n  u8 b;\n  struct Fd *fd;\n  int fildes = 0;\n  struct iovec t = {&b, 1};\n  ssize_t (*readv_impl)(int, const struct iovec *, int);\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    readv_impl = fd->cb->readv;\n  } else {\n    readv_impl = 0;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (readv_impl && readv_impl(fildes, &t, 1) == 1) {\n    return b;\n  } else {\n    return -1;\n  }\n}\n\nstatic int OpE9Write(struct Machine *m, u8 b) {\n  struct Fd *fd;\n  int fildes = 1;\n  struct iovec t = {&b, 1};\n  ssize_t (*writev_impl)(int, const struct iovec *, int);\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    writev_impl = fd->cb->writev;\n  } else {\n    writev_impl = 0;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!writev_impl) return -1;\n  return writev_impl(fildes, &t, 1);\n}\n\nstatic int OpE9Poll(struct Machine *m) {\n  int rc;\n  struct Fd *fd;\n  int fildes = 0;\n  struct pollfd pf;\n  int (*poll_impl)(struct pollfd *, nfds_t, int);\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    poll_impl = fd->cb->poll;\n  } else {\n    poll_impl = 0;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!poll_impl) return -1;\n  pf.fd = fildes;\n  pf.events = POLLIN | POLLOUT;\n  rc = poll_impl(&pf, 1, 20);\n  if (rc > 0) rc = pf.revents;\n  return rc;\n}\n\nstatic int OpSerialIn(struct Machine *m, int r) {\n  int p, s;\n  switch (r) {\n    case UART_DLL:\n      if (!m->system->dlab) {\n        return OpE9Read(m);\n      } else {\n        return 1;\n      }\n    case UART_LSR:\n      if ((p = OpE9Poll(m)) == -1) return -1;\n      s = UART_TTYIDL;\n      if (p & POLLIN) s |= UART_TTYDA;\n      if (p & POLLOUT) s |= UART_TTYTXR;\n      return s;\n    case UART_DLM:\n      return -1;\n    default:\n      return 0;\n  }\n}\n\nstatic int OpSerialOut(struct Machine *m, int r, u32 x) {\n  switch (r) {\n    case UART_DLL:\n      if (!m->system->dlab) {\n        return OpE9Write(m, x);\n      }\n      return 0;\n    case UART_LCR:\n      m->system->dlab = !!(x & UART_DLAB);\n      return 0;\n    default:\n      return -1;\n  }\n}\n\nu64 OpIn(struct Machine *m, u16 p) {\n  switch (p) {\n    case 0xE9:\n      return OpE9Read(m);\n    case 0x3F8:\n    case 0x3F9:\n    case 0x3FA:\n    case 0x3FB:\n    case 0x3FC:\n    case 0x3FD:\n    case 0x3FE:\n    case 0x3FF:\n      return OpSerialIn(m, p - 0x3F8);\n    default:\n      return -1;\n  }\n}\n\nint OpOut(struct Machine *m, u16 p, u32 x) {\n  switch (p) {\n    case 0xE9:\n      return OpE9Write(m, x);\n    case 0x3F8:\n    case 0x3F9:\n    case 0x3FA:\n    case 0x3FB:\n    case 0x3FC:\n    case 0x3FD:\n    case 0x3FE:\n    case 0x3FF:\n      return OpSerialOut(m, p - 0x3F8, x);\n    default:\n      return -1;\n  }\n}\n\n#endif /* DISABLE_METAL */\n"
  },
  {
    "path": "blink/iovs.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/iovs.h\"\n\n#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n\n#include \"blink/endian.h\"\n#include \"blink/errno.h\"\n#include \"blink/limits.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/stats.h\"\n#include \"blink/types.h\"\n#include \"blink/util.h\"\n\nvoid InitIovs(struct Iovs *ib) {\n  ib->p = ib->init;\n  ib->i = 0;\n  ib->n = ARRAYLEN(ib->init);\n}\n\nvoid FreeIovs(struct Iovs *ib) {\n  if (ib->p != ib->init) {\n    free(ib->p);\n  }\n}\n\n/**\n * Appends memory region to i/o vector builder.\n */\nstatic int AppendIovs(struct Iovs *ib, void *base, size_t len) {\n  unsigned i, n;\n  struct iovec *p;\n  if (len) {\n    p = ib->p;\n    i = ib->i;\n    n = ib->n;\n    if (i &&\n        (uintptr_t)base == (uintptr_t)p[i - 1].iov_base + p[i - 1].iov_len) {\n      STATISTIC(++iov_stretches);\n      if (p[i - 1].iov_len + len > NUMERIC_MAX(ssize_t)) return einval();\n      p[i - 1].iov_len += len;\n    } else {\n      if (i < n) {\n        if (!i) {\n          STATISTIC(++iov_created);\n        } else {\n          STATISTIC(++iov_fragments);\n        }\n      } else {\n        STATISTIC(++iov_reallocs);\n        n += n >> 1;\n        if (p == ib->init) {\n          if (!(p = (struct iovec *)malloc(sizeof(*p) * n))) return -1;\n          memcpy(p, ib->init, sizeof(ib->init));\n        } else {\n          if (!(p = (struct iovec *)realloc(p, sizeof(*p) * n))) return -1;\n        }\n        ib->p = p;\n        ib->n = n;\n      }\n      p[i].iov_base = base;\n      p[i].iov_len = len;\n      ++ib->i;\n    }\n  }\n  return 0;\n}\n\nint AppendIovsReal(struct Machine *m, struct Iovs *ib, i64 addr, u64 size,\n                   int prot) {\n  void *real;\n  unsigned got;\n  u64 have, mask, need;\n  if (size > NUMERIC_MAX(ssize_t)) return einval();\n  need = 0;\n  mask = 0;\n  if (prot & PROT_READ) {\n    mask |= PAGE_U;\n    need |= PAGE_U;\n  }\n  if (prot & PROT_WRITE) {\n    mask |= PAGE_RW;\n    need |= PAGE_RW;\n  }\n  while (size && ib->i < GetIovMax()) {\n    if (!(real = LookupAddress2(m, addr, mask, need))) return efault();\n    have = 4096 - (addr & 4095);\n    got = MIN(size, have);\n    if (AppendIovs(ib, real, got) == -1) return -1;\n    addr += got;\n    size -= got;\n  }\n  return 0;\n}\n\nint AppendIovsGuest(struct Machine *m, struct Iovs *iv, i64 iovaddr, int iovlen,\n                    int prot) {\n  int rc;\n  size_t i, iovsize;\n  const struct iovec_linux *guestiovs;\n  if (iovlen > IOV_MAX_LINUX) return einval();\n  iovsize = iovlen * sizeof(struct iovec_linux);\n  if ((guestiovs = (const struct iovec_linux *)SchlepR(m, iovaddr, iovsize))) {\n    for (rc = i = 0; i < iovlen && iv->i < GetIovMax(); ++i) {\n      if (AppendIovsReal(m, iv, Read64(guestiovs[i].base),\n                         Read64(guestiovs[i].len), prot) == -1) {\n        rc = -1;\n        break;\n      }\n    }\n    return rc;\n  } else {\n    return -1;\n  }\n}\n"
  },
  {
    "path": "blink/iovs.h",
    "content": "#ifndef BLINK_IOVS_H_\n#define BLINK_IOVS_H_\n#include <limits.h>\n#include <stddef.h>\n#include <sys/uio.h>\n\n#include \"blink/machine.h\"\n#include \"blink/types.h\"\n\nstruct Iovs {\n  unsigned i, n;\n  struct iovec *p;\n  struct iovec init[8];\n};\n\nvoid FreeIovs(struct Iovs *);\nvoid InitIovs(struct Iovs *);\nint AppendIovsReal(struct Machine *, struct Iovs *, i64, u64, int);\nint AppendIovsGuest(struct Machine *, struct Iovs *, i64, int, int);\n\n#endif /* BLINK_IOVS_H_ */\n"
  },
  {
    "path": "blink/jit.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/jit.h\"\n\n#include <errno.h>\n#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/builtin.h\"\n#include \"blink/checked.h\"\n#include \"blink/debug.h\"\n#include \"blink/dll.h\"\n#include \"blink/end.h\"\n#include \"blink/endian.h\"\n#include \"blink/errno.h\"\n#include \"blink/flag.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/memcpy.h\"\n#include \"blink/stats.h\"\n#include \"blink/thread.h\"\n#include \"blink/tsan.h\"\n#include \"blink/util.h\"\n\n/**\n * @fileoverview Just-In-Time Function Builder\n *\n * This file implements a low-level systems abstraction that enables\n * native functions to be written to memory and then executed. These\n * interfaces are used by Jitter() which is a higher-level interface\n * that's intended for generating implementations of x86 operations.\n *\n * This JIT only supports x86-64 and aarch64. That makes life easier\n * since both architectures have many registers and a register-based\n * calling convention. This JIT works around the restrictions placed\n * upon self-modifying code imposed by both OSes and microprocessors\n * such as:\n *\n * 1. ARM CPUs require a non-trivial flushing of instruction caches.\n * 2. OpenBSD always imposes strict W^X memory protection invariant.\n * 3. Apple requires we use JIT memory and toggle thread JIT states.\n * 4. ISAs limit the distance between JIT memory and our executable.\n * 5. Some platforms have a weird page size, e.g. Apple M1 is 16384.\n *\n * Meeting the requirements of all these platforms, means we have to\n * follow a very narrow path of possibilities, in terms of practices\n * plus design. These APIs make conformance easier. The way it works\n * here is multiple pages of memory are allocated in chunks, that we\n * call \"blocks\". Each time a thread wishes to create a function, it\n * must lease one of these blocks using StartJit(), FinishJit(), and\n * SpliceJit(). During that lease, functions may be generated, which\n * call arbitrary functions built by the compiler. Any function made\n * here needs to have a non-JIT implementation that can be called to\n * allow time for the JIT block to be flushed, at which time the JIT\n * updates a corresponding function hook.\n *\n *     // setup a multi-threaded jit manager\n *     struct Jit jit;\n *     InitJit(&jit, 0);\n *\n *     // workflow for composing two function calls\n *     i64 key = 1234;\n *     long Adder(long x, long y) { return x + y; }\n *     struct JitBlock *jb;\n *     jb = StartJit(jit, key);\n *     AppendJit(jb, kPrologue, sizeof(kPrologue));\n *     AppendJitSetReg(jb, kJitArg0, 1);\n *     AppendJitSetReg(jb, kJitArg1, 2);\n *     AppendJitCall(jb, (void *)Adder);\n *     AppendJitMovReg(jb, kJitRes0, kJitArg0);\n *     AppendJitSetReg(jb, kJitArg1, 3);\n *     AppendJitCall(jb, (void *)Adder);\n *     AppendJit(jb, kEpilogue, sizeof(kEpilogue));\n *     FinishJit(jit, jb);\n *     FlushJit(jit);\n *     printf(\"1+2+3=%ld\\n\", ((long (*)(void))(GetJitHook(jit, key)))());\n *\n *     // destroy jit and all its functions\n *     DestroyJit(&jit);\n *\n * Note that FlushJit() should only be a last resort. Functions will\n * become live immediately on operating systems which authorize self\n * modifying-code using RWX memory and have the appropriate compiler\n * builtin for flushing the CPU instruction cach. If weird platforms\n * aren't a concern, then the hairiness of hooking and/or FlushJit()\n * shouldn't be of any concern. Try using CanJitForImmediateEffect()\n * after having called StartJit() to check.\n */\n\n#define kMaximumAnticipatedPageSize 65536\n\nconst u8 kJitRes[2] = {kJitRes0, kJitRes1};\nconst u8 kJitArg[4] = {kJitArg0, kJitArg1, kJitArg2, kJitArg3};\nconst u8 kJitSav[5] = {kJitSav0, kJitSav1, kJitSav2, kJitSav3, kJitSav4};\n\n#ifdef HAVE_JIT\n\n#define ACTION_MOVE    0x010000\n#define ACTION(a)      ((0xff0000 & a))\n#define MOVE(dst, src) ((dst) | (src) << 8 | ACTION_MOVE)\n#define MOVE_DST(a)    ((0x0000ff & (a)) >> 0)\n#define MOVE_SRC(a)    ((0x00ff00 & (a)) >> 8)\n#define HASH(virt)     (virt)\n\nstatic u8 g_code[kJitMemorySize];\n\nstatic struct JitGlobals {\n  pthread_mutex_t_ lock;\n  _Atomic(long) prot;\n  int freecount;\n  struct Dll *freeblocks;\n} g_jit = {\n    PTHREAD_MUTEX_INITIALIZER_,\n    PROT_READ | PROT_WRITE | PROT_EXEC,\n};\n\nstatic inline u64 RoundupTwoPow(u64 x) {\n  return x > 1 ? (u64)2 << bsr(x - 1) : x ? 1 : 0;\n}\n\n// begins write operation to memory that may be read locklessly\n// - generation is monotonic\n// - even numbers mean memory is ready\n// - odd numbers mean memory is actively being changed\nstatic inline unsigned BeginUpdate(_Atomic(unsigned) *genptr) {\n  unsigned gen = atomic_load_explicit(genptr, memory_order_relaxed);\n  unassert(~gen & 1);  // prevents re-entering transaction\n  atomic_store_explicit(genptr, gen + 1, memory_order_release);\n  return gen;\n}\n\n// finishes write operation to memory that may be read locklessly\nstatic inline void EndUpdate(_Atomic(unsigned) *genptr, unsigned gen) {\n  unassert(~gen & 1);\n  atomic_store_explicit(genptr, gen + 2, memory_order_release);\n}\n\n// determines if lockless operation should be retried or abandoned\nstatic inline unsigned ShallNotPass(unsigned gen1, _Atomic(unsigned) *genptr) {\n  unsigned gen2 = atomic_load_explicit(genptr, memory_order_acquire);\n  unsigned is_being_actively_changed = gen1 & 1;\n  unsigned we_lost_race_with_writers = gen1 ^ gen2;\n  return is_being_actively_changed | we_lost_race_with_writers;\n}\n\n// apple forbids rwx memory on their new m1 macbooks and requires that\n// we use a non-posix api in order to have jit. the problem is the api\n// frequently flakes with \"Trace/BPT trap: 5\" errors. this fixes that.\nstatic void pthread_jit_write_protect_np_workaround(int enabled) {\n#if defined(__APPLE__) && defined(__aarch64__)\n  int count_start = 8192;\n  volatile int count = count_start;\n  uint64_t *addr, val, val2, reread = -1;\n  addr = (uint64_t *)(!enabled ? _COMM_PAGE_APRR_WRITE_ENABLE\n                               : _COMM_PAGE_APRR_WRITE_DISABLE);\n  // other = (uint64_t *)(enabled ? _COMM_PAGE_APRR_WRITE_ENABLE\n  //                              : _COMM_PAGE_APRR_WRITE_DISABLE);\n  switch (*(volatile uint8_t *)_COMM_PAGE_APRR_SUPPORT) {\n    case 1:\n      do {\n        val = *addr;\n        reread = -1;\n        asm volatile(\"msr S3_4_c15_c2_7, %0\\n\"\n                     \"isb sy\\n\"\n                     : /* no outputs */\n                     : \"r\"(val)\n                     : \"memory\");\n        val2 = *addr;\n        asm volatile(\"mrs %0, S3_4_c15_c2_7\\n\"\n                     : \"=r\"(reread)\n                     : /* no inputs */\n                     : \"memory\");\n        if (val2 == reread) {\n          return;\n        }\n        usleep(10);\n      } while (count-- > 0);\n      break;\n    case 3:\n      do {\n        val = *addr;\n        reread = -1;\n        asm volatile(\"msr S3_6_c15_c1_5, %0\\n\"\n                     \"isb sy\\n\"\n                     : /* no outputs */\n                     : \"r\"(val)\n                     : \"memory\");\n        val2 = *addr;\n        asm volatile(\"mrs %0, S3_6_c15_c1_5\\n\"\n                     : \"=r\"(reread)\n                     : /* no inputs */\n                     : \"memory\");\n        if (val2 == reread) {\n          return;\n        }\n        usleep(10);\n      } while (count-- > 0);\n      break;\n    default:\n      pthread_jit_write_protect_np(enabled);\n      return;\n  }\n  ERRF(\"failed to set jit write protection\");\n  Abort();\n#else\n  pthread_jit_write_protect_np(enabled);\n#endif\n}\n\nstatic void *Calloc(size_t nmemb, size_t size) {\n  STATISTIC(++jit_callocs);\n  return calloc(nmemb, size);\n#define calloc please_use_Calloc\n}\n\nstatic void *Realloc(void *p, size_t n) {\n  STATISTIC(++jit_reallocs);\n  return realloc(p, n);\n#define realloc please_use_Realloc\n}\n\nstatic void Free(void *ptr) {\n  if (!ptr) return;\n  STATISTIC(++jit_frees);\n  free(ptr);\n#define free please_use_Free\n}\n\nstatic struct JitJump *NewJitJump(struct Dll **freejumps) {\n  struct Dll *e;\n  struct JitJump *jj;\n  if ((e = dll_first(*freejumps))) {\n    STATISTIC(++jit_jump_alloc_freelist);\n    dll_remove(freejumps, e);\n    jj = JITJUMP_CONTAINER(e);\n  } else if ((jj = (struct JitJump *)Calloc(1, sizeof(struct JitJump)))) {\n    STATISTIC(++jit_jump_alloc_system);\n    dll_init(&jj->elem);\n  }\n  return jj;\n}\n\nstatic struct JitPage *NewJitPage(void) {\n  struct JitPage *jj;\n  if ((jj = (struct JitPage *)Calloc(1, sizeof(struct JitPage)))) {\n    dll_init(&jj->elem);\n  }\n  return jj;\n}\n\nstatic struct JitBlock *NewJitBlock(void) {\n  struct JitBlock *jb;\n  if ((jb = (struct JitBlock *)Calloc(1, sizeof(struct JitBlock)))) {\n    dll_init(&jb->elem);\n    dll_init(&jb->aged);\n    JIT_LOGF(\"new jit block %p\", jb);\n  }\n  return jb;\n}\n\nstatic struct JitStage *NewJitStage(void) {\n  struct JitStage *js;\n  if ((js = (struct JitStage *)Calloc(1, sizeof(struct JitStage)))) {\n    dll_init(&js->elem);\n  }\n  return js;\n}\n\nstatic struct JitFreed *NewJitFreed(void) {\n  struct JitFreed *jf;\n  if ((jf = (struct JitFreed *)Calloc(1, sizeof(struct JitFreed)))) {\n    dll_init(&jf->elem);\n  }\n  return jf;\n}\n\nstatic struct JitIntsSlab *NewJitIntsSlab(void) {\n  struct JitIntsSlab *jis;\n  if ((jis = (struct JitIntsSlab *)Calloc(1, sizeof(struct JitIntsSlab)))) {\n    dll_init(&jis->elem);\n  }\n  return jis;\n}\n\nstatic void FreeJitJump(struct JitJump *jj) {\n  Free(jj);\n}\n\nstatic void FreeJitPage(struct JitPage *jp) {\n  Free(jp);\n}\n\nstatic void FreeJitFreed(struct JitFreed *jf) {\n  Free(jf->data);\n  Free(jf);\n}\n\nstatic void DestroyInts(struct JitInts *ji) {\n  if (ji->p != ji->m) {\n    Free(ji->p);\n  }\n}\n\nstatic void FreeJitBlock(struct JitBlock *jb) {\n  struct Dll *e;\n  JIT_LOGF(\"freed jit block %p\", jb);\n  while ((e = dll_first(jb->freejumps))) {\n    dll_remove(&jb->freejumps, e);\n    FreeJitJump(JITJUMP_CONTAINER(e));\n  }\n  Free(jb);\n}\n\nstatic void FreeJitStage(struct JitStage *js) {\n  Free(js);\n}\n\nstatic void DestroyIntsAllocator(struct JitIntsAllocator *jia) {\n  int i;\n  struct Dll *e, *e2;\n  struct JitIntsSlab *jis;\n  Free(jia->p);\n  for (e = dll_first(jia->slabs); e; e = e2) {\n    e2 = dll_next(jia->slabs, e);\n    jis = JIASLAB_CONTAINER(e);\n    for (i = 0; i < ARRAYLEN(jis->p); ++i) {\n      DestroyInts(jis->p + i);\n    }\n    Free(jis);\n  }\n}\n\nstatic dontinline bool GrowIntsAllocator(struct JitIntsAllocator *jia) {\n  int n2;\n  struct JitInts **p2;\n  p2 = jia->p;\n  n2 = jia->n;\n  if (n2 >= 2) {\n    n2 += n2 >> 1;\n  } else {\n    n2 = 8;\n  }\n  if ((p2 = (struct JitInts **)Realloc(p2, n2 * sizeof(*p2)))) {\n    jia->p = p2;\n    jia->n = n2;\n    return true;\n  } else {\n    return false;\n  }\n}\n\nstatic struct JitInts *NewInts(struct JitIntsAllocator *jia) {\n  struct Dll *e;\n  struct JitInts *ji;\n  struct JitIntsSlab *slab;\n  if (jia->i) {\n    STATISTIC(++jit_ints_alloc_freelist);\n    return jia->p[--jia->i];\n  }\n  if ((e = dll_first(jia->slabs))) {\n    STATISTIC(++jit_ints_alloc_slab);\n    slab = JIASLAB_CONTAINER(e);\n    if (slab->i < ARRAYLEN(slab->p)) {\n      ji = slab->p + slab->i++;\n      ji->p = ji->m;\n      ji->n = ARRAYLEN(ji->m);\n      return ji;\n    }\n  }\n  if ((slab = NewJitIntsSlab())) {\n    STATISTIC(++jit_ints_alloc_system);\n    dll_make_first(&jia->slabs, &slab->elem);\n    return slab->p + slab->i++;\n  }\n  return 0;\n}\n\nstatic void FreeInts(struct JitIntsAllocator *jia, struct JitInts *ji) {\n  if (ji) {\n    ji->i = 0;\n    if (jia->i == jia->n && !GrowIntsAllocator(jia)) return;\n    jia->p[jia->i++] = ji;\n  }\n}\n\nstatic bool GrowInts(struct JitInts *ji) {\n  i64 *p2;\n  size_t i, n2;\n  p2 = ji->p;\n  if (!ji->p) {\n    unassert(!ji->n);\n    ji->p = ji->m;\n    ji->n = ARRAYLEN(ji->m);\n    return true;\n  } else if (ji->p == ji->m) {\n    unassert(ji->n == ARRAYLEN(ji->m));\n    n2 = ARRAYLEN(ji->m) * 2;\n    if ((p2 = Calloc(n2, sizeof(*p2)))) {\n      for (i = 0; i < ARRAYLEN(ji->m); ++i) {\n        p2[i] = ji->m[i];\n      }\n      ji->p = p2;\n      ji->n = n2;\n      return true;\n    } else {\n      return false;\n    }\n  } else {\n    n2 = ji->n;\n    n2 += n2 >> 1;\n    if ((p2 = (i64 *)Realloc(p2, n2 * sizeof(*p2)))) {\n      ji->p = p2;\n      ji->n = n2;\n      return true;\n    } else {\n      return false;\n    }\n  }\n}\n\nstatic bool AddInt(struct JitInts *ji, i64 x) {\n  if (ji->i == ji->n && !GrowInts(ji)) return false;\n  ji->p[ji->i++] = x;\n  return true;\n}\n\nstatic bool RemoveInt(struct JitInts *ji, i64 x) {\n  int i, j;\n  for (i = j = 0; i < ji->i; ++i) {\n    if (ji->p[i] != x) {\n      ji->p[j++] = ji->p[i];\n    }\n  }\n  ji->i -= i - j;\n  return i > j;\n}\n\nstatic void InitEdges(struct JitEdges *e) {\n  memset(e, 0, sizeof(*e));\n  e->n = RoundupTwoPow(kJitInitialEdges);\n  unassert(e->src = (i64 *)Calloc(e->n, sizeof(*e->src)));\n  unassert(e->dst = (struct JitInts **)Calloc(e->n, sizeof(*e->dst)));\n}\n\nstatic void DestroyEdges(struct JitEdges *edges) {\n  DestroyIntsAllocator(&edges->jia);\n  Free(edges->dst);\n  Free(edges->src);\n}\n\nstatic nosideeffect int GetEdge(const struct JitEdges *edges, i64 src) {\n  unsigned hash, spot, step;\n  hash = HASH(src);\n  for (spot = step = 0;; ++step) {\n    spot = (hash + step * ((step + 1) >> 1)) & (edges->n - 1);\n    if (!edges->src[spot] || edges->src[spot] == src) {\n      return spot;\n    }\n  }\n}\n\nstatic unsigned GrowEdges(struct JitEdges *edges) {\n  i64 *src, *src2;\n  struct JitInts **dst, **dst2;\n  unsigned i, i1, i2, n1, n2, used, hash, spot, step;\n  i1 = edges->i;\n  n1 = edges->n;\n  src = edges->src;\n  dst = edges->dst;\n  unassert(n1 > 1 && IS2POW(n1));\n  for (used = i = 0; i < n1; ++i) used += !!dst[i];\n  n2 = n1 << (used > (n1 >> 2));\n  if (!(src2 = (i64 *)Calloc(n2, sizeof(*src2))) ||\n      !(dst2 = (struct JitInts **)Calloc(n2, sizeof(*dst2)))) {\n    Free(src2);\n    return 0;\n  }\n  for (i2 = i = 0; i < n1; ++i) {\n    if (!src[i]) {\n      unassert(!dst[i]);\n      continue;\n    }\n    --i1;\n    if (!dst[i]) {\n      continue;\n    }\n    ++i2;\n    spot = 0;\n    step = 0;\n    hash = HASH(src[i]);\n    do {\n      spot = (hash + step * ((step + 1) >> 1)) & (n2 - 1);\n      unassert(src2[spot] != src[i]);\n      ++step;\n    } while (src2[spot]);\n    src2[spot] = src[i];\n    dst2[spot] = dst[i];\n  }\n  unassert(!i1);\n  edges->i = i2;\n  edges->n = n2;\n  edges->src = src2;\n  edges->dst = dst2;\n  Free(src);\n  Free(dst);\n  return n2;\n}\n\nstatic bool AddEdge(struct JitEdges *edges, i64 src, i64 dst) {\n  int s;\n  if (edges->i == (edges->n >> 1)) {\n    if (!GrowEdges(edges)) return false;\n  }\n  if (!edges->src[(s = GetEdge(edges, src))]) {\n    edges->src[s] = src;\n    ++edges->i;\n  }\n  if (!edges->dst[s]) {\n    if (!(edges->dst[s] = NewInts(&edges->jia))) return false;\n  }\n  return AddInt(edges->dst[s], dst);\n}\n\nstatic void RemoveEdgesByIndex(struct JitEdges *edges, int s) {\n  unassert(s >= 0 && s < edges->n);\n  FreeInts(&edges->jia, edges->dst[s]);\n  edges->dst[s] = 0;\n}\n\nstatic bool RemoveEdges(struct JitEdges *edges, i64 src) {\n  int s;\n  if (!edges->dst[(s = GetEdge(edges, src))]) return false;\n  RemoveEdgesByIndex(edges, s);\n  return true;\n}\n\nstatic bool RemoveEdge(struct JitEdges *edges, i64 src, i64 dst) {\n  int s;\n  if (!edges->dst[(s = GetEdge(edges, src))]) return false;\n  if (!RemoveInt(edges->dst[s], dst)) return false;\n  if (!edges->dst[s]->i) RemoveEdgesByIndex(edges, s);\n  return true;\n}\n\nstatic void ClearEdges(struct JitEdges *edges) {\n  int i;\n  for (i = 0; i < edges->n; ++i) {\n    edges->src[i] = 0;\n    RemoveEdgesByIndex(edges, i);\n  }\n  edges->i = 0;\n}\n\nstatic bool IsCyclic(struct JitEdges *edges, i64 V[kJitDepth], int d, i64 dst) {\n  int i, s;\n  if (d == kJitDepth) {\n    return true;\n  }\n  for (i = 0; i < d; ++i) {\n    if (dst == V[i]) {\n      return true;\n    }\n  }\n  V[d++] = dst;\n  if (edges->dst[(s = GetEdge(edges, dst))]) {\n    for (i = 0; i < edges->dst[s]->i; ++i) {\n      if (IsCyclic(edges, V, d, edges->dst[s]->p[i])) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nstatic inline uintptr_t DecodeJitFunc(int func) {\n  unassert(func);\n  return (intptr_t)IMAGE_END + func;\n}\n\nstatic nosideeffect int EncodeJitFunc(intptr_t addr) {\n  int func;\n  intptr_t base, disp;\n  if (addr) {\n    base = (intptr_t)IMAGE_END;\n    disp = addr - base;\n    func = disp;\n    unassert(func && func == disp);\n  } else {\n    func = 0;\n  }\n  return func;\n}\n\nbool CanJitForImmediateEffect(void) {\n  return atomic_load_explicit(&g_jit.prot, memory_order_relaxed) & PROT_EXEC;\n}\n\nstatic u8 *AllocateJitMemory(long *state) {\n  long i, brk;\n  uintptr_t p;\n  brk = *state;\n  p = (uintptr_t)g_code;\n  i = ROUNDUP(p + brk, FLAG_pagesize) - p;\n  if (i + kJitBlockSize > kJitMemorySize) {\n    return 0;\n  }\n  *state = i + kJitBlockSize;\n  return g_code + i;\n}\n\nstatic int MakeJitJump(u8 buf[5], uintptr_t pc, uintptr_t addr) {\n  int n;\n  intptr_t disp;\n#if defined(__x86_64__)\n  disp = addr - (pc + 5);\n  unassert(kAmdDispMin <= disp && disp <= kAmdDispMax);\n  buf[0] = kAmdJmp;\n  Write32(buf + 1, disp & kAmdDispMask);\n  n = 5;\n#elif defined(__aarch64__)\n  disp = addr - pc;\n  disp >>= 2;\n  unassert(kArmDispMin <= disp && disp <= kArmDispMax);\n  Write32(buf, kArmJmp | (disp & kArmDispMask));\n  n = 4;\n#endif\n  return n;\n}\n\n// Obtains JitBlock from global pool or creates one if none exist.\nstatic struct JitBlock *AcquireJitBlock(struct Jit *jit) {\n  struct Dll *e;\n  struct JitBlock *jb;\n  LOCK(&g_jit.lock);\n  if ((e = dll_first(g_jit.freeblocks))) {\n    dll_remove(&g_jit.freeblocks, e);\n    jb = JITBLOCK_CONTAINER(e);\n    unassert(g_jit.freecount > 0);\n    --g_jit.freecount;\n  } else {\n    jb = 0;\n  }\n  UNLOCK(&g_jit.lock);\n  if (jb) dll_make_last(&jit->agedblocks, &jb->aged);\n  JIT_LOGF(\"acquired jit block %p (freecount=%d)\", jb, g_jit.freecount);\n  return jb;\n}\n\n// Frees JitBlock. The JIT block is added to a global free list, so it\n// can be reclaimed if a new Jit system is created. This is intended for\n// once all threads have shut down, due to exit_group() or execve().\n// @assume jit->lock\nstatic void ReleaseJitBlock(struct JitBlock *jb) {\n  struct Dll *e;\n  JIT_LOGF(\"released jit block %p\", jb);\n  while ((e = dll_first(jb->staged))) {\n    dll_remove(&jb->staged, e);\n    FreeJitStage(JITSTAGE_CONTAINER(e));\n  }\n  dll_make_first(&jb->freejumps, jb->jumps);\n  jb->jumps = 0;\n  jb->start = 0;\n  jb->index = 0;\n  jb->committed = 0;\n  jb->wasretired = false;\n  jb->isprotected = false;\n  dll_init(&jb->aged);\n  LOCK(&g_jit.lock);\n  dll_make_first(&g_jit.freeblocks, &jb->elem);\n  ++g_jit.freecount;\n  UNLOCK(&g_jit.lock);\n}\n\n// Frees JitBlock and adds it to the global free list in such a way that\n// it'll take a long time before it's reused. This is intended for a JIT\n// under active use that's trying to reclaim jit memory.\n// @assume jit->lock\nstatic void RetireJitBlock(struct Jit *jit, struct JitBlock *jb) {\n  JIT_LOGF(\"retiring jit block %p\", jb);\n  unassert(!jb->isprotected);\n  unassert(dll_is_empty(jb->jumps));\n  unassert(dll_is_empty(jb->staged));\n  STATISTIC(++jit_blocks_retired);\n  dll_remove(&jit->blocks, &jb->elem);\n  dll_remove(&jit->agedblocks, &jb->aged);\n  jb->start = 0;\n  jb->index = 0;\n  jb->committed = 0;\n  jb->wasretired = true;\n  LOCK(&g_jit.lock);\n  dll_make_last(&g_jit.freeblocks, &jb->elem);\n  ++g_jit.freecount;\n  UNLOCK(&g_jit.lock);\n}\n\n// creates new jit block and sets up its jit memory\nstatic struct JitBlock *InitJitBlock(struct Jit *jit, long *state) {\n  struct JitBlock *jb;\n  if ((jb = NewJitBlock())) {\n    if (!(jb->addr = AllocateJitMemory(state))) {\n      FreeJitBlock(jb);\n      jb = 0;\n    }\n  }\n  return jb;\n}\n\nstatic void LockJit(struct Jit *jit) {\n  if (jit->threaded) {\n    LOCK(&jit->lock);\n  }\n}\n\nstatic void UnlockJit(struct Jit *jit) {\n  if (jit->threaded) {\n    UNLOCK(&jit->lock);\n  }\n}\n\n/**\n * Initializes memory object for Just-In-Time (JIT) threader.\n *\n * The `jit` struct itself is owned by the caller. Internal memory\n * associated with this object should be reclaimed later by calling\n * DestroyJit().\n *\n * @return 0 on success\n */\nint InitJit(struct Jit *jit, uintptr_t opt_staging_function) {\n  long brk;\n  unsigned n;\n  struct JitBlock *jb;\n  _Atomic(int) *funcs;\n  _Atomic(uintptr_t) *virts;\n  _Static_assert(kJitAlign >= 1, \"\");\n  _Static_assert(kJitBlockSize >= 4096, \"\");\n  _Static_assert(kJitInitialHooks >= 2, \"\");\n  unassert(FLAG_pagesize >= 4096);\n  unassert(kJitBlockSize >= FLAG_pagesize);\n  unassert(!(kJitBlockSize % FLAG_pagesize));\n  memset(jit, 0, sizeof(*jit));\n  InitEdges(&jit->edges);\n  InitEdges(&jit->redges);\n  jit->staging = EncodeJitFunc(opt_staging_function);\n  unassert(!pthread_mutex_init(&jit->lock, 0));\n  jit->hooks.n = n = RoundupTwoPow(kJitInitialHooks);\n  unassert(virts = (_Atomic(uintptr_t) *)Calloc(n, sizeof(*virts)));\n  unassert(funcs = (_Atomic(int) *)Calloc(n, sizeof(*funcs)));\n  atomic_store_explicit(&jit->hooks.virts, virts, memory_order_relaxed);\n  atomic_store_explicit(&jit->hooks.funcs, funcs, memory_order_relaxed);\n  for (brk = 0; (jb = InitJitBlock(jit, &brk));) {\n    dll_make_last(&g_jit.freeblocks, &jb->elem);\n    ++g_jit.freecount;\n  }\n  JIT_LOGF(\"initialized jit %p\", jit);\n  return 0;\n}\n\n/**\n * Destroys initialized JIT object.\n *\n * Passing a value not previously initialized by InitJit() is undefined.\n *\n * @return 0 on success\n */\nint DestroyJit(struct Jit *jit) {\n  struct Dll *e, *e2;\n  LockJit(jit);\n  JIT_LOGF(\"destroying jit %p\", jit);\n  for (e = dll_first(jit->freeds.p); e; e = e2) {\n    e2 = dll_next(jit->freeds.p, e);\n    FreeJitFreed(JITFREED_CONTAINER(e));\n  }\n  while ((e = dll_first(jit->blocks))) {\n    dll_remove(&jit->blocks, e);\n    ReleaseJitBlock(JITBLOCK_CONTAINER(e));\n  }\n  dll_make_first(&jit->freejumps, jit->jumps);\n  for (e = dll_first(jit->freejumps); e; e = e2) {\n    e2 = dll_next(jit->freejumps, e);\n    FreeJitJump(JITJUMP_CONTAINER(e));\n  }\n  for (e = dll_first(jit->pages); e; e = e2) {\n    e2 = dll_next(jit->pages, e);\n    FreeJitPage(JITPAGE_CONTAINER(e));\n  }\n  UnlockJit(jit);\n  unassert(!pthread_mutex_destroy(&jit->lock));\n  DestroyEdges(&jit->redges);\n  DestroyEdges(&jit->edges);\n  Free(jit->hooks.funcs);\n  Free(jit->hooks.virts);\n  return 0;\n}\n\n/**\n * Releases global JIT resources at shutdown.\n */\nint ShutdownJit(void) {\n  struct Dll *e;\n  JIT_LOGF(\"shutting down jit\");\n  while ((e = dll_first(g_jit.freeblocks))) {\n    dll_remove(&g_jit.freeblocks, e);\n    FreeJitBlock(JITBLOCK_CONTAINER(e));\n    --g_jit.freecount;\n  }\n  unassert(!g_jit.freecount);\n  return 0;\n}\n\n/**\n * Disables Just-In-Time threader.\n */\nint DisableJit(struct Jit *jit) {\n  atomic_store_explicit(&jit->disabled, true, memory_order_release);\n  return 0;\n}\n\n/**\n * Enables Just-In-Time threader.\n */\nint EnableJit(struct Jit *jit) {\n  atomic_store_explicit(&jit->disabled, false, memory_order_release);\n  return 0;\n}\n\n/**\n * Fixes the memory protection for existing Just-In-Time code blocks.\n */\nint FixJitProtection(struct Jit *jit) {\n  int prot;\n  struct Dll *e;\n  LockJit(jit);\n  prot = atomic_load_explicit(&g_jit.prot, memory_order_relaxed);\n  for (e = dll_first(jit->blocks); e; e = dll_next(jit->blocks, e)) {\n    unassert(\n        !Mprotect(JITBLOCK_CONTAINER(e)->addr, kJitBlockSize, prot, \"jit\"));\n  }\n  UnlockJit(jit);\n  return 0;\n}\n\n// @assume jit->lock\nstatic struct JitPage *GetJitPage(struct Jit *jit, i64 addr) {\n  i64 page;\n  bool lru;\n  struct Dll *e;\n  struct JitPage *jp;\n  lru = false;\n  page = addr & -4096;\n  for (e = dll_first(jit->pages); e; e = dll_next(jit->pages, e)) {\n    jp = JITPAGE_CONTAINER(e);\n    if (jp->page == page) {\n      if (!lru) {\n        STATISTIC(++jit_pages_hits_1);\n      } else {\n        STATISTIC(++jit_pages_hits_2);\n        dll_remove(&jit->pages, e);\n        dll_make_first(&jit->pages, e);\n      }\n      return jp;\n    }\n    lru = true;\n  }\n  return 0;\n}\n\n// @assume jit->lock\nstatic struct JitPage *GetOrCreateJitPage(struct Jit *jit, i64 addr) {\n  i64 page;\n  struct JitPage *jp;\n  page = addr & -4096;\n  if (!(jp = GetJitPage(jit, page))) {\n    if ((jp = NewJitPage())) {\n      dll_make_first(&jit->pages, &jp->elem);\n      jp->page = page;\n    }\n  }\n  return jp;\n}\n\n// adds heap memory to freelist\n// this is intended for synchronization cooloff\n// @assume jit->lock\nstatic void RetireJitHeap(struct Jit *jit, void *data, size_t size) {\n  struct Dll *e;\n  struct JitFreed *jf = 0;\n  if (!data) return;\n  if (!jit->threaded) {\n    Free(data);\n    return;\n  }\n  if ((e = dll_first(jit->freeds.f))) {\n    dll_remove(&jit->freeds.f, e);\n    jf = JITFREED_CONTAINER(e);\n  } else if (!(jf = NewJitFreed())) {\n    return;  // we can't free data so just leak it\n  }\n  jf->data = data;\n  jf->size = size;\n  dll_make_last(&jit->freeds.p, &jf->elem);\n  ++jit->freeds.n;\n}\n\n// same as calloc, but pilfers old retired heap memory from freelist\n// @assume jit->lock\nstatic void *GetJitHeap(struct Jit *jit, size_t count, size_t elsize) {\n  u64 size;\n  void *res = 0;\n  struct Dll *e;\n  struct JitFreed *jf;\n  if (ckd_mul(&size, count, elsize)) return 0;\n  if (jit->freeds.n > kJitRetireQueue) {\n    for (e = dll_first(jit->freeds.p); e; e = dll_next(jit->freeds.p, e)) {\n      dll_remove(&jit->freeds.p, e);\n      jf = JITFREED_CONTAINER(e);\n      if (jf->size >= size) {\n        res = jf->data;\n        dll_make_first(&jit->freeds.f, e);\n        break;\n      }\n    }\n  }\n  if (res) {\n    memset(res, 0, size);\n  } else {\n    res = Calloc(1, size);\n  }\n  return res;\n}\n\n// @assume jit->lock\nstatic unsigned RehashJitHooks(struct Jit *jit) {\n  int func;\n  uintptr_t key, virt;\n  unsigned i, i2, n1, n2, used, hash, spot, step, kgen;\n  _Atomic(int) *funcs, *funcs2;\n  _Atomic(uintptr_t) *virts, *virts2;\n  virts = atomic_load_explicit(&jit->hooks.virts, memory_order_relaxed);\n  funcs = atomic_load_explicit(&jit->hooks.funcs, memory_order_relaxed);\n  // grow allocation unless this rehash is due to many deleted values\n  n1 = atomic_load_explicit(&jit->hooks.n, memory_order_relaxed);\n  unassert(n1 > 1 && IS2POW(n1));\n  for (used = i = 0; i < n1; ++i) {\n    used += !!atomic_load_explicit(funcs + i, memory_order_relaxed);\n  }\n  n2 = n1 << (used > (n1 >> 2));\n  JIT_LOGF(\"rehashing jit hooks %u -> %u\", n1, n2);\n  // allocate an entirely new hash table\n  if (!(virts2 = (_Atomic(uintptr_t) *)GetJitHeap(jit, n2, sizeof(*virts2))) ||\n      !(funcs2 = (_Atomic(int) *)GetJitHeap(jit, n2, sizeof(*funcs2)))) {\n    RetireJitHeap(jit, virts2, n2 * sizeof(*virts2));\n    return 0;\n  }\n  // copy entries over to new hash table, removing deleted entries\n  for (i2 = i = 0; i < n1; ++i) {\n    virt = atomic_load_explicit(virts + i, memory_order_relaxed);\n    func = atomic_load_explicit(funcs + i, memory_order_relaxed);\n    if (virt && func) {\n      spot = 0;\n      step = 0;\n      hash = HASH(virt);\n      do {\n        spot = (hash + step * ((step + 1) >> 1)) & (n2 - 1);\n        key = atomic_load_explicit(virts2 + spot, memory_order_relaxed);\n        unassert(key != virt);\n        ++step;\n      } while (key);\n      atomic_store_explicit(virts2 + spot, virt, memory_order_relaxed);\n      atomic_store_explicit(funcs2 + spot, func, memory_order_relaxed);\n      ++i2;\n    }\n  }\n  // update the hash table pointers for the lockless reader\n  kgen = BeginUpdate(&jit->keygen);\n  atomic_store_explicit(&jit->hooks.virts, virts2, memory_order_release);\n  atomic_store_explicit(&jit->hooks.funcs, funcs2, memory_order_relaxed);\n  atomic_store_explicit(&jit->hooks.n, n2, memory_order_release);\n  EndUpdate(&jit->keygen, kgen);\n  // leak old table so failed reads won't segfault from free munmap\n  RetireJitHeap(jit, virts, n1 * sizeof(*virts));\n  RetireJitHeap(jit, funcs, n1 * sizeof(*funcs));\n  jit->hooks.i = i2;\n  return n2;\n}\n\n// @assume jit->lock\nstatic bool SetJitHookUnlocked(struct Jit *jit, u64 virt, int cas,\n                               intptr_t funcaddr) {\n  uintptr_t key;\n  int func, oldfunc;\n  struct JitPage *jp;\n  _Atomic(int) *funcs;\n  _Atomic(uintptr_t) *virts;\n  unsigned n, kgen, hash, spot, step;\n  unassert(virt);\n  // ensure there's room to add this hook\n  unassert(jit->hooks.i <= jit->hooks.n / 2);\n  n = atomic_load_explicit(&jit->hooks.n, memory_order_relaxed);\n  if (jit->hooks.i == n / 2 && !(n = RehashJitHooks(jit))) {\n    DisableJit(jit);\n    return false;\n  }\n  // probe for spot in hash table. this is guaranteed to halt since we\n  // never place more than jit->hooks.n/2 items within this hash table\n  spot = 0;\n  step = 0;\n  hash = HASH(virt);\n  virts = atomic_load_explicit(&jit->hooks.virts, memory_order_relaxed);\n  funcs = atomic_load_explicit(&jit->hooks.funcs, memory_order_relaxed);\n  do {\n    spot = (hash + step * ((step + 1) >> 1)) & (n - 1);\n    key = atomic_load_explicit(virts + spot, memory_order_relaxed);\n    ++step;\n  } while (key && key != virt);\n  func = EncodeJitFunc(funcaddr);\n  oldfunc = atomic_load_explicit(funcs + spot, memory_order_relaxed);\n  if (jit->staging) {\n    if (func == jit->staging) {\n      STATISTIC(++jit_hooks_staged);\n      if (key && oldfunc != jit->staging) {\n        STATISTIC(++jit_hooks_deleted);\n      }\n    } else {\n      if (key && cas && oldfunc != cas) {\n        // if staging is enabled and the hook isn't the staging address,\n        // then some other thread must have won the race to install this\n        return false;\n      }\n      STATISTIC(--jit_hooks_staged);\n      if (func) {\n        STATISTIC(++jit_hooks_installed);\n      }\n    }\n  } else {\n    if (key && oldfunc) {\n      STATISTIC(++jit_hooks_deleted);\n    }\n    if (func) {\n      STATISTIC(++jit_hooks_installed);\n    }\n  }\n  if (!key) {\n    ++jit->hooks.i;\n    STATISTIC(jit_hash_elements = MAX(jit_hash_elements, jit->hooks.i));\n  }\n  if (func && (jp = GetOrCreateJitPage(jit, virt))) {\n    jp->bitset |= (u64)1 << ((virt & 4095) >> 6);\n  }\n  kgen = BeginUpdate(&jit->keygen);\n  atomic_store_explicit(virts + spot, virt, memory_order_release);\n  atomic_store_explicit(funcs + spot, func, memory_order_relaxed);\n  EndUpdate(&jit->keygen, kgen);\n  return true;\n}\n\nstatic bool SetJitHook(struct Jit *jit, u64 virt, int cas, intptr_t funcaddr) {\n  bool res;\n  LockJit(jit);\n  res = SetJitHookUnlocked(jit, virt, cas, funcaddr);\n  UnlockJit(jit);\n  return res;\n}\n\n/**\n * Retrieves native function for executing virtual address.\n *\n * @param jit is the System's Jit object\n * @param virt is the hash table key, or virtual address of path start\n * @return native function address, or 0 if it doesn't exist\n */\nuintptr_t GetJitHook(struct Jit *jit, u64 virt) {\n  int off;\n  uintptr_t key, res;\n  _Atomic(int) *funcs;\n  _Atomic(uintptr_t) *virts;\n  unsigned n, kgen, hash, spot, step;\n  COSTLY_STATISTIC(++jit_hash_lookups);\n  hash = HASH(virt);\n  do {\n    kgen = atomic_load_explicit(&jit->keygen, memory_order_relaxed);\n    n = atomic_load_explicit(&jit->hooks.n, memory_order_relaxed);\n    virts = atomic_load_explicit(&jit->hooks.virts, memory_order_acquire);\n    for (spot = step = 0;; ++step) {\n      spot = (hash + step * ((step + 1) >> 1)) & (n - 1);\n      key = atomic_load_explicit(virts + spot, memory_order_acquire);\n      if (key == virt) {\n        funcs = atomic_load_explicit(&jit->hooks.funcs, memory_order_relaxed);\n        off = atomic_load_explicit(funcs + spot, memory_order_relaxed);\n        res = off ? DecodeJitFunc(off) : 0;\n        break;\n      }\n      if (!key) {\n        return 0;\n      }\n      COSTLY_STATISTIC(++jit_hash_collisions);\n    }\n  } while (ShallNotPass(kgen, &jit->keygen));\n  return res;\n}\n\n// removes hook and edges for jit path and all paths that depend on it\n// @assume jit->lock\nstatic void DeleteJitPath(struct Jit *jit, i64 virt) {\n  i64 dep;\n  uintptr_t key;\n  int i, s, old;\n  _Atomic(int) *funcs;\n  _Atomic(uintptr_t) *virts;\n  unsigned n, hash, spot, step;\n  // delete hook for this path from hash table\n  hash = HASH(virt);\n  for (spot = step = 0;; ++step) {\n    n = atomic_load_explicit(&jit->hooks.n, memory_order_relaxed);\n    spot = (hash + step * ((step + 1) >> 1)) & (n - 1);\n    virts = atomic_load_explicit(&jit->hooks.virts, memory_order_relaxed);\n    key = atomic_load_explicit(virts + spot, memory_order_relaxed);\n    if (!key) return;\n    if ((i64)key == virt) {\n      JIT_LOGF(\"deleting jit hook for path starting at %#\" PRIx64, virt);\n      funcs = atomic_load_explicit(&jit->hooks.funcs, memory_order_relaxed);\n      old = atomic_load_explicit(funcs + spot, memory_order_relaxed);\n      if (old) {\n        atomic_store_explicit(funcs + spot, 0, memory_order_release);\n        if (old == jit->staging) {\n          STATISTIC(--jit_hooks_staged);\n        } else {\n          STATISTIC(--jit_hooks_installed);\n          STATISTIC(++jit_hooks_deleted);\n        }\n      }\n      break;\n    }\n  }\n  // delete paths that point to this path\n  while (jit->redges.dst[(s = GetEdge(&jit->redges, virt))] &&\n         jit->redges.dst[s]->i) {\n    dep = jit->redges.dst[s]->p[jit->redges.dst[s]->i - 1];\n    JIT_LOGF(\"jit path %#\" PRIx64 \" depends on %#\" PRIx64, dep, virt);\n    DeleteJitPath(jit, dep);\n  }\n  // delete edges associated with this path from bimap\n  if (jit->edges.dst[(s = GetEdge(&jit->edges, virt))]) {\n    for (i = jit->edges.dst[s]->i; i--;) {\n      RemoveEdge(&jit->redges, jit->edges.dst[s]->p[i], virt);\n    }\n    RemoveEdgesByIndex(&jit->edges, s);\n  }\n}\n\n// @assume jit->lock\nstatic void ResetJitPageHooks(struct Jit *jit, i64 page) {\n  i64 virt;\n  unsigned i, boff;\n  struct JitPage *jp;\n  if (!(jp = GetJitPage(jit, page))) return;\n  STATISTIC(AVERAGE(jit_page_average_bits, popcount(jp->bitset)));\n  while (jp->bitset) {\n    boff = bsr(jp->bitset);\n    virt = page + boff * (4096 / 64);\n    jp->bitset &= ~((u64)1 << boff);\n    for (i = 0; i < 64; ++i) {\n      DeleteJitPath(jit, virt + i);\n    }\n  }\n  dll_remove(&jit->pages, &jp->elem);\n  FreeJitPage(jp);\n}\n\n// @assume jit->lock\nstatic int ResetJitPageUnlocked(struct Jit *jit, i64 virt) {\n  i64 page;\n  unsigned gen;\n  page = virt & -4096;\n  STATISTIC(++jit_page_resets);\n  JIT_LOGF(\"resetting jit page %#\" PRIx64, page);\n  gen = BeginUpdate(&jit->pagegen);\n  ResetJitPageHooks(jit, page);\n  dll_make_first(&jit->freejumps, jit->jumps);\n  jit->jumps = 0;\n  EndUpdate(&jit->pagegen, gen);\n  return 0;\n}\n\n/**\n * Clears JIT paths installed to memory page.\n *\n * This is intended to be called when functions like mmap(), munmap(),\n * and mprotect() cause a memory page to either disappear or lose exec\n * permissions.\n *\n * @param virt is virtual address of 4096-byte page (needn't be aligned)\n * @return 0 on success, or -1 w/ errno\n */\nint ResetJitPage(struct Jit *jit, i64 virt) {\n  int res;\n  if (IsJitDisabled(jit)) return einval();\n  LockJit(jit);\n  res = ResetJitPageUnlocked(jit, virt);\n  UnlockJit(jit);\n  return res;\n}\n\n// @assume jit->lock\nstatic void ForceJitBlocksToRetire(struct Jit *jit) {\n  int i;\n  struct Dll *e, *e2;\n  struct JitBlock *jb;\n  unsigned n, pgen, kgen;\n  JIT_LOGF(\"retiring jit blocks to avoid oom\");\n  dll_make_first(&jit->freejumps, jit->jumps);\n  jit->jumps = 0;\n  pgen = BeginUpdate(&jit->pagegen);\n  for (e = dll_first(jit->agedblocks); e; e = e2) {\n    e2 = dll_next(jit->agedblocks, e);\n    jb = AGEDBLOCK_CONTAINER(e);\n    if (!jb->isprotected) {\n      JIT_LOGF(\"forcing jit block %p to retire\", jb);\n      RetireJitBlock(jit, jb);\n    }\n  }\n  n = atomic_load_explicit(&jit->hooks.n, memory_order_relaxed);\n  for (i = 0; i < n; ++i) {\n    if (atomic_load_explicit(jit->hooks.virts + i, memory_order_relaxed)) {\n      kgen = BeginUpdate(&jit->keygen);\n      atomic_store_explicit(jit->hooks.virts + i, 0, memory_order_release);\n      atomic_store_explicit(jit->hooks.funcs + i, 0, memory_order_relaxed);\n      EndUpdate(&jit->keygen, kgen);\n    }\n  }\n  jit->hooks.i = 0;\n  ClearEdges(&jit->redges);\n  ClearEdges(&jit->edges);\n  EndUpdate(&jit->pagegen, pgen);\n}\n\nstatic bool CheckMmapResult(void *want, void *got) {\n  if (got == MAP_FAILED) {\n    LOGF(\"failed to mmap() jit block: %s\", DescribeHostErrno(errno));\n    return false;\n  }\n  if (got != want) {\n    LOGF(\"jit block mmap(%p) returned unexpected address %p: %s\", want, got,\n         DescribeHostErrno(errno));\n    return false;\n  }\n  return true;\n}\n\nstatic bool PrepareJitMemory(void *addr, size_t size) {\n#ifdef MAP_JIT\n  // Apple M1 only permits RWX memory if we use MAP_JIT, which Apple has\n  // chosen to make incompatible with MAP_FIXED.\n  if (Munmap(addr, size)) {\n    LOGF(\"failed to munmap() jit block: %s\", DescribeHostErrno(errno));\n    return false;\n  }\n  return CheckMmapResult(\n      addr, Mmap(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC,\n                 MAP_JIT | MAP_PRIVATE | MAP_ANONYMOUS_, -1, 0, \"jit\"));\n#else\n  int prot;\n  prot = atomic_load_explicit(&g_jit.prot, memory_order_relaxed);\n  if (!Mprotect(addr, size, prot, \"jit\")) {\n    return true;\n  }\n  if (~prot & PROT_EXEC) {\n    LOGF(\"failed to mprotect() jit block: %s\", DescribeHostErrno(errno));\n    return false;\n  }\n  // OpenBSD imposes a R^X invariant and raises ENOTSUP if RWX\n  // memory is requested. Since other OSes might exist, having\n  // this same requirement, and possible a different errno, we\n  // shall just clear the exec flag and try again.\n  prot &= ~PROT_EXEC;\n  atomic_store_explicit(&g_jit.prot, prot, memory_order_relaxed);\n  return CheckMmapResult(\n      addr, Mmap(addr, size, prot, MAP_PRIVATE | MAP_ANONYMOUS_ | MAP_FIXED, -1,\n                 0, \"jit\"));\n#endif\n}\n\n/**\n * Begins writing function definition to JIT memory.\n *\n * This will acquire a block of JIT memory. Code may be added to the\n * function using methods like AppendJitPrologue() and AppendJitCall().\n * When a chunk is completed, FinishJit() should be called. The calling\n * thread is granted exclusive ownership of the returned block of JIT\n * memory, until it's relinquished by FinishJit().\n *\n * @param opt_virt is hash key for finished function, or 0 for manual\n * @return function builder object\n */\nstruct JitBlock *StartJit(struct Jit *jit, i64 opt_virt) {\n  struct Dll *e;\n  struct JitBlock *jb;\n  if (!IsJitDisabled(jit)) {\n    LockJit(jit);\n    if ((e = dll_first(jit->blocks)) &&  //\n        (jb = JITBLOCK_CONTAINER(e)) &&  //\n        jb->index + kJitFit <= kJitBlockSize) {\n      // we found a block with adequate free space owned by jit\n      dll_remove(&jit->blocks, &jb->elem);\n    } else {\n      if (g_jit.freecount <= kJitRetireQueue) {\n        ForceJitBlocksToRetire(jit);\n      }\n      if (!(jb = AcquireJitBlock(jit))) {\n        LOG_ONCE(LOGF(\"ran out of jit memory\"));\n      } else if (!PrepareJitMemory(jb->addr, kJitBlockSize)) {\n        // this system isn't allowing us to use jit memory\n        dll_remove(&jit->agedblocks, &jb->aged);\n        ReleaseJitBlock(jb);\n        DisableJit(jit);\n        jb = 0;\n      }\n    }\n    if (jb) {\n      dll_make_first(&jb->freejumps, jit->freejumps);\n      jit->freejumps = 0;\n    }\n    UnlockJit(jit);\n  } else {\n    jb = 0;\n  }\n  if (jb) {\n    jb->virt = opt_virt;\n    unassert(!(jb->start & (kJitAlign - 1)));\n    unassert(jb->start == jb->index);\n    jb->pagegen = atomic_load_explicit(&jit->pagegen, memory_order_acquire);\n    if (jb->virt && jit->staging) {\n      unassert(SetJitHook(jit, jb->virt, 0, DecodeJitFunc(jit->staging)));\n    } else {\n      JIT_LOGF(\"marking jit block %p as protected due to manual mode\", jb);\n      jb->isprotected = true;\n    }\n    if (pthread_jit_write_protect_supported_np()) {\n      pthread_jit_write_protect_np_workaround(false);\n    }\n  }\n  return jb;\n}\n\nstatic bool OomJit(struct JitBlock *jb) {\n  jb->index = kJitBlockSize + 1;\n  return false;\n}\n\n/**\n * Appends bytes to JIT block.\n *\n * Errors here safely propagate to FinishJit().\n *\n * @return true if room was available, otherwise false\n */\ninline bool AppendJit(struct JitBlock *jb, const void *data, long size) {\n  unassert(size > 0);\n  jb->lastaction = 0;\n  if (size <= GetJitRemaining(jb)) {\n    memcpy(jb->addr + jb->index, data, size);\n    jb->index += size;\n    return true;\n  } else {\n    return OomJit(jb);\n  }\n}\n\nstatic struct Dll *GetJitJumps(struct Jit *jit, struct JitBlock *jb, u64 virt) {\n  struct JitJump *jj;\n  struct Dll *res, *rem, *e, *e2;\n  LockJit(jit);\n  for (rem = res = 0, e = dll_first(jit->jumps); e; e = e2) {\n    e2 = dll_next(jit->jumps, e);\n    jj = JITJUMP_CONTAINER(e);\n    if (jj->virt == virt) {\n      dll_remove(&jit->jumps, e);\n      dll_make_first(&res, e);\n    } else if (++jj->tries == kJitJumpTries) {\n      dll_remove(&jit->jumps, e);\n      dll_make_first(&rem, e);\n    }\n  }\n  UnlockJit(jit);\n  dll_make_first(&jb->freejumps, rem);\n  return res;\n}\n\nstatic void FixupJitJumps(struct JitBlock *jb, struct Dll *list,\n                          uintptr_t addr) {\n  int n;\n  union {\n    u32 i;\n    u64 q;\n    u8 b[8];\n  } u;\n  struct Dll *e;\n  struct JitJump *jj;\n  for (e = dll_first(list); e; e = dll_next(list, e)) {\n    STATISTIC(++jumps_applied);\n    STATISTIC(++path_connected_directly);\n    jj = JITJUMP_CONTAINER(e);\n    u.q = 0;\n    n = MakeJitJump(u.b, (uintptr_t)jj->code, addr + jj->addend);\n    unassert(!((uintptr_t)jj->code & 3));\n#if defined(__aarch64__)\n    atomic_store_explicit((_Atomic(u32) *)jj->code, u.i, memory_order_release);\n#elif defined(__x86_64__)\n    u64 old, neu;\n    old = atomic_load_explicit((_Atomic(u64) *)jj->code, memory_order_relaxed);\n    do {\n      neu = (old & 0xffffff0000000000) | u.q;\n    } while (!atomic_compare_exchange_weak_explicit(\n        (_Atomic(u64) *)jj->code, &old, neu, memory_order_release,\n        memory_order_relaxed));\n#else\n#error \"not supported\"\n#endif\n    sys_icache_invalidate(jj->code, n);\n  }\n  dll_make_first(&jb->freejumps, list);\n}\n\nstatic bool UpdateJitHook(struct Jit *jit, struct JitBlock *jb, u64 virt,\n                          uintptr_t funcaddr) {\n  struct Dll *jumps;\n  unassert(funcaddr);\n  jumps = GetJitJumps(jit, jb, virt);\n  if (SetJitHook(jit, virt, jit->staging, funcaddr)) {\n    FixupJitJumps(jb, jumps, funcaddr);\n    return true;\n  } else {\n    dll_make_first(&jb->freejumps, jumps);\n    return false;\n  }\n}\n\nstatic void AbandonJitHook(struct Jit *jit, u64 virt) {\n  if (virt && jit->staging) {\n    SetJitHook(jit, virt, 0, 0);\n  }\n}\n\n// mprotects jit memory if a system page worth of code was generated\n// @assume jit->lock\nint CommitJit_(struct Jit *jit, struct JitBlock *jb) {\n  u8 *addr;\n  size_t size;\n  int count = 0;\n  long blockoff;\n  struct JitJump *jj;\n  struct JitStage *js;\n  struct Dll *e, *e2, *rem;\n  unassert(jb->start == jb->index);\n  unassert(!(jb->committed & (FLAG_pagesize - 1)));\n  if (!CanJitForImmediateEffect() &&\n      (blockoff = ROUNDDOWN(jb->start, FLAG_pagesize)) > jb->committed) {\n    addr = jb->addr + jb->committed;\n    size = blockoff - jb->committed;\n    JIT_LOGF(\"jit activating [%p,%p) w/ %zu kb\", addr, addr + size,\n             size / 1024);\n    // abandon fixups pointing into the block being protected\n    LockJit(jit);\n    for (rem = 0, e = dll_first(jit->jumps); e; e = e2) {\n      e2 = dll_next(jit->jumps, e);\n      jj = JITJUMP_CONTAINER(e);\n      if (MAX(jj->code, addr) < MIN(jj->code + 5, addr + size)) {\n        dll_remove(&jit->jumps, e);\n        dll_make_first(&rem, e);\n      }\n    }\n    UnlockJit(jit);\n    for (e = dll_first(rem); e; e = e2) {\n      e2 = dll_next(rem, e);\n      FreeJitJump(JITJUMP_CONTAINER(e));\n    }\n    // ask system to change the page memory protections\n    unassert(!Mprotect(addr, size, PROT_READ | PROT_EXEC, \"jit\"));\n    // update interpreter hooks so our new jit code goes live\n    while ((e = dll_first(jb->staged))) {\n      js = JITSTAGE_CONTAINER(e);\n      unassert(js->index >= jb->committed);\n      if (js->index <= blockoff) {\n        if (!ShallNotPass(js->pagegen, &jit->pagegen)) {\n          UpdateJitHook(jit, jb, js->virt, (uintptr_t)jb->addr + js->start);\n        } else {\n          AbandonJitHook(jit, js->virt);\n        }\n        dll_remove(&jb->staged, e);\n        FreeJitStage(js);\n        ++count;\n      } else {\n        break;\n      }\n    }\n    jb->committed = blockoff;\n  }\n  return count;\n}\n\n// puts user leased block back into jit->blocks pool for potential reuse\n// @assume jit->lock\nvoid ReinsertJitBlock_(struct Jit *jit, struct JitBlock *jb) {\n  unassert(jb->start == jb->index);\n  unassert(dll_is_empty(jb->jumps));\n  if (jb->index < kJitBlockSize) {\n    // there's still memory remaining; reinsert for immediate reuse.\n    dll_make_first(&jit->blocks, &jb->elem);\n  } else {\n    // block has been filled; relegate it to the end of the list.\n    // guarantee that staged hooks shall be committed on openbsd.\n    _Static_assert(kJitBlockSize % kMaximumAnticipatedPageSize == 0,\n                   \"unassert(dll_is_empty(jb->staged)) can't pass \"\n                   \"unless kJitBlockSize is divisible by page size\");\n    unassert(dll_is_empty(jb->staged));\n    dll_make_last(&jit->blocks, &jb->elem);\n  }\n}\n\n// append our list of code fixups to jit system which may apply it later\nstatic void CommitJitJumps(struct Jit *jit, struct JitBlock *jb) {\n  if (!dll_is_empty(jb->jumps)) {\n    LockJit(jit);\n    dll_make_first(&jit->jumps, jb->jumps);\n    jb->jumps = 0;\n    UnlockJit(jit);\n  }\n}\n\n// discards fixups associated with function that couldn't be generated\nstatic void AbandonJitJumps(struct JitBlock *jb) {\n  struct Dll *e, *e2;\n  for (e = dll_first(jb->jumps); e; e = e2) {\n    e2 = dll_next(jb->jumps, e);\n    FreeJitJump(JITJUMP_CONTAINER(e));\n  }\n  jb->jumps = 0;\n}\n\n/**\n * Records jump instruction fixup.\n *\n * When a JIT path ends because it's branching into an address for which\n * a JIT path doesn't exist yet, the caller may choose to generated code\n * that falls back into the main interpreter loop while recording a jump\n * fixup, so that if the destination virtual address is generated later,\n * the JIT will atomically self-modify this code to jump to the new one.\n *\n * @param virt is hash table key of destination (should be empty now)\n * @param addend is added to dest function pointer to compute jump\n */\nbool RecordJitJump(struct JitBlock *jb, u64 virt, int addend) {\n  struct JitJump *jj;\n  if (jb->index > kJitBlockSize) return false;\n#if defined(__x86_64__)\n  unassert(!(GetJitPc(jb) & 7));\n#endif\n  if (!CanJitForImmediateEffect()) return false;\n  if (!(jj = NewJitJump(&jb->freejumps))) return false;\n  jj->tries = 0;\n  jj->virt = virt;\n  jj->code = (u8 *)GetJitPc(jb);\n  jj->addend = addend;\n  dll_make_first(&jb->jumps, &jj->elem);\n  STATISTIC(++jumps_recorded);\n  return true;\n}\n\n// @assume jit->lock\nstatic bool RecordJitEdgeImpl(struct Jit *jit, i64 src, i64 dst) {\n  i64 visits[kJitDepth];\n  if (src == dst) return false;\n  visits[0] = src;\n  if (IsCyclic(&jit->edges, visits, 1, dst)) {\n    STATISTIC(++jit_cycles_avoided);\n    return false;\n  }\n  if (!AddEdge(&jit->edges, src, dst)) {\n    return false;\n  }\n  if (!AddEdge(&jit->redges, dst, src)) {\n    RemoveEdge(&jit->edges, src, dst);\n    return false;\n  }\n  return true;\n}\n\n/**\n * Records JIT edge or returns false if it'd create a cycle.\n */\nbool RecordJitEdge(struct Jit *jit, i64 src, i64 dst) {\n  bool res;\n  LockJit(jit);\n  res = RecordJitEdgeImpl(jit, src, dst);\n  UnlockJit(jit);\n  return res;\n}\n\nstatic void DiscardGeneratedJitCode(struct JitBlock *jb) {\n  jb->index = jb->start;\n}\n\n/**\n * Finishes writing function definition to JIT memory.\n *\n * Errors that happened earlier in AppendJit*() methods will safely\n * propagate to this function. This function may disable the JIT on\n * errors that aren't recoverable.\n *\n * @param jb is function builder object that was returned by StartJit();\n *     this function always relinquishes the calling thread's ownership\n *     of this object, even if this function returns an error\n * @return true if the function was generated, otherwise false if we ran\n *     out of room in the block while building the function, in which\n *     case the caller should simply try again\n */\nbool FinishJit(struct Jit *jit, struct JitBlock *jb) {\n  bool ok;\n  u8 *addr;\n  struct JitStage *js;\n  unassert(jb->index > jb->start);\n  unassert(jb->start >= jb->committed);\n  // check if we lost race with page reset\n  if (ShallNotPass(jb->pagegen, &jit->pagegen)) {\n    return AbandonJit(jit, jb);\n  }\n  // align generated functions using breakpoint opcodes\n  while (jb->index < kJitBlockSize && (jb->index & (kJitAlign - 1))) {\n    unassert(AppendJitTrap(jb));\n    unassert(jb->index <= kJitBlockSize);\n  }\n  if (jb->index <= kJitBlockSize) {\n    // function code was generated successfully\n    if (jb->virt) {\n      // since we have a hash table key we must install the hook\n      JIP_LOGF(\"finishing jit path in block %p at %#\" PRIx64, jb, jb->virt);\n      if (CanJitForImmediateEffect()) {\n        // operating system permits us to use rwx memory\n        addr = jb->addr + jb->start;\n        sys_icache_invalidate(addr, jb->index - jb->start);\n        if (!UpdateJitHook(jit, jb, jb->virt, (uintptr_t)addr)) {\n          // we lost race with another thread creating path at same addr\n          return AbandonJit(jit, jb);\n        }\n      } else if ((js = NewJitStage())) {\n        // updating hook must be deferred until we've filled system page\n        // with code and then change its permission: mprotect(rwx -> rx)\n        js->virt = jb->virt;\n        js->start = jb->start;\n        js->index = jb->index;\n        js->pagegen = jb->pagegen;\n        dll_make_last(&jb->staged, &js->elem);\n      }\n    } else {\n      JIT_LOGF(\"finishing manual mode jit path in block %p\", jb);\n    }\n    CommitJitJumps(jit, jb);\n    // mark the generated jit memory as having been used\n    // if there's only a tiny bit left we advance to end\n    if (jb->index + kJitFit > kJitBlockSize) {\n      JIT_LOGF(\"ending jit block %p due to pretty good fit\", jb);\n      STATISTIC(AVERAGE(jit_average_block, jb->index));\n      jb->index = kJitBlockSize;\n    }\n    jb->start = jb->index;\n    ok = true;\n  } else {\n    // we ran out of jit memory in block while generating the function\n    STATISTIC(++path_ooms);\n    AbandonJitJumps(jb);\n    if (jb->index - jb->start < (kJitBlockSize >> 1)) {\n      // we ran out of block space when trying to create a path that's\n      // shorter than half the maximum block size. in that case, abandon\n      // the path. this will reset the hook on the initial path address.\n      // hopefully the next time it's executed, there'll be enough room.\n      JIT_LOGF(\"oom'd jit block %p at %#\" PRIx64 \" due to lack of room\", jb,\n               jb->virt);\n      AbandonJitHook(jit, jb->virt);\n    } else {\n      // we ran out of block space trying to create a path that's very\n      // long. it's possibly longer than the maximum block size. in that\n      // case, just permanently leave the starting address in staging so\n      // that we won't try to create this path again.\n      JIT_LOGF(\"oom'd jit block %p at %#\" PRIx64 \" because long code is long\",\n               jb, jb->virt);\n    }\n    DiscardGeneratedJitCode(jb);\n    ok = false;\n  }\n  unassert(jb->start == jb->index);\n  CommitJit_(jit, jb);\n  LockJit(jit);\n  ReinsertJitBlock_(jit, jb);\n  if (jb->index >= kJitBlockSize) {\n    dll_make_first(&jit->freejumps, jb->freejumps);\n    jb->freejumps = 0;\n  }\n  UnlockJit(jit);\n  if (pthread_jit_write_protect_supported_np()) {\n    pthread_jit_write_protect_np_workaround(true);\n  }\n  return ok;\n}\n\n/**\n * Abandons writing function definition to JIT memory.\n *\n * @param jb becomes owned by `jit` again after this call\n * @return always false\n */\nbool AbandonJit(struct Jit *jit, struct JitBlock *jb) {\n  JIT_LOGF(\"abandoning jit path in block %p at %#\" PRIx64, jb, jb->virt);\n  STATISTIC(++path_abandoned);\n  AbandonJitJumps(jb);\n  AbandonJitHook(jit, jb->virt);\n  DiscardGeneratedJitCode(jb);\n  LockJit(jit);\n  ReinsertJitBlock_(jit, jb);\n  UnlockJit(jit);\n  if (pthread_jit_write_protect_supported_np()) {\n    pthread_jit_write_protect_np_workaround(true);\n  }\n  return false;\n}\n\n/**\n * Appends NOPs until PC is aligned to `align`.\n *\n * @param align is byte alignment, which must be a two power\n */\nbool AlignJit(struct JitBlock *jb, int align, int misalign) {\n  unassert(align > 0 && IS2POW(align));\n  unassert(misalign >= 0 && misalign < align);\n  while ((jb->index & (align - 1)) != misalign) {\n#ifdef __x86_64__\n    // Intel's Official Multibyte NOP Instructions\n    //\n    //     90                 nop\n    //     6690               xchg %ax,%ax\n    //     0F1F00             nopl (%rax)\n    //     0F1F4000           nopl 0x00(%rax)\n    //     0f1f440000         nopl 0x00(%rax,%rax,1)\n    //     660f1f440000       nopw 0x00(%rax,%rax,1)\n    //     0F1F8000000000     nopl 0x00000000(%rax)\n    //     0F1F840000000000   nopl 0x00000000(%rax,%rax,1)\n    //     660F1F840000000000 nopw 0x00000000(%rax,%rax,1)\n    //\n    // See Intel's Six Thousand Page Manual, Volume 2, Table 4-12:\n    // \"Recommended Multi-Byte Sequence of NOP Instruction\".\n    static const u8 kNops[7][8] = {\n        {1, 0x90},\n        {2, 0x66, 0x90},\n        {3, 0x0f, 0x1f, 0x00},\n        {4, 0x0f, 0x1f, 0x40, 0x00},\n        {5, 0x0f, 0x1f, 0x44, 0x00, 0x00},\n        {6, 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},\n        {7, 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},\n    };\n    int skew, need;\n    skew = jb->index & (align - 1);\n    if (skew > misalign) {\n      need = align - skew + misalign;\n    } else {\n      need = misalign - skew;\n    }\n    if (!AppendJit(jb, kNops[MIN(7, need) - 1] + 1,\n                   kNops[MIN(7, need) - 1][0])) {\n      return false;\n    }\n#else\n    if (!AppendJitNop(jb)) {\n      return false;\n    }\n#endif\n  }\n  unassert((jb->index & (align - 1)) == misalign);\n  return true;\n}\n\n/**\n * Moves one register's value into another register.\n *\n * The `src` and `dst` register indices are architecture defined.\n * Predefined constants such as `kJitArg0` may be used to provide\n * register indices to this function in a portable way.\n *\n * @param dst is the index of the destination register\n * @param src is the index of the source register\n */\nbool AppendJitMovReg(struct JitBlock *jb, int dst, int src) {\n  long action;\n  if (dst == src) return true;\n  if (GetJitRemaining(jb) < 4) return OomJit(jb);\n  if ((action = MOVE(dst, src)) == jb->lastaction) return true;\n#if defined(__x86_64__)\n  unassert(!(dst & ~15));\n  unassert(!(src & ~15));\n  Write32(jb->addr + jb->index,\n          ((kAmdRexw | (src & 8 ? kAmdRexr : 0) | (dst & 8 ? kAmdRexb : 0)) |\n           0x89 << 010 | (0300 | (src & 7) << 3 | (dst & 7)) << 020));\n  jb->index += 3;\n#elif defined(__aarch64__)\n  //               src            target\n  //              ┌─┴─┐           ┌─┴─┐\n  // 0b10101010000000000000001111110011 mov x19, x0\n  // 0b10101010000000010000001111110100 mov x20, x1\n  // 0b10101010000101000000001111100001 mov x1, x20\n  // 0b10101010000100110000001111100000 mov x0, x19\n  unassert(!(dst & ~31));\n  unassert(!(src & ~31));\n  Put32(jb->addr + jb->index, 0xaa0003e0 | src << 16 | dst);\n  jb->index += 4;\n#endif\n  jb->lastaction = action;\n  return true;\n}\n\n/**\n * Appends function call instruction to JIT memory.\n *\n * @param jb is function builder object returned by StartJit()\n * @param func points to another callee function in memory\n * @return true if room was available, otherwise false\n */\nbool AppendJitCall(struct JitBlock *jb, void *func) {\n  int n;\n  intptr_t disp;\n  uintptr_t addr;\n  addr = (uintptr_t)func;\n#if defined(__x86_64__)\n  u8 buf[5];\n  disp = addr - (GetJitPc(jb) + 5);\n  if (kAmdDispMin <= disp && disp <= kAmdDispMax) {\n    // AMD function calls are encoded using an 0xE8 byte, followed by a\n    // 32-bit signed two's complement little-endian integer, containing\n    // the relative location between the function being called, and the\n    // instruction at the location that follows our 5 byte call opcode.\n    buf[0] = kAmdCall;\n    Write32(buf + 1, disp & kAmdDispMask);\n    n = 5;\n  } else {\n    AppendJitSetReg(jb, kAmdAx, addr);\n    buf[0] = kAmdCallAx[0];\n    buf[1] = kAmdCallAx[1];\n    n = 2;\n  }\n#elif defined(__aarch64__)\n  uint32_t buf[1];\n  // ARM function calls are encoded as:\n  //\n  //       BL          displacement\n  //     ┌─┴──┐┌────────────┴───────────┐\n  //   0b100101sddddddddddddddddddddddddd\n  //\n  // Where:\n  //\n  //   - BL (0x94000000) is what ARM calls its CALL instruction\n  //\n  //   - sddddddddddddddddddddddddd is a 26-bit two's complement integer\n  //     of how far away the function is that's being called. This is\n  //     measured in terms of instructions rather than bytes. Unlike AMD\n  //     the count here starts at the Program Counter (PC) address where\n  //     the BL INSN is stored, rather than the one that follows.\n  //\n  // Displacement is computed as such:\n  //\n  //   INSN = BL | (((FUNC - PC) >> 2) & 0x03ffffffu)\n  //\n  // The inverse of the above operation is:\n  //\n  //   FUNC = PC + ((i32)((u32)(INSN & 0x03ffffffu) << 6) >> 4)\n  //\n  disp = addr - GetJitPc(jb);\n  disp >>= 2;\n  unassert(kArmDispMin <= disp && disp <= kArmDispMax);\n  buf[0] = kArmCall | (disp & kArmDispMask);\n  n = 4;\n#endif\n  return AppendJit(jb, buf, n);\n}\n\n/**\n * Appends unconditional branch instruction to JIT memory.\n *\n * @param jb is function builder object returned by StartJit()\n * @param code points to some other code address in memory\n * @return true if room was available, otherwise false\n */\nbool AppendJitJump(struct JitBlock *jb, void *code) {\n  u8 buf[5];\n  int n = MakeJitJump(buf, GetJitPc(jb), (uintptr_t)code);\n  return AppendJit(jb, buf, n);\n}\n\n/**\n * Sets register to immediate value.\n *\n * @param jb is function builder object returned by StartJit()\n * @param param is the zero-based index into the register file\n * @param value is the constant value to use as the parameter\n * @return true if room was available, otherwise false\n */\nbool AppendJitSetReg(struct JitBlock *jb, int reg, u64 value) {\n  long lastaction;\n#if defined(__x86_64__)\n  u8 rex = 0;\n  if (GetJitRemaining(jb) < 10) return OomJit(jb);\n  if (reg & 8) rex |= kAmdRexb;\n  if (!value) {\n    if (reg & 8) rex |= kAmdRexr;\n    if (rex) jb->addr[jb->index++] = rex;\n    jb->addr[jb->index++] = kAmdXor;\n    jb->addr[jb->index++] = 0300 | (reg & 7) << 3 | (reg & 7);\n  } else if ((i64)value < 0 && (i64)value >= INT32_MIN) {\n    jb->addr[jb->index++] = rex | kAmdRexw;\n    jb->addr[jb->index++] = 0xC7;\n    jb->addr[jb->index++] = 0300 | (reg & 7);\n    Write32(jb->addr + jb->index, value);\n    jb->index += 4;\n  } else {\n    if (value > 0xffffffff) rex |= kAmdRexw;\n    if (rex) jb->addr[jb->index++] = rex;\n    jb->addr[jb->index++] = kAmdMovImm | (reg & 7);\n    if ((rex & kAmdRexw) != kAmdRexw) {\n      Write32(jb->addr + jb->index, value);\n      jb->index += 4;\n    } else {\n      Write64(jb->addr + jb->index, value);\n      jb->index += 8;\n    }\n  }\n#elif defined(__aarch64__)\n  // ARM immediate moves are encoded as:\n  //\n  //     ┌64-bit\n  //     │\n  //     │┌{sign,???,zero,non}-extending\n  //     ││\n  //     ││       ┌short[4] index\n  //     ││       │\n  //     ││  MOV  │    immediate   register\n  //     │├┐┌─┴──┐├┐┌──────┴───────┐┌─┴─┐\n  //   0bmxx100101iivvvvvvvvvvvvvvvvrrrrr\n  //\n  // Which allows 16 bits to be loaded into a register at a time, with\n  // tricks for clearing other parts of the register. For example, the\n  // sign-extending mode will set the higher order shorts to all ones,\n  // and it expects the immediate to be encoded using ones' complement\n  u32 op;\n  u32 *p;\n  int i, n = 0;\n  unassert(!(reg & ~kArmRegMask));\n  if (GetJitRemaining(jb) < 16) return OomJit(jb);\n  p = (u32 *)(jb->addr + jb->index);\n  // TODO: This could be improved some more.\n  if ((i64)value < 0 && (i64)value >= -0x8000) {\n    p[n++] = kArmMovSex | ~value << kArmImmOff | reg << kArmRegOff;\n  } else {\n    i = 0;\n    op = kArmMovZex;\n    while (value && !(value & 0xffff)) {\n      value >>= 16;\n      ++i;\n    }\n    do {\n      op |= (value & 0xffff) << kArmImmOff;\n      op |= reg << kArmRegOff;\n      op |= i++ << kArmIdxOff;\n      p[n++] = op;\n      op = kArmMovNex;\n    } while ((value >>= 16));\n  }\n  jb->index += n * 4;\n#endif\n  lastaction = jb->lastaction;\n  if (ACTION(lastaction) == ACTION_MOVE &&  //\n      MOVE_DST(lastaction) != reg &&        //\n      MOVE_SRC(lastaction) != reg) {\n    jb->lastaction = lastaction;\n  }\n  return true;\n}\n\n/**\n * Appends return instruction.\n */\nbool AppendJitRet(struct JitBlock *jb) {\n#if defined(__x86_64__)\n  u8 buf[1] = {0xc3};\n#elif defined(__aarch64__)\n  u32 buf[1] = {0xd65f03c0};\n#endif\n  return AppendJit(jb, buf, sizeof(buf));\n}\n\n/**\n * Appends no-op instruction.\n */\nbool AppendJitNop(struct JitBlock *jb) {\n#if defined(__x86_64__)\n  u8 buf[1] = {0x90};  // nop\n#elif defined(__aarch64__)\n  u32 buf[1] = {0xd503201f};  // nop\n#endif\n  return AppendJit(jb, buf, sizeof(buf));\n}\n\n/**\n * Appends pause instruction.\n */\nbool AppendJitPause(struct JitBlock *jb) {\n#if defined(__x86_64__)\n  u8 buf[2] = {0xf3, 0x90};  // pause\n#elif defined(__aarch64__)\n  u32 buf[1] = {0xd503203f};  // yield\n#endif\n  return AppendJit(jb, buf, sizeof(buf));\n}\n\n/**\n * Appends debugger breakpoint.\n */\nbool AppendJitTrap(struct JitBlock *jb) {\n#if defined(__x86_64__)\n  u8 buf[1] = {0xcc};  // int3\n#elif defined(__aarch64__)\n  u32 buf[1] = {0xd4207d00};  // brk #0x3e8\n#endif\n  return AppendJit(jb, buf, sizeof(buf));\n}\n\n#endif /* HAVE_JIT */\n"
  },
  {
    "path": "blink/jit.h",
    "content": "#ifndef BLINK_JIT_H_\n#define BLINK_JIT_H_\n#include <inttypes.h>\n#include <stdbool.h>\n\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/dll.h\"\n#include \"blink/thread.h\"\n#include \"blink/tunables.h\"\n#include \"blink/types.h\"\n\n#define kJitFit          1000\n#define kJitDepth        16\n#define kJitAlign        16\n#define kJitJumpTries    16\n#define kJitBlockSize    262144\n#define kJitMemorySize   32505856\n#define kJitRetireQueue  (int)(kJitMemorySize / kJitBlockSize * .10)\n#define kJitSlabInts     (65536 / sizeof(struct JitInts))\n#define kJitInitialHooks 16384\n#define kJitInitialEdges 4096\n\n#ifdef __x86_64__\n#define kJitRes0 kAmdAx\n#define kJitRes1 kAmdDx\n#ifdef __CYGWIN__\n#define kJitArg0 kAmdCx\n#define kJitArg1 kAmdDx\n#define kJitArg2 8\n#define kJitArg3 9\n#else\n#define kJitArg0 kAmdDi\n#define kJitArg1 kAmdSi\n#define kJitArg2 kAmdDx\n#define kJitArg3 kAmdCx\n#endif\n#define kJitSav0 kAmdBx\n#define kJitSav1 12\n#define kJitSav2 13\n#define kJitSav3 14\n#define kJitSav4 15\n#else\n#define kJitRes0 0\n#define kJitRes1 1\n#define kJitArg0 0\n#define kJitArg1 1\n#define kJitArg2 2\n#define kJitArg3 3\n#define kJitSav0 19\n#define kJitSav1 20\n#define kJitSav2 21\n#define kJitSav3 22\n#define kJitSav4 23\n#endif\n\n#ifdef __x86_64__\n#define kAmdXor           0x31\n#define kAmdRet           0xc3\n#define kAmdJmp           0xe9\n#define kAmdCall          0xe8\n#define kAmdJmpAx         \"\\377\\340\"\n#define kAmdCallAx        \"\\377\\320\"\n#define kAmdDispMin       INT32_MIN\n#define kAmdDispMax       INT32_MAX\n#define kAmdDispMask      0xffffffffu\n#define kAmdRex           0x40  // turns ah/ch/dh/bh into spl/bpl/sil/dil\n#define kAmdRexb          0x41  // turns 0007 (r/m) of modrm into r8..r15\n#define kAmdRexr          0x44  // turns 0070 (reg) of modrm into r8..r15\n#define kAmdRexw          0x48  // makes register 64-bit\n#define kAmdAx            0     // first function result\n#define kAmdCx            1     // third function parameter\n#define kAmdDx            2     // fourth function parameter, second result\n#define kAmdBx            3     // generic saved register\n#define kAmdSp            4     // stack pointer\n#define kAmdBp            5     // backtrace pointer\n#define kAmdSi            6     // second function parameter\n#define kAmdDi            7     // first function parameter\n#define kAmdWord          1     // turns `op Eb,Gb` into `op Evqp,Gvqp`\n#define kAmdFlip          2     // turns `op r/m,r` into `op r,r/m`\n#define kAmdModrmRdiDisp8 0107  // ModR/M [-128,127](%rdi)\n#define kAmdMovImm        0xb8  // or'd with register, imm size is same as reg\n#define kAmdMov           0x88  // may be or'd with kAmdWord, kAmdFlip\n#endif\n\n#ifdef __aarch64__\n#define kArmJmp    0x14000000u  // B\n#define kArmCall   0x94000000u  // BL\n#define kArmRet    0xd65f03c0u  // RET\n#define kArmMovNex 0xf2800000u  // sets sub-word of register to immediate\n#define kArmMovZex 0xd2800000u  // load immediate into reg w/ zero-extend\n#define kArmMovSex 0x92800000u  // load 1's complement imm w/ sign-extend\n#define kArmAdr    0x10000000u  // form PC-relative byte address\n#define kArmAdrp   0x90000000u  // form PC-relative page address\n#define kArmLdrPc \\\n  0x18000000u                        // load PC-relative memory into register\n                                     // (general or SIMD)\n#define kArmLdrswPc     0x98000000u  // load PC-relative short w/ sign-extend\n#define kArmPrfmPc      0xd8000000u  // prefetch PC-relative memory\n#define kArmDispMin     -33554432    // can jump -2**25 ints backward\n#define kArmDispMax     +33554431    // can jump +2**25-1 ints forward\n#define kArmDispMask    0x03ffffffu  // mask of branch displacement\n#define kArmRegOff      0            // bit offset of destination register\n#define kArmRegMask     0x0000001fu  // mask of destination register\n#define kArmImmOff      5            // bit offset of mov immediate value\n#define kArmImmMask     0x001fffe0u  // bit offset of mov immediate value\n#define kArmImmMax      0xffffu      // maximum immediate value per instruction\n#define kArmIdxOff      21           // bit offset of u16[4] sub-word index\n#define kArmIdxMask     0x00600000u  // mask of u16[4] sub-word index\n#define kArmAdrMask     0x9f000000u  // mask of ADR opcode\n#define kArmAdrpMask    0x9f000000u  // mask of ADRP opcode\n#define kArmLdrPcMask   0xbb000000u  // mask of PC-relative LDR opcodes\n#define kArmLdrswPcMask 0xff000000u  // mask of PC-relative LDRSW opcode\n#define kArmPrfmPcMask  0xff000000u  // mask of PC-relative PRFM opcode\n#endif\n\n#define JITJUMP_CONTAINER(e)   DLL_CONTAINER(struct JitJump, elem, e)\n#define JITPAGE_CONTAINER(e)   DLL_CONTAINER(struct JitPage, elem, e)\n#define JITSTAGE_CONTAINER(e)  DLL_CONTAINER(struct JitStage, elem, e)\n#define JITBLOCK_CONTAINER(e)  DLL_CONTAINER(struct JitBlock, elem, e)\n#define JITFREED_CONTAINER(e)  DLL_CONTAINER(struct JitFreed, elem, e)\n#define AGEDBLOCK_CONTAINER(e) DLL_CONTAINER(struct JitBlock, aged, e)\n#define JIASLAB_CONTAINER(e)   DLL_CONTAINER(struct JitIntsSlab, elem, e)\n\nstruct JitInts {\n  int i, n;\n  i64 *p, m[2];\n};\n\nstruct JitIntsSlab {\n  int i;\n  struct Dll elem;\n  struct JitInts p[kJitSlabInts];\n};\n\nstruct JitIntsAllocator {\n  int i, n;\n  struct JitInts **p;\n  struct Dll *slabs;\n};\n\nstruct JitEdges {\n  int i, n;\n  i64 *src;\n  struct JitInts **dst;\n  struct JitIntsAllocator jia;\n};\n\nstruct JitJump {\n  u8 *code;\n  u64 virt;\n  int tries;\n  int addend;\n  struct Dll elem;\n};\n\nstruct JitStage {\n  long start;\n  long index;\n  u64 virt;\n  unsigned pagegen;\n  struct Dll elem;\n};\n\nstruct JitFreed {\n  void *data;\n  size_t size;\n  struct Dll elem;\n};\n\nstruct JitFreeds {\n  int n;\n  struct Dll *p;\n  struct Dll *f;\n};\n\nstruct JitPage {\n  i64 page;\n  u64 bitset;\n  struct Dll elem;\n};\n\nstruct JitBlock {\n  u8 *addr;\n  i64 virt;\n  long start;\n  long index;\n  long committed;\n  long lastaction;\n  bool wasretired;\n  bool isprotected;\n  unsigned pagegen;\n  struct Dll elem;\n  struct Dll aged;\n  struct Dll *jumps;\n  struct Dll *staged;\n  struct Dll *freejumps;\n};\n\nstruct JitHooks {\n  unsigned i;\n  _Atomic(unsigned) n;\n  _Atomic(_Atomic(int) *) funcs;\n  _Atomic(_Atomic(uintptr_t) *) virts;\n};\n\nstruct Jit {\n  int staging;\n  bool threaded;\n  _Atomic(bool) disabled;\n  struct JitHooks hooks;\n  struct JitEdges edges;\n  struct JitEdges redges;\n  struct JitFreeds freeds;\n  struct Dll *agedblocks;\n  struct Dll *blocks;\n  struct Dll *jumps;\n  struct Dll *freejumps;\n  struct Dll *pages;\n  pthread_mutex_t_ lock;\n  _Atomic(unsigned) keygen;\n  _Atomic(unsigned) pagegen;\n};\n\nextern const u8 kJitRes[2];\nextern const u8 kJitSav[5];\nextern const u8 kJitArg[4];\n\nint ShutdownJit(void);\nint EnableJit(struct Jit *);\nint DisableJit(struct Jit *);\nint DestroyJit(struct Jit *);\nint FixJitProtection(struct Jit *);\nint InitJit(struct Jit *, uintptr_t);\nbool CanJitForImmediateEffect(void) nosideeffect;\nbool AppendJit(struct JitBlock *, const void *, long);\nbool AbandonJit(struct Jit *, struct JitBlock *);\nint FlushJit(struct Jit *);\nstruct JitBlock *StartJit(struct Jit *, i64);\nbool AlignJit(struct JitBlock *, int, int);\nbool AppendJitRet(struct JitBlock *);\nbool AppendJitNop(struct JitBlock *);\nbool AppendJitPause(struct JitBlock *);\nbool AppendJitTrap(struct JitBlock *);\nbool AppendJitJump(struct JitBlock *, void *);\nbool AppendJitCall(struct JitBlock *, void *);\nbool AppendJitSetReg(struct JitBlock *, int, u64);\nbool AppendJitMovReg(struct JitBlock *, int, int);\nbool FinishJit(struct Jit *, struct JitBlock *);\nbool RecordJitJump(struct JitBlock *, u64, int);\nbool RecordJitEdge(struct Jit *, i64, i64);\nuintptr_t GetJitHook(struct Jit *, u64);\nint ResetJitPage(struct Jit *, i64);\n\nint CommitJit_(struct Jit *, struct JitBlock *);\nvoid ReinsertJitBlock_(struct Jit *, struct JitBlock *);\n\n/**\n * Returns number of bytes of space remaining in JIT memory block.\n *\n * @return number of bytes of space that can be appended into, or -1 if\n *     if an append operation previously failed due to lack of space\n */\nstatic inline long GetJitRemaining(const struct JitBlock *jb) {\n  return kJitBlockSize - jb->index;\n}\n\n/**\n * Returns current program counter or instruction pointer of JIT block.\n *\n * @return absolute instruction pointer memory address in bytes\n */\nstatic inline uintptr_t GetJitPc(const struct JitBlock *jb) {\n  return (uintptr_t)jb->addr + jb->index;\n}\n\n/**\n * Returns true if DisableJit() was called or AcquireJit() had failed.\n */\nstatic inline bool IsJitDisabled(const struct Jit *jit) {\n#ifdef HAVE_JIT\n  return atomic_load_explicit(&jit->disabled, memory_order_acquire);\n#else\n  return true;\n#endif\n}\n\n#endif /* BLINK_JIT_H_ */\n"
  },
  {
    "path": "blink/jitflush.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/dll.h\"\n#include \"blink/flag.h\"\n#include \"blink/jit.h\"\n#include \"blink/macros.h\"\n#include \"blink/thread.h\"\n\n/**\n * Forces activation of committed JIT chunks.\n *\n * Normally JIT chunks become active and have their function pointer\n * hook updated automatically once the system block fills up with jit\n * code. In some cases, such as unit tests, it's necessary to ensure\n * that JIT code goes live sooner. The tradeoff of flushing is it'll\n * lead to wasted memory and less performance, due to the additional\n * mprotect() system call overhead.\n */\nint FlushJit(struct Jit *jit) {\n  int count = 0;\n  struct Dll *e;\n  struct JitBlock *jb;\n  struct JitStage *js;\n  if (!CanJitForImmediateEffect()) {\n    LOCK(&jit->lock);\n  StartOver:\n    for (e = dll_first(jit->blocks); e; e = dll_next(jit->blocks, e)) {\n      jb = JITBLOCK_CONTAINER(e);\n      if (jb->start >= kJitBlockSize) break;\n      if (!dll_is_empty(jb->staged)) {\n        dll_remove(&jit->blocks, e);\n        UNLOCK(&jit->lock);\n        js = JITSTAGE_CONTAINER(dll_last(jb->staged));\n        jb->start = ROUNDUP(js->index, FLAG_pagesize);\n        jb->index = jb->start;\n        count += CommitJit_(jit, jb);\n        ReinsertJitBlock_(jit, jb);\n        LOCK(&jit->lock);\n        goto StartOver;\n      }\n    }\n    UNLOCK(&jit->lock);\n  }\n  return count;\n}\n"
  },
  {
    "path": "blink/ldbl.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/ldbl.h\"\n\n#include \"blink/endian.h\"\n#include \"blink/macros.h\"\n#include \"blink/pun.h\"\n\nu8 *SerializeLdbl(u8 b[10], double f) {\n  int e;\n  union DoublePun u = {f};\n  e = (u.i >> 52) & 0x7ff;\n  if (!e) {\n    e = 0;\n  } else if (e == 0x7ff) {\n    e = 0x7fff;\n  } else {\n    e -= 0x3ff;\n    e += 0x3fff;\n  }\n  Write16(b + 8, e | u.i >> 63 << 15);\n  Write64(b, (u.i & 0x000fffffffffffff) << 11 | (u64) !!u.f << 63);\n  return b;\n}\n\ndouble DeserializeLdbl(const u8 b[10]) {\n  union DoublePun u;\n  u.i = (u64)(MAX(-1023, MIN(1024, ((Read16(b + 8) & 0x7fff) - 0x3fff))) + 1023)\n            << 52 |\n        ((Read64(b) & 0x7fffffffffffffff) + (1 << (11 - 1))) >> 11 |\n        (u64)(b[9] >> 7) << 63;\n  return u.f;\n}\n"
  },
  {
    "path": "blink/ldbl.h",
    "content": "#ifndef BLINK_LDBL_H_\n#define BLINK_LDBL_H_\n#include \"blink/types.h\"\n\ndouble DeserializeLdbl(const u8[10]);\nu8 *SerializeLdbl(u8[10], double);\n\n#endif /* BLINK_LDBL_H_ */\n"
  },
  {
    "path": "blink/legacy.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n\n#include \"blink/alu.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/x86.h\"\n\n#ifndef DISABLE_METAL\n\nrelegated void OpIncZv(P) {\n  if (!Osz(rde)) {\n    Put32(RegSrm(m, rde), Inc32(m, Get32(RegSrm(m, rde)), 0));\n  } else {\n    Put16(RegSrm(m, rde), Inc16(m, Get16(RegSrm(m, rde)), 0));\n  }\n}\n\nrelegated void OpDecZv(P) {\n  if (!Osz(rde)) {\n    Put32(RegSrm(m, rde), Dec32(m, Get32(RegSrm(m, rde)), 0));\n  } else {\n    Put16(RegSrm(m, rde), Dec16(m, Get16(RegSrm(m, rde)), 0));\n  }\n}\n\nstatic relegated void PushaCommon(struct Machine *m, void *b, size_t n) {\n  u32 v;\n  switch (m->mode.omode) {\n    case XED_MODE_REAL:\n      Put16(m->sp, (v = (Get16(m->sp) - n) & 0xffff));\n      break;\n    case XED_MODE_LEGACY:\n      Put64(m->sp, (v = (Get32(m->sp) - n) & 0xffffffff));\n      break;\n    default:\n      __builtin_unreachable();\n  }\n  CopyToUser(m, m->ss.base + v, b, n);\n}\n\nstatic relegated void Pushaw(P) {\n  u8 b[8][2];\n  memcpy(b[0], m->di, 2);\n  memcpy(b[1], m->si, 2);\n  memcpy(b[2], m->bp, 2);\n  memcpy(b[3], m->sp, 2);\n  memcpy(b[4], m->bx, 2);\n  memcpy(b[5], m->dx, 2);\n  memcpy(b[6], m->cx, 2);\n  memcpy(b[7], m->ax, 2);\n  PushaCommon(m, b, sizeof(b));\n}\n\nstatic relegated void Pushad(P) {\n  u8 b[8][4];\n  memcpy(b[0], m->di, 4);\n  memcpy(b[1], m->si, 4);\n  memcpy(b[2], m->bp, 4);\n  memcpy(b[3], m->sp, 4);\n  memcpy(b[4], m->bx, 4);\n  memcpy(b[5], m->dx, 4);\n  memcpy(b[6], m->cx, 4);\n  memcpy(b[7], m->ax, 4);\n  PushaCommon(m, b, sizeof(b));\n}\n\nstatic relegated void PopaCommon(struct Machine *m, void *b, size_t n) {\n  u64 addr;\n  switch (m->mode.omode) {\n    case XED_MODE_REAL:\n      addr = m->ss.base + Read16(m->sp);\n      if (CopyFromUser(m, b, addr, n) == -1) {\n        ThrowSegmentationFault(m, addr);\n      }\n      Put16(m->sp, (Get16(m->sp) + n) & 0xffff);\n      break;\n    case XED_MODE_LEGACY:\n      addr = m->ss.base + Read32(m->sp);\n      if (CopyFromUser(m, b, addr, n) == -1) {\n        ThrowSegmentationFault(m, addr);\n      }\n      Put64(m->sp, (Get32(m->sp) + n) & 0xffffffff);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic relegated void Popaw(P) {\n  u8 b[8][2];\n  PopaCommon(m, b, sizeof(b));\n  memcpy(m->di, b[0], 2);\n  memcpy(m->si, b[1], 2);\n  memcpy(m->bp, b[2], 2);\n  memcpy(m->bx, b[4], 2);\n  memcpy(m->dx, b[5], 2);\n  memcpy(m->cx, b[6], 2);\n  memcpy(m->ax, b[7], 2);\n}\n\nstatic relegated void Popad(P) {\n  u8 b[8][4];\n  PopaCommon(m, b, sizeof(b));\n  memcpy(m->di, b[0], 4);\n  memcpy(m->si, b[1], 4);\n  memcpy(m->bp, b[2], 4);\n  memcpy(m->bx, b[4], 4);\n  memcpy(m->dx, b[5], 4);\n  memcpy(m->cx, b[6], 4);\n  memcpy(m->ax, b[7], 4);\n}\n\nrelegated void OpPusha(P) {\n  switch (m->mode.omode) {\n    case XED_MODE_REAL:\n    case XED_MODE_LEGACY:\n      if (Osz(rde)) {\n        Pushaw(A);\n      } else {\n        Pushad(A);\n      }\n      break;\n    case XED_MODE_LONG:\n      OpUdImpl(m);\n    default:\n      __builtin_unreachable();\n  }\n}\n\nrelegated void OpPopa(P) {\n  switch (m->mode.omode) {\n    case XED_MODE_REAL:\n    case XED_MODE_LEGACY:\n      if (Osz(rde)) {\n        Popaw(A);\n      } else {\n        Popad(A);\n      }\n      break;\n    case XED_MODE_LONG:\n      OpUdImpl(m);\n    default:\n      __builtin_unreachable();\n  }\n}\n\nrelegated void OpCallf(P) {\n  Push(A, m->cs.sel);\n  Push(A, m->ip);\n  LongBranch(A, uimm0, disp & (Osz(rde) ? 0xffff : 0xffffffff));\n}\n\nrelegated void OpRetf(P) {\n  u64 ip = Pop(A, 0);\n  u16 cs = Pop(A, uimm0);\n  LongBranch(A, cs, ip);\n}\n\n#endif /* DISABLE_METAL */\n"
  },
  {
    "path": "blink/likely.h",
    "content": "#ifndef BLINK_LIKELY_H_\n#define BLINK_LIKELY_H_\n#include \"blink/builtin.h\"\n\n#define LIKELY(x)   __builtin_expect(!!(x), 1)\n#define UNLIKELY(x) __builtin_expect(!!(x), 0)\n\n#if __GNUC__ + 0 >= 9 && !defined(__chibicc__)\n#define VERY_LIKELY(x) __builtin_expect_with_probability(!!(x), 1, 0.999)\n#else\n#define VERY_LIKELY(x) LIKELY(x)\n#endif\n\n#if __GNUC__ + 0 >= 9 && !defined(__chibicc__)\n#define VERY_UNLIKELY(x) __builtin_expect_with_probability(!!(x), 0, 0.999)\n#else\n#define VERY_UNLIKELY(x) UNLIKELY(x)\n#endif\n\n#endif /* BLINK_LIKELY_H_ */\n"
  },
  {
    "path": "blink/limits.h",
    "content": "#ifndef BLINK_LIMITS_H_\n#define BLINK_LIMITS_H_\n#include <limits.h>\n#include <stdint.h>\n#include <unistd.h>\n\n#define NUMERIC_MAX(t)         \\\n  (((t) ~(t)0) > 1 ? (t) ~(t)0 \\\n                   : (t)((((uintmax_t)1) << (sizeof(t) * CHAR_BIT - 1)) - 1))\n\nstatic inline long GetIovMax(void) {\n#ifdef IOV_MAX\n  return IOV_MAX;\n#elif defined(_SC_IOV_MAX)\n  return sysconf(_SC_IOV_MAX);\n#elif defined(_XOPEN_IOV_MAX)\n  return _XOPEN_IOV_MAX;\n#else\n  return 16;\n#endif\n}\n\nstatic inline long GetSymloopMax(void) {\n#ifdef SYMLOOP_MAX\n  return SYMLOOP_MAX;\n#elif defined(_SC_SYMLOOP_MAX)\n  return sysconf(_SC_SYMLOOP_MAX);\n#elif defined(_POSIX_SYMLOOP_MAX)\n  return _POSIX_SYMLOOP_MAX;\n#else\n  return 8;\n#endif\n}\n\n#endif /* BLINK_LIMITS_H_ */\n"
  },
  {
    "path": "blink/lines.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/lines.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/builtin.h\"\n\nstruct Lines *NewLines(void) {\n  return (struct Lines *)calloc(1, sizeof(struct Lines));\n}\n\nvoid FreeLines(struct Lines *lines) {\n  size_t i;\n  for (i = 0; i < lines->n; ++i) {\n    free(lines->p[i]);\n  }\n  free(lines->p);\n  free(lines);\n}\n\nvoid AppendLine(struct Lines *lines, const char *s, int n) {\n  if (n < 0) n = strlen(s);\n  lines->p = (char **)realloc(lines->p, ++lines->n * sizeof(*lines->p));\n  lines->p[lines->n - 1] = strndup(s, n);\n}\n\nvoid AppendLines(struct Lines *lines, const char *s) {\n  const char *p;\n  for (;;) {\n    p = strchr(s, '\\n');\n    if (p) {\n      AppendLine(lines, s, p - s);\n      s = p + 1;\n    } else {\n      if (*s) {\n        AppendLine(lines, s, -1);\n      }\n      break;\n    }\n  }\n}\n"
  },
  {
    "path": "blink/lines.h",
    "content": "#ifndef BLINK_LINES_H_\n#define BLINK_LINES_H_\n#include <stddef.h>\n\nstruct Lines {\n  size_t n;\n  char **p;\n};\n\nstruct Lines *NewLines(void);\nvoid FreeLines(struct Lines *);\nvoid AppendLine(struct Lines *, const char *, int);\nvoid AppendLines(struct Lines *, const char *);\n\n#endif /* BLINK_LINES_H_ */\n"
  },
  {
    "path": "blink/linux.h",
    "content": "#ifndef BLINK_LINUX_H_\n#define BLINK_LINUX_H_\n#include \"blink/types.h\"\n\n#define EPERM_LINUX           1\n#define ENOENT_LINUX          2\n#define ESRCH_LINUX           3\n#define EINTR_LINUX           4\n#define EIO_LINUX             5\n#define ENXIO_LINUX           6\n#define E2BIG_LINUX           7\n#define ENOEXEC_LINUX         8\n#define EBADF_LINUX           9\n#define ECHILD_LINUX          10\n#define EAGAIN_LINUX          11\n#define ENOMEM_LINUX          12\n#define EACCES_LINUX          13\n#define EFAULT_LINUX          14\n#define ENOTBLK_LINUX         15\n#define EBUSY_LINUX           16\n#define EEXIST_LINUX          17\n#define EXDEV_LINUX           18\n#define ENODEV_LINUX          19\n#define ENOTDIR_LINUX         20\n#define EISDIR_LINUX          21\n#define EINVAL_LINUX          22\n#define ENFILE_LINUX          23\n#define EMFILE_LINUX          24\n#define ENOTTY_LINUX          25\n#define ETXTBSY_LINUX         26\n#define EFBIG_LINUX           27\n#define ENOSPC_LINUX          28\n#define ESPIPE_LINUX          29\n#define EROFS_LINUX           30\n#define EMLINK_LINUX          31\n#define EPIPE_LINUX           32\n#define EDOM_LINUX            33\n#define ERANGE_LINUX          34\n#define EDEADLK_LINUX         35\n#define ENAMETOOLONG_LINUX    36\n#define ENOLCK_LINUX          37\n#define ENOSYS_LINUX          38\n#define ENOTEMPTY_LINUX       39\n#define ELOOP_LINUX           40\n#define ENOMSG_LINUX          42\n#define EIDRM_LINUX           43\n#define ENOSTR_LINUX          60\n#define ENODATA_LINUX         61\n#define ETIME_LINUX           62\n#define ENOSR_LINUX           63\n#define ENONET_LINUX          64\n#define EREMOTE_LINUX         66\n#define ENOLINK_LINUX         67\n#define EPROTO_LINUX          71\n#define EMULTIHOP_LINUX       72\n#define EBADMSG_LINUX         74\n#define EOVERFLOW_LINUX       75\n#define EBADFD_LINUX          77\n#define EILSEQ_LINUX          84\n#define ERESTART_LINUX        85\n#define EUSERS_LINUX          87\n#define ENOTSOCK_LINUX        88\n#define EDESTADDRREQ_LINUX    89\n#define EMSGSIZE_LINUX        90\n#define EPROTOTYPE_LINUX      91\n#define ENOPROTOOPT_LINUX     92\n#define EPROTONOSUPPORT_LINUX 93\n#define ESOCKTNOSUPPORT_LINUX 94\n#define ENOTSUP_LINUX         95\n#define EOPNOTSUPP_LINUX      95\n#define EPFNOSUPPORT_LINUX    96\n#define EAFNOSUPPORT_LINUX    97\n#define EADDRINUSE_LINUX      98\n#define EADDRNOTAVAIL_LINUX   99\n#define ENETDOWN_LINUX        100\n#define ENETUNREACH_LINUX     101\n#define ENETRESET_LINUX       102\n#define ECONNABORTED_LINUX    103\n#define ECONNRESET_LINUX      104\n#define ENOBUFS_LINUX         105\n#define EISCONN_LINUX         106\n#define ENOTCONN_LINUX        107\n#define ESHUTDOWN_LINUX       108\n#define ETOOMANYREFS_LINUX    109\n#define ETIMEDOUT_LINUX       110\n#define ECONNREFUSED_LINUX    111\n#define EHOSTDOWN_LINUX       112\n#define EHOSTUNREACH_LINUX    113\n#define EALREADY_LINUX        114\n#define EINPROGRESS_LINUX     115\n#define ESTALE_LINUX          116\n#define EDQUOT_LINUX          122\n#define ENOMEDIUM_LINUX       123\n#define EMEDIUMTYPE_LINUX     124\n#define ECANCELED_LINUX       125\n#define EOWNERDEAD_LINUX      130\n#define ENOTRECOVERABLE_LINUX 131\n#define ERFKILL_LINUX         132\n#define EHWPOISON_LINUX       133\n\n#define AT_FDCWD_LINUX            -100\n#define AT_SYMLINK_NOFOLLOW_LINUX 0x0100\n#define AT_REMOVEDIR_LINUX        0x0200\n#define AT_EACCESS_LINUX          0x0200\n#define AT_SYMLINK_FOLLOW_LINUX   0x0400\n#define AT_NO_AUTOMOUNT_LINUX     0x0800\n#define AT_EMPTY_PATH_LINUX       0x1000\n\n#define O_RDONLY_LINUX  0\n#define O_WRONLY_LINUX  1\n#define O_RDWR_LINUX    2\n#define O_ACCMODE_LINUX 3\n\n#define O_APPEND_LINUX        0x000400\n#define O_CREAT_LINUX         0x000040\n#define O_EXCL_LINUX          0x000080\n#define O_TRUNC_LINUX         0x000200\n#define O_NDELAY_LINUX        0x000800\n#define O_DIRECT_LINUX        0x004000\n#define O_DIRECTORY_LINUX     0x010000\n#define __O_TMPFILE_LINUX     0x400000\n#define O_TMPFILE_LINUX       (__O_TMPFILE_LINUX | O_DIRECTORY_LINUX)\n#define O_NOFOLLOW_LINUX      0x020000\n#define O_CLOEXEC_LINUX       0x080000\n#define O_NOCTTY_LINUX        0x000100\n#define O_ASYNC_LINUX         0x002000\n#define O_NOATIME_LINUX       0x040000\n#define O_PATH_LINUX          0x200000\n#define O_LARGEFILE_LINUX     0x008000\n#define O_DSYNC_LINUX         0x001000\n#define __O_SYNC_LINUX        0x100000\n#define O_SYNC_LINUX          (__O_SYNC_LINUX | O_DSYNC_LINUX)\n#define F_DUPFD_LINUX         0\n#define F_DUPFD_CLOEXEC_LINUX 0x0406\n\n#define F_GETFD_LINUX    1\n#define F_SETFD_LINUX    2\n#define FD_CLOEXEC_LINUX 1\n\n#define F_GETFL_LINUX 3\n#define F_SETFL_LINUX 4\n\n#define F_GETLK_LINUX  5\n#define F_SETLK_LINUX  6\n#define F_SETLKW_LINUX 7\n#define F_RDLCK_LINUX  0\n#define F_WRLCK_LINUX  1\n#define F_UNLCK_LINUX  2\n\n#define F_SETSIG_LINUX 10\n#define F_GETSIG_LINUX 11\n\n#define F_SETOWN_LINUX        8\n#define F_GETOWN_LINUX        9\n#define F_SETOWN_EX_LINUX     15\n#define F_GETOWN_EX_LINUX     16\n#define F_GETOWNER_UIDS_LINUX 17\n#define F_OWNER_TID_LINUX     0\n#define F_OWNER_PID_LINUX     1\n#define F_OWNER_PGRP_LINUX    2\n\n#define SOCK_CLOEXEC_LINUX  O_CLOEXEC_LINUX\n#define SOCK_NONBLOCK_LINUX O_NDELAY_LINUX\n\n#define TIOCGWINSZ_LINUX     0x5413\n#define TIOCSWINSZ_LINUX     0x5414\n#define TCGETS_LINUX         0x5401\n#define TCSETS_LINUX         0x5402\n#define TCSETSW_LINUX        0x5403\n#define TCSETSF_LINUX        0x5404\n#define TIOCGPGRP_LINUX      0x540f\n#define TIOCSPGRP_LINUX      0x5410\n#define ARCH_SET_GS_LINUX    0x1001\n#define ARCH_SET_FS_LINUX    0x1002\n#define ARCH_GET_FS_LINUX    0x1003\n#define ARCH_GET_GS_LINUX    0x1004\n#define ARCH_GET_CPUID_LINUX 0x1011\n#define ARCH_SET_CPUID_LINUX 0x1012\n#define O_CLOEXEC_LINUX      0x080000\n#define POLLIN_LINUX         0x01\n#define POLLPRI_LINUX        0x02\n#define POLLOUT_LINUX        0x04\n#define POLLERR_LINUX        0x08\n#define POLLHUP_LINUX        0x10\n#define POLLNVAL_LINUX       0x20\n#define TIMER_ABSTIME_LINUX  0x01\n\n#define MAP_TYPE_LINUX            0x0000000f\n#define MAP_FILE_LINUX            0x00000000\n#define MAP_SHARED_LINUX          0x00000001\n#define MAP_PRIVATE_LINUX         0x00000002\n#define MAP_FIXED_LINUX           0x00000010\n#define MAP_ANONYMOUS_LINUX       0x00000020\n#define MAP_GROWSDOWN_LINUX       0x00000100\n#define MAP_NORESERVE_LINUX       0x00004000\n#define MAP_POPULATE_LINUX        0x00008000\n#define MAP_NONBLOCK_LINUX        0x00010000\n#define MAP_STACK_LINUX           0x00020000\n#define MAP_HUGETLB_LINUX         0x00040000\n#define MAP_SYNC_LINUX            0x00080000\n#define MAP_FIXED_NOREPLACE_LINUX 0x00100000\n#define MAP_UNINITIALIZED_LINUX   0x04000000\n\n#define PROT_NONE_LINUX      0\n#define PROT_READ_LINUX      1\n#define PROT_WRITE_LINUX     2\n#define PROT_EXEC_LINUX      4\n#define PROT_SEM_LINUX       8\n#define PROT_GROWSDOWN_LINUX 0x01000000\n#define PROT_GROWSUP_LINUX   0x02000000\n\n#define CLONE_VM_LINUX             0x00000100\n#define CLONE_THREAD_LINUX         0x00010000\n#define CLONE_FS_LINUX             0x00000200\n#define CLONE_FILES_LINUX          0x00000400\n#define CLONE_SIGHAND_LINUX        0x00000800\n#define CLONE_VFORK_LINUX          0x00004000\n#define CLONE_SYSVSEM_LINUX        0x00040000\n#define CLONE_SETTLS_LINUX         0x00080000\n#define CLONE_PARENT_SETTID_LINUX  0x00100000\n#define CLONE_CHILD_CLEARTID_LINUX 0x00200000\n#define CLONE_DETACHED_LINUX       0x00400000\n#define CLONE_CHILD_SETTID_LINUX   0x01000000\n#define CLONE_NEWCGROUP_LINUX      0x02000000\n#define CLONE_NEWUTS_LINUX         0x04000000\n#define CLONE_NEWIPC_LINUX         0x08000000\n#define CLONE_NEWUSER_LINUX        0x10000000\n#define CLONE_NEWPID_LINUX         0x20000000\n#define CLONE_NEWNET_LINUX         0x40000000\n#define CLONE_IO_LINUX             0x80000000\n\n#define FUTEX_WAIT_LINUX           0\n#define FUTEX_WAKE_LINUX           1\n#define FUTEX_WAIT_BITSET_LINUX    9\n#define FUTEX_PRIVATE_FLAG_LINUX   128\n#define FUTEX_CLOCK_REALTIME_LINUX 256\n\n#define DT_UNKNOWN_LINUX 0\n#define DT_FIFO_LINUX    1\n#define DT_CHR_LINUX     2\n#define DT_DIR_LINUX     4\n#define DT_BLK_LINUX     6\n#define DT_REG_LINUX     8\n#define DT_LNK_LINUX     10\n#define DT_SOCK_LINUX    12\n\n#define SEEK_SET_LINUX 0\n#define SEEK_CUR_LINUX 1\n#define SEEK_END_LINUX 2\n\n#define F_OK_LINUX 0\n#define X_OK_LINUX 1\n#define W_OK_LINUX 2\n#define R_OK_LINUX 4\n\n#define SHUT_RD_LINUX   0\n#define SHUT_WR_LINUX   1\n#define SHUT_RDWR_LINUX 2\n\n#define SIG_DFL_LINUX 0\n#define SIG_IGN_LINUX 1\n\n#define SIG_BLOCK_LINUX   0\n#define SIG_UNBLOCK_LINUX 1\n#define SIG_SETMASK_LINUX 2\n\n#define SIGHUP_LINUX    1\n#define SIGINT_LINUX    2\n#define SIGQUIT_LINUX   3\n#define SIGILL_LINUX    4\n#define SIGTRAP_LINUX   5\n#define SIGABRT_LINUX   6\n#define SIGBUS_LINUX    7\n#define SIGFPE_LINUX    8\n#define SIGKILL_LINUX   9\n#define SIGUSR1_LINUX   10\n#define SIGSEGV_LINUX   11\n#define SIGUSR2_LINUX   12\n#define SIGPIPE_LINUX   13\n#define SIGALRM_LINUX   14\n#define SIGTERM_LINUX   15\n#define SIGSTKFLT_LINUX 16\n#define SIGCHLD_LINUX   17\n#define SIGCONT_LINUX   18\n#define SIGSTOP_LINUX   19\n#define SIGTSTP_LINUX   20\n#define SIGTTIN_LINUX   21\n#define SIGTTOU_LINUX   22\n#define SIGURG_LINUX    23\n#define SIGXCPU_LINUX   24\n#define SIGXFSZ_LINUX   25\n#define SIGVTALRM_LINUX 26\n#define SIGPROF_LINUX   27\n#define SIGWINCH_LINUX  28\n#define SIGIO_LINUX     29\n#define SIGSYS_LINUX    31\n#define SIGINFO_LINUX   63\n#define SIGEMT_LINUX    64\n#define SIGPWR_LINUX    30\n#define SIGTHR_LINUX    32\n#define SIGRTMIN_LINUX  32\n#define SIGRTMAX_LINUX  64\n\n#define AT_NULL_LINUX          0\n#define AT_IGNORE_LINUX        1\n#define AT_EXECFD_LINUX        2\n#define AT_PHDR_LINUX          3\n#define AT_PHENT_LINUX         4\n#define AT_PHNUM_LINUX         5\n#define AT_PAGESZ_LINUX        6\n#define AT_BASE_LINUX          7\n#define AT_FLAGS_LINUX         8\n#define AT_ENTRY_LINUX         9\n#define AT_NOTELF_LINUX        10\n#define AT_UID_LINUX           11\n#define AT_EUID_LINUX          12\n#define AT_GID_LINUX           13\n#define AT_EGID_LINUX          14\n#define AT_PLATFORM_LINUX      15\n#define AT_HWCAP_LINUX         16\n#define AT_CLKTCK_LINUX        17\n#define AT_SECURE_LINUX        23\n#define AT_BASE_PLATFORM_LINUX 24\n#define AT_RANDOM_LINUX        25\n#define AT_HWCAP2_LINUX        26\n#define AT_EXECFN_LINUX        31\n#define AT_MINSIGSTKSZ_LINUX   51\n\n#define IFNAMSIZ_LINUX 16\n\n#define SIOCGIFCONF_LINUX    0x8912\n#define SIOCGIFADDR_LINUX    0x8915\n#define SIOCGIFNETMASK_LINUX 0x891b\n#define SIOCGIFBRDADDR_LINUX 0x8919\n#define SIOCGIFDSTADDR_LINUX 0x8917\n\n#define FIOSETOWN_LINUX    0x8901  // int *\n#define SIOCSPGRP_LINUX    0x8902  // int *\n#define FIOGETOWN_LINUX    0x8903  // int *\n#define SIOCGPGRP_LINUX    0x8904  // int *\n#define SIOCATMARK_LINUX   0x8905  // int *\n#define SIOCGSTAMP_LINUX   0x8906  // struct timeval_linux *\n#define SIOCGSTAMPNS_LINUX 0x8907  // struct timespec_linux *\n\n#define AF_UNSPEC_LINUX  0\n#define AF_UNIX_LINUX    1\n#define AF_INET_LINUX    2\n#define AF_INET6_LINUX   10\n#define AF_NETLINK_LINUX 16\n#define AF_PACKET_LINUX  17\n#define AF_VSOCK_LINUX   40\n\n#define SOL_IP_LINUX     0\n#define SOL_SOCKET_LINUX 1\n#define SOL_TCP_LINUX    6\n#define SOL_UDP_LINUX    17\n#define SOL_IPV6_LINUX   41\n\n#define IPPROTO_IP_LINUX     0\n#define IPPROTO_ICMP_LINUX   1\n#define IPPROTO_TCP_LINUX    6\n#define IPPROTO_UDP_LINUX    17\n#define IPPROTO_ICMPV6_LINUX 58\n#define IPPROTO_RAW_LINUX    255\n\n#define SA_NOCLDSTOP_LINUX      1\n#define SA_NOCLDWAIT_LINUX      2\n#define SA_SIGINFO_LINUX        4\n#define SA_UNSUPPORTED_LINUX    0x00000400\n#define SA_EXPOSE_TAGBITS_LINUX 0x00000800\n#define SA_RESTORER_LINUX       0x04000000\n#define SA_ONSTACK_LINUX        0x08000000\n#define SA_RESTART_LINUX        0x10000000\n#define SA_NODEFER_LINUX        0x40000000\n#define SA_RESETHAND_LINUX      0x80000000\n\n#define SCHED_OTHER_LINUX    0\n#define SCHED_FIFO_LINUX     1\n#define SCHED_RR_LINUX       2\n#define SCHED_BATCH_LINUX    3\n#define SCHED_IDLE_LINUX     5\n#define SCHED_DEADLINE_LINUX 6\n\n#define MSG_OOB_LINUX          0x00000001  // send, recv [portable]\n#define MSG_PEEK_LINUX         0x00000002  // recv       [portable]\n#define MSG_DONTROUTE_LINUX    0x00000004  // send       [portable]\n#define MSG_TRUNC_LINUX        0x00000020  // recv       [portable]\n#define MSG_DONTWAIT_LINUX     0x00000040  // send, recv [portable]\n#define MSG_EOR_LINUX          0x00000080  // send       [portable]\n#define MSG_WAITALL_LINUX      0x00000100  // recv       [portable]\n#define MSG_NOSIGNAL_LINUX     0x00004000  // send       [portable]\n#define MSG_CMSG_CLOEXEC_LINUX 0x40000000  // recv\n#define MSG_CONFIRM_LINUX      0x00000800  // send\n#define MSG_ERRQUEUE_LINUX     0x00002000  // recv\n#define MSG_MORE_LINUX         0x00008000  // send\n\n#define MSG_FASTOPEN_LINUX     0x20000000\n#define MSG_CTRUNC_LINUX       8\n#define MSG_NOERROR_LINUX      0x1000\n#define MSG_WAITFORONE_LINUX   0x010000\n#define MSG_BATCH_LINUX        0x040000\n#define MSG_EXCEPT_LINUX       0x2000\n#define MSG_FIN_LINUX          0x0200\n#define MSG_EOF_LINUX          0x0200\n#define MSG_INFO_LINUX         12\n#define MSG_PARITY_ERROR_LINUX 9\n#define MSG_PROXY_LINUX        0x10\n#define MSG_RST_LINUX          0x1000\n#define MSG_STAT_LINUX         11\n#define MSG_SYN_LINUX          0x0400\n#define MSG_NOTIFICATION_LINUX 0x8000\n\n#define GRND_NONBLOCK_LINUX 1\n#define GRND_RANDOM_LINUX   2\n\n#define NCCS_LINUX     19\n#define VINTR_LINUX    0\n#define VQUIT_LINUX    1\n#define VERASE_LINUX   2\n#define VKILL_LINUX    3\n#define VEOF_LINUX     4\n#define VTIME_LINUX    5\n#define VMIN_LINUX     6\n#define VSWTC_LINUX    7\n#define VSTART_LINUX   8\n#define VSTOP_LINUX    9\n#define VSUSP_LINUX    10\n#define VEOL_LINUX     11\n#define VREPRINT_LINUX 12\n#define VDISCARD_LINUX 13\n#define VWERASE_LINUX  14\n#define VLNEXT_LINUX   15\n#define VEOL2_LINUX    16\n\n#define RLIMIT_CPU_LINUX        0\n#define RLIMIT_FSIZE_LINUX      1\n#define RLIMIT_DATA_LINUX       2\n#define RLIMIT_STACK_LINUX      3\n#define RLIMIT_CORE_LINUX       4\n#define RLIMIT_RSS_LINUX        5\n#define RLIMIT_NPROC_LINUX      6\n#define RLIMIT_NOFILE_LINUX     7\n#define RLIMIT_MEMLOCK_LINUX    8\n#define RLIMIT_AS_LINUX         9\n#define RLIMIT_LOCKS_LINUX      10\n#define RLIMIT_SIGPENDING_LINUX 11\n#define RLIMIT_MSGQUEUE_LINUX   12\n#define RLIMIT_NICE_LINUX       13\n#define RLIMIT_RTPRIO_LINUX     14\n#define RLIMIT_RTTIME_LINUX     15\n#define RLIM_INFINITY_LINUX     0xffffffffffffffffull\n#define RLIM_NLIMITS_LINUX      16\n\n#define MINSIGSTKSZ_LINUX   2048\n#define SS_ONSTACK_LINUX    1\n#define SS_DISABLE_LINUX    2\n#define SS_AUTODISARM_LINUX 0x80000000u\n\n// termios::c_iflag\n#define IGNBRK_LINUX  0000001\n#define BRKINT_LINUX  0000002\n#define IGNPAR_LINUX  0000004\n#define PARMRK_LINUX  0000010\n#define INPCK_LINUX   0000020\n#define ISTRIP_LINUX  0000040\n#define INLCR_LINUX   0000100\n#define IGNCR_LINUX   0000200\n#define ICRNL_LINUX   0000400\n#define IUCLC_LINUX   0001000\n#define IXON_LINUX    0002000\n#define IXANY_LINUX   0004000\n#define IXOFF_LINUX   0010000\n#define IMAXBEL_LINUX 0020000\n#define IUTF8_LINUX   0040000\n\n// termios::c_oflag\n#define OPOST_LINUX  0000001\n#define OLCUC_LINUX  0000002\n#define ONLCR_LINUX  0000004\n#define OCRNL_LINUX  0000010\n#define ONOCR_LINUX  0000020\n#define ONLRET_LINUX 0000040\n#define OFILL_LINUX  0000100\n#define OFDEL_LINUX  0000200\n#define NLDLY_LINUX  0000400\n#define NL0_LINUX    0000000\n#define NL1_LINUX    0000400\n#define CRDLY_LINUX  0003000\n#define CR0_LINUX    0000000\n#define CR1_LINUX    0001000\n#define CR2_LINUX    0002000\n#define CR3_LINUX    0003000\n#define TABDLY_LINUX 0014000\n#define TAB0_LINUX   0000000\n#define TAB1_LINUX   0004000\n#define TAB2_LINUX   0010000\n#define TAB3_LINUX   0014000\n#define XTABS_LINUX  0014000\n#define BSDLY_LINUX  0020000\n#define BS0_LINUX    0000000\n#define BS1_LINUX    0020000\n#define VTDLY_LINUX  0040000\n#define VT0_LINUX    0000000\n#define VT1_LINUX    0040000\n#define FFDLY_LINUX  0100000\n#define FF0_LINUX    0000000\n#define FF1_LINUX    0100000\n\n// termios::c_cflag\n#define EXTA_LINUX     B19200\n#define EXTB_LINUX     B38400\n#define CSIZE_LINUX    0000060\n#define CS5_LINUX      0000000\n#define CS6_LINUX      0000020\n#define CS7_LINUX      0000040\n#define CS8_LINUX      0000060\n#define CSTOPB_LINUX   0000100\n#define CREAD_LINUX    0000200\n#define PARENB_LINUX   0000400\n#define PARODD_LINUX   0001000\n#define HUPCL_LINUX    0002000\n#define CLOCAL_LINUX   0004000\n#define CBAUD_LINUX    0010017\n#define CBAUDEX_LINUX  0010000\n#define B0_LINUX       0000000  // shut it down\n#define B50_LINUX      0000001\n#define B75_LINUX      0000002\n#define B110_LINUX     0000003\n#define B134_LINUX     0000004\n#define B150_LINUX     0000005\n#define B200_LINUX     0000006\n#define B300_LINUX     0000007\n#define B600_LINUX     0000010\n#define B1200_LINUX    0000011\n#define B1800_LINUX    0000012\n#define B2400_LINUX    0000013\n#define B4800_LINUX    0000014\n#define B9600_LINUX    0000015\n#define B19200_LINUX   0000016\n#define B38400_LINUX   0000017\n#define B57600_LINUX   0010001\n#define B115200_LINUX  0010002\n#define B230400_LINUX  0010003\n#define B460800_LINUX  0010004\n#define B500000_LINUX  0010005\n#define B576000_LINUX  0010006\n#define B921600_LINUX  0010007\n#define B1000000_LINUX 0010010\n#define B1152000_LINUX 0010011\n#define B1500000_LINUX 0010012\n#define B2000000_LINUX 0010013\n#define B2500000_LINUX 0010014\n#define B3000000_LINUX 0010015\n#define B3500000_LINUX 0010016\n#define B4000000_LINUX 0010017\n#define CIBAUD_LINUX   002003600000  // input baud rate (isn't used)\n#define CMSPAR_LINUX   010000000000  // sticky parity\n#define CRTSCTS_LINUX  020000000000  // flow control\n\n// termios::c_lflag\n#define ISIG_LINUX    0000001\n#define ICANON_LINUX  0000002\n#define XCASE_LINUX   0000004\n#define ECHO_LINUX    0000010\n#define ECHOE_LINUX   0000020\n#define ECHOK_LINUX   0000040\n#define ECHONL_LINUX  0000100\n#define NOFLSH_LINUX  0000200\n#define TOSTOP_LINUX  0000400\n#define ECHOCTL_LINUX 0001000\n#define ECHOPRT_LINUX 0002000\n#define ECHOKE_LINUX  0004000\n#define FLUSHO_LINUX  0010000\n#define PENDIN_LINUX  0040000\n#define IEXTEN_LINUX  0100000\n\n#define FD_SETSIZE_LINUX 1024\n\n#define FUTEX_WAITERS_LINUX    0x80000000\n#define FUTEX_OWNER_DIED_LINUX 0x40000000\n#define FUTEX_TID_MASK_LINUX   0x3fffffff\n\n#define UTIME_NOW_LINUX  ((1l << 30) - 1l)\n#define UTIME_OMIT_LINUX ((1l << 30) - 2l)\n\n#define ITIMER_REAL_LINUX    0\n#define ITIMER_VIRTUAL_LINUX 1\n#define ITIMER_PROF_LINUX    2\n\n#define FIOASYNC_LINUX           0x5452\n#define FIOCLEX_LINUX            0x5451\n#define FIONBIO_LINUX            0x5421\n#define FIONCLEX_LINUX           0x5450\n#define FIONREAD_LINUX           0x541b\n#define FIOQSIZE_LINUX           0x5460\n#define TCFLSH_LINUX             0x540b\n#define TCGETA_LINUX             0x5405\n#define TCGETS_LINUX             0x5401\n#define TCGETX_LINUX             0x5432\n#define TCSBRK_LINUX             0x5409\n#define TCSBRKP_LINUX            0x5425\n#define TCSETA_LINUX             0x5406\n#define TCSETAF_LINUX            0x5408\n#define TCSETAW_LINUX            0x5407\n#define TCSETS_LINUX             0x5402\n#define TCSETSF_LINUX            0x5404\n#define TCSETSW_LINUX            0x5403\n#define TCSETX_LINUX             0x5433\n#define TCSETXF_LINUX            0x5434\n#define TCSETXW_LINUX            0x5435\n#define TCXONC_LINUX             0x540a\n#define TIOCCBRK_LINUX           0x5428\n#define TIOCCONS_LINUX           0x541d\n#define TIOCEXCL_LINUX           0x540c\n#define TIOCGDEV_LINUX           0x80045432\n#define TIOCGETD_LINUX           0x5424\n#define TIOCGEXCL_LINUX          0x80045440\n#define TIOCGICOUNT_LINUX        0x545d\n#define TIOCGISO7816_LINUX       0x80285442\n#define TIOCGLCKTRMIOS_LINUX     0x5456\n#define TIOCGPGRP_LINUX          0x540f\n#define TIOCGPKT_LINUX           0x80045438\n#define TIOCGPTLCK_LINUX         0x80045439\n#define TIOCGPTN_LINUX           0x80045430\n#define TIOCGPTPEER_LINUX        0x5441\n#define TIOCGRS485_LINUX         0x542e\n#define TIOCGSERIAL_LINUX        0x541e\n#define TIOCGSID_LINUX           0x5429\n#define TIOCGSOFTCAR_LINUX       0x5419\n#define TIOCGWINSZ_LINUX         0x5413\n#define TIOCINQ_LINUX            0x541b\n#define TIOCLINUX_LINUX          0x541c\n#define TIOCMBIC_LINUX           0x5417\n#define TIOCMBIS_LINUX           0x5416\n#define TIOCMGET_LINUX           0x5415\n#define TIOCMIWAIT_LINUX         0x545c\n#define TIOCMSET_LINUX           0x5418\n#define TIOCNOTTY_LINUX          0x5422\n#define TIOCNXCL_LINUX           0x540d\n#define TIOCOUTQ_LINUX           0x5411\n#define TIOCPKT_LINUX            0x5420\n#define TIOCPKT_DATA_LINUX       0\n#define TIOCPKT_DOSTOP_LINUX     0x20\n#define TIOCPKT_FLUSHREAD_LINUX  0x1\n#define TIOCPKT_FLUSHWRITE_LINUX 0x2\n#define TIOCPKT_IOCTL_LINUX      0x40\n#define TIOCPKT_NOSTOP_LINUX     0x10\n#define TIOCPKT_START_LINUX      0x8\n#define TIOCPKT_STOP_LINUX       0x4\n#define TIOCSBRK_LINUX           0x5427\n#define TIOCSCTTY_LINUX          0x540e\n#define TIOCSERCONFIG_LINUX      0x5453\n#define TIOCSERGETLSR_LINUX      0x5459\n#define TIOCSERGETMULTI_LINUX    0x545a\n#define TIOCSERGSTRUCT_LINUX     0x5458\n#define TIOCSERGWILD_LINUX       0x5454\n#define TIOCSERSETMULTI_LINUX    0x545b\n#define TIOCSERSWILD_LINUX       0x5455\n#define TIOCSER_TEMT_LINUX       0x1\n#define TIOCSETD_LINUX           0x5423\n#define TIOCSIG_LINUX            0x40045436\n#define TIOCSISO7816_LINUX       0xc0285443\n#define TIOCSLCKTRMIOS_LINUX     0x5457\n#define TIOCSPGRP_LINUX          0x5410\n#define TIOCSPTLCK_LINUX         0x40045431\n#define TIOCSRS485_LINUX         0x542f\n#define TIOCSSERIAL_LINUX        0x541f\n#define TIOCSSOFTCAR_LINUX       0x541a\n#define TIOCSTI_LINUX            0x5412\n#define TIOCSWINSZ_LINUX         0x5414\n#define TIOCVHANGUP_LINUX        0x5437\n\n#define TCIFLUSH_LINUX  0\n#define TCOFLUSH_LINUX  1\n#define TCIOFLUSH_LINUX 2\n\n#define SO_DEBUG_LINUX             1\n#define SO_REUSEADDR_LINUX         2\n#define SO_TYPE_LINUX              3\n#define SO_ERROR_LINUX             4\n#define SO_DONTROUTE_LINUX         5\n#define SO_SNDBUF_LINUX            7\n#define SO_RCVBUF_LINUX            8\n#define SO_KEEPALIVE_LINUX         9\n#define SO_LINGER_LINUX            13\n#define SO_REUSEPORT_LINUX         15\n#define SO_RCVTIMEO_LINUX          20\n#define SO_SNDTIMEO_LINUX          21\n#define SO_RCVLOWAT_LINUX          18\n#define SO_SNDLOWAT_LINUX          19\n#define SO_BROADCAST_LINUX         6\n#define IP_TOS_LINUX               1\n#define IP_TTL_LINUX               2\n#define IP_HDRINCL_LINUX           3\n#define IP_OPTIONS_LINUX           4\n#define IP_RETOPTS_LINUX           7\n#define IP_RECVERR_LINUX           11\n#define IP_RECVTTL_LINUX           12\n#define IP_MTU_LINUX               14\n#define IPV6_RECVERR_LINUX         25\n#define TCP_NODELAY_LINUX          1\n#define TCP_MAXSEG_LINUX           2\n#define TCP_CORK_LINUX             3\n#define TCP_NOPUSH_LINUX           3\n#define TCP_KEEPIDLE_LINUX         4\n#define TCP_KEEPINTVL_LINUX        5\n#define TCP_KEEPCNT_LINUX          6\n#define TCP_SYNCNT_LINUX           7\n#define TCP_DEFER_ACCEPT_LINUX     9\n#define TCP_WINDOW_CLAMP_LINUX     10\n#define TCP_FASTOPEN_LINUX         23\n#define TCP_NOTSENT_LOWAT_LINUX    25\n#define TCP_FASTOPEN_CONNECT_LINUX 30\n#define TCP_QUICKACK_LINUX         12\n#define TCP_SAVE_SYN_LINUX         27\n\n#define CLOSE_RANGE_UNSHARE_LINUX 2\n#define CLOSE_RANGE_CLOEXEC_LINUX 4\n\n#define SOCK_STREAM_LINUX 1\n#define SOCK_DGRAM_LINUX  2\n#define SOCK_RAW_LINUX    3\n\n#define IOV_MAX_LINUX 1024\n\n#define WNOHANG_LINUX     0x00000001\n#define WUNTRACED_LINUX   0x00000002\n#define WEXITED_LINUX     0x00000004\n#define WCONTINUED_LINUX  0x00000008\n#define WNOWAIT_LINUX     0x01000000\n#define __WNOTHREAD_LINUX 0x20000000\n#define __WALL_LINUX      0x40000000\n#define __WCLONE_LINUX    0x80000000\n\n#define MS_SYNC_LINUX       4\n#define MS_ASYNC_LINUX      1\n#define MS_INVALIDATE_LINUX 2\n\n#define LOCK_SH_LINUX 1\n#define LOCK_EX_LINUX 2\n#define LOCK_NB_LINUX 4\n#define LOCK_UN_LINUX 8\n\n#define SCM_RIGHTS_LINUX      1\n#define SCM_CREDENTIALS_LINUX 2\n\n#define ST_RDONLY_LINUX      1\n#define ST_NOSUID_LINUX      2\n#define ST_NODEV_LINUX       4\n#define ST_NOEXEC_LINUX      8\n#define ST_SYNCHRONOUS_LINUX 16\n#define ST_NOATIME_LINUX     0x0040\n#define ST_RELATIME_LINUX    0x1000\n#define ST_APPEND_LINUX      0x0100\n#define ST_IMMUTABLE_LINUX   0x0200\n#define ST_MANDLOCK_LINUX    0x0040\n#define ST_NODIRATIME_LINUX  0x0800\n#define ST_WRITE_LINUX       0x0080\n#define ST_NOSYMFOLLOW_LINUX 0x2000\n\n#define SCM_MAX_FD_LINUX 253\n\n#define SI_USER_LINUX       0\n#define SI_QUEUE_LINUX      -1\n#define SI_TIMER_LINUX      -2\n#define SI_TKILL_LINUX      -6\n#define SI_MESGQ_LINUX      -3\n#define SI_ASYNCIO_LINUX    -4\n#define SI_ASYNCNL_LINUX    -60\n#define SI_KERNEL_LINUX     128\n#define SI_NOINFO_LINUX     32767\n#define CLD_EXITED_LINUX    1\n#define CLD_KILLED_LINUX    2\n#define CLD_DUMPED_LINUX    3\n#define CLD_TRAPPED_LINUX   4\n#define CLD_STOPPED_LINUX   5\n#define CLD_CONTINUED_LINUX 6\n#define TRAP_BRKPT_LINUX    1\n#define TRAP_TRACE_LINUX    2\n#define SEGV_MAPERR_LINUX   1\n#define SEGV_ACCERR_LINUX   2\n#define SEGV_PKUERR_LINUX   -1\n#define FPE_INTDIV_LINUX    1\n#define FPE_INTOVF_LINUX    2\n#define FPE_FLTDIV_LINUX    3\n#define FPE_FLTOVF_LINUX    4\n#define FPE_FLTUND_LINUX    5\n#define FPE_FLTRES_LINUX    6\n#define FPE_FLTINV_LINUX    7\n#define FPE_FLTSUB_LINUX    8\n#define ILL_ILLOPC_LINUX    1\n#define ILL_ILLOPN_LINUX    2\n#define ILL_ILLADR_LINUX    3\n#define ILL_ILLTRP_LINUX    4\n#define ILL_PRVOPC_LINUX    5\n#define ILL_PRVREG_LINUX    6\n#define ILL_COPROC_LINUX    7\n#define ILL_BADSTK_LINUX    8\n#define BUS_ADRALN_LINUX    1\n#define BUS_ADRERR_LINUX    2\n#define BUS_OBJERR_LINUX    3\n#define BUS_OOMERR_LINUX    -1\n#define BUS_MCEERR_AR_LINUX 4\n#define BUS_MCEERR_AO_LINUX 5\n#define POLL_IN_LINUX       1\n#define POLL_OUT_LINUX      2\n#define POLL_MSG_LINUX      3\n#define POLL_ERR_LINUX      4\n#define POLL_PRI_LINUX      5\n#define POLL_HUP_LINUX      6\n\n#define RENAME_NOREPLACE_LINUX 1\n#define RENAME_EXCHANGE_LINUX  2\n#define RENAME_WHITEOUT_LINUX  4\n\n#define CLOCK_REALTIME_LINUX           0\n#define CLOCK_MONOTONIC_LINUX          1\n#define CLOCK_PROCESS_CPUTIME_ID_LINUX 2\n#define CLOCK_THREAD_CPUTIME_ID_LINUX  3\n#define CLOCK_MONOTONIC_RAW_LINUX      4\n#define CLOCK_REALTIME_COARSE_LINUX    5\n#define CLOCK_MONOTONIC_COARSE_LINUX   6\n#define CLOCK_BOOTTIME_LINUX           7\n#define CLOCK_REALTIME_ALARM_LINUX     8\n#define CLOCK_BOOTTIME_ALARM_LINUX     9\n#define CLOCK_TAI_LINUX                11\n\n#define PR_GET_SECCOMP_LINUX      21\n#define PR_SET_SECCOMP_LINUX      22\n#define PR_CAPBSET_READ_LINUX     23\n#define PR_CAPBSET_DROP_LINUX     24\n#define PR_GET_TSC_LINUX          25\n#define PR_SET_TSC_LINUX          26\n#define PR_TSC_ENABLE_LINUX       1\n#define PR_TSC_SIGSEGV_LINUX      2\n#define PR_SET_NO_NEW_PRIVS_LINUX 38\n#define PR_GET_TID_ADDRESS_LINUX  40\n\n#define EPOLL_CLOEXEC_LINUX O_CLOEXEC_LINUX\n\n#define EPOLL_CTL_ADD_LINUX 1\n#define EPOLL_CTL_DEL_LINUX 2\n#define EPOLL_CTL_MOD_LINUX 3\n\n#define EPOLLIN_LINUX        0x00000001u\n#define EPOLLPRI_LINUX       0x00000002u\n#define EPOLLOUT_LINUX       0x00000004u\n#define EPOLLERR_LINUX       0x00000008u\n#define EPOLLHUP_LINUX       0x00000010u\n#define EPOLLNVAL_LINUX      0x00000020u\n#define EPOLLRDNORM_LINUX    0x00000040u\n#define EPOLLRDBAND_LINUX    0x00000080u\n#define EPOLLWRNORM_LINUX    0x00000100u\n#define EPOLLWRBAND_LINUX    0x00000200u\n#define EPOLLMSG_LINUX       0x00000400u\n#define EPOLLRDHUP_LINUX     0x00002000u\n#define EPOLLEXCLUSIVE_LINUX 0x10000000u\n#define EPOLLWAKEUP_LINUX    0x20000000u\n#define EPOLLONESHOT_LINUX   0x40000000u\n#define EPOLLET_LINUX        0x80000000u\n\n#define MS_RDONLY_LINUX       1\n#define MS_NOSUID_LINUX       2\n#define MS_NODEV_LINUX        4\n#define MS_NOEXEC_LINUX       8\n#define MS_SYNCHRONOUS_LINUX  16\n#define MS_REMOUNT_LINUX      32\n#define MS_MANDLOCK_LINUX     64\n#define MS_DIRSYNC_LINUX      128\n#define MS_NOSYMFOLLOW_LINUX  256\n#define MS_NOATIME_LINUX      1024\n#define MS_NODIRATIME_LINUX   2048\n#define MS_BIND_LINUX         4096\n#define MS_MOVE_LINUX         8192\n#define MS_REC_LINUX          16384\n#define MS_SILENT_LINUX       32768\n#define MS_POSIXACL_LINUX     (1 << 16)\n#define MS_UNBINDABLE_LINUX   (1 << 17)\n#define MS_PRIVATE_LINUX      (1 << 18)\n#define MS_SLAVE_LINUX        (1 << 19)\n#define MS_SHARED_LINUX       (1 << 20)\n#define MS_RELATIME_LINUX     (1 << 21)\n#define MS_KERNMOUNT_LINUX    (1 << 22)\n#define MS_I_VERSION_LINUX    (1 << 23)\n#define MS_STRICTATIME_LINUX  (1 << 24)\n#define MS_LAZYTIME_LINUX     (1 << 25)\n#define MS_NOREMOTELOCK_LINUX (1 << 27)\n#define MS_NOSEC_LINUX        (1 << 28)\n#define MS_BORN_LINUX         (1 << 29)\n#define MS_ACTIVE_LINUX       (1 << 30)\n#define MS_NOUSER_LINUX       (1U << 31)\n\nstruct iovec_linux {\n  u8 base[8];\n  u8 len[8];\n};\n\nstruct pollfd_linux {\n  u8 fd[4];\n  u8 events[2];\n  u8 revents[2];\n};\n\nstruct timeval_linux {\n  u8 sec[8];\n  u8 usec[8];\n};\n\nstruct timespec_linux {\n  u8 sec[8];\n  u8 nsec[8];\n};\n\nstruct timezone_linux {\n  u8 minuteswest[4];\n  u8 dsttime[4];\n};\n\nstruct sigaction_linux {\n  u8 handler[8];\n  u8 flags[8];\n  u8 restorer[8];\n  u8 mask[8];\n};\n\nstruct winsize_linux {\n  u8 row[2];\n  u8 col[2];\n  u8 xpixel[2];\n  u8 ypixel[2];\n};\n\nstruct termios_linux {\n  u8 iflag[4];\n  u8 oflag[4];\n  u8 cflag[4];\n  u8 lflag[4];\n  u8 line;\n  u8 cc[NCCS_LINUX];\n};\n\nstruct sockaddr_linux {\n  u8 family[2];\n};\n\nstruct sockaddr_un_linux {\n  u8 family[2];\n  char path[108];\n};\n\nstruct sockaddr_in_linux {\n  u8 family[2];\n  u16 port;\n  u32 addr;\n  u8 zero[8];\n};\n\nstruct sockaddr_in6_linux {\n  u8 family[2];\n  u16 port;\n  u8 flowinfo[4];\n  u8 addr[16];\n  u8 scope_id[4];\n};\n\nstruct sockaddr_storage_linux {\n  union {\n    u8 family[2];\n    char storage[128];\n  };\n};\n\nstruct stat_linux {\n  u8 dev[8];\n  u8 ino[8];\n  u8 nlink[8];\n  u8 mode[4];\n  u8 uid[4];\n  u8 gid[4];\n  u8 pad_[4];\n  u8 rdev[8];\n  u8 size[8];\n  u8 blksize[8];\n  u8 blocks[8];\n  struct timespec_linux atim;\n  struct timespec_linux mtim;\n  struct timespec_linux ctim;\n};\n\nstruct itimerval_linux {\n  struct timeval_linux interval;\n  struct timeval_linux value;\n};\n\nstruct rusage_linux {\n  struct timeval_linux utime;\n  struct timeval_linux stime;\n  u8 maxrss[8];\n  u8 ixrss[8];\n  u8 idrss[8];\n  u8 isrss[8];\n  u8 minflt[8];\n  u8 majflt[8];\n  u8 nswap[8];\n  u8 inblock[8];\n  u8 oublock[8];\n  u8 msgsnd[8];\n  u8 msgrcv[8];\n  u8 nsignals[8];\n  u8 nvcsw[8];\n  u8 nivcsw[8];\n};\n\nstruct siginfo_linux {\n  u8 signo[4];\n  u8 errno_[4];\n  u8 code[4];\n  u8 pad1_[4];\n  union {\n    struct {\n      union {\n        struct {\n          // signals sent by kill() and sigqueue() set these\n          u8 pid[4];\n          u8 uid[4];\n        };\n        struct {\n          // SIGALRM sets these\n          u8 timerid[4];\n          u8 overrun[4];\n        };\n      };\n      union {\n        u8 value[8];  // provided by third arg of sigqueue(2)\n        struct {\n          u8 status[4];\n          u8 pad2_[4];\n          u8 utime[8];\n          u8 stime[8];\n        };\n      };\n    };\n    struct {\n      // SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP\n      u8 addr[8];\n      u8 addr_lsb[2];\n      u8 pad3_[6];\n      union {\n        struct {\n          u8 lower[8];\n          u8 upper[8];\n        };\n        u8 pkey[4];\n      };\n    };\n    struct {\n      u8 band[8];  // SIGPOLL\n      u8 fd[4];\n    };\n    struct {\n      u8 call_addr[8];\n      u8 syscall[4];\n      u8 arch[4];\n    };\n    u8 payload[112];\n  };\n};\n\nstruct fpstate_linux {\n  u8 cwd[2];\n  u8 swd[2];\n  u8 ftw[2];\n  u8 fop[2];\n  u8 rip[8];\n  u8 rdp[8];\n  u8 mxcsr[4];\n  u8 mxcr_mask[4];\n  u8 st[8][16];\n  u8 xmm[16][16];\n  u8 padding_[96];\n};\n\nstruct ucontext_linux {\n  u8 uc__flags[8];\n  u8 uc__link[8];\n  u8 ss__sp[8];\n  u8 ss__flags[4];\n  u8 pad0_[4];\n  u8 ss_size[8];\n  u8 r8[8];\n  u8 r9[8];\n  u8 r10[8];\n  u8 r11[8];\n  u8 r12[8];\n  u8 r13[8];\n  u8 r14[8];\n  u8 r15[8];\n  u8 rdi[8];\n  u8 rsi[8];\n  u8 rbp[8];\n  u8 rbx[8];\n  u8 rdx[8];\n  u8 rax[8];\n  u8 rcx[8];\n  u8 rsp[8];\n  u8 rip[8];\n  u8 eflags[8];\n  u8 cs[2];\n  u8 gs[2];\n  u8 fs[2];\n  u8 ss[2];\n  u8 err[8];\n  u8 trapno[8];\n  u8 oldmask[8];\n  u8 cr2[8];\n  u8 fpstate[8];\n  u8 pad1_[64];\n  u8 sigmask[8];\n};\n\nstruct utsname_linux {\n  char sysname[65];\n  char nodename[65];\n  char release[65];\n  char version[65];\n  char machine[65];\n  char domainname[65];\n};\n\nstruct rlimit_linux {\n  u8 cur[8];\n  u8 max[8];\n};\n\nstruct dirent_linux {\n  u8 ino[8];       // inode number\n  u8 off[8];       // implementation-dependent location number\n  u8 reclen[2];    // byte length of this whole struct and string\n  u8 type[1];      // DT_REG, DT_DIR, DT_UNKNOWN, DT_BLK, etc.\n  char name[256];  // NUL-terminated basename\n};\n\nstruct ifconf_linux {\n  u8 len[4];\n  u8 pad[4];\n  u8 buf[8];\n};\n\nstruct ifreq_linux {\n  u8 name[IFNAMSIZ_LINUX];\n  union {\n    struct sockaddr_in_linux addr;\n    struct sockaddr_in_linux dstaddr;\n    struct sockaddr_in_linux netmask;\n    struct sockaddr_in_linux broadaddr;\n    u8 flags[2];\n    u8 pad[24];\n  };\n};\n\nstruct flock_linux {\n  u8 type[2];\n  u8 whence[2];\n  u8 pad1_[4];\n  u8 start[8];\n  u8 len[8];\n  u8 pid[4];\n  u8 pad2_[4];\n};\n\nstruct sysinfo_linux {\n  u8 uptime[8];     // seconds since boot\n  u8 loads[3][8];   // 1-5-15 min active process averages\n  u8 totalram[8];   // system physical memory\n  u8 freeram[8];    // amount of ram currently going to waste\n  u8 sharedram[8];  // bytes w/ pages mapped into multiple progs\n  u8 bufferram[8];  // lingering disk pages; see fadvise\n  u8 totalswap[8];  // size of emergency memory\n  u8 freeswap[8];   // hopefully equal to totalswap\n  u8 procs[2];      // number of processes\n  u8 ignore_[6];    // padding\n  u8 totalhigh[8];  // wut\n  u8 freehigh[8];   // wut\n  u8 mem_unit[4];   // ram stuff above is multiples of this\n};\n\nstruct tms_linux {\n  u8 utime[8];   // user time\n  u8 stime[8];   // system time\n  u8 cutime[8];  // user time of children\n  u8 cstime[8];  // system time of children\n};\n\nstruct sigaltstack_linux {\n  u8 sp[8];     // base address of stack\n  u8 flags[4];  // SS_???_LINUX flags\n  u8 pad1_[4];  //\n  u8 size[8];   // size of stack\n};\n\nstruct pselect6_linux {\n  u8 sigmaskaddr[8];\n  u8 sigmasksize[8];\n};\n\nstruct sigset_linux {\n  u8 sigmask[8];\n};\n\nstruct robust_list_linux {\n  u8 next[8];\n  u8 offset[8];\n  u8 pending[8];\n};\n\nstruct utimbuf_linux {\n  u8 actime[8];\n  u8 modtime[8];\n};\n\nstruct f_owner_ex_linux {\n  u8 type[4];\n  u8 pid[4];\n};\n\nstruct statfs_linux {\n  u8 type[8];     // type of filesystem\n  u8 bsize[8];    // optimal transfer block size\n  u8 blocks[8];   // total data blocks in filesystem\n  u8 bfree[8];    // free blocks in filesystem\n  u8 bavail[8];   // free blocks available to unprivileged user\n  u8 files[8];    // total file nodes in filesystem\n  u8 ffree[8];    // free file nodes in filesystem\n  u8 fsid[2][4];  // filesystem id\n  u8 namelen[8];  // maximum length of filenames\n  u8 frsize[8];   // fragment size\n  u8 flags[8];    // mount flags of filesystem 2.6.36\n  u8 spare[4][8];\n};\n\nstruct linger_linux {\n  u8 onoff[4];   // on/off\n  u8 linger[4];  // seconds\n};\n\nstruct msghdr_linux {\n  u8 name[8];        // optional pointer to address\n  u8 namelen[4];     // socklen_t size of name\n  u8 pad1_[4];       //\n  u8 iov[8];         // points to scatter/gather array\n  u8 iovlen[8];      // u64 # elements in iov\n  u8 control[8];     // points to ancillary data c. cmsghdr\n  u8 controllen[8];  // u64 ancillary data buffer len\n  u8 flags[4];       // u32 MSG_XXX (only applies to recvmsg)\n  u8 pad2_[4];       //\n};\n\nstruct mmsghdr_linux {\n  struct msghdr_linux hdr;\n  u8 len[4];\n  u8 pad_[4];\n};\n\nstruct cmsghdr_linux {\n  u8 len[8];    // u64 bytes in message (including this)\n  u8 level[4];  // i32 e.g. SOL_SOCKET\n  u8 type[4];   // i32 e.g. SCM_RIGHTS\n};\n\nstruct ucred_linux {  // 8-byte aligned\n  u8 pid[4];          // process id of sending process\n  u8 uid[4];          // user id of sending process\n  u8 gid[4];          // group id of sending process\n};\n\nstruct epoll_event_linux {\n  u8 events[4];\n  u8 data[8];\n};\n\nint sysinfo_linux(struct sysinfo_linux *);\n\n#endif /* BLINK_LINUX_H_ */\n"
  },
  {
    "path": "blink/loader.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/loader.h\"\n\n#include <errno.h>\n#include <fcntl.h>\n#include <inttypes.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/biosrom.h\"\n#include \"blink/builtin.h\"\n#include \"blink/end.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/overlays.h\"\n#include \"blink/procfs.h\"\n#include \"blink/random.h\"\n#include \"blink/tunables.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n#include \"blink/x86.h\"\n\n#define READ64(p) Read64((const u8 *)(p))\n#define READ32(p) Read32((const u8 *)(p))\n\n#ifndef __COSMOPOLITAN__\n#define IsWindows() 0\n#endif\n\nstatic bool CanEmulateImpl(struct Machine *, char **, char ***, bool);\n\nstatic void LoaderCopy(struct Machine *m, i64 vaddr, size_t amt, void *image,\n                       i64 offset, int prot) {\n  i64 base;\n  bool memory_might_be_write_protected;\n  if (!amt) return;\n  ELF_LOGF(\"copy %\" PRIx64 \"-%\" PRIx64 \" from %\" PRIx64 \"-%\" PRIx64, vaddr,\n           vaddr + amt, offset, offset + amt);\n  base = ROUNDDOWN(vaddr, 4096);\n  if ((memory_might_be_write_protected =\n           (prot & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE) ||\n           (!IsJitDisabled(&m->system->jit) &&\n            prot == (PROT_READ | PROT_WRITE | PROT_EXEC)))) {\n    unassert(!ProtectVirtual(m->system, base, vaddr + amt - base,\n                             PROT_READ | PROT_WRITE, false));\n  }\n  unassert(!CopyToUser(m, vaddr, (u8 *)image + offset, amt));\n  if (memory_might_be_write_protected) {\n    unassert(!ProtectVirtual(m->system, base, vaddr + amt - base, prot, false));\n  }\n}\n\nstatic i64 LoadElfLoadSegment(struct Machine *m, const char *path, void *image,\n                              size_t imagesize, const Elf64_Phdr_ *phdr,\n                              i64 last_end, int *last_prot, u64 aslr, int fd) {\n  i64 bulk;\n  size_t amt;\n  void *blank;\n  int overprot;\n  struct System *s = m->system;\n  u32 flags = Read32(phdr->flags);\n  i64 vaddr = Read64(phdr->vaddr) + aslr;\n  i64 memsz = Read64(phdr->memsz);\n  i64 offset = Read64(phdr->offset);\n  i64 filesz = Read64(phdr->filesz);\n  long pagesize = HasLinearMapping() ? FLAG_pagesize : 4096;\n  i64 start = ROUNDDOWN(vaddr, pagesize);\n  i64 end = ROUNDUP(vaddr + memsz, pagesize);\n  long skew = vaddr & (pagesize - 1);\n  u64 key = (flags & PF_R_ ? PAGE_U : 0) |   //\n            (flags & PF_W_ ? PAGE_RW : 0) |  //\n            (flags & PF_X_ ? 0 : PAGE_XD);\n  int prot = (flags & PF_R_ ? PROT_READ : 0) |   //\n             (flags & PF_W_ ? PROT_WRITE : 0) |  //\n             (flags & PF_X_ ? PROT_EXEC : 0);\n\n  SYS_LOGF(\"PT_LOAD %c%c%c [%\" PRIx64 \",%\" PRIx64 \") %s\",  //\n           (flags & PF_R_ ? 'R' : '.'),                    //\n           (flags & PF_W_ ? 'W' : '.'),                    //\n           (flags & PF_X_ ? 'X' : '.'),                    //\n           vaddr, vaddr + memsz, path);\n\n  ELF_LOGF(\"PROGRAM HEADER\");\n  ELF_LOGF(\"  path = %s\", path);\n  ELF_LOGF(\"  aslr = %\" PRIx64, aslr);\n  ELF_LOGF(\"  flags = %s%s%s\",          //\n           (flags & PF_R_ ? \"R\" : \"\"),  //\n           (flags & PF_W_ ? \"W\" : \"\"),  //\n           (flags & PF_X_ ? \"X\" : \"\"));\n  ELF_LOGF(\"  vaddr = %\" PRIx64, vaddr);\n  ELF_LOGF(\"  memsz = %\" PRIx64, memsz);\n  ELF_LOGF(\"  offset = %\" PRIx64, offset);\n  ELF_LOGF(\"  filesz = %\" PRIx64, filesz);\n  ELF_LOGF(\"  pagesize = %ld\", pagesize);\n  ELF_LOGF(\"  start = %\" PRIx64, start);\n  ELF_LOGF(\"  end = %\" PRIx64, end);\n  ELF_LOGF(\"  skew = %lx\", skew);\n\n  if (!memsz) {\n    return last_end;\n  }\n  if (offset > imagesize) {\n    ERRF(\"bad phdr offset\");\n    exit(EXIT_FAILURE_EXEC_FAILED);\n  }\n  if (filesz > imagesize) {\n    ERRF(\"bad phdr filesz\");\n    exit(EXIT_FAILURE_EXEC_FAILED);\n  }\n  if (filesz && offset + filesz > imagesize) {\n    ERRF(\"corrupt elf program header\");\n    exit(EXIT_FAILURE_EXEC_FAILED);\n  }\n  if (end < last_end) {\n    ERRF(\"program headers aren't ordered, expected %\" PRIx64 \" >= %\" PRIx64,\n         end, last_end);\n    exit(EXIT_FAILURE_EXEC_FAILED);\n  }\n  if (skew != (offset & (pagesize - 1))) {\n    WriteErrorString(\n        \"p_vaddr p_offset skew unequal w.r.t. page size; try either \"\n        \"(1) rebuilding your program using the linker flags: -static \"\n        \"-Wl,-z,common-page-size=65536,-z,max-page-size=65536 or (2) \"\n        \"using `blink -m` to disable the linear memory optimization\\n\");\n    exit(EXIT_FAILURE_EXEC_FAILED);\n  }\n\n  // on systems with a page size greater than the elf executable (e.g.\n  // apple m1) it's possible for the second program header load to end\n  // up overlapping the previous one.\n  if (HasLinearMapping() && start < last_end) {\n    unassert(pagesize > 4096);\n    unassert(vaddr < last_end);\n    unassert(start == last_end - pagesize);\n    unassert(skew + (last_end - vaddr) == pagesize);\n    overprot = prot | *last_prot;\n    unassert(!ProtectVirtual(m->system, start, pagesize, overprot, false));\n    amt = MIN(filesz, last_end - vaddr);\n    LoaderCopy(m, vaddr, amt, image, offset, overprot);\n    filesz -= amt;\n    offset += last_end - vaddr;\n    vaddr += last_end - vaddr;\n    start = last_end;\n    skew = 0;\n  }\n\n  // if there's still a skew then the elf program header is documenting\n  // the precise byte offset within the file where this program starts.\n  // in that case, it's harmless to just round down the mmap request to\n  // ingest the previous bytes which shouldn't even need to be cleared.\n  if (skew) {\n    unassert(skew < pagesize);\n    vaddr -= skew;\n    offset -= skew;\n    if (filesz) {\n      filesz += skew;\n    }\n  }\n\n  // associate the file name with the memory mapping\n  // this makes it possible for debug symbols to be loaded\n  if (filesz) {\n    key |= PAGE_FILE;\n    unassert(AddFileMap(m->system, start, filesz, path, offset));\n  }\n\n  // load the aligned program header\n  unassert(start <= end);\n  unassert(vaddr == start);\n  unassert(vaddr + filesz <= end);\n  unassert(!(vaddr & (pagesize - 1)));\n  unassert(!(start & (pagesize - 1)));\n  unassert(!(offset & (pagesize - 1)));\n  if (start < end) {\n    // it's also harmless to extend the size to the next host page\n    // boundary when mapping a file. if some extra bytes go beyond\n    // the end of the file then they'll be zero'd and sigbus won't\n    // be raised if they're used. if extra file content does exist\n    // beyond filesz, then we shall manually bzero() it afterwards\n    if ((bulk = ROUNDUP(filesz, pagesize))) {\n      // map the bulk of .text directly into memory without copying.\n      ELF_LOGF(\"load %\" PRIx64 \"-%\" PRIx64 \" from %\" PRIx64 \"-%\" PRIx64, start,\n               start + bulk, offset, offset + bulk);\n      if (ReserveVirtual(s, start, bulk, key, fd, offset, 0, 0) == -1) {\n        ERRF(\"failed to map elf program header file data\");\n        exit(EXIT_FAILURE_EXEC_FAILED);\n      }\n      if ((amt = bulk - filesz)) {\n        ELF_LOGF(\"note: next copy is actually bzero() kludge\");\n        unassert(blank = calloc(1, amt));\n        LoaderCopy(m, start + filesz, amt, blank, 0, prot);\n        free(blank);\n      }\n    }\n    start += bulk;\n    // allocate any remaining zero-initialized memory\n    if (start < end) {\n      ELF_LOGF(\"alloc %\" PRIx64 \"-%\" PRIx64, start, end);\n      if (ReserveVirtual(s, start, end - start, key, -1, 0, 0, 0) == -1) {\n        ERRF(\"failed to allocate program header bss\");\n        exit(EXIT_FAILURE_EXEC_FAILED);\n      }\n    }\n  }\n\n  *last_prot = prot;\n  s->brk = MAX(s->brk, end);\n\n  if (flags & PF_X_) {\n    if (!s->codesize) {\n      s->codestart = vaddr;\n      s->codesize = memsz;\n    } else if (vaddr == s->codestart + s->codesize) {\n      s->codesize += memsz;\n    }\n  }\n\n  return end;\n}\n\nstatic bool IsFreebsdExecutable(Elf64_Ehdr_ *ehdr, size_t size) {\n  // APE uses the FreeBSD OS ABI too, but never with ET_DYN\n  return Read16(ehdr->type) == ET_DYN_ &&\n         ehdr->ident[EI_OSABI_] == ELFOSABI_FREEBSD_ &&\n         ehdr->ident[EI_VERSION_] == 1;\n}\n\nstatic bool IsOpenbsdExecutable(struct Elf64_Ehdr_ *ehdr, size_t size) {\n  size_t off;\n  unsigned i;\n  Elf64_Phdr_ *phdr;\n  if (Read64(ehdr->phoff) < size) {\n    for (i = 0; i < Read16(ehdr->phnum); ++i) {\n      off = Read64(ehdr->phoff) + Read16(ehdr->phentsize) * i;\n      if (off + Read16(ehdr->phentsize) > size) {\n        return false;\n      }\n      phdr = (Elf64_Phdr_ *)((u8 *)ehdr + off);\n      if (Read32(phdr->type) == PT_OPENBSD_RANDOMIZE_) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nstatic bool IsHaikuExecutable(Elf64_Ehdr_ *ehdr, size_t size) {\n#ifdef __HAIKU__\n  int i, n;\n  bool res = false;\n  const char *stab;\n  const Elf64_Sym_ *st;\n  if ((stab = GetElfStringTable(ehdr, size)) &&\n      (st = GetElfSymbolTable(ehdr, size, &n))) {\n    for (i = 0; i < n; ++i) {\n      if (ELF64_ST_TYPE_(st[i].info) == STT_OBJECT_ &&\n          !strcmp(stab + Read32(st[i].name), \"_gSharedObjectHaikuVersion\")) {\n        res = true;\n        break;\n      }\n    }\n  }\n  return res;\n#else\n  return false;\n#endif\n}\n\nstatic bool IsShebangExecutable(void *image, size_t size) {\n  return size >= 2 && ((char *)image)[0] == '#' && ((char *)image)[1] == '!';\n}\n\nstatic void ExplainWhyItCantBeEmulated(const char *path, const char *reason) {\n  LOGF(\"%s: can't emulate: %s\", path, reason);\n}\n\nstatic bool IsBinFile(const char *prog) {\n  return EndsWith(prog, \".bin\") ||  //\n         EndsWith(prog, \".BIN\") ||  //\n         EndsWith(prog, \".img\") ||  //\n         EndsWith(prog, \".IMG\") ||  //\n         EndsWith(prog, \".raw\") ||  //\n         EndsWith(prog, \".RAW\");\n}\n\nbool IsSupportedExecutable(const char *path, void *image, size_t size) {\n  Elf64_Ehdr_ *ehdr;\n  if (IsBinFile(path)) {\n    return true;\n  }\n  if (size >= sizeof(Elf64_Ehdr_) && READ32(image) == READ32(\"\\177ELF\")) {\n    ehdr = (Elf64_Ehdr_ *)image;\n    if (Read16(ehdr->type) != ET_EXEC_ &&  //\n        Read16(ehdr->type) != ET_DYN_) {\n      ExplainWhyItCantBeEmulated(path, \"ELF is neither ET_EXEC or ET_DYN\");\n      return false;\n    }\n    if (ehdr->ident[EI_CLASS_] == ELFCLASS32_) {\n      ExplainWhyItCantBeEmulated(path, \"32-bit ELF not supported\");\n      return false;\n    }\n    if (Read16(ehdr->machine) != EM_NEXGEN32E_) {\n      ExplainWhyItCantBeEmulated(path, \"ELF is not AMD64\");\n      return false;\n    }\n    if (IsFreebsdExecutable(ehdr, size)) {\n      ExplainWhyItCantBeEmulated(path, \"ELF is FreeBSD executable\");\n      return false;\n    }\n    if (IsOpenbsdExecutable(ehdr, size)) {\n      ExplainWhyItCantBeEmulated(path, \"ELF is OpenBSD executable\");\n      return false;\n    }\n    if (IsHaikuExecutable(ehdr, size)) {\n      ExplainWhyItCantBeEmulated(path, \"ELF is Haiku executable\");\n      return false;\n    }\n#if defined(__ELF__) && !defined(__linux)\n    LOGF(\"blink believes %s is an x86_64-linux executable\", path);\n#endif\n    return true;\n  }\n  if (size >= 4096 && (READ64(image) == READ64(\"MZqFpD='\") ||\n                       READ64(image) == READ64(\"jartsr='\"))) {\n    return true;\n  }\n  if (!IsShebangExecutable(image, size)) {\n    ExplainWhyItCantBeEmulated(path, \"not ELF, not APE, and not a .bin file\");\n  }\n  return false;\n}\n\nstatic void LoadFlatExecutable(struct Machine *m, uintptr_t base,\n                               const char *prog, void *image, size_t imagesize,\n                               int fd) {\n  int prot = 0;\n  Elf64_Phdr_ phdr;\n  i64 end = INT64_MIN;\n  Write32(phdr.type, PT_LOAD_);\n  Write32(phdr.flags, PF_X_ | PF_R_ | PF_W_);\n  Write64(phdr.offset, 0);\n  Write64(phdr.vaddr, base);\n  Write64(phdr.filesz, imagesize);\n  Write64(phdr.memsz, ROUNDUP(imagesize + kRealSize, 4096));\n  LoadElfLoadSegment(m, prog, image, imagesize, &phdr, end, &prot, 0, fd);\n  m->ip = base;\n}\n\nstatic i64 ChooseAslr(const Elf64_Ehdr_ *ehdr, size_t size, i64 dflt,\n                      i64 *base) {\n  i64 aslr;\n  if (GetElfMemorySize(ehdr, size, base) <= 0) {\n    ERRF(\"couldn't determine boundaries of loaded executable\");\n    exit(EXIT_FAILURE_EXEC_FAILED);\n  }\n  if (Read16(ehdr->type) == ET_DYN_ && !*base) {\n    aslr = dflt;\n    ELF_LOGF(\"choosing base skew %\" PRIx64 \" because dynamic\", aslr);\n  } else {\n    aslr = 0;\n    ELF_LOGF(\"won't skew base since not dynamic\");\n  }\n  *base += aslr;\n  if (!(*base & ~(FLAG_pagesize - 1))) {\n    ERRF(\"won't load program to null base address\");\n    exit(EXIT_FAILURE_EXEC_FAILED);\n  }\n  return aslr;\n}\n\nstatic bool LoadElf(struct Machine *m,  //\n                    struct Elf *elf,    //\n                    Elf64_Ehdr_ *ehdr,  //\n                    size_t esize,       //\n                    int fd) {\n  int i, prot;\n  Elf64_Phdr_ *phdr;\n  i64 end = INT64_MIN;\n  bool execstack = true;\n  elf->aslr = ChooseAslr(ehdr, esize, m->system->brk, &elf->base);\n  m->ip = elf->at_entry = elf->aslr + Read64(ehdr->entry);\n  m->cs.sel = USER_CS_LINUX;\n  m->ss.sel = USER_DS_LINUX;\n  elf->at_phdr = elf->base + Read64(ehdr->phoff);\n  elf->at_phent = Read16(ehdr->phentsize);\n  elf->at_phnum = 0;\n  for (prot = i = 0; i < Read16(ehdr->phnum); ++i) {\n    ++elf->at_phnum;\n    phdr = (Elf64_Phdr_ *)((u8 *)ehdr + Read64(ehdr->phoff) +\n                           Read16(ehdr->phentsize) * i);\n    switch (Read32(phdr->type)) {\n      case PT_GNU_STACK_:\n        execstack = Read32(phdr->flags) & PF_X_;\n        break;\n      case PT_LOAD_:\n        end = LoadElfLoadSegment(m, elf->execfn, ehdr, esize, phdr, end, &prot,\n                                 elf->aslr, fd);\n        break;\n      case PT_INTERP_:\n        elf->interpreter = (char *)ehdr + Read64(phdr->offset);\n        if (elf->interpreter[Read64(phdr->filesz) - 1]) {\n          ELF_LOGF(\"elf interpreter not nul terminated\");\n          exit(EXIT_FAILURE_EXEC_FAILED);\n        }\n        break;\n      default:\n        break;\n    }\n  }\n  if (elf->interpreter) {\n    int fd;\n    i64 aslr;\n    char ibuf[21];\n    struct stat st;\n    Elf64_Ehdr_ *ehdri;\n    end = INT64_MIN;\n    ELF_LOGF(\"loading elf interpreter %s\", elf->interpreter);\n    errno = 0;\n    SYS_LOGF(\"LoadInterpreter %s\", elf->interpreter);\n    if ((fd = VfsOpen(AT_FDCWD, elf->interpreter, O_RDONLY, 0)) == -1 ||\n        (VfsFstat(fd, &st) == -1 || !st.st_size) ||\n        (ehdri = (Elf64_Ehdr_ *)Mmap(0, st.st_size, PROT_READ | PROT_WRITE,\n                                     MAP_PRIVATE, fd, 0, \"loader\")) ==\n            MAP_FAILED ||\n        !IsSupportedExecutable(elf->interpreter, ehdri, st.st_size)) {\n      WriteErrorString(elf->interpreter);\n      WriteErrorString(\": failed to load interpreter (errno \");\n      FormatInt64(ibuf, errno);\n      WriteErrorString(ibuf);\n      WriteErrorString(\")\\n\");\n      exit(EXIT_FAILURE_EXEC_FAILED);\n    }\n    aslr = ChooseAslr(\n        ehdri, st.st_size,\n        elf->aslr ? elf->aslr - (16 * 1024 * 1024) : FLAG_dyninterpaddr,\n        &elf->at_base);\n    m->ip = elf->at_base + Read64(ehdri->entry);\n    for (prot = i = 0; i < Read16(ehdri->phnum); ++i) {\n      phdr = GetElfProgramHeaderAddress(ehdri, st.st_size, i);\n      switch (Read32(phdr->type)) {\n        case PT_LOAD_:\n          end = LoadElfLoadSegment(m, elf->interpreter, ehdri, st.st_size, phdr,\n                                   end, &prot, aslr, fd);\n          break;\n        default:\n          break;\n      }\n    }\n    unassert(!Munmap(ehdri, st.st_size));\n    unassert(!VfsClose(fd));\n  }\n  return execstack;\n}\n\nvoid BootProgram(struct Machine *m,  //\n                 struct Elf *elf,    //\n                 u8 bootdrive) {\n  int fd;\n  SetDefaultBiosIntVectors(m);\n  memset(m->beg, 0, sizeof(m->beg));  // reinitialize registers\n  memset(m->seg, 0, sizeof(m->seg));\n  m->flags = SetFlag(m->flags, FLAGS_IF, 1);\n  m->ip = 0x7c00;\n  elf->base = 0x7c00;\n  Write64(m->sp, 0x6f00);  // following QEMU\n  m->dl = bootdrive;\n  SetDefaultBiosDataArea(m);\n  memset(m->system->real + 0x500, 0, kBiosOptBase - 0x500);\n  memset(m->system->real + 0x00100000, 0, kRealSize - 0x00100000);\n  if ((fd = VfsOpen(AT_FDCWD, m->system->elf.prog, O_RDONLY, 0)) == -1 ||\n      VfsRead(fd, m->system->real + 0x7c00, 512) <= 0) {\n    // if we failed to load the boot sector for whatever reason, then...\n    // ...arrange to invoke int 0x18 (diskless boot hook)\n    // TODO: maybe error out more quickly?\n    Write16(m->system->real + 0x7c00, 0x18CD);\n  }\n  VfsClose(fd);\n  SetWriteAddr(m, 0x7c00, 512);\n}\n\nstatic int GetElfHeader(char ehdr[64], const char *prog, const char *image) {\n  int c, i;\n  const char *p;\n  for (p = image; p < image + 4096; ++p) {\n    if (READ64(p) != READ64(\"printf '\")) {\n      continue;\n    }\n    for (i = 0, p += 8; p + 3 < image + 4096 && (c = *p++) != '\\'';) {\n      if (c == '\\\\') {\n        if ('0' <= *p && *p <= '7') {\n          c = *p++ - '0';\n          if ('0' <= *p && *p <= '7') {\n            c *= 8;\n            c += *p++ - '0';\n            if ('0' <= *p && *p <= '7') {\n              c *= 8;\n              c += *p++ - '0';\n            }\n          }\n        }\n      }\n      if (i < 64) {\n        ehdr[i++] = c;\n      } else {\n        ERRF(\"%s: ape printf elf header too long\\n\", prog);\n        return -1;\n      }\n    }\n    if (i != 64) {\n      ERRF(\"%s: ape printf elf header too short\\n\", prog);\n      return -1;\n    }\n    if (READ32(ehdr) != READ32(\"\\177ELF\")) {\n      ERRF(\"%s: ape printf elf header didn't have elf magic\\n\", prog);\n      return -1;\n    }\n    return 0;\n  }\n  ERRF(\"%s: printf statement not found in first 4096 bytes\\n\", prog);\n  return -1;\n}\n\nstatic void FreeProgName(void) {\n  free(g_progname);\n}\n\nstatic int CheckExecutableFile(const char *prog, const struct stat *st) {\n  if (!S_ISREG(st->st_mode)) {\n    LOGF(\"execve needs regular file\");\n    errno = EACCES;\n    return -1;\n  }\n  if (!IsWindows() && !(st->st_mode & 0111) && !IsBinFile(prog)) {\n    LOGF(\"execve needs chmod +x\");\n    errno = EACCES;\n    return -1;\n  }\n  if (!st->st_size) {\n    LOGF(\"executable file empty\");\n    errno = ENOEXEC;\n    return -1;\n  }\n  return 0;\n}\n\n// SHELL RUNS\n//   ./script.sh foo bar\n// SCRIPT HAS\n//   #!/bin/interp one arg\n// BLINK DOES\n//   AT_EXECFN = ./script.sh\n//   argv[0] = /bin/interp\n//   argv[1] = one arg\n//   argv[2] = ./script.sh\n//   argv[3] = foo\n//   argv[4] = bar\nstatic bool HasShebang(struct Machine *m, const char *p, size_t n, char **prog,\n                       char **args) {\n  char *b;\n  size_t i, j, t;\n  n = MIN(n, kMaxShebang);\n  if (n < 4) return false;\n  if (p[0] != '#') return false;\n  if (p[1] != '!') return false;\n  if (!(b = (char *)AddToFreeList(m, calloc(1, n + 1)))) return false;\n  for (t = 0, j = 0, i = 2; i < n; ++i) {\n    if (!(32 <= p[i] && p[i] < 0177) && p[i] != '\\n') return false;\n    if (!t) {\n      // STATE 0: COPY INTERPRETER FILENAME\n      if (p[i] == ' ') {\n        *prog = b;\n        b = 0;\n        j = 0;\n        t = 1;\n      } else if (p[i] == '\\n') {\n        *prog = b;\n        *args = 0;\n        return true;\n      } else {\n        b[j++] = p[i];\n        b[j] = 0;\n      }\n    } else if (t == 1) {\n      // STATE 1: HANDLE SPACES BETWEEN INTERPRETER AND ITS ARGS\n      if (p[i] == ' ') {\n        // do nothing\n      } else if (p[i] == '\\n') {\n        *args = 0;\n        return true;\n      } else {\n        if (!(b = (char *)AddToFreeList(m, calloc(1, n + 1)))) return false;\n        b[j++] = p[i];\n        b[j] = 0;\n        t = 2;\n      }\n    } else if (t == 2) {\n      // STATE 2: COPY INTERPRETER ARGS AS A SINGLE ARGUMENT\n      if (p[i] == '\\n') {\n        *args = b;\n        return true;\n      } else {\n        b[j++] = p[i];\n        b[j] = 0;\n      }\n    } else {\n      __builtin_unreachable();\n    }\n  }\n  return false;\n}\n\nstatic size_t CountStrList(char **a) {\n  size_t n = 0;\n  while (*a++) ++n;\n  return n;\n}\n\nstatic char **ConcatStrLists(struct Machine *m, char **a, char **b) {\n  size_t i, n;\n  char **c, *e;\n  if ((c = (char **)AddToFreeList(\n           m, malloc(((n = CountStrList(a) + CountStrList(b)) + 2) *\n                     sizeof(*c))))) {\n    i = 0;\n    while ((e = *a++)) c[i++] = e;\n    while ((e = *b++)) c[i++] = e;\n    unassert(i == n);\n    c[i++] = 0;\n    c[i] = 0;\n  }\n  return c;\n}\n\nstatic int CanEmulateData(struct Machine *m, char **prog, char ***argv,\n                          bool isfirst, char *img, size_t imglen) {\n  char **newargv;\n  char *interp[3] = {0};\n  if (IsSupportedExecutable(*prog, img, imglen)) {\n    return 1;\n  } else if (isfirst && HasShebang(m, img, imglen, interp, interp + 1) &&\n             CanEmulateImpl(m, interp, 0, false) &&\n             (newargv = ConcatStrLists(m, interp, *argv))) {\n    newargv[1 + !!interp[1]] = *prog;\n    *prog = interp[0];\n    *argv = newargv;\n    return 2;\n  } else {\n    return 0;\n  }\n}\n\nstatic bool IsApeBinary(const char *path) {\n  int fd;\n  ssize_t rc;\n  char buf[8];\n  fd = open(path, O_RDONLY | O_CLOEXEC | O_NOCTTY);\n  if (fd == -1) return false;\n  rc = pread(fd, buf, 8, 0);\n  close(fd);\n  if (rc != 8) return false;\n  return !memcmp(buf, \"MZqFpD='\", 8) ||  //\n         !memcmp(buf, \"jartsr='\", 8);\n}\n\nvoid LoadProgram(struct Machine *m, char *execfn, char *prog, char **args,\n                 char **vars, const char *biosprog) {\n  int fd;\n  i64 stack;\n  void *map;\n  int status;\n  char tmp[64];\n  bool isfirst;\n  long pagesize;\n  size_t mapsize;\n  bool execstack;\n  struct stat st;\n  struct Elf *elf;\n  static bool once;\n  if (!once) {\n    atexit(FreeProgName);\n    once = true;\n  }\n  elf = &m->system->elf;\n  m->system->loaded = false;\n  unassert(GetRandom(elf->rng, sizeof(elf->rng), 0) == sizeof(elf->rng));\n  for (isfirst = true;;) {\n    unassert(prog);\n    elf->execfn = execfn;\n    elf->prog = prog;\n    elf->interpreter = 0;\n    elf->at_phdr = 0;\n    elf->at_base = -1;\n    elf->at_phent = 56;\n    free(g_progname);\n    g_progname = strdup(prog);\n    SYS_LOGF(\"LoadProgram %s\", prog);\n    if ((fd = VfsOpen(AT_FDCWD, prog, O_RDONLY, 0)) == -1 ||\n        VfsFstat(fd, &st) == -1 || CheckExecutableFile(prog, &st) == -1 ||\n        (map = Mmap(0, (mapsize = st.st_size), PROT_READ | PROT_WRITE,\n                    MAP_PRIVATE, fd, 0, \"loader\")) == MAP_FAILED) {\n      WriteErrorString(prog);\n      WriteErrorString(\": failed to load executable (errno \");\n      FormatInt64(tmp, errno);\n      WriteErrorString(tmp);\n      WriteErrorString(\")\\n\");\n      exit(EXIT_FAILURE_EXEC_FAILED);\n    }\n    status = CanEmulateData(m, &prog, &args, isfirst, (char *)map, mapsize);\n    if (!status) {\n      WriteErrorString(\"\\\nerror: unsupported executable; we need:\\n\\\n- x86_64-linux elf executables\\n\\\n- flat executables (.bin files)\\n\\\n- actually portable executables (MZqFpD/jartsr)\\n\\\n- scripts with #!shebang meeting above criteria\\n\");\n      exit(EXIT_FAILURE_EXEC_FAILED);\n    } else if (status == 1) {\n      break;  // file is a real executable\n    } else if (status == 2) {\n      // turns out it's a shell script\n      if (isfirst) {\n        // start over using the shebang interpreter instead\n        unassert(!VfsMunmap(map, mapsize));\n        unassert(!VfsClose(fd));\n        isfirst = false;\n      } else {\n        LOGF(\"shell scripts can't interpret shell scripts\");\n        exit(EXIT_FAILURE_EXEC_FAILED);\n      }\n    } else {\n      __builtin_unreachable();\n    }\n  }\n  ResetCpu(m);\n  m->system->codesize = 0;\n  m->system->codestart = 0;\n  m->system->brk = FLAG_imagestart;\n  m->system->automap = FLAG_automapstart;\n  if (HasLinearMapping()) {\n    m->system->brk ^= Read64(elf->rng) & FLAG_aslrmask;\n    m->system->automap ^= (Read64(elf->rng) & FLAG_aslrmask);\n  }\n  if (m->mode.genmode == XED_GEN_MODE_REAL) {\n    LoadBios(m, biosprog);\n    if (IsApeBinary(prog)) {\n      // cosmo convention (see also binbase)\n      AddFileMap(m->system, 4 * 1024 * 1024, 512, prog, 0);\n    } else {\n      // sectorlisp convention\n      AddFileMap(m->system, 0, 512, prog, 0);\n    }\n  } else {\n    m->flags = SetFlag(m->flags, FLAGS_IF, 1);\n    m->system->cr0 = CR0_PE | CR0_MP | CR0_ET | CR0_PG;\n    m->system->cr3 = AllocatePageTable(m->system);\n    if (IsBinFile(prog)) {\n      elf->base = 0x400000;\n      LoadFlatExecutable(m, elf->base, prog, map, mapsize, fd);\n      execstack = true;\n    } else if (READ32(map) == READ32(\"\\177ELF\")) {\n      execstack = LoadElf(m, elf, (Elf64_Ehdr_ *)map, mapsize, fd);\n    } else if (READ64(map) == READ64(\"MZqFpD='\") ||\n               READ64(map) == READ64(\"jartsr='\")) {\n      m->system->iscosmo = true;\n      // Cosmopolitan programs pretty much require at least 47-bit virtual\n      // addresses; if the host lacks these, then emulate them w/ software\n      if (FLAG_vabits < 47) FLAG_nolinear = true;\n      if (GetElfHeader(tmp, prog, (const char *)map) == -1) exit(EXIT_FAILURE_EXEC_FAILED);\n      memcpy(map, tmp, 64);\n      execstack = LoadElf(m, elf, (Elf64_Ehdr_ *)map, mapsize, fd);\n    } else {\n      unassert(!\"impossible condition\");\n    }\n    stack = HasLinearMapping() && FLAG_vabits <= 47 && !kSkew\n                ? 0\n                : kStackTop - kStackSize;\n    if ((stack = ReserveVirtual(\n             m->system, stack, kStackSize,\n             PAGE_FILE | PAGE_U | PAGE_RW | (execstack ? 0 : PAGE_XD), -1, 0, 0,\n             0)) != -1) {\n      unassert(AddFileMap(m->system, stack, kStackSize, \"[stack]\", -1));\n      Put64(m->sp, stack + kStackSize);\n    } else {\n      LOGF(\"failed to reserve stack memory\");\n      exit(EXIT_FAILURE_EXEC_FAILED);\n    }\n    m->system->loaded = true;  // in case rwx stack is smc write-protected :'(\n    LoadArgv(m, execfn, prog, args, vars, elf->rng);\n  }\n  pagesize = FLAG_pagesize;\n  pagesize = MAX(4096, pagesize);\n  if (elf->interpreter) {\n    elf->interpreter = strdup(elf->interpreter);\n  }\n  unassert(CheckMemoryInvariants(m->system));\n  elf->execfn = strdup(elf->execfn);\n  elf->prog = strdup(elf->prog);\n  unassert(!VfsMunmap(map, mapsize));\n  unassert(!VfsClose(fd));\n  m->system->loaded = true;\n#ifndef DISABLE_VFS\n  unassert(!ProcfsRegisterExe(getpid(), elf->prog));\n#endif\n}\n\nstatic bool CanEmulateImpl(struct Machine *m, char **prog, char ***argv,\n                           bool isfirst) {\n  int fd;\n  bool res;\n  void *img;\n  struct stat st;\n  if ((fd = VfsOpen(AT_FDCWD, *prog, O_RDONLY | O_CLOEXEC, 0)) == -1) {\n  CantEmulate:\n    LOGF(\"%s: can't emulate: %s\", *prog, strerror(errno));\n    return false;\n  }\n  unassert(!VfsFstat(fd, &st));\n  if (CheckExecutableFile(*prog, &st) == -1) {\n    VfsClose(fd);\n    return false;\n  }\n  img = VfsMmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);\n  VfsClose(fd);\n  if (img == MAP_FAILED) goto CantEmulate;\n  res = !!CanEmulateData(m, prog, argv, isfirst, (char *)img, st.st_size);\n  unassert(!VfsMunmap(img, st.st_size));\n  return res;\n}\n\nbool CanEmulateExecutable(struct Machine *m, char **prog, char ***argv) {\n  int err;\n  bool res;\n  err = errno;\n  res = CanEmulateImpl(m, prog, argv, true);\n  errno = err;\n  return res;\n}\n"
  },
  {
    "path": "blink/loader.h",
    "content": "#ifndef BLINK_LOADER_H_\n#define BLINK_LOADER_H_\n#include \"blink/elf.h\"\n#include \"blink/machine.h\"\n\nbool CanEmulateExecutable(struct Machine *, char **, char ***);\nvoid BootProgram(struct Machine *, struct Elf *, u8);\nvoid LoadProgram(struct Machine *, char *, char *, char **, char **,\n                 const char *);\nvoid LoadDebugSymbols(struct System *);\nvoid LoadFileSymbols(struct System *, const char *, i64);\nbool IsSupportedExecutable(const char *, void *, size_t);\n\n#endif /* BLINK_LOADER_H_ */\n"
  },
  {
    "path": "blink/log.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/log.h\"\n\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <signal.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/fspath.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/thread.h\"\n#include \"blink/tsan.h\"\n#include \"blink/types.h\"\n#include \"blink/util.h\"\n\n#define LOG_ERR  0\n#define LOG_INFO 1\n\n#define DEFAULT_LOG_PATH \"blink.log\"\n\n#define APPEND(F, ...) \\\n  n += F(b + n, n > PIPE_BUF ? 0 : PIPE_BUF - n, __VA_ARGS__)\n\nstatic struct Log {\n  pthread_once_t_ once;\n  int level;\n  int fd;\n  char *path;\n} g_log = {\n    PTHREAD_ONCE_INIT_,\n    LOG_ERR,\n};\n\nstatic char *GetTimestamp(void) {\n  int x;\n  struct timespec ts;\n  _Thread_local static i64 last;\n  _Thread_local static char s[27];\n  _Thread_local static struct tm tm;\n  IGNORE_RACES_START();\n  clock_gettime(CLOCK_REALTIME, &ts);\n  if (ts.tv_sec != last) {\n    localtime_r(&ts.tv_sec, &tm);\n    x = tm.tm_year + 1900;\n    s[0] = '0' + x / 1000;\n    s[1] = '0' + x / 100 % 10;\n    s[2] = '0' + x / 10 % 10;\n    s[3] = '0' + x % 10;\n    s[4] = '-';\n    x = tm.tm_mon + 1;\n    s[5] = '0' + x / 10;\n    s[6] = '0' + x % 10;\n    s[7] = '-';\n    x = tm.tm_mday;\n    s[8] = '0' + x / 10;\n    s[9] = '0' + x % 10;\n    s[10] = 'T';\n    x = tm.tm_hour;\n    s[11] = '0' + x / 10;\n    s[12] = '0' + x % 10;\n    s[13] = ':';\n    x = tm.tm_min;\n    s[14] = '0' + x / 10;\n    s[15] = '0' + x % 10;\n    s[16] = ':';\n    x = tm.tm_sec;\n    s[17] = '0' + x / 10;\n    s[18] = '0' + x % 10;\n    s[19] = '.';\n    s[26] = 0;\n    last = ts.tv_sec;\n  }\n  IGNORE_RACES_END();\n  x = ts.tv_nsec;\n  s[20] = '0' + x / 100000000;\n  s[21] = '0' + x / 10000000 % 10;\n  s[22] = '0' + x / 1000000 % 10;\n  s[23] = '0' + x / 100000 % 10;\n  s[24] = '0' + x / 10000 % 10;\n  s[25] = '0' + x / 1000 % 10;\n  return s;\n}\n\nstatic void OpenLog(void) {\n  int fd;\n  if (!g_log.path) return;\n  if (!strcmp(g_log.path, \"-\") ||  //\n      !strcmp(g_log.path, \"/dev/stderr\")) {\n    fd = 2;\n  } else if (!strcmp(g_log.path, \"/dev/stdout\")) {\n    fd = 1;\n  } else {\n    fd = open(g_log.path, O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC, 0644);\n    if (fd == -1) {\n      perror(g_log.path);\n      g_log.fd = -1;\n      return;\n    }\n  }\n  unassert((g_log.fd = fcntl(fd, F_DUPFD_CLOEXEC, kMinBlinkFd)) != -1);\n  unassert(!close(fd));\n}\n\nstatic void Log(const char *file, int line, const char *fmt, va_list va,\n                int level) {\n  char b[4096];\n  int err, n = 0;\n  err = errno;\n  unassert(!pthread_once_(&g_log.once, OpenLog));\n  APPEND(snprintf, \"%c%s:%s:%d:%d \", \"EI\"[level], GetTimestamp(), file, line,\n         g_machine ? g_machine->tid : 0);\n  APPEND(vsnprintf, fmt, va);\n  APPEND(snprintf, \"\\n\");\n  if (n > PIPE_BUF - 1) {\n    n = PIPE_BUF - 1;\n    b[n - 1] = '\\n';\n    b[n - 2] = '.';\n    b[n - 3] = '.';\n    b[n - 4] = '.';\n  }\n  if (g_log.fd != -1) {\n    WriteError(g_log.fd, b, n);\n  }\n  if (FLAG_alsologtostderr || (!FLAG_nologstderr && level <= g_log.level)) {\n    WriteError(2, b, n);\n  }\n  errno = err;\n}\n\nvoid LogErr(const char *file, int line, const char *fmt, ...) {\n  va_list va;\n  va_start(va, fmt);\n  Log(file, line, fmt, va, LOG_ERR);\n  va_end(va);\n}\n\nvoid LogInfo(const char *file, int line, const char *fmt, ...) {\n  va_list va;\n  va_start(va, fmt);\n  Log(file, line, fmt, va, LOG_INFO);\n  va_end(va);\n}\n\nvoid LogSys(const char *file, int line, const char *fmt, ...) {\n  va_list va;\n  va_start(va, fmt);\n  Log(file, line, fmt, va, LOG_INFO);\n  va_end(va);\n}\n\nstatic void FreeLogPath(void) {\n  free(g_log.path);\n  g_log.path = 0;\n}\n\nstatic void SetLogPath(const char *path) {\n  if (path) {\n    g_log.path = ExpandUser(path);\n  } else {\n    g_log.path = JoinPath(GetStartDir(), DEFAULT_LOG_PATH);\n  }\n  atexit(FreeLogPath);\n}\n\nvoid LogInit(const char *path) {\n  WriteErrorInit();\n  SetLogPath(path);\n}\n"
  },
  {
    "path": "blink/log.h",
    "content": "#ifndef BLINK_LOG_H_\n#define BLINK_LOG_H_\n#include <stdio.h>\n\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/flag.h\"\n\n#ifndef NDEBUG\n#define LOG_ENABLED 1\n#else\n#define LOG_ENABLED 0\n#endif\n\n#define LOG_SIG 0  // log signal handling behaviors\n#define LOG_ASM 0  // log executed assembly opcodes\n#define LOG_JIT 0  // just-in-time compilation logs\n#define LOG_JIP 0  // jit path construction logging\n#define LOG_JIX 0  // verbose jit execution logging\n#define LOG_MEM 0  // system memory mapping logging\n#define LOG_THR 0  // multi-threaded operation logs\n#define LOG_ELF 0  // elf executable loader logging\n#define LOG_SPX 0  // speculative execution logging\n#define LOG_CPU 0  // produce txt file of registers\n#define LOG_COD 0  // produce asm file of jit codes\n#define LOG_VFS 0  // log from emulated filesystems\n\n#if LOG_ENABLED\n#define ERRF(...) LogErr(__FILE__, __LINE__, __VA_ARGS__)\n#define LOGF(...) LogInfo(__FILE__, __LINE__, __VA_ARGS__)\n#else\n#define ERRF(...) (void)0\n#define LOGF(...) (void)0\n#endif\n\n#if LOG_ENABLED\n#define SYS_LOGF(...)                                   \\\n  do {                                                  \\\n    if (__builtin_expect(FLAG_strace, 0)) {             \\\n      LogSys(__FILE__, __LINE__, \"(sys) \" __VA_ARGS__); \\\n    }                                                   \\\n  } while (0)\n#else\n#define SYS_LOGF(...) (void)0\n#endif\n\n#if LOG_SIG\n#define SIG_LOGF(...) LogInfo(__FILE__, __LINE__, \"(sig) \" __VA_ARGS__)\n#else\n#define SIG_LOGF(...) (void)0\n#endif\n\n#if LOG_ASM\n#define ASM_LOGF(...) LogInfo(__FILE__, __LINE__, \"(asm) \" __VA_ARGS__)\n#else\n#define ASM_LOGF(...) (void)0\n#endif\n\n#if LOG_JIT\n#define JIT_LOGF(...) LogInfo(__FILE__, __LINE__, \"(jit) \" __VA_ARGS__)\n#else\n#define JIT_LOGF(...) (void)0\n#endif\n\n#if LOG_JIP\n#define JIP_LOGF(...) LogInfo(__FILE__, __LINE__, \"(pat) \" __VA_ARGS__)\n#else\n#define JIP_LOGF(...) (void)0\n#endif\n\n#if LOG_JIX\n#define JIX_LOGF(...) LogInfo(__FILE__, __LINE__, \"(jix) \" __VA_ARGS__)\n#else\n#define JIX_LOGF(...) (void)0\n#endif\n\n#if LOG_MEM\n#define MEM_LOGF(...) LogInfo(__FILE__, __LINE__, \"(mem) \" __VA_ARGS__)\n#else\n#define MEM_LOGF(...) (void)0\n#endif\n\n#if LOG_THR\n#define THR_LOGF(...) LogInfo(__FILE__, __LINE__, \"(thr) \" __VA_ARGS__)\n#else\n#define THR_LOGF(...) (void)0\n#endif\n\n#if LOG_ELF\n#define ELF_LOGF(...) LogInfo(__FILE__, __LINE__, \"(elf) \" __VA_ARGS__)\n#else\n#define ELF_LOGF(...) (void)0\n#endif\n\n#if LOG_SPX\n#define SPX_LOGF(...) LogInfo(__FILE__, __LINE__, \"(spx) \" __VA_ARGS__)\n#else\n#define SPX_LOGF(...) (void)0\n#endif\n\n#if LOG_VFS\n#define VFS_LOGF(...) LogInfo(__FILE__, __LINE__, \"(vfs) \" __VA_ARGS__)\n#else\n#define VFS_LOGF(...) (void)0\n#endif\n\n#if LOG_ENABLED\n#define LOG_ONCE(x)                                                   \\\n  do {                                                                \\\n    static _Atomic(int) once_;                                        \\\n    if (!atomic_exchange_explicit(&once_, 1, memory_order_relaxed)) { \\\n      x;                                                              \\\n    }                                                                 \\\n  } while (0)\n#else\n#define LOG_ONCE(x) (void)0\n#endif\n\nextern char *g_progname;\n\nvoid LogInit(const char *);\nvoid LogSys(const char *, int, const char *, ...) printf_attr(3);\nvoid LogErr(const char *, int, const char *, ...) printf_attr(3);\nvoid LogInfo(const char *, int, const char *, ...) printf_attr(3);\nint WriteError(int, const char *, int);\nvoid WriteErrorInit(void);\nint WriteErrorString(const char *);\n\n#endif /* BLINK_LOG_H_ */\n"
  },
  {
    "path": "blink/logcpu.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <inttypes.h>\n#include <stdio.h>\n\n#include \"blink/debug.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n\n// use cosmopolitan/tool/build/fastdiff.c\nvoid LogCpu(struct Machine *m) {\n  static FILE *f;\n  if (!f) f = fopen(\"/tmp/cpu.log\", \"w\");\n  fprintf(f,\n          \"\\n\"\n          \"IP %\" PRIx64 \"\\n\"\n          \"AX %#\" PRIx64 \"\\n\"\n          \"CX %#\" PRIx64 \"\\n\"\n          \"DX %#\" PRIx64 \"\\n\"\n          \"BX %#\" PRIx64 \"\\n\"\n          \"SP %#\" PRIx64 \"\\n\"\n          \"BP %#\" PRIx64 \"\\n\"\n          \"SI %#\" PRIx64 \"\\n\"\n          \"DI %#\" PRIx64 \"\\n\"\n          \"R8 %#\" PRIx64 \"\\n\"\n          \"R9 %#\" PRIx64 \"\\n\"\n          \"R10 %#\" PRIx64 \"\\n\"\n          \"R11 %#\" PRIx64 \"\\n\"\n          \"R12 %#\" PRIx64 \"\\n\"\n          \"R13 %#\" PRIx64 \"\\n\"\n          \"R14 %#\" PRIx64 \"\\n\"\n          \"R15 %#\" PRIx64 \"\\n\"\n          \"FLAGS %s\\n\"\n          \"%s\\n\",\n          m->ip, Read64(m->ax), Read64(m->cx), Read64(m->dx), Read64(m->bx),\n          Read64(m->sp), Read64(m->bp), Read64(m->si), Read64(m->di),\n          Read64(m->r8), Read64(m->r9), Read64(m->r10), Read64(m->r11),\n          Read64(m->r12), Read64(m->r13), Read64(m->r14), Read64(m->r15),\n          DescribeCpuFlags(m->flags), DescribeOp(m, GetPc(m)));\n}\n"
  },
  {
    "path": "blink/machine.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/machine.h\"\n\n#include <errno.h>\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/alu.h\"\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/biosrom.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/case.h\"\n#include \"blink/debug.h\"\n#include \"blink/endian.h\"\n#include \"blink/flag.h\"\n#include \"blink/flags.h\"\n#include \"blink/fpu.h\"\n#include \"blink/jit.h\"\n#include \"blink/likely.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/modrm.h\"\n#include \"blink/random.h\"\n#include \"blink/signal.h\"\n#include \"blink/sse.h\"\n#include \"blink/stats.h\"\n#include \"blink/string.h\"\n#include \"blink/swap.h\"\n#include \"blink/syscall.h\"\n#include \"blink/thread.h\"\n#include \"blink/time.h\"\n#include \"blink/util.h\"\n#include \"blink/x86.h\"\n#include \"blink/xlat.h\"\n\n_Thread_local siginfo_t g_siginfo;\n_Thread_local struct Machine *g_machine;\n\nstatic void OpHintNopEv(P) {\n}\n\nstatic void OpCmc(P) {\n  m->flags ^= CF;\n}\n\nstatic void OpClc(P) {\n  m->flags = SetFlag(m->flags, FLAGS_CF, false);\n}\n\nstatic void OpStc(P) {\n  m->flags = SetFlag(m->flags, FLAGS_CF, true);\n}\n\nstatic void OpCli(P) {\n  m->flags = SetFlag(m->flags, FLAGS_IF, false);\n}\n\nstatic void OpSti(P) {\n  m->flags = SetFlag(m->flags, FLAGS_IF, true);\n}\n\nstatic void OpCld(P) {\n  m->flags = SetFlag(m->flags, FLAGS_DF, false);\n}\n\nstatic void OpStd(P) {\n  m->flags = SetFlag(m->flags, FLAGS_DF, true);\n}\n\nstatic void OpPushf(P) {\n  Push(A, ExportFlags(m->flags) & 0xFCFFFF);\n}\n\nstatic void OpPopf(P) {\n  if (!Osz(rde)) {\n    ImportFlags(m, Pop(A, 0));\n  } else {\n    ImportFlags(m, (m->flags & ~0xffff) | Pop(A, 0));\n  }\n}\n\nstatic void OpLahf(P) {\n  m->ah = ExportFlags(m->flags);\n}\n\nstatic void OpSahf(P) {\n  ImportFlags(m, (m->flags & ~0xff) | m->ah);\n}\n\nstatic void OpLeaGvqpM(P) {\n  WriteRegister(rde, RegRexrReg(m, rde), LoadEffectiveAddress(A).addr);\n  if (IsMakingPath(m)) {\n    Jitter(A, \"L\"      // res0 = LoadEffectiveAddress()\n              \"r0C\");  // PutReg(RexrReg, res0)\n  }\n}\n\nstatic void OpMovEvqpGvqp(P) {\n  WriteRegisterOrMemory(rde, GetModrmRegisterWordPointerWriteOszRexw(A),\n                        ReadRegister(rde, RegRexrReg(m, rde)));\n  if (IsMakingPath(m)) {\n    Jitter(A, \"A\"      // res0 = GetReg(RexrReg)\n              \"r0D\");  // PutRegOrMem(RexbRm, res0)\n  }\n}\n\nstatic void OpMovGvqpEvqp(P) {\n  WriteRegister(rde, RegRexrReg(m, rde),\n                ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(A)));\n  if (IsMakingPath(m)) {\n    Jitter(A, \"B\"      // res0 = GetRegOrMem(RexbRm)\n              \"r0C\");  // PutReg(RexrReg, res0)\n  }\n}\n\nstatic void OpMovzbGvqpEb(P) {\n  WriteRegister(rde, RegRexrReg(m, rde),\n                Load8(GetModrmRegisterBytePointerRead1(A)));\n  if (IsMakingPath(m)) {\n    Jitter(A, \"B\"       // res0 = GetRegOrMem(RexbRm)\n              \"r0wC\");  // PutReg[force16/32/64bit](RexrReg, res0)\n  }\n}\n\nstatic void OpMovzwGvqpEw(P) {\n  WriteRegister(rde, RegRexrReg(m, rde),\n                Load16(GetModrmRegisterWordPointerRead2(A)));\n  if (IsMakingPath(m)) {\n    Jitter(A, \"z1B\"    // res0 = GetRegOrMem[force16bit](RexbRm)\n              \"r0C\");  // PutReg(RexrReg, res0)\n  }\n}\n\nstatic void OpMovsbGvqpEb(P) {\n  WriteRegister(rde, RegRexrReg(m, rde),\n                (i8)Load8(GetModrmRegisterBytePointerRead1(A)));\n  if (IsMakingPath(m)) {\n    Jitter(A, \"B\"       // res0 = GetRegOrMem(RexbRm)\n              \"r0x\"     // res0 = SignExtend(res0)\n              \"r0wC\");  // PutReg[force16/32/64bit](RexrReg, res0)\n  }\n}\n\nstatic void OpMovswGvqpEw(P) {\n  WriteRegister(rde, RegRexrReg(m, rde),\n                (i16)Load16(GetModrmRegisterWordPointerRead2(A)));\n  if (IsMakingPath(m)) {\n    Jitter(A, \"z1B\"    // res0 = GetRegOrMem[force16bit](RexbRm)\n              \"r0z1x\"  // res0 = SignExtend[force16bit](res0)\n              \"r0C\");  // PutReg(RexrReg, res0)\n  }\n}\n\nstatic void OpMovslGdqpEd(P) {\n  WriteRegister(rde, RegRexrReg(m, rde),\n                (i32)Load32(GetModrmRegisterWordPointerRead4(A)));\n  if (IsMakingPath(m)) {\n    Jitter(A, \"z2B\"    // res0 = GetRegOrMem[force32bit](RexbRm)\n              \"r0z2x\"  // res0 = SignExtend[force32bit](res0)\n              \"r0C\");  // PutReg(RexrReg, res0)\n  }\n}\n\nstatic relegated u64 GetDescriptorLimit(u64 d) {\n  u64 lim = (d & 0x000f000000000000) >> 32 | (d & 0xffff);\n  if ((d & 0x0080000000000000) != 0) lim = (lim << 12) | 0xfff;\n  return lim;\n}\n\nrelegated int GetDescriptor(struct Machine *m, int selector,\n                            u64 *out_descriptor) {\n  u64 base = m->system->gdt_base, daddr;\n  selector &= -8;\n  if (8 <= selector && selector + 7 <= m->system->gdt_limit) {\n    daddr = base + selector;\n    if (daddr >= kRealSize || daddr + 8 > kRealSize) return -1;\n    SetReadAddr(m, daddr, 8);\n    *out_descriptor = Load64(m->system->real + daddr);\n    return 0;\n  } else {\n    return -1;\n  }\n}\n\nstatic relegated void OpLsl(P) {\n  u64 descriptor;\n  if (GetDescriptor(m, Load16(GetModrmRegisterWordPointerRead2(A)),\n                    &descriptor) != -1) {\n    WriteRegister(rde, RegRexrReg(m, rde), GetDescriptorLimit(descriptor));\n    m->flags = SetFlag(m->flags, FLAGS_ZF, true);\n  } else {\n    m->flags = SetFlag(m->flags, FLAGS_ZF, false);\n  }\n}\n\nvoid SetMachineMode(struct Machine *m, struct XedMachineMode mode) {\n  m->mode = mode;\n  m->system->mode = mode;\n}\n\nstatic relegated void OpXlatAlBbb(P) {\n  i64 v;\n  v = MaskAddress(Eamode(rde), Get64(m->bx) + Get8(m->ax));\n  v = DataSegment(A, v);\n  SetReadAddr(m, v, 1);\n  m->al = Load8(ResolveAddress(m, v));\n}\n\nstatic void OpXchgZvqp(P) {\n  u64 x, y;\n  x = Get64(m->ax);\n  y = Get64(RegRexbSrm(m, rde));\n  WriteRegister(rde, m->ax, y);\n  WriteRegister(rde, RegRexbSrm(m, rde), x);\n}\n\nstatic void OpCmpxchg8b(P) {\n  uint8_t *p;\n  uint32_t d, a;\n  p = GetModrmRegisterXmmPointerRead8(A);\n  if (Lock(rde)) LockBus(p);\n  a = Read32(p + 0);\n  d = Read32(p + 4);\n  if (a == Read32(m->ax) && d == Read32(m->dx)) {\n    m->flags = SetFlag(m->flags, FLAGS_ZF, true);\n    memcpy(p + 0, m->bx, 4);\n    memcpy(p + 4, m->cx, 4);\n  } else {\n    m->flags = SetFlag(m->flags, FLAGS_ZF, false);\n    Write32(m->ax, a);\n    Write32(m->dx, d);\n  }\n  if (Lock(rde)) UnlockBus(p);\n}\n\nstatic void OpCmpxchg16b(P) {\n  uint8_t *p;\n  uint64_t d, a;\n  p = GetModrmRegisterXmmPointerRead16(A);\n  if (Lock(rde)) LockBus(p);\n  a = Read64(p + 0);\n  d = Read64(p + 8);\n  if (a == Read64(m->ax) && d == Read64(m->dx)) {\n    m->flags = SetFlag(m->flags, FLAGS_ZF, true);\n    memcpy(p + 0, m->bx, 8);\n    memcpy(p + 8, m->cx, 8);\n  } else {\n    m->flags = SetFlag(m->flags, FLAGS_ZF, false);\n    Write64(m->ax, a);\n    Write64(m->dx, d);\n  }\n  if (Lock(rde)) UnlockBus(p);\n}\n\nstatic void Op1c7(P) {\n  bool ismem;\n  ismem = !IsModrmRegister(rde);\n  switch (ModrmReg(rde)) {\n    case 1:\n      if (ismem) {\n        if (Rexw(rde)) {\n          OpCmpxchg16b(A);\n        } else {\n          OpCmpxchg8b(A);\n        }\n      } else {\n        OpUdImpl(m);\n      }\n      break;\n    case 6:\n      if (!ismem) {\n        OpRdrand(A);\n      } else {\n        OpUdImpl(m);\n      }\n      break;\n    case 7:\n      if (!ismem) {\n        if (Rep(rde) == 3) {\n          OpRdpid(A);\n        } else {\n          OpRdseed(A);\n        }\n      } else {\n        OpUdImpl(m);\n      }\n      break;\n    default:\n      OpUdImpl(m);\n  }\n}\n\nstatic void TripleOp(P, const nexgen32e_f ops[3]) {\n  nexgen32e_f op;\n  op = ops[WordLog2(rde) - 1];\n  op(A);\n  if (IsMakingPath(m)) {\n    Jitter(A, \"m\", op);  // call micro-op\n  }\n}\n\nstatic void OpSax(P) {\n  TripleOp(A, kSax);\n}\n\nstatic void OpConvert(P) {\n  TripleOp(A, kConvert);\n}\n\nstatic void OpBswapZvqp(P) {\n  u64 x = Get64(RegRexbSrm(m, rde));\n  if (Rexw(rde)) {\n    Put64(RegRexbSrm(m, rde), SWAP64(x));\n  } else if (!Osz(rde)) {\n    Put64(RegRexbSrm(m, rde), SWAP32(x));\n  } else {\n    Put16(RegRexbSrm(m, rde), SWAP16(x));\n  }\n}\n\nstatic void OpMovAlOb(P) {\n  i64 addr = AddressOb(A);\n  SetWriteAddr(m, addr, 1);\n  Put8(m->ax, Load8(ResolveAddress(m, addr)));\n}\n\nstatic void OpMovObAl(P) {\n  i64 addr = AddressOb(A);\n  SetReadAddr(m, addr, 1);\n  Store8(ResolveAddress(m, addr), Get8(m->ax));\n}\n\nstatic void OpMovRaxOvqp(P) {\n  i64 v = DataSegment(A, disp);\n  SetReadAddr(m, v, 1 << RegLog2(rde));\n  WriteRegister(rde, m->ax, ReadMemory(rde, ResolveAddress(m, v)));\n}\n\nstatic void OpMovOvqpRax(P) {\n  i64 v = DataSegment(A, disp);\n  SetWriteAddr(m, v, 1 << RegLog2(rde));\n  WriteMemory(rde, ResolveAddress(m, v), Get64(m->ax));\n}\n\nstatic void OpMovEbGb(P) {\n  Store8(GetModrmRegisterBytePointerWrite1(A), Get8(ByteRexrReg(m, rde)));\n  if (IsMakingPath(m)) {\n    Jitter(A, \"A\"      // res0 = GetReg(RexrReg)\n              \"r0D\");  // PutRegOrMem(RexbRm, res0)\n  }\n}\n\nstatic void OpMovGbEb(P) {\n  Put8(ByteRexrReg(m, rde), Load8(GetModrmRegisterBytePointerRead1(A)));\n  unassert(!RegLog2(rde));\n  if (IsMakingPath(m)) {\n    Jitter(A, \"B\"      // res0 = GetRegOrMem(RexbRm)\n              \"r0C\");  // PutReg(RexrReg, res0)\n  }\n}\n\nstatic void OpMovZbIb(P) {\n  Put8(ByteRexbSrm(m, rde), uimm0);\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"a2\"    // push arg2\n           \"i\"     // <pop> = uimm0\n           \"u\"     // unpop\n           \"z0F\",  // PutReg[force8bit](RexbSrm, arg2)\n           uimm0);\n  }\n}\n\nstatic void OpMovZvqpIvqp(P) {\n  WriteRegister(rde, RegRexbSrm(m, rde), uimm0);\n  if (IsMakingPath(m)) {\n    if (!Rexw(rde) && !Osz(rde)) {\n      unassert(uimm0 == (u32)uimm0);\n      Jitter(A,\n             \"a0\"    // push arg2\n             \"i\"     // <pop> = uimm0\n             \"u\"     // unpop\n             \"z3F\",  // PutReg[kludge64bit](RexbSrm, arg2)\n             uimm0);\n    } else {\n      Jitter(A,\n             \"a0\"   // push arg2\n             \"i\"    // <pop> = uimm0\n             \"u\"    // unpop\n             \"wF\",  // PutReg[force16+bit](RexbSrm, arg2)\n             uimm0);\n    }\n  }\n}\n\nstatic void OpMovImm(P) {\n  WriteRegisterOrMemoryBW(rde, GetModrmWriteBW(A), uimm0);\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"a3\"  // push arg3\n           \"i\"   // <pop> = uimm0\n           \"u\"   // unpop\n           \"D\",  // PutRegOrMem(RexbRm, arg3)\n           uimm0);\n  }\n}\n\n// we want to have independent jit paths jump directly into one another\n// to avoid having control flow drop back to the main interpreter loop.\nvoid Connect(P, u64 pc, bool avoid_cycles) {\n#ifdef HAVE_JIT\n  void *jump;\n  uintptr_t f;\n  STATISTIC(++path_connected_total);\n  // 1. cyclic paths can block asynchronous sigs & deadlock exit\n  // 2. we don't want to stitch together paths on separate pages\n  if ((!avoid_cycles && m->path.start == pc) ||\n      RecordJitEdge(&m->system->jit, m->path.start, pc)) {\n    // is a preexisting jit path installed at destination?\n    if ((f = GetJitHook(&m->system->jit, pc)) &&\n        f != (uintptr_t)JitlessDispatch) {\n      // tail call into the other generated jit path function\n      jump = (u8 *)f + GetPrologueSize();\n      STATISTIC(++path_connected_directly);\n    } else {\n      STATISTIC(++path_connected_lazily);\n      // generate assembly to drop back into main interpreter\n      // then apply an smc fixup later on, if dest is created\n      if (!FLAG_noconnect) {\n        RecordJitJump(m->path.jb, pc, GetPrologueSize());\n      }\n      jump = (void *)m->system->ender;\n    }\n  } else {\n    // generate assembly to drop back into main interpreter\n    STATISTIC(++path_connected_interpreter);\n    jump = (void *)m->system->ender;\n  }\n  AppendJitJump(m->path.jb, jump);\n#endif\n}\n\nstatic void AluRo(P, const aluop_f ops[4], const aluop_f fops[4]) {\n  ops[RegLog2(rde)](m, ReadRegisterOrMemoryBW(rde, GetModrmReadBW(A)),\n                    ReadRegisterBW(rde, RegLog2(rde) ? RegRexrReg(m, rde)\n                                                     : ByteRexrReg(m, rde)));\n  if (IsMakingPath(m)) {\n    STATISTIC(++alu_ops);\n    LoadAluArgs(A);\n    switch (GetNeededFlags(m, m->ip, CF | ZF | SF | OF | AF | PF)) {\n      case 0:\n      CASE_ALU_FAST:\n        STATISTIC(++alu_simplified);\n        Jitter(A,\n               \"q\"   // arg0 = sav0 (machine)\n               \"m\",  // call micro-op\n               fops[RegLog2(rde)]);\n        break;\n      default:\n        Jitter(A,\n               \"q\"   // arg0 = sav0 (machine)\n               \"c\",  // call function\n               ops[RegLog2(rde)]);\n        break;\n    }\n  }\n}\n\nstatic void OpAluTest(P) {\n  if (IsMakingPath(m) && FuseBranchTest(A)) {\n    kAlu[ALU_AND][RegLog2(rde)](\n        m, ReadRegisterOrMemoryBW(rde, GetModrmReadBW(A)),\n        ReadRegisterBW(\n            rde, RegLog2(rde) ? RegRexrReg(m, rde) : ByteRexrReg(m, rde)));\n    return;\n  }\n  AluRo(A, kAlu[ALU_AND], kAluFast[ALU_AND]);\n}\n\nstatic void OpAluCmp(P) {\n  if (IsMakingPath(m) && FuseBranchCmp(A, false)) {\n    kAlu[ALU_SUB][RegLog2(rde)](\n        m, ReadRegisterOrMemoryBW(rde, GetModrmReadBW(A)),\n        ReadRegisterBW(\n            rde, RegLog2(rde) ? RegRexrReg(m, rde) : ByteRexrReg(m, rde)));\n    return;\n  }\n  AluRo(A, kAlu[ALU_SUB], kAluFast[ALU_SUB]);\n}\n\nstatic void OpAluFlip(P) {\n  aluop_f op = kAlu[(Opcode(rde) & 070) >> 3][RegLog2(rde)];\n  u8 *q = RegLog2(rde) ? RegRexrReg(m, rde) : ByteRexrReg(m, rde);\n  WriteRegisterBW(rde, q,\n                  op(m, ReadRegisterBW(rde, q),\n                     ReadRegisterOrMemoryBW(rde, GetModrmReadBW(A))));\n  if (IsMakingPath(m)) {\n    STATISTIC(++alu_ops);\n    LoadAluFlipArgs(A);\n    switch (GetNeededFlags(m, m->ip, CF | ZF | SF | OF | AF | PF)) {\n      case 0:\n        STATISTIC(++alu_unflagged);\n        if (GetFlagDeps(rde)) Jitter(A, \"q\");  // arg0 = sav0 (machine)\n        Jitter(A,\n               \"m\"     // call micro-op\n               \"r0C\",  // PutReg(RexrReg, res0)\n               kJustAlu[(Opcode(rde) & 070) >> 3]);\n        break;\n      CASE_ALU_FAST:\n        STATISTIC(++alu_simplified);\n        Jitter(A,\n               \"q\"     // arg0 = sav0 (machine)\n               \"m\"     // call micro-op\n               \"r0C\",  // PutReg(RexrReg, res0)\n               kAluFast[(Opcode(rde) & 070) >> 3][RegLog2(rde)]);\n        break;\n      default:\n        Jitter(A,\n               \"q\"     // arg0 = sav0 (machine)\n               \"c\"     // call function\n               \"r0C\",  // PutReg(RexrReg, res0)\n               op);\n        break;\n    }\n  }\n}\n\nstatic void OpAluFlipCmp(P) {\n  aluop_f op = kAlu[ALU_SUB][RegLog2(rde)];\n  u8 *q = RegLog2(rde) ? RegRexrReg(m, rde) : ByteRexrReg(m, rde);\n  op(m, ReadRegisterBW(rde, q), ReadRegisterOrMemoryBW(rde, GetModrmReadBW(A)));\n  if (IsMakingPath(m)) {\n    STATISTIC(++alu_ops);\n    LoadAluFlipArgs(A);\n    switch (GetNeededFlags(m, m->ip, CF | ZF | SF | OF | AF | PF)) {\n      case 0:\n      CASE_ALU_FAST:\n        STATISTIC(++alu_simplified);\n        Jitter(A,\n               \"q\"   // arg0 = sav0 (machine)\n               \"m\",  // call micro-op\n               kAluFast[ALU_SUB][RegLog2(rde)]);\n        break;\n      default:\n        Jitter(A,\n               \"q\"   // arg0 = sav0 (machine)\n               \"c\",  // call function\n               op);\n        break;\n    }\n  }\n}\n\nstatic void OpAluAxImm(P) {\n  aluop_f op;\n  op = kAlu[(Opcode(rde) & 070) >> 3][RegLog2(rde)];\n  WriteRegisterBW(rde, m->ax, op(m, ReadRegisterBW(rde, m->ax), uimm0));\n  if (IsMakingPath(m)) {\n    switch (GetNeededFlags(m, m->ip, CF | ZF | SF | OF | AF | PF)) {\n      case 0:\n      CASE_ALU_FAST:\n        STATISTIC(++alu_simplified);\n        Jitter(A,\n               \"G\"      // res0 = %ax\n               \"r0a1=\"  // arg1 = res0\n               \"a2i\"    //\n               \"q\"      // arg0 = machine\n               \"m\"      // call op\n               \"r0H\",   // %ax = res0\n               uimm0, kAluFast[(Opcode(rde) & 070) >> 3][RegLog2(rde)]);\n        break;\n      default:\n        Jitter(A,\n               \"G\"      // res0 = %ax\n               \"r0a1=\"  // arg1 = res0\n               \"a2i\"    //\n               \"q\"      // arg0 = machine\n               \"c\"      // call op\n               \"r0H\",   // %ax = res0\n               uimm0, op);\n        break;\n    }\n  }\n}\n\nstatic void OpRoAxImm(P, const aluop_f ops[4], const aluop_f fops[4]) {\n  ops[RegLog2(rde)](m, ReadRegisterBW(rde, m->ax), uimm0);\n  if (IsMakingPath(m)) {\n    STATISTIC(++alu_ops);\n    switch (GetNeededFlags(m, m->ip, CF | ZF | SF | OF | AF | PF)) {\n      case 0:\n      CASE_ALU_FAST:\n        STATISTIC(++alu_simplified);\n        Jitter(A,\n               \"G\"      // r0 = GetReg(AX)\n               \"a2i\"    // arg2 = uimm0\n               \"r0a1=\"  // arg1 = res0\n               \"q\"      // arg0 = sav0 (machine)\n               \"m\",     // call micro-op\n               uimm0, fops[RegLog2(rde)]);\n        break;\n      default:\n        Jitter(A,\n               \"G\"      // r0 = GetReg(AX)\n               \"a2i\"    // arg2 = uimm0\n               \"r0a1=\"  // arg1 = res0\n               \"q\"      // arg0 = sav0 (machine)\n               \"c\",     // call function\n               uimm0, ops[RegLog2(rde)]);\n        break;\n    }\n  }\n}\n\nstatic void OpCmpAxImm(P) {\n  OpRoAxImm(A, kAlu[ALU_SUB], kAluFast[ALU_SUB]);\n}\n\nstatic void OpTestAxImm(P) {\n  OpRoAxImm(A, kAlu[ALU_AND], kAluFast[ALU_AND]);\n}\n\nstatic void OpBsuwiCl(P) {\n  aluop_f op = kBsu[ModrmReg(rde)][RegLog2(rde)];\n  u8 *p = GetModrmRegisterWordPointerWriteOszRexw(A);\n  WriteRegisterOrMemory(rde, p, op(m, ReadMemory(rde, p), m->cl));\n  if (IsMakingPath(m)) {\n    switch (ModrmReg(rde)) {\n      case BSU_ROL:\n      case BSU_ROR:\n      case BSU_SHL:\n      case BSU_SHR:\n      case BSU_SAL:\n      case BSU_SAR:\n        if (!GetNeededFlags(m, m->ip, GetFlagClobbers(rde))) {\n          if (Rexw(rde)) {\n            Jitter(A,\n                   \"B\"      // res0 = GetRegOrMem(RexbRm)\n                   \"s0a1=\"  // arg1 = machine\n                   \"t\"      // arg0 = res0\n                   \"m\"      // call function\n                   \"r0D\",   // PutRegOrMem(RexbRm, res0)\n                   kJustBsuCl64[ModrmReg(rde)]);\n          } else if (!Osz(rde)) {\n            Jitter(A,\n                   \"B\"      // res0 = GetRegOrMem(RexbRm)\n                   \"s0a1=\"  // arg1 = machine\n                   \"t\"      // arg0 = res0\n                   \"m\"      // call function\n                   \"r0D\",   // PutRegOrMem(RexbRm, res0)\n                   kJustBsuCl32[ModrmReg(rde)]);\n          }\n        }\n        break;\n      default:\n        break;\n    }\n  }\n}\n\nstatic void BsuwiConstant(P, u64 y) {\n  aluop_f op = kBsu[ModrmReg(rde)][RegLog2(rde)];\n  u8 *p = GetModrmRegisterWordPointerWriteOszRexw(A);\n  WriteRegisterOrMemory(rde, p, op(m, ReadMemory(rde, p), y));\n  if (IsMakingPath(m)) {\n    switch (ModrmReg(rde)) {\n      case BSU_ROL:\n      case BSU_ROR:\n      case BSU_SHL:\n      case BSU_SHR:\n      case BSU_SAL:\n      case BSU_SAR:\n        STATISTIC(++alu_ops);\n        if (!GetNeededFlags(m, m->ip, GetFlagClobbers(rde))) {\n          if (Rexw(rde) && (y &= 63)) {\n            STATISTIC(++alu_unflagged);\n            Jitter(A,\n                   \"B\"     // res0 = GetRegOrMem(RexbRm)\n                   \"a3i\"   // arg3 = shift amount\n                   \"\"      // arg2 = undefined\n                   \"\"      // arg1 = undefined\n                   \"t\"     // arg0 = res0\n                   \"m\"     // call micro-op\n                   \"r0D\",  // PutRegOrMem(RexbRm, res0)\n                   y, kJustBsu[ModrmReg(rde)]);\n            return;\n          } else if (!Osz(rde) && (y &= 31)) {\n            STATISTIC(++alu_unflagged);\n            Jitter(A,\n                   \"B\"     // res0 = GetRegOrMem(RexbRm)\n                   \"a3i\"   // arg3 = shift amount\n                   \"\"      // arg2 = undefined\n                   \"\"      // arg1 = undefined\n                   \"t\"     // arg0 = res0\n                   \"m\"     // call micro-op\n                   \"r0D\",  // PutRegOrMem(RexbRm, res0)\n                   y, kJustBsu32[ModrmReg(rde)]);\n            return;\n          }\n        }\n        break;\n      default:\n        break;\n    }\n    Jitter(A,\n           \"B\"      // res0 = GetRegOrMem(RexbRm)\n           \"a2i\"    // arg2 = shift amount\n           \"r0a1=\"  // arg1 = res0\n           \"q\"      // arg0 = sav0 (machine)\n           \"c\"      // call function\n           \"r0D\",   // PutRegOrMem(RexbRm, res0)\n           y, op);\n  }\n}\n\nstatic void OpBsuwi1(P) {\n  BsuwiConstant(A, 1);\n}\n\nstatic void OpBsuwiImm(P) {\n  BsuwiConstant(A, uimm0);\n}\n\nstatic aluop_f Bsubi(P, u64 y) {\n  aluop_f op = kBsu[ModrmReg(rde)][RegLog2(rde)];\n  u8 *a = GetModrmRegisterBytePointerWrite1(A);\n  Store8(a, op(m, Load8(a), y));\n  return op;\n}\n\nstatic void OpBsubiCl(P) {\n  aluop_f op;\n  op = Bsubi(A, m->cl);\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"B\"      // res0 = GetRegOrMem(RexbRm)\n           \"r0s1=\"  // sav1 = res0\n           \"%cl\"    //\n           \"r0a2=\"  // arg2 = res0\n           \"s1a1=\"  // arg1 = sav1\n           \"q\"      // arg0 = sav0 (machine)\n           \"c\"      // call function\n           \"r0D\",\n           op);\n  }\n}\n\nstatic void BsubiConstant(P, u64 y) {\n  aluop_f op;\n  op = Bsubi(A, y);\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"B\"      // res0 = GetRegOrMem(RexbRm)\n           \"r0a1=\"  // arg1 = res0\n           \"q\"      // arg0 = sav0 (machine)\n           \"a2i\"    //\n           \"c\"      // call function\n           \"r0D\",   //\n           y, op);\n  }\n}\n\nstatic void OpBsubi1(P) {\n  BsubiConstant(A, 1);\n}\n\nstatic void OpBsubiImm(P) {\n  BsubiConstant(A, uimm0);\n}\n\nstatic void OpPushImm(P) {\n  Push(A, uimm0);\n}\n\nstatic void GenInterrupt(P, u8 trapno) {\n#ifdef DISABLE_METAL\n  HaltMachine(m, trapno);\n#else\n  u16 offset;\n  struct System *s;\n  switch (m->mode.genmode) {\n    default:\n      HaltMachine(m, trapno);\n      break;\n    case XED_GEN_MODE_REAL:\n      offset = (u16)trapno * 4;\n      s = m->system;\n      if (offset + 3 > s->idt_limit) {\n        ThrowProtectionFault(m);\n      } else if (!Osz(rde) || Asz(rde)) {\n        OpUdImpl(m);\n      } else {\n        u8 *pfp = ReserveAddress(m, s->idt_base + offset, 4, false), *pisr;\n        u32 fp, isrinsn;\n        u16 isrseg, isroff;\n        bool optim = false;\n        fp = Load32(pfp);\n        isrseg = (u16)(fp >> 16);\n        isroff = (u16)fp;\n        Push(A, ExportFlags(m->flags));\n        Push(A, m->cs.sel);\n        Push(A, m->ip);\n        // optimize for cases where ISR is simply a `hvtailcall` & a few\n        // other conditions are met; this bypasses the usual instruction\n        // decoding so it should be done with care to preserve semantics\n        if (trapno < 0x80 && isrseg == kBiosSeg) {\n          pisr = s->real + kBiosBase + isroff;\n          if (Read8(pisr) == 0x0F) {\n            isrinsn = Load32(pisr);\n            if (isrinsn == ((u32)0x0F | (u32)0xFF << 8 | (u32)0167 << 16 |\n                            (u32)trapno << 24)) {\n              optim = true;\n            }\n          }\n        }\n        if (optim) {\n          u64 sp = Get16(m->sp);\n          Put16(m->sp, sp + 6);\n          HaltMachine(m, trapno);\n        } else {\n          m->flags = SetFlag(m->flags, FLAGS_IF, false);\n          m->flags = SetFlag(m->flags, FLAGS_TF, false);\n          m->flags = SetFlag(m->flags, FLAGS_AC, false);\n          LongBranch(A, isrseg, isroff);\n        }\n      }\n  }\n#endif\n}\n\nstatic void OpInterruptImm(P) {\n  GenInterrupt(A, uimm0);\n}\n\nstatic void OpInterrupt1(P) {\n  GenInterrupt(A, 1);\n}\n\nstatic void OpInterrupt3(P) {\n  GenInterrupt(A, 3);\n}\n\n#ifndef DISABLE_METAL\nstatic void OpInto(P) {\n  if (Mode(rde) != XED_MODE_LONG) {\n    if (GetFlag(m->flags, FLAGS_OF)) HaltMachine(m, 4);\n  } else {\n    OpUdImpl(m);\n  }\n}\n\nstatic void OpIret(P) {\n  if (m->mode.genmode == XED_GEN_MODE_REAL) {\n    OpRetf(A);\n    if (!Osz(rde)) {\n      // Intel V2A § 3.2 says that iretl should only update some parts of\n      // eflags, not all; more precisely:\n      //   \"tempEFLAGS ← Pop();\n      //    EFLAGS ← (tempEFLAGS AND 257FD5H) OR (EFLAGS AND 1A0000H);\"\n      // it should be OK though to update all the bits in eflags's lower half\n      u32 mask = ID | AC | RF | 0xffff;\n      ImportFlags(m, (m->flags & ~mask) | (Pop(A, 0) & mask));\n    } else {\n      ImportFlags(m, (m->flags & ~0xffff) | Pop(A, 0));\n    }\n  } else {\n    OpUdImpl(m);\n  }\n}\n#endif\n\nvoid Terminate(P, void uop(struct Machine *, u64)) {\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"a1i\"  // arg1 = disp\n           \"m\"    // call micro-op\n           \"q\",   // arg0 = sav0 (machine)\n           disp, uop);\n    AlignJit(m->path.jb, 8, 0);\n    Connect(A, m->ip, true);\n    FinishPath(m);\n  }\n}\n\nstatic void OpJmp(P) {\n  m->ip += disp;\n  Terminate(A, FastJmp);\n}\n\nstatic cc_f GetCc(P) {\n  int code;\n  code = Opcode(rde) & 15;\n  unassert(code != 0xA);  // JP\n  unassert(code != 0xB);  // JNP\n  return kConditionCode[code];\n}\n\nstatic void OpJcc(P) {\n  cc_f cc;\n  cc = GetCc(A);\n  if (IsMakingPath(m)) {\n    FlushSkew(A);\n#ifdef __x86_64__\n    Jitter(A, \"mq\", cc);\n    AlignJit(m->path.jb, 8, 4);\n    u8 code[] = {\n        0x85, 0300 | kJitRes0 << 3 | kJitRes0,  // test %eax,%eax\n        0x75, 5,                                // jnz  +5\n    };\n#else\n    Jitter(A,\n           \"m\"      // res0 = condition code\n           \"r0a2=\"  // arg2 = res0\n           \"q\",     // arg0 = machine\n           cc);\n    u32 code[] = {\n        0xb5000000 | (8 / 4) << 5 | kJitArg2,  // cbnz x2,#8\n    };\n#endif\n    AppendJit(m->path.jb, code, sizeof(code));\n    Connect(A, m->ip, true);\n    Jitter(A,\n           \"a1i\"  // arg1 = disp\n           \"m\"    // call micro-op\n           \"q\",   // arg0 = machine\n           disp, FastJmp);\n    AlignJit(m->path.jb, 8, 0);\n    Connect(A, m->ip + disp, false);\n    FinishPath(m);\n  }\n  if (cc(m)) {\n    m->ip += disp;\n  }\n}\n\nstatic void OpJp(P) {\n  if (IsParity(m)) {\n    m->ip += disp;\n  }\n}\n\nstatic void OpJnp(P) {\n  if (!IsParity(m)) {\n    m->ip += disp;\n  }\n}\n\nstatic void SetEb(P, bool x) {\n  Store8(GetModrmRegisterBytePointerWrite1(A), x);\n}\n\nstatic void OpSetcc(P) {\n  cc_f cc;\n  cc = GetCc(A);\n  SetEb(A, cc(m));\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"m\"       // call micro-op\n           \"r0z0D\",  // PutRegOrMem[force8](RexbRm, res0)\n           cc);\n  }\n}\n\nstatic void OpSetp(P) {\n  SetEb(A, IsParity(m));\n}\n\nstatic void OpSetnp(P) {\n  SetEb(A, !IsParity(m));\n}\n\nstatic void OpCmovImpl(P, bool cond) {\n  u64 x;\n  if (cond) {\n    x = ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(A));\n  } else {\n    x = Get64(RegRexrReg(m, rde));\n  }\n  WriteRegister(rde, RegRexrReg(m, rde), x);\n}\n\nstatic void OpCmov(P) {\n  cc_f cc;\n  cc = GetCc(A);\n  OpCmovImpl(A, cc(m));\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"wB\"     // res0 = GetRegOrMem[force16+bit](RexbRm)\n           \"r0s1=\"  // sav1 = res0\n           \"wA\"     // res0 = GetReg[force16+bit](RexrReg)\n           \"r0s2=\"  // sav2 = res0\n           \"q\"      // arg0 = sav0 (machine)\n           \"m\"      // call micro-op (cc)\n           \"s2a2=\"  // arg2 = sav2\n           \"s1a1=\"  // arg1 = sav1\n           \"t\"      // arg0 = res0\n           \"m\"      // call micro-op (Pick)\n           \"r0wC\",  // PutReg[force16+bit](RexrReg, res0)\n           cc, Pick);\n  }\n}\n\nstatic void OpCmovp(P) {\n  OpCmovImpl(A, IsParity(m));\n}\n\nstatic void OpCmovnp(P) {\n  OpCmovImpl(A, !IsParity(m));\n}\n\nstatic void OpJcxz(P) {\n  if (!MaskAddress(Eamode(rde), Get64(m->cx))) {\n    m->ip += disp;\n  }\n}\n\nstatic u64 AluPopcnt(u64 x, struct Machine *m) {\n  m->flags = SetFlag(m->flags, FLAGS_ZF, !x);\n  m->flags = SetFlag(m->flags, FLAGS_CF, false);\n  m->flags = SetFlag(m->flags, FLAGS_SF, false);\n  m->flags = SetFlag(m->flags, FLAGS_OF, false);\n  m->flags = SetFlag(m->flags, FLAGS_PF, false);\n  return popcount(x);\n}\n\nstatic u64 AluLzcnt(u64 x, struct Machine *m, int bits) {\n  u64 r = x ? bsf(x) : bits;\n  m->flags = SetFlag(m->flags, FLAGS_CF, !x);\n  m->flags = SetFlag(m->flags, FLAGS_ZF, !r);\n  return r;\n}\nstatic u64 AluLzcnt64(u64 x, struct Machine *m) {\n  return AluLzcnt(x, m, 64);\n}\nstatic u64 AluLzcnt32(u64 x, struct Machine *m) {\n  return AluLzcnt(x, m, 32);\n}\nstatic u64 AluLzcnt16(u64 x, struct Machine *m) {\n  return AluLzcnt(x, m, 16);\n}\nstatic u64 AluBsf(u64 x, struct Machine *m) {\n  m->flags = SetFlag(m->flags, FLAGS_ZF, !x);\n  return x ? bsf(x) : 0;\n}\n\nstatic u64 AluTzcnt(u64 x, struct Machine *m, int bits) {\n  u64 r = x ? bsr(x) : bits;\n  m->flags = SetFlag(m->flags, FLAGS_CF, !x);\n  m->flags = SetFlag(m->flags, FLAGS_ZF, !r);\n  return r;\n}\nstatic u64 AluTzcnt64(u64 x, struct Machine *m) {\n  return AluTzcnt(x, m, 64);\n}\nstatic u64 AluTzcnt32(u64 x, struct Machine *m) {\n  return AluTzcnt(x, m, 32);\n}\nstatic u64 AluTzcnt16(u64 x, struct Machine *m) {\n  return AluTzcnt(x, m, 16);\n}\nstatic u64 AluBsr(u64 x, struct Machine *m) {\n  m->flags = SetFlag(m->flags, FLAGS_ZF, !x);\n  return x ? bsr(x) : 0;\n}\n\nstatic void Bitscan(P, u64 op(u64, struct Machine *)) {\n  WriteRegister(\n      rde, RegRexrReg(m, rde),\n      op(ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(A)), m));\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"wB\"     // res0 = GetRegOrMem[force16+bit](RexbRm)\n           \"s0a1=\"  // arg1 = sav0\n           \"t\"      // arg0 = res0\n           \"c\"      // call function (op)\n           \"r0wC\",  // PutReg[force16+bit](RexrReg, res0)\n           op);\n  }\n}\n\nstatic void OpBsf(P) {\n  u64 (*op)(u64, struct Machine *);\n  if (Rep(rde) == 3) {\n    if (Rexw(rde)) {\n      op = AluLzcnt64;\n    } else if (!Osz(rde)) {\n      op = AluLzcnt32;\n    } else {\n      op = AluLzcnt16;\n    }\n  } else {\n    op = AluBsf;\n  }\n  Bitscan(A, op);\n}\n\nstatic void OpBsr(P) {\n  u64 (*op)(u64, struct Machine *);\n  if (Rep(rde) == 3) {\n    if (Rexw(rde)) {\n      op = AluTzcnt64;\n    } else if (!Osz(rde)) {\n      op = AluTzcnt32;\n    } else {\n      op = AluTzcnt16;\n    }\n  } else {\n    op = AluBsr;\n  }\n  Bitscan(A, op);\n}\n\nstatic void Op1b8(P) {\n  if (Rep(rde) == 3) {\n    Bitscan(A, AluPopcnt);\n  } else {\n    OpUdImpl(m);\n  }\n}\n\nstatic relegated void Loop(P, bool cond) {\n  u64 cx;\n  cx = Get64(m->cx) - 1;\n  if (Eamode(rde) != XED_MODE_REAL) {\n    if (Eamode(rde) == XED_MODE_LEGACY) {\n      cx &= 0xffffffff;\n    }\n    Put64(m->cx, cx);\n  } else {\n    cx &= 0xffff;\n    Put16(m->cx, cx);\n  }\n  if (cx && cond) {\n    m->ip += disp;\n  }\n}\n\nstatic relegated void OpLoope(P) {\n  Loop(A, GetFlag(m->flags, FLAGS_ZF));\n}\n\nstatic relegated void OpLoopne(P) {\n  Loop(A, !GetFlag(m->flags, FLAGS_ZF));\n}\n\nstatic relegated void OpLoop1(P) {\n  Loop(A, true);\n}\n\nstatic const nexgen32e_f kOp0f6[] = {\n    OpTest,\n    OpTest,\n    OpNotEb,\n    OpNegEb,\n    OpMulAxAlEbUnsigned,\n    OpMulAxAlEbSigned,\n    OpDivAlAhAxEbUnsigned,\n    OpDivAlAhAxEbSigned,\n};\n\nstatic void Op0f6(P) {\n  kOp0f6[ModrmReg(rde)](A);\n}\n\nstatic const nexgen32e_f kOp0f7[] = {\n    OpTest,\n    OpTest,\n    OpNotEvqp,\n    OpNegEvqp,\n    OpMulRdxRaxEvqpUnsigned,\n    OpMulRdxRaxEvqpSigned,\n    OpDivRdxRaxEvqpUnsigned,\n    OpDivRdxRaxEvqpSigned,\n};\n\nstatic void Op0f7(P) {\n  kOp0f7[ModrmReg(rde)](A);\n}\n\n#ifdef DISABLE_METAL\n#define OpCallfEq OpUd\n#define OpJmpfEq  OpUd\n#endif\n\nstatic const nexgen32e_f kOp0ff[] = {\n    OpIncEvqp,  //\n    OpDecEvqp,  //\n    OpCallEq,   //\n    OpCallfEq,  //\n    OpJmpEq,    //\n    OpJmpfEq,   //\n    OpPushEvq,  //\n    OpUd,       //\n};\n\nstatic void Op0ff(P) {\n  kOp0ff[ModrmReg(rde)](A);\n}\n\nstatic void OpDoubleShift(P) {\n  u8 *p;\n  u8 W[2][2] = {{2, 3}, {1, 3}};\n  p = GetModrmRegisterWordPointerWriteOszRexw(A);\n  WriteRegisterOrMemory(\n      rde, p,\n      BsuDoubleShift(m, W[Osz(rde)][Rexw(rde)], ReadMemory(rde, p),\n                     ReadRegister(rde, RegRexrReg(m, rde)),\n                     Opcode(rde) & 1 ? m->cl : uimm0, Opcode(rde) & 8));\n}\n\nstatic void OpFxsave(P) {\n  i64 v;\n  u8 buf[32];\n  memset(buf, 0, 32);\n  Write16(buf + 0, m->fpu.cw);\n#ifndef DISABLE_X87\n  Write16(buf + 2, m->fpu.sw);\n  Write8(buf + 4, m->fpu.tw);\n  Write16(buf + 6, m->fpu.op);\n  Write32(buf + 8, m->fpu.ip);\n#endif\n  Write32(buf + 24, m->mxcsr);\n  v = ComputeAddress(A);\n  CopyToUser(m, v + 0, buf, 32);\n#ifndef DISABLE_X87\n  CopyToUser(m, v + 32, m->fpu.st, 128);\n#endif\n  CopyToUser(m, v + 160, m->xmm, 256);\n  SetWriteAddr(m, v, 416);\n}\n\nstatic void OpFxrstor(P) {\n  i64 v;\n  u8 buf[32];\n  v = ComputeAddress(A);\n  SetReadAddr(m, v, 416);\n  CopyFromUser(m, buf, v + 0, 32);\n#ifndef DISABLE_X87\n  CopyFromUser(m, m->fpu.st, v + 32, 128);\n#endif\n  CopyFromUser(m, m->xmm, v + 160, 256);\n  m->fpu.cw = Load16(buf + 0);\n#ifndef DISABLE_X87\n  m->fpu.sw = Load16(buf + 2);\n  m->fpu.tw = Load8(buf + 4);\n  m->fpu.op = Load16(buf + 6);\n  m->fpu.ip = Load32(buf + 8);\n#endif\n  m->mxcsr = Load32(buf + 24);\n}\n\nstatic void OpXsave(P) {\n}\n\nstatic void OpLdmxcsr(P) {\n  m->mxcsr = Load32(ComputeReserveAddressRead4(A));\n}\n\nstatic void OpStmxcsr(P) {\n  Store32(ComputeReserveAddressWrite4(A), m->mxcsr);\n}\n\nstatic void OpRdfsbase(P) {\n  WriteRegister(rde, RegRexbRm(m, rde), m->fs.base);\n}\n\nstatic void OpRdgsbase(P) {\n  WriteRegister(rde, RegRexbRm(m, rde), m->gs.base);\n}\n\nstatic void OpWrfsbase(P) {\n  m->fs.base = ReadRegister(rde, RegRexbRm(m, rde));\n}\n\nstatic void OpWrgsbase(P) {\n  m->gs.base = ReadRegister(rde, RegRexbRm(m, rde));\n}\n\nstatic void OpMfence(P) {\n  atomic_thread_fence(memory_order_seq_cst);\n}\n\nstatic void OpLfence(P) {\n  OpMfence(A);\n}\n\nstatic void OpSfence(P) {\n  OpMfence(A);\n}\n\nstatic void OpWbinvd(P) {\n  OpMfence(A);\n}\n\nstatic void OpClflush(P) {\n  OpMfence(A);\n}\n\nstatic void Op1ae(P) {\n  bool ismem;\n  ismem = !IsModrmRegister(rde);\n  switch (ModrmReg(rde)) {\n    case 0:\n      if (ismem) {\n        OpFxsave(A);\n      } else {\n        OpRdfsbase(A);\n      }\n      break;\n    case 1:\n      if (ismem) {\n        OpFxrstor(A);\n      } else {\n        OpRdgsbase(A);\n      }\n      break;\n    case 2:\n      if (ismem) {\n        OpLdmxcsr(A);\n      } else {\n        OpWrfsbase(A);\n      }\n      break;\n    case 3:\n      if (ismem) {\n        OpStmxcsr(A);\n      } else {\n        OpWrgsbase(A);\n      }\n      break;\n    case 4:\n      if (ismem) {\n        OpXsave(A);\n      } else {\n        OpUdImpl(m);\n      }\n      break;\n    case 5:\n      OpLfence(A);\n      break;\n    case 6:\n      OpMfence(A);\n      break;\n    case 7:\n      if (ismem) {\n        OpClflush(A);\n      } else {\n        OpSfence(A);\n      }\n      break;\n    default:\n      OpUdImpl(m);\n  }\n}\n\nstatic relegated void OpSalc(P) {\n  if (GetFlag(m->flags, FLAGS_CF)) {\n    m->al = 255;\n  } else {\n    m->al = 0;\n  }\n}\n\nstatic relegated void OpBofram(P) {\n  if (disp) {\n    m->bofram[0] = m->ip;\n    m->bofram[1] = m->ip + (disp & 0xff);\n  } else {\n    m->bofram[0] = 0;\n    m->bofram[1] = 0;\n  }\n}\n\nstatic relegated void OpBinbase(P) {\n  if (m->system->onbinbase) {\n    m->system->onbinbase(m);\n  }\n}\n\nstatic void OpNoop(P) {\n  if (IsMakingPath(m)) {\n    AppendJitNop(m->path.jb);\n  }\n}\n\nstatic void OpNopEv(P) {\n  switch (ModrmMod(rde) << 6 | ModrmReg(rde) << 3 | ModrmRm(rde)) {\n    case 0105:\n      OpBofram(A);\n      break;\n    case 0007:\n    case 0107:\n    case 0207:\n      OpBinbase(A);\n      break;\n    default:\n      OpNoop(A);\n  }\n}\n\n#ifndef DISABLE_METAL\nstatic void OpHvcall(P) {\n  HaltMachine(m, disp);\n}\n\nstatic void OpHvtailcall(P) {\n  OpIret(A);\n  HaltMachine(m, disp);\n}\n\nstatic void OpUd0GvqpEvqp(P) {\n  if (Cpl(m) == 3) {\n    OpUd(A);\n  } else {\n    // define `hvcall` & `hvtailcall` instructions which trap to our Blink\n    // hypervisor; these are encoded as x86 \"invalid opcodes\" in 16-bit mode:\n    // - 0f ff 3f         hvcall 0          ud0 (%bx), %di\n    // - 0f ff 7f disp8   hvcall ±disp      ud0 ±disp(%bx), %di\n    // - 0f ff bf disp16  hvcall ±disp      ud0 ±disp(%bx), %di\n    // - 0f ff 37         hvtailcall 0      ud0 (%bx), %si\n    // - 0f ff 77 disp8   hvtailcall ±disp  ud0 ±disp(%bx), %si\n    // - 0f ff b7 disp16  hvtailcall ±disp  ud0 ±disp(%bx), %si\n    //\n    // `hvcall` invokes a \"hypervisor trap\" with the trap number given by\n    // the displacement value\n    //\n    // `hvtailcall`, when run from within an interrupt service routine, will\n    // return (`iret`) to the ISR's caller & then invoke the numbered trap\n    switch (Rep(rde) << 9 | ModrmMod(rde) << 6 | ModrmReg(rde) << 3 |\n            ModrmRm(rde)) {\n      case 00067:\n      case 00167:\n      case 00267:\n        OpHvtailcall(A);\n        break;\n      case 00077:\n      case 00177:\n      case 00277:\n        OpHvcall(A);\n        break;\n      default:\n        OpUd(A);\n    }\n  }\n}\n#endif\n\nstatic void OpNop(P) {\n  if (Rexb(rde)) {\n    OpXchgZvqp(A);\n  } else if (Rep(rde) == 3) {\n    OpPause(A);\n  } else {\n    OpNoop(A);\n  }\n}\n\nstatic void OpEmms(P) {\n#ifndef DISABLE_X87\n  m->fpu.tw = -1;\n#endif\n}\n\n#ifdef DISABLE_METAL\n#define OpCallf       OpUd\n#define OpDecZv       OpUd\n#define OpInAlDx      OpUd\n#define OpInAlImm     OpUd\n#define OpInAxDx      OpUd\n#define OpInAxImm     OpUd\n#define OpIncZv       OpUd\n#define OpJmpf        OpUd\n#define OpLds         OpUd\n#define OpLes         OpUd\n#define OpLfs         OpUd\n#define OpLgs         OpUd\n#define OpLss         OpUd\n#define OpMovCqRq     OpUd\n#define OpMovEvqpSw   OpUd\n#define OpMovRqCq     OpUd\n#define OpMovSwEvqp   OpUd\n#define OpOutDxAl     OpUd\n#define OpOutDxAx     OpUd\n#define OpOutImmAl    OpUd\n#define OpOutImmAx    OpUd\n#define OpPopSeg      OpUd\n#define OpPopa        OpUd\n#define OpPushSeg     OpUd\n#define OpPusha       OpUd\n#define OpClts        OpUd\n#define OpRdmsr       OpUd\n#define OpRetf        OpUd\n#define OpInto        OpUd\n#define OpIret        OpUd\n#define OpWrmsr       OpUd\n#define OpUd0GvqpEvqp OpUd\n#endif\n\n#ifdef DISABLE_X87\n#define OpFwait OpUd\n#endif\n\n#ifdef DISABLE_BMI2\n#define Op2f5  OpUd\n#define Op2f6  OpUd\n#define OpShx  OpUd\n#define OpRorx OpUd\n#endif\n\n#ifdef DISABLE_BCD\n#define OpDas OpUd\n#define OpAaa OpUd\n#define OpAas OpUd\n#define OpAam OpUd\n#define OpAad OpUd\n#define OpDaa OpUd\n#endif\n\nstatic const nexgen32e_f kNexgen32e[] = {\n    /*000*/ OpAlub,                  //\n    /*001*/ OpAluw,                  // #8    (5.653689%)\n    /*002*/ OpAluFlip,               // #180  (0.000087%)\n    /*003*/ OpAluFlip,               // #7    (5.840835%)\n    /*004*/ OpAluAxImm,              //\n    /*005*/ OpAluAxImm,              // #166  (0.000114%)\n    /*006*/ OpPushSeg,               //\n    /*007*/ OpPopSeg,                //\n    /*008*/ OpAlub,                  // #154  (0.000207%)\n    /*009*/ OpAluw,                  // #21   (0.520082%)\n    /*00A*/ OpAluFlip,               // #120  (0.001072%)\n    /*00B*/ OpAluFlip,               // #114  (0.001252%)\n    /*00C*/ OpAluAxImm,              //\n    /*00D*/ OpAluAxImm,              // #282  (0.000001%)\n    /*00E*/ OpPushSeg,               //\n    /*00F*/ OpPopSeg,                //\n    /*010*/ OpAlub,                  //\n    /*011*/ OpAluw,                  // #11   (5.307809%)\n    /*012*/ OpAluFlip,               //\n    /*013*/ OpAluFlip,               // #108  (0.001526%)\n    /*014*/ OpAluAxImm,              // #97   (0.002566%)\n    /*015*/ OpAluAxImm,              //\n    /*016*/ OpPushSeg,               //\n    /*017*/ OpPopSeg,                //\n    /*018*/ OpAlub,                  //\n    /*019*/ OpAluw,                  // #65   (0.015300%)\n    /*01A*/ OpAluFlip,               //\n    /*01B*/ OpAluFlip,               // #44   (0.241806%)\n    /*01C*/ OpAluAxImm,              // #96   (0.002566%)\n    /*01D*/ OpAluAxImm,              //\n    /*01E*/ OpPushSeg,               //\n    /*01F*/ OpPopSeg,                //\n    /*020*/ OpAlub,                  // #165  (0.000130%)\n    /*021*/ OpAluw,                  // #59   (0.019691%)\n    /*022*/ OpAluFlip,               //\n    /*023*/ OpAluFlip,               // #41   (0.279852%)\n    /*024*/ OpAluAxImm,              // #279  (0.000001%)\n    /*025*/ OpAluAxImm,              // #43   (0.275823%)\n    /*026*/ OpUd,                    //\n    /*027*/ OpDaa,                   //\n    /*028*/ OpAlub,                  //\n    /*029*/ OpAluw,                  // #29   (0.334693%)\n    /*02A*/ OpAluFlip,               // #179  (0.000087%)\n    /*02B*/ OpAluFlip,               // #71   (0.012465%)\n    /*02C*/ OpAluAxImm,              //\n    /*02D*/ OpAluAxImm,              // #112  (0.001317%)\n    /*02E*/ OpUd,                    //\n    /*02F*/ OpDas,                   //\n    /*030*/ OpAlub,                  // #140  (0.000397%)\n    /*031*/ OpAluw,                  // #3    (6.612252%)\n    /*032*/ OpAluFlip,               // #81   (0.007453%)\n    /*033*/ OpAluFlip,               // #47   (0.138021%)\n    /*034*/ OpAluAxImm,              //\n    /*035*/ OpAluAxImm,              // #295  (0.000000%)\n    /*036*/ OpUd,                    //\n    /*037*/ OpAaa,                   //\n    /*038*/ OpAluCmp,                // #98   (0.002454%)\n    /*039*/ OpAluCmp,                // #2    (6.687374%)\n    /*03A*/ OpAluFlipCmp,            // #103  (0.001846%)\n    /*03B*/ OpAluFlipCmp,            // #75   (0.010320%)\n    /*03C*/ OpCmpAxImm,              // #85   (0.006267%)\n    /*03D*/ OpCmpAxImm,              // #42   (0.279462%)\n    /*03E*/ OpUd,                    //\n    /*03F*/ OpAas,                   //\n    /*040*/ OpIncZv,                 //\n    /*041*/ OpIncZv,                 //\n    /*042*/ OpIncZv,                 //\n    /*043*/ OpIncZv,                 //\n    /*044*/ OpIncZv,                 //\n    /*045*/ OpIncZv,                 //\n    /*046*/ OpIncZv,                 //\n    /*047*/ OpIncZv,                 //\n    /*048*/ OpDecZv,                 //\n    /*049*/ OpDecZv,                 //\n    /*04A*/ OpDecZv,                 //\n    /*04B*/ OpDecZv,                 //\n    /*04C*/ OpDecZv,                 //\n    /*04D*/ OpDecZv,                 //\n    /*04E*/ OpDecZv,                 //\n    /*04F*/ OpDecZv,                 //\n    /*050*/ OpPushZvq,               // #82   (0.007191%)\n    /*051*/ OpPushZvq,               // #91   (0.003740%)\n    /*052*/ OpPushZvq,               // #138  (0.000405%)\n    /*053*/ OpPushZvq,               // #27   (0.343891%)\n    /*054*/ OpPushZvq,               // #30   (0.332411%)\n    /*055*/ OpPushZvq,               // #16   (0.661109%)\n    /*056*/ OpPushZvq,               // #35   (0.297138%)\n    /*057*/ OpPushZvq,               // #38   (0.289927%)\n    /*058*/ OpPopZvq,                // #155  (0.000199%)\n    /*059*/ OpPopZvq,                // #190  (0.000054%)\n    /*05A*/ OpPopZvq,                // #74   (0.011075%)\n    /*05B*/ OpPopZvq,                // #28   (0.343770%)\n    /*05C*/ OpPopZvq,                // #31   (0.332403%)\n    /*05D*/ OpPopZvq,                // #17   (0.659868%)\n    /*05E*/ OpPopZvq,                // #36   (0.296997%)\n    /*05F*/ OpPopZvq,                // #39   (0.289680%)\n    /*060*/ OpPusha,                 //\n    /*061*/ OpPopa,                  //\n    /*062*/ OpUd,                    //\n    /*063*/ OpMovslGdqpEd,           // #58   (0.026117%)\n    /*064*/ OpUd,                    //\n    /*065*/ OpUd,                    //\n    /*066*/ OpUd,                    //\n    /*067*/ OpUd,                    //\n    /*068*/ OpPushImm,               // #168  (0.000112%)\n    /*069*/ OpImulGvqpEvqpImm,       // #147  (0.000253%)\n    /*06A*/ OpPushImm,               // #143  (0.000370%)\n    /*06B*/ OpImulGvqpEvqpImm,       // #131  (0.000720%)\n    /*06C*/ OpIns,                   //\n    /*06D*/ OpIns,                   //\n    /*06E*/ OpOuts,                  //\n    /*06F*/ OpOuts,                  //\n    /*070*/ OpJcc,                   // #177  (0.000094%)\n    /*071*/ OpJcc,                   // #200  (0.000034%)\n    /*072*/ OpJcc,                   // #64   (0.015441%)\n    /*073*/ OpJcc,                   // #9    (5.615257%)\n    /*074*/ OpJcc,                   // #15   (0.713108%)\n    /*075*/ OpJcc,                   // #13   (0.825247%)\n    /*076*/ OpJcc,                   // #23   (0.475584%)\n    /*077*/ OpJcc,                   // #48   (0.054677%)\n    /*078*/ OpJcc,                   // #66   (0.014096%)\n    /*079*/ OpJcc,                   // #84   (0.006506%)\n    /*07A*/ OpJp,                    // #175  (0.000112%)\n    /*07B*/ OpJnp,                   // #174  (0.000112%)\n    /*07C*/ OpJcc,                   // #223  (0.000008%)\n    /*07D*/ OpJcc,                   // #80   (0.007801%)\n    /*07E*/ OpJcc,                   // #70   (0.012536%)\n    /*07F*/ OpJcc,                   // #76   (0.010144%)\n    /*080*/ OpAlui,                  // #53   (0.033021%)\n    /*081*/ OpAlui,                  // #60   (0.018910%)\n    /*082*/ OpAlui,                  //\n    /*083*/ OpAlui,                  // #4    (6.518845%)\n    /*084*/ OpAluTest,               // #54   (0.030642%)\n    /*085*/ OpAluTest,               // #18   (0.628547%)\n    /*086*/ OpXchgGbEb,              // #219  (0.000011%)\n    /*087*/ OpXchgGvqpEvqp,          // #161  (0.000141%)\n    /*088*/ OpMovEbGb,               // #49   (0.042510%)\n    /*089*/ OpMovEvqpGvqp,           // #1    (22.226650%)\n    /*08A*/ OpMovGbEb,               // #51   (0.038177%)\n    /*08B*/ OpMovGvqpEvqp,           // #12   (2.903141%)\n    /*08C*/ OpMovEvqpSw,             //\n    /*08D*/ OpLeaGvqpM,              // #14   (0.800508%)\n    /*08E*/ OpMovSwEvqp,             //\n    /*08F*/ OpPopEvq,                // #288  (0.000000%)\n    /*090*/ OpNop,                   // #218  (0.000011%)\n    /*091*/ OpXchgZvqp,              // #278  (0.000001%)\n    /*092*/ OpXchgZvqp,              // #284  (0.000001%)\n    /*093*/ OpXchgZvqp,              // #213  (0.000018%)\n    /*094*/ OpXchgZvqp,              //\n    /*095*/ OpXchgZvqp,              //\n    /*096*/ OpXchgZvqp,              //\n    /*097*/ OpXchgZvqp,              // #286  (0.000001%)\n    /*098*/ OpSax,                   // #83   (0.006728%)\n    /*099*/ OpConvert,               // #163  (0.000137%)\n    /*09A*/ OpCallf,                 //\n    /*09B*/ OpFwait,                 //\n    /*09C*/ OpPushf,                 //\n    /*09D*/ OpPopf,                  //\n    /*09E*/ OpSahf,                  //\n    /*09F*/ OpLahf,                  //\n    /*0A0*/ OpMovAlOb,               //\n    /*0A1*/ OpMovRaxOvqp,            //\n    /*0A2*/ OpMovObAl,               //\n    /*0A3*/ OpMovOvqpRax,            //\n    /*0A4*/ OpMovsb,                 // #73   (0.011594%)\n    /*0A5*/ OpMovs,                  // #158  (0.000147%)\n    /*0A6*/ OpCmps,                  //\n    /*0A7*/ OpCmps,                  //\n    /*0A8*/ OpTestAxImm,             // #115  (0.001247%)\n    /*0A9*/ OpTestAxImm,             // #113  (0.001300%)\n    /*0AA*/ OpStosb,                 // #67   (0.013327%)\n    /*0AB*/ OpStos,                  // #194  (0.000044%)\n    /*0AC*/ OpLods,                  // #198  (0.000035%)\n    /*0AD*/ OpLods,                  // #296  (0.000000%)\n    /*0AE*/ OpScas,                  // #157  (0.000152%)\n    /*0AF*/ OpScas,                  // #292  (0.000000%)\n    /*0B0*/ OpMovZbIb,               // #135  (0.000500%)\n    /*0B1*/ OpMovZbIb,               // #178  (0.000093%)\n    /*0B2*/ OpMovZbIb,               // #176  (0.000099%)\n    /*0B3*/ OpMovZbIb,               // #202  (0.000028%)\n    /*0B4*/ OpMovZbIb,               //\n    /*0B5*/ OpMovZbIb,               // #220  (0.000010%)\n    /*0B6*/ OpMovZbIb,               // #136  (0.000488%)\n    /*0B7*/ OpMovZbIb,               // #216  (0.000014%)\n    /*0B8*/ OpMovZvqpIvqp,           // #33   (0.315404%)\n    /*0B9*/ OpMovZvqpIvqp,           // #50   (0.039176%)\n    /*0BA*/ OpMovZvqpIvqp,           // #32   (0.315927%)\n    /*0BB*/ OpMovZvqpIvqp,           // #93   (0.003549%)\n    /*0BC*/ OpMovZvqpIvqp,           // #109  (0.001380%)\n    /*0BD*/ OpMovZvqpIvqp,           // #101  (0.002061%)\n    /*0BE*/ OpMovZvqpIvqp,           // #68   (0.013223%)\n    /*0BF*/ OpMovZvqpIvqp,           // #79   (0.008900%)\n    /*0C0*/ OpBsubiImm,              // #111  (0.001368%)\n    /*0C1*/ OpBsuwiImm,              // #20   (0.536537%)\n    /*0C2*/ OpRetIw,                 //\n    /*0C3*/ OpRet,                   // #24   (0.422698%)\n    /*0C4*/ OpLes,                   //\n    /*0C5*/ OpLds,                   //\n    /*0C6*/ OpMovImm,                // #90   (0.004525%)\n    /*0C7*/ OpMovImm,                // #45   (0.161349%)\n    /*0C8*/ OpEnter,                 //\n    /*0C9*/ OpLeave,                 // #116  (0.001237%)\n    /*0CA*/ OpRetf,                  //\n    /*0CB*/ OpRetf,                  //\n    /*0CC*/ OpInterrupt3,            //\n    /*0CD*/ OpInterruptImm,          //\n    /*0CE*/ OpInto,                  //\n    /*0CF*/ OpIret,                  //\n    /*0D0*/ OpBsubi1,                // #212  (0.000021%)\n    /*0D1*/ OpBsuwi1,                // #61   (0.016958%)\n    /*0D2*/ OpBsubiCl,               //\n    /*0D3*/ OpBsuwiCl,               // #19   (0.621270%)\n    /*0D4*/ OpAam,                   //\n    /*0D5*/ OpAad,                   //\n    /*0D6*/ OpSalc,                  //\n    /*0D7*/ OpXlatAlBbb,             //\n    /*0D8*/ OpFpu,                   // #258  (0.000005%)\n    /*0D9*/ OpFpu,                   // #145  (0.000335%)\n    /*0DA*/ OpFpu,                   // #290  (0.000000%)\n    /*0DB*/ OpFpu,                   // #139  (0.000399%)\n    /*0DC*/ OpFpu,                   // #283  (0.000001%)\n    /*0DD*/ OpFpu,                   // #144  (0.000340%)\n    /*0DE*/ OpFpu,                   // #193  (0.000046%)\n    /*0DF*/ OpFpu,                   // #215  (0.000014%)\n    /*0E0*/ OpLoopne,                //\n    /*0E1*/ OpLoope,                 //\n    /*0E2*/ OpLoop1,                 //\n    /*0E3*/ OpJcxz,                  //\n    /*0E4*/ OpInAlImm,               //\n    /*0E5*/ OpInAxImm,               //\n    /*0E6*/ OpOutImmAl,              //\n    /*0E7*/ OpOutImmAx,              //\n    /*0E8*/ OpCallJvds,              // #25   (0.403872%)\n    /*0E9*/ OpJmp,                   // #22   (0.476546%)\n    /*0EA*/ OpJmpf,                  //\n    /*0EB*/ OpJmp,                   // #6    (6.012044%)\n    /*0EC*/ OpInAlDx,                //\n    /*0ED*/ OpInAxDx,                //\n    /*0EE*/ OpOutDxAl,               //\n    /*0EF*/ OpOutDxAx,               //\n    /*0F0*/ OpUd,                    //\n    /*0F1*/ OpInterrupt1,            //\n    /*0F2*/ OpUd,                    //\n    /*0F3*/ OpUd,                    //\n    /*0F4*/ OpHlt,                   //\n    /*0F5*/ OpCmc,                   //\n    /*0F6*/ Op0f6,                   // #56   (0.028122%)\n    /*0F7*/ Op0f7,                   // #10   (5.484639%)\n    /*0F8*/ OpClc,                   // #156  (0.000187%)\n    /*0F9*/ OpStc,                   //\n    /*0FA*/ OpCli,                   //\n    /*0FB*/ OpSti,                   //\n    /*0FC*/ OpCld,                   // #142  (0.000379%)\n    /*0FD*/ OpStd,                   // #141  (0.000379%)\n    /*0FE*/ Op0fe,                   // #181  (0.000083%)\n    /*0FF*/ Op0ff,                   // #5    (6.314024%)\n    /*100*/ OpUd,                    //\n    /*101*/ Op101,                   //\n    /*102*/ OpUd,                    //\n    /*103*/ OpLsl,                   //\n    /*104*/ OpUd,                    //\n    /*105*/ OpSyscall,               // #133  (0.000663%)\n    /*106*/ OpClts,                  //\n    /*107*/ OpUd,                    //\n    /*108*/ OpUd,                    //\n    /*109*/ OpWbinvd,                //\n    /*10A*/ OpUd,                    //\n    /*10B*/ OpUd,                    //\n    /*10C*/ OpUd,                    //\n    /*10D*/ OpHintNopEv,             //\n    /*10E*/ OpUd,                    //\n    /*10F*/ OpUd,                    //\n    /*110*/ OpMov0f10,               // #89   (0.004629%)\n    /*111*/ OpMovWpsVps,             // #104  (0.001831%)\n    /*112*/ OpMov0f12,               //\n    /*113*/ OpMov0f13,               //\n    /*114*/ OpUnpcklpsd,             //\n    /*115*/ OpUnpckhpsd,             //\n    /*116*/ OpMov0f16,               //\n    /*117*/ OpMov0f17,               //\n    /*118*/ OpHintNopEv,             //\n    /*119*/ OpHintNopEv,             //\n    /*11A*/ OpHintNopEv,             //\n    /*11B*/ OpHintNopEv,             //\n    /*11C*/ OpHintNopEv,             //\n    /*11D*/ OpHintNopEv,             //\n    /*11E*/ OpHintNopEv,             //\n    /*11F*/ OpNopEv,                 // #62   (0.016260%)\n    /*120*/ OpMovRqCq,               //\n    /*121*/ OpUd,                    //\n    /*122*/ OpMovCqRq,               //\n    /*123*/ OpUd,                    //\n    /*124*/ OpUd,                    //\n    /*125*/ OpUd,                    //\n    /*126*/ OpUd,                    //\n    /*127*/ OpUd,                    //\n    /*128*/ OpMov0f28,               // #100  (0.002220%)\n    /*129*/ OpMovWpsVps,             // #99   (0.002294%)\n    /*12A*/ OpCvt0f2a,               // #173  (0.000112%)\n    /*12B*/ OpMov0f2b,               //\n    /*12C*/ OpCvtt0f2c,              // #172  (0.000112%)\n    /*12D*/ OpCvt0f2d,               //\n    /*12E*/ OpComissVsWs,            // #153  (0.000223%)\n    /*12F*/ OpComissVsWs,            // #152  (0.000223%)\n    /*130*/ OpWrmsr,                 //\n    /*131*/ OpRdtsc,                 // #214  (0.000016%)\n    /*132*/ OpRdmsr,                 //\n    /*133*/ OpUd,                    //\n    /*134*/ OpUd,                    //\n    /*135*/ OpUd,                    //\n    /*136*/ OpUd,                    //\n    /*137*/ OpUd,                    //\n    /*138*/ OpUd,                    //\n    /*139*/ OpUd,                    //\n    /*13A*/ OpUd,                    //\n    /*13B*/ OpUd,                    //\n    /*13C*/ OpUd,                    //\n    /*13D*/ OpUd,                    //\n    /*13E*/ OpUd,                    //\n    /*13F*/ OpUd,                    //\n    /*140*/ OpCmov,                  //\n    /*141*/ OpCmov,                  //\n    /*142*/ OpCmov,                  // #69   (0.012667%)\n    /*143*/ OpCmov,                  // #276  (0.000002%)\n    /*144*/ OpCmov,                  // #134  (0.000584%)\n    /*145*/ OpCmov,                  // #132  (0.000700%)\n    /*146*/ OpCmov,                  // #125  (0.000945%)\n    /*147*/ OpCmov,                  // #40   (0.289378%)\n    /*148*/ OpCmov,                  // #130  (0.000774%)\n    /*149*/ OpCmov,                  // #149  (0.000228%)\n    /*14A*/ OpCmovp,                 //\n    /*14B*/ OpCmovnp,                //\n    /*14C*/ OpCmov,                  // #102  (0.002008%)\n    /*14D*/ OpCmov,                  // #196  (0.000044%)\n    /*14E*/ OpCmov,                  // #110  (0.001379%)\n    /*14F*/ OpCmov,                  // #121  (0.001029%)\n    /*150*/ OpMovmskpsd,             //\n    /*151*/ OpSqrtpsd,               //\n    /*152*/ OpRsqrtps,               //\n    /*153*/ OpRcpps,                 //\n    /*154*/ OpAndpsd,                // #171  (0.000112%)\n    /*155*/ OpAndnpsd,               //\n    /*156*/ OpOrpsd,                 //\n    /*157*/ OpXorpsd,                // #148  (0.000245%)\n    /*158*/ OpAddpsd,                // #151  (0.000223%)\n    /*159*/ OpMulpsd,                // #150  (0.000223%)\n    /*15A*/ OpCvt0f5a,               //\n    /*15B*/ OpCvt0f5b,               //\n    /*15C*/ OpSubpsd,                // #146  (0.000335%)\n    /*15D*/ OpMinpsd,                //\n    /*15E*/ OpDivpsd,                // #170  (0.000112%)\n    /*15F*/ OpMaxpsd,                //\n    /*160*/ OpSsePunpcklbw,          // #259  (0.000003%)\n    /*161*/ OpSsePunpcklwd,          // #221  (0.000009%)\n    /*162*/ OpSsePunpckldq,          // #262  (0.000003%)\n    /*163*/ OpSsePacksswb,           // #297  (0.000000%)\n    /*164*/ OpSsePcmpgtb,            // #274  (0.000003%)\n    /*165*/ OpSsePcmpgtw,            // #273  (0.000003%)\n    /*166*/ OpSsePcmpgtd,            // #272  (0.000003%)\n    /*167*/ OpSsePackuswb,           // #231  (0.000005%)\n    /*168*/ OpSsePunpckhbw,          // #271  (0.000003%)\n    /*169*/ OpSsePunpckhwd,          // #261  (0.000003%)\n    /*16A*/ OpSsePunpckhdq,          // #260  (0.000003%)\n    /*16B*/ OpSsePackssdw,           // #257  (0.000005%)\n    /*16C*/ OpSsePunpcklqdq,         // #264  (0.000003%)\n    /*16D*/ OpSsePunpckhqdq,         // #263  (0.000003%)\n    /*16E*/ OpMov0f6e,               // #289  (0.000000%)\n    /*16F*/ OpMov0f6f,               // #191  (0.000051%)\n    /*170*/ OpShuffle,               // #164  (0.000131%)\n    /*171*/ Op171,                   // #294  (0.000000%)\n    /*172*/ Op172,                   // #293  (0.000000%)\n    /*173*/ Op173,                   // #211  (0.000022%)\n    /*174*/ OpSsePcmpeqb,            // #118  (0.001215%)\n    /*175*/ OpSsePcmpeqw,            // #201  (0.000028%)\n    /*176*/ OpSsePcmpeqd,            // #222  (0.000008%)\n    /*177*/ OpEmms,                  //\n    /*178*/ OpUd,                    //\n    /*179*/ OpUd,                    //\n    /*17A*/ OpUd,                    //\n    /*17B*/ OpUd,                    //\n    /*17C*/ OpHaddpsd,               //\n    /*17D*/ OpHsubpsd,               //\n    /*17E*/ OpMov0f7e,               // #122  (0.001005%)\n    /*17F*/ OpMov0f7f,               // #192  (0.000048%)\n    /*180*/ OpJcc,                   //\n    /*181*/ OpJcc,                   //\n    /*182*/ OpJcc,                   // #107  (0.001532%)\n    /*183*/ OpJcc,                   // #72   (0.011761%)\n    /*184*/ OpJcc,                   // #55   (0.029121%)\n    /*185*/ OpJcc,                   // #57   (0.027593%)\n    /*186*/ OpJcc,                   // #46   (0.147358%)\n    /*187*/ OpJcc,                   // #86   (0.005907%)\n    /*188*/ OpJcc,                   // #106  (0.001569%)\n    /*189*/ OpJcc,                   // #160  (0.000142%)\n    /*18A*/ OpJp,                    //\n    /*18B*/ OpJnp,                   //\n    /*18C*/ OpJcc,                   // #105  (0.001786%)\n    /*18D*/ OpJcc,                   // #281  (0.000001%)\n    /*18E*/ OpJcc,                   // #77   (0.009607%)\n    /*18F*/ OpJcc,                   // #126  (0.000890%)\n    /*190*/ OpSetcc,                 // #280  (0.000001%)\n    /*191*/ OpSetcc,                 //\n    /*192*/ OpSetcc,                 // #26   (0.364366%)\n    /*193*/ OpSetcc,                 // #183  (0.000063%)\n    /*194*/ OpSetcc,                 // #78   (0.009363%)\n    /*195*/ OpSetcc,                 // #94   (0.003096%)\n    /*196*/ OpSetcc,                 // #162  (0.000139%)\n    /*197*/ OpSetcc,                 // #92   (0.003559%)\n    /*198*/ OpSetcc,                 //\n    /*199*/ OpSetcc,                 //\n    /*19A*/ OpSetp,                  //\n    /*19B*/ OpSetnp,                 //\n    /*19C*/ OpSetcc,                 // #119  (0.001079%)\n    /*19D*/ OpSetcc,                 // #275  (0.000002%)\n    /*19E*/ OpSetcc,                 // #167  (0.000112%)\n    /*19F*/ OpSetcc,                 // #95   (0.002688%)\n    /*1A0*/ OpPushSeg,               //\n    /*1A1*/ OpPopSeg,                //\n    /*1A2*/ OpCpuid,                 // #285  (0.000001%)\n    /*1A3*/ OpBit,                   //\n    /*1A4*/ OpDoubleShift,           //\n    /*1A5*/ OpDoubleShift,           //\n    /*1A6*/ OpUd,                    //\n    /*1A7*/ OpUd,                    //\n    /*1A8*/ OpPushSeg,               //\n    /*1A9*/ OpPopSeg,                //\n    /*1AA*/ OpUd,                    //\n    /*1AB*/ OpBit,                   // #291  (0.000000%)\n    /*1AC*/ OpDoubleShift,           //\n    /*1AD*/ OpDoubleShift,           //\n    /*1AE*/ Op1ae,                   // #287  (0.000000%)\n    /*1AF*/ OpImulGvqpEvqp,          // #34   (0.299503%)\n    /*1B0*/ OpCmpxchgEbAlGb,         //\n    /*1B1*/ OpCmpxchgEvqpRaxGvqp,    // #87   (0.005376%)\n    /*1B2*/ OpLss,                   //\n    /*1B3*/ OpBit,                   // #199  (0.000035%)\n    /*1B4*/ OpLfs,                   //\n    /*1B5*/ OpLgs,                   //\n    /*1B6*/ OpMovzbGvqpEb,           // #37   (0.296523%)\n    /*1B7*/ OpMovzwGvqpEw,           // #137  (0.000433%)\n    /*1B8*/ Op1b8,                   //\n    /*1B9*/ OpUd,                    //\n    /*1BA*/ OpBit,                   // #127  (0.000879%)\n    /*1BB*/ OpBit,                   //\n    /*1BC*/ OpBsf,                   // #88   (0.005117%)\n    /*1BD*/ OpBsr,                   // #123  (0.000985%)\n    /*1BE*/ OpMovsbGvqpEb,           // #52   (0.035351%)\n    /*1BF*/ OpMovswGvqpEw,           // #63   (0.015753%)\n    /*1C0*/ OpXaddEbGb,              //\n    /*1C1*/ OpXaddEvqpGvqp,          //\n    /*1C2*/ OpCmppsd,                //\n    /*1C3*/ OpMovntiMdqpGdqp,        //\n    /*1C4*/ OpPinsrwVdqEwIb,         // #124  (0.000981%)\n    /*1C5*/ OpPextrwGdqpUdqIb,       // #277  (0.000002%)\n    /*1C6*/ OpShufpsd,               //\n    /*1C7*/ Op1c7,                   // #189  (0.000054%)\n    /*1C8*/ OpBswapZvqp,             // #159  (0.000145%)\n    /*1C9*/ OpBswapZvqp,             // #182  (0.000069%)\n    /*1CA*/ OpBswapZvqp,             // #197  (0.000039%)\n    /*1CB*/ OpBswapZvqp,             // #217  (0.000012%)\n    /*1CC*/ OpBswapZvqp,             //\n    /*1CD*/ OpBswapZvqp,             //\n    /*1CE*/ OpBswapZvqp,             // #129  (0.000863%)\n    /*1CF*/ OpBswapZvqp,             // #128  (0.000863%)\n    /*1D0*/ OpAddsubpsd,             //\n    /*1D1*/ OpSsePsrlwv,             // #256  (0.000005%)\n    /*1D2*/ OpSsePsrldv,             // #255  (0.000005%)\n    /*1D3*/ OpSsePsrlqv,             // #254  (0.000005%)\n    /*1D4*/ OpSsePaddq,              // #253  (0.000005%)\n    /*1D5*/ OpSsePmullw,             // #188  (0.000054%)\n    /*1D6*/ OpMov0fD6,               // #169  (0.000112%)\n    /*1D7*/ OpPmovmskbGdqpNqUdq,     // #117  (0.001235%)\n    /*1D8*/ OpSsePsubusb,            // #252  (0.000005%)\n    /*1D9*/ OpSsePsubusw,            // #251  (0.000005%)\n    /*1DA*/ OpSsePminub,             // #250  (0.000005%)\n    /*1DB*/ OpSsePand,               // #249  (0.000005%)\n    /*1DC*/ OpSsePaddusb,            // #248  (0.000005%)\n    /*1DD*/ OpSsePaddusw,            // #247  (0.000005%)\n    /*1DE*/ OpSsePmaxub,             // #246  (0.000005%)\n    /*1DF*/ OpSsePandn,              // #245  (0.000005%)\n    /*1E0*/ OpSsePavgb,              // #244  (0.000005%)\n    /*1E1*/ OpSsePsrawv,             // #230  (0.000005%)\n    /*1E2*/ OpSsePsradv,             // #224  (0.000008%)\n    /*1E3*/ OpSsePavgw,              // #243  (0.000005%)\n    /*1E4*/ OpSsePmulhuw,            // #229  (0.000005%)\n    /*1E5*/ OpSsePmulhw,             // #187  (0.000054%)\n    /*1E6*/ OpCvt0fE6,               //\n    /*1E7*/ OpMov0fE7,               //\n    /*1E8*/ OpSsePsubsb,             // #242  (0.000005%)\n    /*1E9*/ OpSsePsubsw,             // #241  (0.000005%)\n    /*1EA*/ OpSsePminsw,             // #240  (0.000005%)\n    /*1EB*/ OpSsePor,                // #239  (0.000005%)\n    /*1EC*/ OpSsePaddsb,             // #238  (0.000005%)\n    /*1ED*/ OpSsePaddsw,             // #228  (0.000006%)\n    /*1EE*/ OpSsePmaxsw,             // #237  (0.000005%)\n    /*1EF*/ OpSsePxor,               // #195  (0.000044%)\n    /*1F0*/ OpLddquVdqMdq,           //\n    /*1F1*/ OpSsePsllwv,             // #226  (0.000006%)\n    /*1F2*/ OpSsePslldv,             // #225  (0.000006%)\n    /*1F3*/ OpSsePsllqv,             // #236  (0.000005%)\n    /*1F4*/ OpSsePmuludq,            // #186  (0.000054%)\n    /*1F5*/ OpSsePmaddwd,            // #185  (0.000054%)\n    /*1F6*/ OpSsePsadbw,             // #270  (0.000003%)\n    /*1F7*/ OpMaskMovDiXmmRegXmmRm,  //\n    /*1F8*/ OpSsePsubb,              // #235  (0.000005%)\n    /*1F9*/ OpSsePsubw,              // #234  (0.000005%)\n    /*1FA*/ OpSsePsubd,              // #184  (0.000054%)\n    /*1FB*/ OpSsePsubq,              // #269  (0.000003%)\n    /*1FC*/ OpSsePaddb,              // #233  (0.000005%)\n    /*1FD*/ OpSsePaddw,              // #227  (0.000006%)\n    /*1FE*/ OpSsePaddd,              // #232  (0.000005%)\n    /*1FF*/ OpUd0GvqpEvqp,           //\n    /*200*/ OpSsePshufb,             // #268  (0.000003%)\n    /*201*/ OpSsePhaddw,             // #204  (0.000027%)\n    /*202*/ OpSsePhaddd,             // #210  (0.000027%)\n    /*203*/ OpSsePhaddsw,            // #203  (0.000027%)\n    /*204*/ OpSsePmaddubsw,          // #209  (0.000027%)\n    /*205*/ OpSsePhsubw,             // #208  (0.000027%)\n    /*206*/ OpSsePhsubd,             // #207  (0.000027%)\n    /*207*/ OpSsePhsubsw,            // #206  (0.000027%)\n    /*208*/ OpSsePsignb,             // #267  (0.000003%)\n    /*209*/ OpSsePsignw,             // #266  (0.000003%)\n    /*20A*/ OpSsePsignd,             // #265  (0.000003%)\n    /*20B*/ OpSsePmulhrsw,           // #205  (0.000027%)\n};\n\nnexgen32e_f GetOp(long op) {\n  if (op < ARRAYLEN(kNexgen32e)) {\n    return kNexgen32e[op];\n  } else {\n    switch (op) {\n      XLAT(0x21c, OpSsePabsb);\n      XLAT(0x21d, OpSsePabsw);\n      XLAT(0x21e, OpSsePabsd);\n      XLAT(0x22a, OpMovntdqaVdqMdq);\n      XLAT(0x240, OpSsePmulld);\n      XLAT(0x2f0, Op2f01);\n      XLAT(0x2f1, Op2f01);\n      XLAT(0x2f5, Op2f5);\n      XLAT(0x2f6, Op2f6);\n      XLAT(0x2f7, OpShx);\n      XLAT(0x30f, OpSsePalignr);\n      XLAT(0x344, OpSsePclmulqdq);\n      XLAT(0x3f0, OpRorx);\n      default:\n        return OpUd;\n    }\n  }\n}\n\nstatic bool CanJit(struct Machine *m) {\n  return !IsJitDisabled(&m->system->jit);\n}\n\nvoid JitlessDispatch(P) {\n  ASM_LOGF(\"decoding [%s] at address %\" PRIx64, DescribeOp(m, GetPc(m)),\n           GetPc(m));\n  COSTLY_STATISTIC(++instructions_dispatched);\n  LoadInstruction(m, GetPc(m));\n  rde = m->xedd->op.rde;\n  disp = m->xedd->op.disp;\n  uimm0 = m->xedd->op.uimm0;\n  m->oplen = Oplength(rde);\n  m->ip += Oplength(rde);\n  GetOp(Mopcode(rde))(A);\n  if (m->stashaddr) CommitStash(m);\n  m->oplen = 0;\n}\n\nstatic void GeneralDispatch(P) {\n#ifdef HAVE_JIT\n  int opclass;\n  uintptr_t jitpc = 0;\n  bool op_overlaps_page_boundary;\n  bool path_would_overlap_page_boundary;\n  ASM_LOGF(\"decoding [%s] at address %\" PRIx64, DescribeOp(m, GetPc(m)),\n           GetPc(m));\n  LoadInstruction(m, GetPc(m));\n  rde = m->xedd->op.rde;\n  disp = m->xedd->op.disp;\n  uimm0 = m->xedd->op.uimm0;\n  opclass = ClassifyOp(rde);\n  // try to fast-track precious ops, since they hit this every time\n  // each jit path should be fully contained within a single page\n  op_overlaps_page_boundary =\n      (m->ip & -4096) != ((m->ip + Oplength(rde) - 1) & -4096);\n  path_would_overlap_page_boundary =\n      IsMakingPath(m) && (m->ip & -4096) != (m->path.start & -4096);\n  if (IsMakingPath(m) &&\n      (opclass == kOpPrecious || opclass == kOpSerializing ||\n       op_overlaps_page_boundary || path_would_overlap_page_boundary)) {\n    // complete path where last instruction in path is previously run op\n    CompletePath(A);\n  }\n  // if we're in a jit path, or we're able to create a new path\n  if (IsMakingPath(m) ||\n      (opclass != kOpPrecious && opclass != kOpSerializing &&\n       !op_overlaps_page_boundary && CanJit(m) && CreatePath(A))) {\n    // begin adding this op to the jit path\n    unassert(opclass == kOpNormal || opclass == kOpBranching);\n    ++m->path.elements;\n    STATISTIC(++path_elements);\n    AddPath_StartOp(A);\n    jitpc = GetJitPc(m->path.jb);\n    JIP_LOGF(\"adding [%s] from address %\" PRIx64\n             \" to path starting at %\" PRIx64,\n             DescribeOp(m, GetPc(m)), GetPc(m), m->path.start);\n  }\n  // advance the instruction pointer\n  // record the op length so it can be rewound upon fault\n  m->oplen = Oplength(rde);\n  m->ip += Oplength(rde);\n  // call the c implementation of the opcode\n  GetOp(Mopcode(rde))(A);\n  // cleanup after ReserveAddress() if a memory access overlapped a page\n  if (m->stashaddr) {\n    CommitStash(m);\n  }\n  if (IsMakingPath(m)) {\n    // finish adding new element to jit path\n    unassert(opclass == kOpNormal || opclass == kOpBranching);\n    // did the op generate its own assembly code?\n    if (GetJitPc(m->path.jb) != jitpc) {\n      // it did; that means we're done\n      AddPath_EndOp(A);\n    } else {\n      // otherwise generate \"one size fits all\" assembly code\n      AddPath(A);\n      AddPath_EndOp(A);\n      STATISTIC(++path_elements_auto);\n    }\n    if (opclass == kOpBranching) {\n      // branches, calls, and jumps always force end of path\n      // unlike precious ops the branching op can be in path\n      CompletePath(A);\n    }\n  }\n  m->oplen = 0;\n#endif\n}\n\nvoid ExecuteInstruction(struct Machine *m) {\n#if LOG_CPU\n  LogCpu(m);\n#endif\n#ifdef HAVE_JIT\n  u8 *dst;\n  nexgen32e_f func;\n  unassert(m->canhalt);\n  if (CanJit(m)) {\n    if ((func = (nexgen32e_f)GetJitHook(&m->system->jit, m->ip))) {\n      if (!IsMakingPath(m)) {\n        func(DISPATCH_NOTHING);\n        return;\n      } else if (func == JitlessDispatch) {\n        JIT_LOGF(\"abandoning path starting at %\" PRIx64\n                 \" due to running into staged path\",\n                 m->path.start);\n        AbandonPath(m);\n        func(DISPATCH_NOTHING);\n        return;\n      } else {\n        JIT_LOGF(\"splicing path starting at %#\" PRIx64\n                 \" into previously created function %p at %#\" PRIx64,\n                 m->path.start, func, m->ip);\n        FlushSkew(DISPATCH_NOTHING);\n        AppendJitSetReg(m->path.jb, kJitArg0, kJitSav0);\n        STATISTIC(++path_spliced);\n        if (RecordJitEdge(&m->system->jit, m->path.start, m->ip)) {\n          dst = (u8 *)(uintptr_t)func + GetPrologueSize();\n          STATISTIC(++path_connected_directly);\n        } else {\n          STATISTIC(++path_connected_interpreter);\n          dst = (u8 *)m->system->ender;\n        }\n        AppendJitJump(m->path.jb, dst);\n        FinishPath(m);\n        func(DISPATCH_NOTHING);\n        return;\n      }\n    }\n    GeneralDispatch(DISPATCH_NOTHING);\n  } else {\n    JitlessDispatch(DISPATCH_NOTHING);\n  }\n#else\n  JitlessDispatch(DISPATCH_NOTHING);\n#endif\n}\n\nvoid Actor(struct Machine *mm) {\n#ifdef __CYGWIN__\n  // TODO: Why does JIT clobber %rbx on Cygwin?\n  struct Machine *volatile m;\n#else\n  struct Machine *m;\n#endif\n  for (g_machine = mm, m = mm;;) {\n#ifndef __CYGWIN__\n    STATISTIC(++interps);\n#endif\n    if (!atomic_load_explicit(&m->attention, memory_order_acquire)) {\n      ExecuteInstruction(m);\n    } else {\n      CheckForSignals(m);\n    }\n  }\n}\n\nvoid Blink(struct Machine *m) {\n  int rc;\n  for (;;) {\n    if (!(rc = sigsetjmp(m->onhalt, 1))) {\n      m->canhalt = true;\n      Actor(m);\n    }\n    m->sysdepth = 0;\n    m->sigdepth = 0;\n    m->canhalt = false;\n    m->nofault = false;\n    m->insyscall = false;\n    CollectPageLocks(m);\n    CollectGarbage(m, 0);\n    if (IsMakingPath(m)) {\n      AbandonPath(m);\n    }\n    if (rc == kMachineFatalSystemSignal) {\n      HandleFatalSystemSignal(m, &g_siginfo);\n    }\n  }\n}\n\nvoid HandleFatalSystemSignal(struct Machine *m, const siginfo_t *si) {\n  int sig;\n  RestoreIp(m);\n  m->faultaddr = ConvertHostToGuestAddress(m->system, si->si_addr, 0);\n  sig = UnXlatSignal(si->si_signo);\n  DeliverSignalToUser(m, sig, UnXlatSiCode(sig, si->si_code));\n}\n"
  },
  {
    "path": "blink/machine.h",
    "content": "#ifndef BLINK_MACHINE_H_\n#define BLINK_MACHINE_H_\n#include <limits.h>\n#include <setjmp.h>\n#include <signal.h>\n#include <stdbool.h>\n\n#ifdef __COSMOPOLITAN__\n#define _COSMO_SOURCE\n#include <libc/dce.h>\n#endif\n\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/dll.h\"\n#include \"blink/elf.h\"\n#include \"blink/fds.h\"\n#include \"blink/jit.h\"\n#include \"blink/linux.h\"\n#include \"blink/log.h\"\n#include \"blink/thread.h\"\n#include \"blink/tsan.h\"\n#include \"blink/tunables.h\"\n#include \"blink/x86.h\"\n\n#define EXIT_FAILURE_EXEC_FAILED 127\n#define EXIT_FAILURE_WITH_SIGNAL(sig) 128 + sig\n\n#define kArgRde   1\n#define kArgDisp  2\n#define kArgUimm0 3\n#define kArgArg   4\n\n#define kOpNormal      0\n#define kOpBranching   1\n#define kOpPrecious    2\n#define kOpSerializing kOpPrecious\n\n#define kMaxThreadIds 32768\n#define kMinThreadId  262144\n\n#define kInstructionBytes 40\n\n#define kMachineExit                 256\n#define kMachineHalt                 -1\n#define kMachineDecodeError          -2\n#define kMachineUndefinedInstruction -3\n#define kMachineSegmentationFault    -4\n#define kMachineEscape               -5\n#define kMachineDivideError          -6\n#define kMachineFpuException         -7\n#define kMachineProtectionFault      -8\n#define kMachineSimdException        -9\n#define kMachineExitTrap             -10\n#define kMachineFatalSystemSignal    -11\n\n#define CR0_PE 0x01        // protected mode enabled\n#define CR0_MP 0x02        // monitor coprocessor\n#define CR0_EM 0x04        // no x87 fpu present if set\n#define CR0_TS 0x08        // task switched x87\n#define CR0_ET 0x10        // extension type 287 or 387\n#define CR0_NE 0x20        // enable x87 error reporting\n#define CR0_WP 0x00010000  // write protect read-only pages @pl0\n#define CR0_AM 0x00040000  // alignment mask\n#define CR0_NW 0x20000000  // global write-through cache disable\n#define CR0_CD 0x40000000  // global cache disable\n#define CR0_PG 0x80000000  // paging enabled\n\n/* Long Mode Paging\n   @see Intel Manual V.3A §4.1 §4.5\n                                       IsValid (ignored on CR3) V┐\n  ┌XD:No Inst. Fetches (if NXE)   IsWritable (ignored on CR3) RW┐│\n  │                                 Permit User-Mode Access - u┐││\n  │                             Page-level Write-Through - PWT┐│││\n  │                            Page-level Cache Disable - PCD┐││││\n  │                          Set if has been read - Accessed┐│││││\n  │                         Set if has been written - Dirty┐││││││\n  │           IsPage 2MB/1GB (if PDPTE/PDE) or PAT (if PT)┐│││││││\n  │                (If this maps page and CR4.PGE) Global┐││││││││\n  │      (If IsPage 2MB/1GB, see Intel V3A § 11.12) PAT  │││││││││\n  │                                                  │   │││││││││\n  │            ┌─────────────────────────────────────┤   │││││││││\n  │  Must Be 0┐│ Next Page Table Address (!IsPage)   │   │││││││││\n  │           │├─────────────────────────────────────┤   │││││││││\n  │           ││ Physical Address 4KB                │   │││││││││\n  │┌──┐┌─────┐│├────────────────────────────┐        │ign│││││││││\n  ││PK││ ign │││ Physical Address 2MB       │        │┌┴┐│││││││││\n  ││  ││     ││├───────────────────┐        │        ││ ││││││││││\n  ││  ││     │││ Phys. Addr. 1GB   │        │        ││ ││││││││││\n  ││  ││     │││                   │        │        ││ ││││││││││\n  ───────────────────────────────────────────────────────────────*/\n#define PAGE_V     0x0000000000000001  // valid\n#define PAGE_RW    0x0000000000000002  // writeable\n#define PAGE_U     0x0000000000000004  // permit ring3 access or read protect\n#define PAGE_PS    0x0000000000000080  // IsPage (PDPTE/PDE) or PAT (PT)\n#define PAGE_G     0x0000000000000100  // global\n#define PAGE_RSRV  0x0000000000000200  // PAGE_TA bits havent been chosen yet\n#define PAGE_HOST  0x0000000000000400  // PAGE_TA bits point to system memory\n#define PAGE_MAP   0x0000000000000800  // PAGE_TA bits are a linear host mmap\n#define PAGE_TA    0x0000fffffffff000  // bits used for host, or real address\n#define PAGE_GROW  0x0010000000000000  // for future support of MAP_GROWSDOWN\n#define PAGE_MUG   0x0020000000000000  // host page magic mapped individually\n#define PAGE_FILE  0x0040000000000000  // page has tracking bit in s->filemap\n#define PAGE_LOCK  0x0080000000000000  // a bit used to increment lock counts\n#define PAGE_LOCKS 0x7f80000000000000  // a page can be locked by 255 threads\n#define PAGE_XD    0x8000000000000000  // disable executing memory if bit set\n\n#define SREG_ES 0\n#define SREG_CS 1\n#define SREG_SS 2\n#define SREG_DS 3\n#define SREG_FS 4\n#define SREG_GS 5\n\n#define P                struct Machine *m, u64 rde, i64 disp, u64 uimm0\n#define A                m, rde, disp, uimm0\n#define DISPATCH_NOTHING m, 0, 0, 0\n\n#define MACHINE_CONTAINER(e)  DLL_CONTAINER(struct Machine, elem, e)\n#define FILEMAP_CONTAINER(e)  DLL_CONTAINER(struct FileMap, elem, e)\n#define HOSTPAGE_CONTAINER(e) DLL_CONTAINER(struct HostPage, elem, e)\n\n#if defined(NOLINEAR) || defined(__SANITIZE_THREAD__) ||                       \\\n    defined(__CYGWIN__) || defined(__NetBSD__) || defined(__COSMOPOLITAN__) || \\\n    defined(__FILC__)\n#define CanHaveLinearMemory() false\n#else\n#define CanHaveLinearMemory() CAN_64BIT\n#endif\n\n#ifdef HAVE_JIT\n#define IsMakingPath(m) m->path.jb\n#else\n#define IsMakingPath(m) 0\n#endif\n\n#define HasLinearMapping() (CanHaveLinearMemory() && !FLAG_nolinear)\n\n#if CAN_64BIT\n#define _Atomicish(t) _Atomic(t)\n#else\n#define _Atomicish(t) t\n#endif\n\nMICRO_OP_SAFE u8 *ToHost(i64 v) {\n  return (u8 *)(uintptr_t)(v + kSkew);\n}\n\nstatic inline i64 ToGuest(void *r) {\n  i64 v = (uintptr_t)r - kSkew;\n  return v;\n}\n\nstruct Dis;\nstruct Machine;\ntypedef void (*nexgen32e_f)(P);\n\nstruct FreeList {\n  int n;\n  void **p;\n};\n\nstruct HostPage {\n  u8 *page;\n  struct HostPage *next;\n};\n\nstruct HostPages {\n  size_t n;\n  size_t c;\n  u8 **p;\n};\n\nstruct PageLock {\n  i64 page;\n  u8 *pslot;\n  int sysdepth;\n};\n\nstruct SmcQueue {\n  i64 p[kSmcQueueSize];\n};\n\nstruct PageLocks {\n  int i, n;\n  struct PageLock *p;\n};\n\nstruct FileMap {\n  i64 virt;         // start address of map\n  i64 size;         // bytes originally mapped\n  u64 pages;        // population count of present\n  i64 offset;       // file offset (-1 if descriptive)\n  char *path;       // duplicated (owned) pointer to filename\n  u64 *present;     // bitset of present pages in [virt,virt+size)\n  struct Dll elem;  // see System::filemaps\n};\n\nstruct MachineFpu {\n#ifndef DISABLE_X87\n  double st[8];\n  u32 sw;\n  int tw;\n  int op;\n  i64 ip;\n#endif\n  u32 cw;\n  i64 dp;\n};\n\nstruct MachineMemstat {\n  long tables;\n  long reserved;\n  long committed;\n};\n\n// Segment descriptor cache\n// @see Intel Manual V3A §3.4.3\n// Currently only the base address for each segment register is maintained;\n// a full implementation will also cache its limit & access rights\nstruct DescriptorCache {\n  u16 sel;   // visible selector value (or paragraph value in real mode)\n  u64 base;  // base linear address\n};\n\nstruct MachineState {\n  u64 ip;\n  struct DescriptorCache cs;\n  struct DescriptorCache ss;\n  struct DescriptorCache es;\n  struct DescriptorCache ds;\n  struct DescriptorCache fs;\n  struct DescriptorCache gs;\n  u8 weg[16][8];\n  u8 xmm[16][16];\n  u32 mxcsr;\n  struct MachineFpu fpu;\n  struct MachineMemstat memstat;\n};\n\nstruct Elf {\n  char *prog;\n  char *execfn;\n  char *interpreter;\n  i64 base;\n  i64 aslr;\n  u8 rng[16];\n  i64 at_base;\n  i64 at_phdr;\n  i64 at_phent;\n  i64 at_entry;\n  i64 at_phnum;\n};\n\nstruct OpCache {\n  u8 stash[16];   // for memory ops that overlap page\n  u64 codevirt;   // current rip page in guest memory\n  u8 *codehost;   // current rip page in host memory\n  u32 stashsize;  // for writes that overlap page\n  bool writable;\n  _Atomic(bool) invalidated;\n  u64 icache[512][kInstructionBytes / 8];\n};\n\nstruct System {\n  struct XedMachineMode mode;\n  bool dlab;\n  bool isfork;\n  bool exited;\n  bool loaded;\n  bool iscosmo;\n  bool trapexit;\n  bool brkchanged;\n  _Atomic(bool) killer;\n  u16 gdt_limit;\n  u16 idt_limit;\n  int exitcode;\n  u32 efer;\n  int pid;\n  unsigned next_tid;\n  u8 *real;\n  u64 gdt_base;\n  u64 idt_base;\n  u64 cr0;\n  u64 cr2;\n  u64 cr3;\n  u64 cr4;\n  i64 brk;\n  i64 automap;\n  i64 memchurn;\n  i64 codestart;\n  long codesize;\n  _Atomic(long) rss;\n  _Atomic(long) vss;\n  struct Dis *dis;\n  struct Dll *filemaps;\n  struct MachineMemstat memstat;\n  struct Dll *machines;\n  uintptr_t ender;\n  struct Jit jit;\n  struct Fds fds;\n  struct Elf elf;\n  sigset_t exec_sigmask;\n  struct sigaction_linux hands[64];\n  u64 blinksigs;  // signals blink itself handles\n  struct rlimit_linux rlim[RLIM_NLIMITS_LINUX];\n#ifdef HAVE_THREADS\n  pthread_cond_t_ machines_cond;\n  pthread_mutex_t_ machines_lock;\n  pthread_cond_t_ pagelocks_cond;\n  pthread_mutex_t_ pagelocks_lock;\n  pthread_mutex_t_ exec_lock;\n  pthread_mutex_t_ sig_lock;\n  pthread_mutex_t_ mmap_lock;\n#endif\n  void (*onfilemap)(struct System *, struct FileMap *);\n  void (*onsymbols)(struct System *);\n  void (*onbinbase)(struct Machine *);\n  void (*onlongbranch)(struct Machine *);\n  void (*onromwriteattempt)(struct Machine *, u8 *);\n  int (*exec)(char *, char *, char **, char **);\n  void (*redraw)(bool);\n};\n\n// Default segment selector values in non-metal mode, per Linux 5.9\n#define USER_DS_LINUX 0x2b  // default selector for ss (N.B.)\n#define USER_CS_LINUX 0x33  // default selector for cs\n\nstruct JitPath {\n  int skip;\n  int elements;\n  u64 skew;\n  i64 start;\n  struct JitBlock *jb;\n};\n\nstruct MachineTlb {\n  i64 page;\n  u64 entry;\n};\n\nstruct Machine {               //\n  u64 ip;                      // instruction pointer\n  u8 oplen;                    // length of operation\n  struct XedMachineMode mode;  // [dup] XED_MACHINE_MODE_REAL etc.\n  bool threaded;               // must use synchronization\n  _Atomic(bool) attention;     // signals main interpreter loop\n  u32 flags;                   // x86 eflags register\n  i64 stashaddr;               // it's our page overlap buffer\n  union {                      // GENERAL REGISTER FILE\n    u64 align8_;               //\n    u8 beg[128];               //\n    u8 weg[16][8];             //\n    struct {                   //\n      union {                  //\n        u8 ax[8];              // [vol] accumulator, result:1/2\n        struct {               //\n          u8 al;               // lo byte of ax\n          u8 ah;               // hi byte of ax\n        };  //\n      };  //\n      union {      //\n        u8 cx[8];  // [vol] param:4/6\n        struct {   //\n          u8 cl;   // lo byte of cx\n          u8 ch;   // hi byte of cx\n        };  //\n      };  //\n      union {      //\n        u8 dx[8];  // [vol] param:3/6, result:2/2\n        struct {   //\n          u8 dl;   // lo byte of dx\n          u8 dh;   // hi byte of dx\n        };  //\n      };  //\n      union {      //\n        u8 bx[8];  // [sav] base index\n        struct {   //\n          u8 bl;   // lo byte of bx\n          u8 bh;   // hi byte of bx\n        };  //\n      };  //\n      u8 sp[8];   // [sav] stack pointer\n      u8 bp[8];   // [sav] backtrace pointer\n      u8 si[8];   // [vol] param:2/6\n      u8 di[8];   // [vol] param:1/6\n      u8 r8[8];   // [vol] param:5/6\n      u8 r9[8];   // [vol] param:6/6\n      u8 r10[8];  // [vol]\n      u8 r11[8];  // [vol]\n      u8 r12[8];  // [sav]\n      u8 r13[8];  // [sav]\n      u8 r14[8];  // [sav]\n      u8 r15[8];  // [sav]\n    };  //\n  };  //\n  _Alignas(16) u8 xmm[16][16];      // 128-BIT VECTOR REGISTER FILE\n  struct XedDecodedInst *xedd;      // ->opcache->icache if non-jit\n  i64 readaddr;                     // so tui can show memory reads\n  i64 writeaddr;                    // so tui can show memory write\n  i64 readsize;                     // bytes length of last read op\n  i64 writesize;                    // byte length of last write op\n  union {                           //\n    struct DescriptorCache seg[8];  //\n    struct {                        //\n      struct DescriptorCache es;    // xtra segment (legacy / real)\n      struct DescriptorCache cs;    // code segment (legacy / real)\n      struct DescriptorCache ss;    // stak segment (legacy / real)\n      struct DescriptorCache ds;    // data segment (legacy / real)\n      struct DescriptorCache fs;    // thred-local segment register\n      struct DescriptorCache gs;    // winple thread-local register\n    };  //\n  };  //\n  struct MachineFpu fpu;                 // FLOATING-POINT REGISTER FILE\n  u32 mxcsr;                             // SIMD status control register\n  pthread_t thread;                      // POSIX thread of this machine\n  struct FreeList freelist;              // to make system calls simpler\n  struct PageLocks pagelocks;            // track page table entry locks\n  struct JitPath path;                   // under construction jit route\n  _Atomicish(u64) signals;               // [attention] pending delivery\n  _Atomicish(u64) sigmask;               // signals that've been blocked\n  i64 bofram[2];                         // helps debug bootloading code\n  i64 faultaddr;                         // used for tui error reporting\n  struct System *system;                 //\n  int sigdepth;                          //\n  int sysdepth;                          //\n  _Atomic(bool) killed;                  // [attention] slay this thread\n  _Atomic(bool) invalidated;             // the tlb must be flushed\n  bool restored;                         // [attention] rt_sigreturn()'d\n  bool selfmodifying;                    // [attention] need usmc restore\n  bool reserving;                        //\n  bool insyscall;                        //\n  bool nofault;                          //\n  bool canhalt;                          //\n  bool metal;                            //\n  bool interrupted;                      //\n  bool issigsuspend;                     //\n  bool traprdtsc;                        //\n  bool trapcpuid;                        //\n  bool boop;                             //\n  i8 trapno;                             //\n  i8 segvcode;                           //\n  struct MachineTlb tlb[32];             //\n  sigjmp_buf onhalt;                     //\n  struct sigaltstack_linux sigaltstack;  //\n  i64 robust_list;                       //\n  i64 ctid;                              //\n  int tid;                               //\n  sigset_t spawn_sigmask;                //\n  struct Dll elem;                       //\n  struct SmcQueue smcqueue;              //\n  struct OpCache opcache[1];             //\n};  //\n\nextern struct HostPages g_hostpages;\nextern _Thread_local siginfo_t g_siginfo;\nextern _Thread_local struct Machine *g_machine;\nextern const nexgen32e_f kConvert[3];\nextern const nexgen32e_f kSax[3];\n\nstruct System *NewSystem(struct XedMachineMode);\nvoid FreeSystem(struct System *);\nvoid SignalActor(struct Machine *);\nvoid SetMachineMode(struct Machine *, struct XedMachineMode);\nstruct Machine *NewMachine(struct System *, struct Machine *);\ni64 AreAllPagesUnlocked(struct System *) nosideeffect;\nbool IsOrphan(struct Machine *) nosideeffect;\n_Noreturn void Blink(struct Machine *);\n_Noreturn void Actor(struct Machine *);\nvoid Jitter(P, const char *, ...);\nvoid FreeMachine(struct Machine *);\nvoid InvalidateSystem(struct System *, bool, bool);\nvoid RemoveOtherThreads(struct System *);\nvoid KillOtherThreads(struct System *);\nvoid ResetCpu(struct Machine *);\nvoid ResetTlb(struct Machine *);\nvoid CollectGarbage(struct Machine *, size_t);\nvoid ResetInstructionCache(struct Machine *);\nnexgen32e_f GetOp(long);\nvoid LoadInstruction(struct Machine *, u64);\nint LoadInstruction2(struct Machine *, u64);\nvoid ExecuteInstruction(struct Machine *);\nu64 AllocatePageTable(struct System *);\nu64 AllocateAnonymousPage(struct System *);\nvoid FreeAnonymousPage(struct System *, u8 *);\nu64 FindPageTableEntry(struct Machine *, u64);\nbool CheckMemoryInvariants(struct System *) nosideeffect dontdiscard;\ni64 ReserveVirtual(struct System *, i64, i64, u64, int, i64, bool, bool);\nchar *FormatPml4t(struct Machine *);\ni64 FindVirtual(struct System *, i64, i64);\nint FreeVirtual(struct System *, i64, i64);\nvoid CleanseMemory(struct System *, size_t);\nvoid LoadArgv(struct Machine *, char *, char *, char **, char **, u8[16]);\n_Noreturn void HaltMachine(struct Machine *, int);\n_Noreturn void RaiseDivideError(struct Machine *);\n_Noreturn void ThrowSegmentationFault(struct Machine *, i64);\n_Noreturn void ThrowProtectionFault(struct Machine *);\n_Noreturn void OpUdImpl(struct Machine *);\n_Noreturn void OpUd(P);\nvoid OpHlt(P);\nvoid JitlessDispatch(P);\nvoid RestoreIp(struct Machine *);\nvoid CheckForSignals(struct Machine *);\nvoid UnlockRobustFutexes(struct Machine *);\nvoid *AddToFreeList(struct Machine *, void *);\n\nbool IsValidAddrSize(i64, i64) pureconst;\nchar **CopyStrList(struct Machine *, i64);\nchar *CopyStr(struct Machine *, i64);\nchar *LoadStr(struct Machine *, i64);\nvoid *Schlep(struct Machine *, i64, size_t, u64, u64);\nvoid *SchlepR(struct Machine *, i64, size_t);\nvoid *SchlepW(struct Machine *, i64, size_t);\nvoid *SchlepRW(struct Machine *, i64, size_t);\nbool IsValidMemory(struct Machine *, i64, i64, int);\nint RegisterMemory(struct Machine *, i64, void *, size_t);\ni64 ConvertHostToGuestAddress(struct System *, void *, u64 *);\nu8 *GetPageAddress(struct System *, u64, bool);\nu8 *GetHostAddress(struct Machine *, u64, long);\nu8 *AccessRam(struct Machine *, i64, size_t, void *[2], u8 *, bool);\nu8 *BeginLoadStore(struct Machine *, i64, size_t, void *[2], u8 *);\nu8 *BeginStore(struct Machine *, i64, size_t, void *[2], u8 *);\nu8 *BeginStoreNp(struct Machine *, i64, size_t, void *[2], u8 *);\nint GetFileDescriptorLimit(struct System *);\nbool HasPageLock(const struct Machine *, i64) nosideeffect;\nvoid CollectPageLocks(struct Machine *);\nu8 *LookupAddress(struct Machine *, i64);\nu8 *LookupAddress2(struct Machine *, i64, u64, u64);\nu8 *SpyAddress(struct Machine *, i64);\nu8 *Load(struct Machine *, i64, size_t, u8 *);\nu8 *MallocPage(void);\nu8 *RealAddress(struct Machine *, i64);\nu8 *ReserveAddress(struct Machine *, i64, size_t, bool);\nu8 *ResolveAddress(struct Machine *, i64);\nu8 *GetAddress(struct Machine *, i64);\nvoid CommitStash(struct Machine *);\nint CopyFromUser(struct Machine *, void *, i64, u64);\nint CopyFromUserRead(struct Machine *, void *, i64, u64);\nint CopyToUser(struct Machine *, i64, void *, u64);\nint CopyToUserWrite(struct Machine *, i64, void *, u64);\nvoid EndStore(struct Machine *, i64, size_t, void *[2], u8 *);\nvoid EndStoreNp(struct Machine *, i64, size_t, void *[2], u8 *);\nint GetDescriptor(struct Machine *, int, u64 *);\nvoid ResetRam(struct Machine *);\nvoid SetReadAddr(struct Machine *, i64, u32);\nvoid SetWriteAddr(struct Machine *, i64, u32);\nint SyncVirtual(struct System *, i64, i64, int);\nint ProtectVirtual(struct System *, i64, i64, int, bool);\nbool IsFullyMapped(struct System *, i64, i64);\nbool IsFullyUnmapped(struct System *, i64, i64);\nint GetProtection(u64);\nu64 SetProtection(int);\nint ClassifyOp(u64) pureconst;\nvoid Terminate(P, void (*)(struct Machine *, u64));\nlong GetMaxRss(struct System *);\nlong GetMaxVss(struct System *);\n\nvoid FlushSmcQueue(struct Machine *);\nbool IsPageInSmcQueue(struct Machine *, i64);\nvoid AddPageToSmcQueue(struct Machine *, i64);\ni64 ProtectRwxMemory(struct System *, i64, i64, i64, long, int);\nvoid HandleFatalSystemSignal(struct Machine *, const siginfo_t *);\nbool IsSelfModifyingCodeSegfault(struct Machine *, const siginfo_t *);\n\nint FixXnuSignal(struct Machine *, int, siginfo_t *);\nint FixPpcSignal(struct Machine *, int, siginfo_t *);\n\nvoid CountOp(long *);\nvoid FastPush(struct Machine *, long);\nvoid FastPop(struct Machine *, long);\nvoid FastCall(struct Machine *, u64);\nvoid FastCallAbs(u64, struct Machine *);\nvoid FastJmp(struct Machine *, u64);\nvoid FastJmpAbs(u64, struct Machine *);\nvoid FastLeave(struct Machine *);\ni64 PredictRet(struct Machine *, i64);\n\ntypedef void (*putreg64_f)(u64, struct Machine *);\nextern const putreg64_f kPutReg64[16];\n\nu64 Pick(u32, u64, u64);\ntypedef u32 (*cc_f)(struct Machine *);\nextern const cc_f kConditionCode[16];\n\nvoid Push(P, u64);\nu64 Pop(P, u16);\nvoid PopVq(P);\nvoid PushVq(P);\nint OpOut(struct Machine *, u16, u32);\nu64 OpIn(struct Machine *, u16);\n\nvoid OpBit(P);\nvoid Op0fe(P);\nvoid Op101(P);\nvoid Op171(P);\nvoid Op172(P);\nvoid Op173(P);\nvoid OpAaa(P);\nvoid OpAad(P);\nvoid OpAam(P);\nvoid OpAas(P);\nvoid OpAlub(P);\nvoid OpAluw(P);\nvoid OpAluwi(P);\nvoid OpCallEq(P);\nvoid OpCallJvds(P);\nvoid OpCallf(P);\nvoid OpCallfEq(P);\nvoid OpCmpxchgEbAlGb(P);\nvoid OpCmpxchgEvqpRaxGvqp(P);\nvoid OpCpuid(P);\nvoid OpCvt0f2a(P);\nvoid OpCvt0f2d(P);\nvoid OpCvt0f5a(P);\nvoid OpCvt0f5b(P);\nvoid OpCvt0fE6(P);\nvoid OpCvtt0f2c(P);\nvoid OpDaa(P);\nvoid OpDas(P);\nvoid OpDecEvqp(P);\nvoid OpDivAlAhAxEbSigned(P);\nvoid OpDivAlAhAxEbUnsigned(P);\nvoid OpDivRdxRaxEvqpSigned(P);\nvoid OpDivRdxRaxEvqpUnsigned(P);\nvoid OpEnter(P);\nvoid OpImulGvqpEvqp(P);\nvoid OpImulGvqpEvqpImm(P);\nvoid OpIncEvqp(P);\nvoid OpJmpEq(P);\nvoid OpLeave(P);\nvoid OpMulAxAlEbSigned(P);\nvoid OpMulAxAlEbUnsigned(P);\nvoid OpMulRdxRaxEvqpSigned(P);\nvoid OpMulRdxRaxEvqpUnsigned(P);\nvoid OpNegEb(P);\nvoid OpNegEvqp(P);\nvoid OpNotEb(P);\nvoid OpNotEvqp(P);\nvoid OpPopEvq(P);\nvoid OpPopZvq(P);\nvoid OpPopa(P);\nvoid OpPushEvq(P);\nvoid OpPushZvq(P);\nvoid OpPusha(P);\nvoid OpRdrand(P);\nvoid OpRdseed(P);\nvoid OpRet(P);\nvoid OpRetf(P);\nvoid OpRetIw(P);\nvoid OpSsePclmulqdq(P);\nvoid OpXaddEbGb(P);\nvoid OpXaddEvqpGvqp(P);\nvoid OpXchgGbEb(P);\nvoid OpXchgGvqpEvqp(P);\nvoid Op2f5(P);\nvoid Op2f6(P);\nvoid OpShx(P);\nvoid OpRorx(P);\n\nvoid FreeBig(void *, size_t);\nvoid *AllocateBig(size_t, int, int, int, off_t);\n\nu64 MaskAddress(u32, u64);\ni64 GetIp(struct Machine *);\ni64 GetPc(struct Machine *);\nu64 AddressOb(P);\nu64 AddressDi(P);\ni64 AddressSi(P);\nu64 GetSegmentBase(P, unsigned);\nvoid SetCs(P, u16);\nvoid LongBranch(P, u16, u64);\ni64 DataSegment(P, u64);\ni64 AddSegment(P, u64, u64);\n\nvoid OpLddquVdqMdq(P);\nvoid OpMaskMovDiXmmRegXmmRm(P);\nvoid OpMov0f10(P);\nvoid OpMov0f12(P);\nvoid OpMov0f13(P);\nvoid OpMov0f16(P);\nvoid OpMov0f17(P);\nvoid OpMov0f28(P);\nvoid OpMov0f29(P);\nvoid OpMov0f2b(P);\nvoid OpMov0f6e(P);\nvoid OpMov0f6f(P);\nvoid OpMov0f7e(P);\nvoid OpMov0f7f(P);\nvoid OpMov0fD6(P);\nvoid OpMov0fE7(P);\nvoid OpMovWpsVps(P);\nvoid OpMovntdqaVdqMdq(P);\nvoid OpMovntiMdqpGdqp(P);\nvoid OpPmovmskbGdqpNqUdq(P);\n\nvoid OpUnpcklpsd(P);\nvoid OpUnpckhpsd(P);\nvoid OpPextrwGdqpUdqIb(P);\nvoid OpPinsrwVdqEwIb(P);\nvoid OpShuffle(P);\nvoid OpShufpsd(P);\nvoid OpSqrtpsd(P);\nvoid OpRsqrtps(P);\nvoid OpRcpps(P);\nvoid OpComissVsWs(P);\nvoid OpAddpsd(P);\nvoid OpMulpsd(P);\nvoid OpSubpsd(P);\nvoid OpDivpsd(P);\nvoid OpMinpsd(P);\nvoid OpMaxpsd(P);\nvoid OpCmppsd(P);\nvoid OpAndpsd(P);\nvoid OpAndnpsd(P);\nvoid OpOrpsd(P);\nvoid OpXorpsd(P);\nvoid OpHaddpsd(P);\nvoid OpHsubpsd(P);\nvoid OpAddsubpsd(P);\nvoid OpMovmskpsd(P);\n\nvoid OpIncZv(P);\nvoid OpDecZv(P);\nvoid OpLes(P);\nvoid OpLds(P);\nvoid OpLss(P);\nvoid OpLfs(P);\nvoid OpLgs(P);\nvoid OpJmpf(P);\nvoid OpJmpfEq(P);\nvoid OpClts(P);\nvoid OpRdmsr(P);\nvoid OpWrmsr(P);\nvoid OpMovRqCq(P);\nvoid OpMovCqRq(P);\nvoid OpInAlImm(P);\nvoid OpInAxImm(P);\nvoid OpInAlDx(P);\nvoid OpInAxDx(P);\nvoid OpOutImmAl(P);\nvoid OpOutImmAx(P);\nvoid OpOutDxAl(P);\nvoid OpOutDxAx(P);\nvoid OpMovSwEvqp(P);\nvoid OpMovEvqpSw(P);\nvoid OpPushSeg(P);\nvoid OpPopSeg(P);\n\nextern void (*AddPath_StartOp_Hook)(P);\n\nbool AddPath(P);\nvoid FlushSkew(P);\nbool CreatePath(P);\nvoid CompletePath(P);\nvoid AddPath_EndOp(P);\nbool FuseBranchTest(P);\nvoid AddPath_StartOp(P);\nvoid Connect(P, u64, bool);\nlong GetPrologueSize(void);\nbool FuseBranchCmp(P, bool);\ni64 GetIp(struct Machine *);\nvoid FinishPath(struct Machine *);\nvoid FuseOp(struct Machine *, i64);\nvoid AbandonPath(struct Machine *);\nvoid AddIp(struct Machine *, long);\nvoid BeginCod(struct Machine *, i64);\nvoid AdvanceIp(struct Machine *, long);\nvoid SkewIp(struct Machine *, long, long);\n\nvoid Op2f01(P);\nvoid OpTest(P);\nvoid OpAlui(P);\nvoid LoadAluArgs(P);\nvoid LoadAluFlipArgs(P);\nvoid ZeroRegFlags(struct Machine *, long);\n\ni32 Imul32(i32, i32, struct Machine *);\ni64 Imul64(i64, i64, struct Machine *);\nvoid Mulx64(u64, struct Machine *, long, long);\nu32 JustMul32(u32, u32, struct Machine *);\nu64 JustMul64(u64, u64, struct Machine *);\nvoid MulAxDx(u64, struct Machine *);\nvoid JustMulAxDx(u64, struct Machine *);\n\nvoid OpPsdMuls1(u8 *, struct Machine *, long);\nvoid OpPsdAdds1(u8 *, struct Machine *, long);\nvoid OpPsdSubs1(u8 *, struct Machine *, long);\nvoid OpPsdDivs1(u8 *, struct Machine *, long);\nvoid OpPsdMins1(u8 *, struct Machine *, long);\nvoid OpPsdMaxs1(u8 *, struct Machine *, long);\n\nvoid OpPsdMuld1(u8 *, struct Machine *, long);\nvoid OpPsdAddd1(u8 *, struct Machine *, long);\nvoid OpPsdSubd1(u8 *, struct Machine *, long);\nvoid OpPsdDivd1(u8 *, struct Machine *, long);\nvoid OpPsdMind1(u8 *, struct Machine *, long);\nvoid OpPsdMaxd1(u8 *, struct Machine *, long);\n\nvoid Int64ToFloat(i64, struct Machine *, long);\nvoid Int32ToFloat(i32, struct Machine *, long);\nvoid Int64ToDouble(i64, struct Machine *, long);\nvoid Int32ToDouble(i32, struct Machine *, long);\nvoid MovsdWpsVpsOp(u8 *, struct Machine *, long);\n\nvoid LogCpu(struct Machine *);\nconst char *GetBacktrace(struct Machine *);\nconst char *DescribeOp(struct Machine *, i64);\nint GetInstruction(struct Machine *, i64, struct XedDecodedInst *);\n\nstruct FileMap *GetFileMap(struct System *, i64);\nconst char *GetDirFildesPath(struct System *, int);\nstruct FileMap *AddFileMap(struct System *, i64, i64, const char *, u64);\n\nvoid FlushCod(struct JitBlock *);\n#if LOG_COD\nvoid SetupCod(struct Machine *);\nvoid WriteCod(const char *, ...) printf_attr(1);\nvoid LogCodOp(struct Machine *, const char *);\n#else\n#define SetupCod(m)    (void)0\n#define LogCodOp(m, s) (void)0\n#define WriteCod(...)  (void)0\n#endif\n\nMICRO_OP_SAFE u8 Cpl(struct Machine *m) {\n  return !m->metal                              ? 3u\n         : m->mode.genmode != XED_GEN_MODE_REAL ? (m->cs.sel & 3u)\n                                                : 0u;\n}\n\n#define BEGIN_NO_PAGE_FAULTS \\\n  {                          \\\n    bool nofault_;           \\\n    nofault_ = m->nofault;   \\\n    m->nofault = true\n\n#define END_NO_PAGE_FAULTS \\\n  m->nofault = nofault_;   \\\n  }\n\nstatic inline u8 *FindHostPage(u64 entry) {\n  if (HasLinearMapping()) {\n    return (u8 *)(uintptr_t)(entry & PAGE_TA);\n  } else {\n    return g_hostpages.p[(entry & PAGE_TA) >> 12];\n  }\n}\n\n#endif /* BLINK_MACHINE_H_ */\n"
  },
  {
    "path": "blink/macros.h",
    "content": "#ifndef BLINK_MACROS_H_\n#define BLINK_MACROS_H_\n\n#ifdef MIN\n#undef MIN\n#endif\n\n#ifdef MAX\n#undef MAX\n#endif\n\n#define ROUNDDOWN(X, K) ((X) & -(K))\n#define ROUNDUP(X, K)   (((X) + (K)-1) & -(K))\n#define IS2POW(X)       (!((X) & ((X)-1)))\n#define ABS(X)          ((X) >= 0 ? (X) : -(X))\n#define MIN(X, Y)       ((Y) > (X) ? (X) : (Y))\n#define MAX(X, Y)       ((Y) < (X) ? (X) : (Y))\n#define ARRAYLEN(A) \\\n  ((long)((sizeof(A) / sizeof(*(A))) / ((unsigned)!(sizeof(A) % sizeof(*(A))))))\n\n#endif /* BLINK_MACROS_H_ */\n"
  },
  {
    "path": "blink/magikarp.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/macros.h\"\n#include \"blink/types.h\"\n#include \"blink/util.h\"\n\n/**\n * Decimates array using John Costella's Magic Kernel Sharp.\n *\n * The Magic Kernel Sharp is the combination of two kernels:\n *\n * - `{1, 3, 3, 1}` for scaling\n * - `{1, 6, 1}` for sharpening\n *\n * Together they form the kernel `{-1, -3, 3, 17, 17, 3, -3, -1}` which\n * resembles the sinc function. Here's an example of how it works. Let's\n * say we want to shrink the following array in half:\n *\n *     u8 A[] = {20, 20, 0, 0, 20, 20, 0, 0, 20, 20};\n *\n * Using Magikarp, we'd write the following code:\n *\n *     int i, n = Magikarp(A, ARRAYLEN(A));\n *     for (i = 0; i < n; ++i) {\n *       if (i) printf(\", \");\n *       printf(\"%d\", A[i]);\n *     }\n *     printf(\"\\n\");\n *\n * Which would then print the new array:\n *\n *     20, 0, 20, 0, 20\n *\n * @param p is array of unsigned bytes, which is modified in place\n * @param n is number of bytes in `p`\n * @return new length of array\n */\nlong Magikarp(u8 *p, long n) {\n  u8 *q;\n  long h, i;\n  if (n < 2) return n;\n  q = (u8 *)malloc(3 + n + 4);\n  q[0] = p[0];\n  q[1] = p[0];\n  q[2] = p[0];\n  memcpy(q + 3, p, n);\n  q[3 + n + 0] = p[n - 1];\n  q[3 + n + 1] = p[n - 1];\n  q[3 + n + 2] = p[n - 1];\n  q[3 + n + 3] = p[n - 1];\n  q += 3;\n  h = (n + 1) >> 1;\n  for (i = 0; i < h; ++i) {\n    short x0, x1, x2, x3, x4, x5, x6, x7;\n    x0 = q[i * 2 - 3];\n    x1 = q[i * 2 - 2];\n    x2 = q[i * 2 - 1];\n    x3 = q[i * 2 + 0];\n    x4 = q[i * 2 + 1];\n    x5 = q[i * 2 + 2];\n    x6 = q[i * 2 + 3];\n    x7 = q[i * 2 + 4];\n    x0 *= -1;\n    x1 *= -3;\n    x2 *= +3;\n    x3 *= 17;\n    x4 *= 17;\n    x5 *= +3;\n    x6 *= -3;\n    x7 *= -1;\n    x0 += x1;\n    x2 += x3;\n    x4 += x5;\n    x6 += x7;\n    x0 += x2;\n    x4 += x6;\n    x0 += x4;\n    x0 += 1 << 4;\n    x0 >>= 5;\n    p[i] = MIN(255, MAX(0, x0));\n  }\n  free(q - 3);\n  return h;\n}\n"
  },
  {
    "path": "blink/map.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/map.h\"\n\n#include <errno.h>\n#include <inttypes.h>\n#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/bus.h\"\n#include \"blink/debug.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/tunables.h\"\n#include \"blink/types.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n\nstatic long GetSystemPageSize(void) {\n#ifdef __EMSCRIPTEN__\n  // \"pages\" in Emscripten only refer to the granularity the memory\n  // buffer can be grown at but does not affect functions like mmap\n  return 4096;\n#else\n  long z;\n#ifdef _SC_GRANSIZE\n  unassert((z = sysconf(_SC_GRANSIZE)) > 0);\n#else\n  unassert((z = sysconf(_SC_PAGESIZE)) > 0);\n#endif\n  unassert(IS2POW(z));\n  return MAX(4096, z);\n#endif\n}\n\nstatic void *PortableMmap(void *addr,     //\n                          size_t length,  //\n                          int prot,       //\n                          int flags,      //\n                          int fd,         //\n                          off_t offset) {\n  void *res;\n#ifdef HAVE_MAP_ANONYMOUS\n  res = VfsMmap(addr, length, prot, flags, fd, offset);\n#else\n  // MAP_ANONYMOUS isn't defined by POSIX.1\n  // they do however define the unlink hack\n  _Static_assert(!(MAP_ANONYMOUS_ & MAP_FIXED), \"\");\n  _Static_assert(!(MAP_ANONYMOUS_ & MAP_SHARED), \"\");\n  _Static_assert(!(MAP_ANONYMOUS_ & MAP_PRIVATE), \"\");\n  int tfd;\n  char path[] = \"/tmp/blink.dat.XXXXXX\";\n  if (~flags & MAP_ANONYMOUS_) {\n    res = VfsMmap(addr, length, prot, flags, fd, offset);\n  } else if ((tfd = mkstemp(path)) != -1) {\n    unlink(path);\n    if (!ftruncate(tfd, length)) {\n      res = mmap(addr, length, prot, flags & ~MAP_ANONYMOUS_, tfd, 0);\n    } else {\n      res = MAP_FAILED;\n    }\n    close(tfd);\n  } else {\n    res = MAP_FAILED;\n  }\n#endif\n#ifdef MAP_FIXED_NOREPLACE\n  if ((flags & MAP_FIXED_NOREPLACE) && res == MAP_FAILED &&\n      errno == EOPNOTSUPP) {\n    res = VfsMmap(addr, length, prot, flags & ~MAP_FIXED_NOREPLACE, fd, offset);\n    if (res != addr) {\n      VfsMunmap(res, length);\n      res = MAP_FAILED;\n      errno = EEXIST;\n    }\n  }\n#endif\n  return res;\n}\n\nstatic int GetBitsInAddressSpace(void) {\n#ifdef __EMSCRIPTEN__\n  return 32;\n#else\n  int i;\n  void *ptr;\n  uint64_t want;\n  for (i = 16; i < 40; ++i) {\n    want = UINT64_C(0x8123000000000000) >> i;\n    if (want > UINTPTR_MAX) continue;\n    if (Msync((void *)(uintptr_t)want, 1, MS_ASYNC, \"vabits\") == 0 ||\n        errno == EBUSY) {\n      return 64 - i;\n    }\n    ptr = PortableMmap((void *)(uintptr_t)want, 1, PROT_READ,\n                       MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS_, -1, 0);\n    if (ptr != MAP_FAILED) {\n      VfsMunmap(ptr, 1);\n      return 64 - i;\n    }\n  }\n  Abort();\n#endif\n}\n\nstatic u64 GetVirtualAddressSpace(int vabits, long pagesize) {\n  u64 vaspace;\n  vaspace = (u64)1 << (vabits - 1);  // 0000400000000000\n  vaspace |= vaspace - 1;            // 00007fffffffffff\n  vaspace &= ~(pagesize - 1);        // 00007ffffffff000\n  return vaspace;\n}\n\nstatic u64 ScaleAddress(u64 address) {\n  long pagesize;\n  u64 result, vaspace;\n  vaspace = FLAG_vaspace;\n  pagesize = FLAG_pagesize;\n  result = address;\n  do result &= ~(pagesize - 1);\n  while ((result & ~vaspace) && (result >>= 1));\n  return result;\n}\n\n// if the guest used mmap(0, ...) to let blink decide the address,\n// then the goal is to supply mmap(0, ...) to the host kernel too;\n// but we can't do that on systems like rasberry pi, since they'll\n// assign addresses greater than 2**47 which won't fit with x86_64\nvoid InitMap(void) {\n  FLAG_pagesize = GetSystemPageSize();\n  FLAG_vabits = GetBitsInAddressSpace();\n  FLAG_vaspace = GetVirtualAddressSpace(FLAG_vabits, FLAG_pagesize);\n  FLAG_aslrmask = ScaleAddress(kAslrMask);\n  FLAG_imagestart = ScaleAddress(kImageStart);\n  FLAG_automapstart = ScaleAddress(kAutomapStart);\n  FLAG_automapend = ScaleAddress(kAutomapEnd);\n  FLAG_dyninterpaddr = ScaleAddress(kDynInterpAddr);\n  FLAG_stacktop = ScaleAddress(kStackTop);\n}\n\nvoid *Mmap(void *addr,     //\n           size_t length,  //\n           int prot,       //\n           int flags,      //\n           int fd,         //\n           off_t offset,   //\n           const char *owner) {\n  void *res;\n#if LOG_MEM\n  char szbuf[16];\n#endif\n#if defined(__NetBSD__)\n  if (!(flags & MAP_SHARED)) {\n    prot |= PROT_MPROTECT(PROT_EXEC | PROT_WRITE | PROT_READ);\n  }\n#endif\n  res = PortableMmap(addr, length, prot, flags, fd, offset);\n#if LOG_MEM\n  FormatSize(szbuf, length, 1024);\n  if (res != MAP_FAILED) {\n    MEM_LOGF(\"%s created %s byte %smap [%p,%p) as %s flags=%#x fd=%d \"\n             \"offset=%#\" PRIx64,\n             owner, szbuf, (flags & MAP_SHARED) ? \"shared \" : \"\", res,\n             (u8 *)res + length, DescribeProt(prot), flags, fd, (i64)offset);\n  } else {\n    MEM_LOGF(\"%s failed to create %s map [%p,%p) as %s flags %#x: %s \"\n             \"(system page size is %ld)\",\n             owner, szbuf, (u8 *)addr, (u8 *)addr + length, DescribeProt(prot),\n             flags, DescribeHostErrno(errno), FLAG_pagesize);\n  }\n#endif\n  return res;\n}\n\nint Munmap(void *addr, size_t length) {\n  int rc;\n  rc = VfsMunmap(addr, length);\n#if LOG_MEM\n  char szbuf[16];\n  FormatSize(szbuf, length, 1024);\n  if (!rc) {\n    MEM_LOGF(\"unmapped %s bytes at [%p,%p)\", szbuf, addr, (u8 *)addr + length);\n  } else {\n    MEM_LOGF(\"failed to unmap %s bytes at [%p,%p): %s\", szbuf, addr,\n             (u8 *)addr + length, DescribeHostErrno(errno));\n  }\n#endif\n  return rc;\n}\n\nint Mprotect(void *addr,     //\n             size_t length,  //\n             int prot,       //\n             const char *owner) {\n  int res = VfsMprotect(addr, length, prot);\n#if LOG_MEM\n  char szbuf[16];\n  FormatSize(szbuf, length, 1024);\n  if (res != -1) {\n    MEM_LOGF(\"%s protected %s byte map [%p,%p) as %s\", owner, szbuf, addr,\n             (u8 *)addr + length, DescribeProt(prot));\n  } else {\n    MEM_LOGF(\"%s failed to protect %s byte map [%p,%p) as %s: %s\", owner, szbuf,\n             (u8 *)addr, (u8 *)addr + length, DescribeProt(prot),\n             DescribeHostErrno(errno));\n  }\n#endif\n  return res;\n}\n\nint Msync(void *addr,     //\n          size_t length,  //\n          int flags,      //\n          const char *owner) {\n#if defined(__FILC__)\n  if (1) return 0;\n#endif\n  int res = VfsMsync(addr, length, flags);\n#if LOG_MEM\n  char szbuf[16];\n  FormatSize(szbuf, length, 1024);\n  if (res != -1) {\n    MEM_LOGF(\"%s synced %s byte map [%p,%p) as %#x\", owner, szbuf, addr,\n             (u8 *)addr + length, flags);\n  } else {\n    MEM_LOGF(\"%s failed to sync %s byte map [%p,%p) as %#x: %s\", owner, szbuf,\n             (u8 *)addr, (u8 *)addr + length, flags, DescribeHostErrno(errno));\n  }\n#endif\n  return res;\n}\n"
  },
  {
    "path": "blink/map.h",
    "content": "#ifndef BLINK_MAP_H_\n#define BLINK_MAP_H_\n#include <errno.h>\n#include <sys/mman.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/thread.h\"\n#include \"blink/types.h\"\n\n#ifndef MAP_NORESERVE\n#define MAP_NORESERVE 0\n#endif\n\n#if defined(__APPLE__) && defined(__aarch64__)\n#include <libkern/OSCacheControl.h>\n#else\n#define pthread_jit_write_protect_supported_np() 0\n#define pthread_jit_write_protect_np(x)          (void)(x)\n#define sys_icache_invalidate(addr, size) \\\n  __builtin___clear_cache((char *)(addr), (char *)(addr) + (size));\n#endif\n\n#ifdef HAVE_MAP_ANONYMOUS\n#define MAP_ANONYMOUS_ MAP_ANONYMOUS\n#else\n#define MAP_ANONYMOUS_ 0x10000000\n#endif\n\n// MAP_DEMAND means use MAP_FIXED only if it won't clobber other maps\n#if defined(MAP_FIXED_NOREPLACE) && !defined(__SANITIZE_THREAD__)\n// The mmap() address parameter without MAP_FIXED is documented by\n// Linux as a hint for locality. However our testing indicates the\n// kernel is still likely to assign addresses that're outrageously\n// far away from what was requested. So we're just going to choose\n// something that's past the program break, and hope for the best.\n#define MAP_DEMAND MAP_FIXED_NOREPLACE\n#define MAP_DENIED EEXIST\n#elif defined(MAP_EXCL)\n// FreeBSD also supports this feature but it uses a clumsier errno\n#define MAP_DEMAND (MAP_FIXED | MAP_EXCL)\n#define MAP_DENIED EINVAL\n#else\n// Otherwise detect overlap when mmap() returns an unexpected address\n#define MAP_DEMAND 0\n#define MAP_DENIED 0\n#endif\n\n// from the xnu codebase\n#define _COMM_PAGE_START_ADDRESS      UINT64_C(0x0000000FFFFFC000)\n#define _COMM_PAGE_APRR_SUPPORT       (_COMM_PAGE_START_ADDRESS + 0x10C)\n#define _COMM_PAGE_APRR_WRITE_ENABLE  (_COMM_PAGE_START_ADDRESS + 0x110)\n#define _COMM_PAGE_APRR_WRITE_DISABLE (_COMM_PAGE_START_ADDRESS + 0x118)\n\nvoid InitMap(void);\nint Munmap(void *, size_t);\nint Msync(void *, size_t, int, const char *);\nvoid *Mmap(void *, size_t, int, int, int, off_t, const char *);\nint Mprotect(void *, size_t, int, const char *);\nvoid OverridePageSize(long);\n\n#endif /* BLINK_MAP_H_ */\n"
  },
  {
    "path": "blink/mda.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/mda.h\"\n\n#include \"blink/bda.h\"\n#include \"blink/blinkenlights.h\"\n#include \"blink/buffer.h\"\n#include \"blink/macros.h\"\n#include \"blink/util.h\"\n\n#define kBlink     1\n#define kVisible   2\n#define kUnderline 4\n#define kBold      8\n#define kReverse   16\n\n#define CURSOR '_'\n\n/**\n * Decodes Monochrome Display Adapter attributes.\n * @see https://www.seasip.info/VintagePC/mda.html\n */\nstatic u8 DecodeMdaAttributes(i8 a) {\n  u8 r = 0;\n  if (a & 0x77) {\n    if ((a & 0x77) == 0x70) r |= kReverse;\n    if ((a & 0x07) == 0x01) r |= kUnderline;\n    if (a & 0x08) r |= kBold;\n    if (a < 0) r |= kBlink;\n    r |= kVisible;\n  }\n  return r;\n}\n\nvoid DrawMda(struct Panel *p, u8 v[25][80][2], int curx, int cury) {\n  wint_t wch = 0;\n  unsigned y, x, n, a, b, ch, attr;\n  n = MIN(25, p->bottom - p->top);\n  for (y = 0; y < n; ++y) {\n    a = -1;\n    for (x = 0; x < 80; ++x) {\n      ch = v[y][x][0];\n      attr = v[y][x][1];\n      if (!BdaCurhidden && x == curx && y == cury) {\n        if (ch == ' ' || ch == '\\0') {\n          ch = CURSOR;\n          attr = 0x07;\n        } else {\n          wch = GetVidyaByte(ch);\n          attr = 0x70;\n        }\n        a = -1;\n      } else {\n        wch = GetVidyaByte(ch);\n      }\n      b = DecodeMdaAttributes(attr);\n      if (a != b) {\n        a = b;\n        AppendStr(&p->lines[y], \"\\033[0\");\n        if (a & kBold) AppendStr(&p->lines[y], \";1\");\n        if (a & kUnderline) AppendStr(&p->lines[y], \";4\");\n        if (a & kBlink) AppendStr(&p->lines[y], \";5\");\n        if (a & kReverse) AppendStr(&p->lines[y], \";7\");\n        AppendChar(&p->lines[y], 'm');\n      }\n      AppendWide(&p->lines[y], wch);\n    }\n  }\n}\n"
  },
  {
    "path": "blink/mda.h",
    "content": "#ifndef BLINK_MDA_H_\n#define BLINK_MDA_H_\n#include \"blink/panel.h\"\n#include \"blink/types.h\"\n\nvoid DrawMda(struct Panel *, u8[25][80][2], int, int);\n\n#endif /* BLINK_MDA_H_ */\n"
  },
  {
    "path": "blink/memccpy.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/util.h\"\n\nvoid *memccpy_(void *dst, const void *src, int c, size_t n) {\n  size_t i;\n  unsigned char *d = (unsigned char *)dst;\n  const unsigned char *s = (const unsigned char *)src;\n  for (i = 0; i < n; ++i) {\n    if ((d[i] = s[i]) == (c & 255)) {\n      return d + i + 1;\n    }\n  }\n  return 0;\n}\n"
  },
  {
    "path": "blink/memcpy.h",
    "content": "#ifndef BLINK_MEMCPY_H_\n#define BLINK_MEMCPY_H_\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"blink/builtin.h\"\n\n#if !defined(TINY) && defined(__x86_64__) && defined(__GNUC__) && \\\n    !defined(__COSMOPOLITAN__) && !defined(__GLIBC__) && !defined(__FILC__)\n\n#ifdef memcpy\n#undef memcpy\n#endif\n\n#define memcpy(x, y, z) BetterMemcpyX86(x, y, z)\n\nforceinline void *RepMovsb(void *di, const void *si, size_t cx) {\n  asm(\"rep movsb\"\n      : \"=D\"(di), \"=S\"(si), \"=c\"(cx), \"=m\"(*(char(*)[cx])di)\n      : \"0\"(di), \"1\"(si), \"2\"(cx), \"m\"(*(char(*)[cx])si));\n  return di;\n}\n\nstatic inline void *BetterMemcpyX86(void *dst, const void *src, size_t n) {\n  char *d;\n  size_t i;\n  uint64_t a, b;\n  const char *s;\n  d = (char *)dst;\n  s = (const char *)src;\n  switch (n) {\n    case 0:\n      return d;\n    case 1:\n      *d = *s;\n      return d;\n    case 2:\n      __builtin_memcpy(&a, s, 2);\n      __builtin_memcpy(d, &a, 2);\n      return d;\n    case 3:\n      __builtin_memcpy(&a, s, 2);\n      __builtin_memcpy(&b, s + 1, 2);\n      __builtin_memcpy(d, &a, 2);\n      __builtin_memcpy(d + 1, &b, 2);\n      return d;\n    case 4:\n      __builtin_memcpy(&a, s, 4);\n      __builtin_memcpy(d, &a, 4);\n      return d;\n    case 5:\n    case 6:\n    case 7:\n      __builtin_memcpy(&a, s, 4);\n      __builtin_memcpy(&b, s + n - 4, 4);\n      __builtin_memcpy(d, &a, 4);\n      __builtin_memcpy(d + n - 4, &b, 4);\n      return d;\n    case 8:\n      __builtin_memcpy(&a, s, 8);\n      __builtin_memcpy(d, &a, 8);\n      return d;\n    case 9:\n    case 10:\n    case 11:\n    case 12:\n    case 13:\n    case 14:\n    case 15:\n    case 16:\n      __builtin_memcpy(&a, s, 8);\n      __builtin_memcpy(&b, s + n - 8, 8);\n      __builtin_memcpy(d, &a, 8);\n      __builtin_memcpy(d + n - 8, &b, 8);\n      return d;\n    default:\n      if (n <= 64) {\n        i = 0;\n        do {\n          __builtin_memcpy(&a, s + i, 8);\n          asm volatile(\"\" ::: \"memory\");\n          __builtin_memcpy(d + i, &a, 8);\n        } while ((i += 8) + 8 <= n);\n        for (; i < n; ++i) d[i] = s[i];\n        return d;\n      } else {\n        RepMovsb(d, s, n);\n        return d;\n      }\n  }\n}\n\n#endif /* MUSL */\n#endif /* BLINK_MEMCPY_H_ */\n"
  },
  {
    "path": "blink/memory.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n\n#include \"blink/assert.h\"\n#include \"blink/biosrom.h\"\n#include \"blink/bus.h\"\n#include \"blink/checked.h\"\n#include \"blink/debug.h\"\n#include \"blink/endian.h\"\n#include \"blink/errno.h\"\n#include \"blink/linux.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/pml4t.h\"\n#include \"blink/stats.h\"\n#include \"blink/thread.h\"\n#include \"blink/util.h\"\n#include \"blink/x86.h\"\n\nvoid SetReadAddr(struct Machine *m, i64 addr, u32 size) {\n  if (size) {\n    m->readaddr = addr;\n    m->readsize = size;\n  }\n}\n\nvoid SetWriteAddr(struct Machine *m, i64 addr, u32 size) {\n  if (size) {\n    m->writeaddr = addr;\n    m->writesize = size;\n  }\n}\n\nu8 *GetPageAddress(struct System *s, u64 entry, bool is_cr3) {\n  unassert(is_cr3 || (entry & PAGE_V));\n  unassert(~entry & PAGE_RSRV);\n  if (entry & PAGE_HOST) {\n    return FindHostPage(entry);\n  } else {\n    unassert(s->real);\n    if ((entry & PAGE_TA) + 4096 <= kRealSize) {\n      return s->real + (entry & PAGE_TA);\n    } else {\n      return 0;\n    }\n  }\n}\n\nu64 HandlePageFault(struct Machine *m, u8 *pslot, u64 entry) {\n  u64 x, page;\n  unassert(entry & PAGE_RSRV);\n  unassert(!HasLinearMapping());\n  if (m->nofault) {\n    m->segvcode = SEGV_MAPERR_LINUX;\n    errno = ENOBUFS;\n    return 0;\n  }\n  do {\n    if (entry & (PAGE_HOST | PAGE_MAP | PAGE_MUG)) {\n      // a file-mapped page is being accessed for the first time\n      unassert((entry & (PAGE_HOST | PAGE_MAP)) == (PAGE_HOST | PAGE_MAP));\n      x = entry & ~PAGE_RSRV;\n      if (CasPte(pslot, entry, x)) {\n        m->system->memstat.committed += 1;\n        m->system->memstat.reserved -= 1;\n        m->system->rss += 1;\n        entry = x;\n      } else {\n        entry = LoadPte(pslot);\n      }\n    } else {\n      // an anonymous page is being accessed for the first time\n      if ((page = AllocateAnonymousPage(m->system)) == -1) {\n        m->segvcode = SEGV_MAPERR_LINUX;\n        entry = 0;\n        break;\n      }\n      x = (page & (PAGE_TA | PAGE_HOST)) | (entry & ~(PAGE_TA | PAGE_RSRV));\n      if (CasPte(pslot, entry, x)) {\n        m->system->memstat.committed += 1;\n        m->system->memstat.reserved -= 1;\n        entry = x;\n      } else {\n        FreeAnonymousPage(m->system, (u8 *)(uintptr_t)(page & PAGE_TA));\n        entry = LoadPte(pslot);\n        m->system->rss -= 1;\n      }\n    }\n  } while (entry & PAGE_RSRV);\n  return entry;\n}\n\nbool HasPageLock(const struct Machine *m, i64 page) {\n  int i;\n  unassert(!(page & 4095));\n  for (i = m->pagelocks.i; i--;) {\n    if (m->pagelocks.p[i].page == page) {\n      return true;\n    }\n  }\n  return false;\n}\n\nstatic bool RecordPageLock(struct Machine *m, i64 page, u8 *pslot) {\n  unassert(m->sysdepth > 0);\n  unassert(!m->pagelocks.i ||\n           m->pagelocks.p[m->pagelocks.i - 1].sysdepth <= m->sysdepth);\n  if (m->pagelocks.i == m->pagelocks.n) {\n    int n2;\n    struct PageLock *p2;\n    p2 = m->pagelocks.p;\n    n2 = m->pagelocks.n;\n    n2 += 3;\n    n2 += n2 >> 1;\n    if ((p2 = (struct PageLock *)realloc(p2, n2 * sizeof(*p2)))) {\n      m->pagelocks.p = p2;\n      m->pagelocks.n = n2;\n    } else {\n      return false;\n    }\n  }\n  m->pagelocks.p[m->pagelocks.i].page = page;\n  m->pagelocks.p[m->pagelocks.i].pslot = pslot;\n  m->pagelocks.p[m->pagelocks.i].sysdepth = m->sysdepth;\n  ++m->pagelocks.i;\n  STATISTIC(++page_locks);\n  return true;\n}\n\nstatic void ReleasePageLock(u8 *pslot) {\n  u64 entry;\n  do {\n    entry = LoadPte(pslot);\n    unassert(entry & PAGE_V);\n    unassert(entry & PAGE_LOCKS);\n  } while (!CasPte(pslot, entry, entry - PAGE_LOCK));\n}\n\nstatic bool HasOutdatedPageLocks(struct Machine *m) {\n  return m->pagelocks.i &&\n         m->pagelocks.p[m->pagelocks.i - 1].sysdepth > m->sysdepth;\n}\n\nvoid CollectPageLocks(struct Machine *m) {\n  if (HasOutdatedPageLocks(m)) {\n    LOCK(&m->system->pagelocks_lock);\n    do ReleasePageLock(m->pagelocks.p[--m->pagelocks.i].pslot);\n    while (HasOutdatedPageLocks(m));\n    unassert(!pthread_cond_broadcast(&m->system->pagelocks_cond));\n    UNLOCK(&m->system->pagelocks_lock);\n  }\n}\n\n// returns page directory entry associated with virtual address\n// @return raw page directory entry contents, or zero w/ errno\n// @raise EFAULT if a valid 4096 page didn't exist at address\n// @raise ENOMEM if memory couldn't be allocated internally\n// @raise EAGAIN if too many locks are held on a page\nu64 FindPageTableEntry(struct Machine *m, u64 page) {\n  u8 *pslot;\n  i64 table;\n  u64 entry;\n  long tlbkey;\n  unsigned level, index;\n  if (UNLIKELY(atomic_load_explicit(&m->invalidated, memory_order_acquire))) {\n    ResetTlb(m);\n    atomic_store_explicit(&m->invalidated, false, memory_order_relaxed);\n  }\n  tlbkey = (page >> 12) & (ARRAYLEN(m->tlb) - 1);\n  if (LIKELY(m->tlb[tlbkey].page == page &&\n             ((entry = m->tlb[tlbkey].entry) & PAGE_V))) {\n    STATISTIC(++tlb_hits);\n    return entry;\n  }\n  STATISTIC(++tlb_misses);\n  unassert(!(page & 4095));\n  if (!(-0x800000000000 <= (i64)page && (i64)page < 0x800000000000)) {\n    m->segvcode = SEGV_MAPERR_LINUX;\n    return (u64)(uintptr_t)efault0();\n  }\nTryAgain:\n  unassert((entry = m->system->cr3));\n  level = 39;\n  do {\n    table = entry;\n    index = (page >> level) & 511;\n    pslot = GetPageAddress(m->system, table, level == 39) + index * 8;\n    if (!pslot) goto MapError;\n    entry = LoadPte(pslot);\n    if (!(entry & PAGE_V)) goto MapError;\n    if (m->metal) {\n      entry &= ~(u64)(PAGE_RSRV | PAGE_HOST | PAGE_MAP | PAGE_GROW | PAGE_MUG |\n                      PAGE_FILE);\n    }\n    if ((entry & PAGE_PS) && level > 12) {\n      // huge (1 GiB or 2 MiB) page; \"rewrite\" the TLB copy of the page table\n      // entry, to point to the 4 KiB subpage being accessed\n      // TODO: if partial TLB flushes are implemented in the future, we will\n      // also need to somehow record the original huge page size in the TLB,\n      // so we can correctly invalidate all TLB entries for the huge page\n      u64 submask = ((u64)1 << level) - 4096;\n      entry &= ~submask;\n      entry |= page & submask;\n      break;\n    }\n  } while ((level -= 9) >= 12);\n  if ((entry & PAGE_RSRV) && !(entry = HandlePageFault(m, pslot, entry))) {\n    return 0;\n  }\n  // system calls lock the pages they access\n  // this prevents race conditions w/ munmap\n  if (m->insyscall && !m->nofault && !HasPageLock(m, page)) {\n    if ((entry & PAGE_LOCKS) < PAGE_LOCKS) {\n      if (CasPte(pslot, entry, entry + PAGE_LOCK)) {\n        unassert(LoadPte(pslot) & PAGE_LOCKS);\n        if (RecordPageLock(m, page, pslot)) {\n          entry += PAGE_LOCK;\n        } else {\n          ReleasePageLock(pslot);\n          m->segvcode = SEGV_MAPERR_LINUX;\n          return 0;\n        }\n      } else {\n        goto TryAgain;\n      }\n    } else {\n      LOGF(\"too many threads locked page %#\" PRIx64, page);\n      m->segvcode = SEGV_MAPERR_LINUX;\n      errno = EAGAIN;\n      return 0;\n    }\n  }\n  m->tlb[tlbkey].page = page;\n  m->tlb[tlbkey].entry = entry;\n  return entry;\nMapError:\n  m->segvcode = SEGV_MAPERR_LINUX;\n  return (uintptr_t)efault0();\n}\n\nu8 *LookupAddress2(struct Machine *m, i64 virt, u64 mask, u64 need) {\n  u8 *host;\n  u64 entry;\n  if (!m->metal || m->mode.omode == XED_MODE_LONG ||\n      (m->mode.genmode != XED_GEN_MODE_REAL && (m->system->cr0 & CR0_PG))) {\n    if (!(entry = FindPageTableEntry(m, virt & -4096))) {\n      return 0;\n    }\n  } else if (virt >= 0 && virt <= 0xffffffff &&\n             (virt & 0xffffffff) + 4095 < kRealSize) {\n    unassert(m->system->real);\n    return m->system->real + virt;\n  } else {\n    m->segvcode = SEGV_MAPERR_LINUX;\n    return (u8 *)efault0();\n  }\n  if ((entry & mask) != need) {\n    m->segvcode = SEGV_ACCERR_LINUX;\n    return (u8 *)efault0();\n  }\n#ifndef DISABLE_JIT\n  if ((need & PAGE_RW) &&\n      (entry & (PAGE_U | PAGE_RW | PAGE_XD)) == (PAGE_U | PAGE_RW) &&\n      !IsJitDisabled(&m->system->jit) && !IsPageInSmcQueue(m, virt)) {\n    AddPageToSmcQueue(m, virt);\n  }\n#endif\n  if ((host = GetPageAddress(m->system, entry, false))) {\n    return host + (virt & 4095);\n  } else {\n    m->segvcode = SEGV_MAPERR_LINUX;\n    return (u8 *)efault0();\n  }\n}\n\nu8 *LookupAddress(struct Machine *m, i64 virt) {\n  u64 need = 0;\n  if (Cpl(m) == 3) need = PAGE_U;\n  return LookupAddress2(m, virt, need, need);\n}\n\nflattencalls u8 *GetAddress(struct Machine *m, i64 v) {\n  if (HasLinearMapping()) return ToHost(v);\n  return LookupAddress(m, v);\n}\n\n/**\n * Translates virtual address into pointer.\n *\n * This function bypasses memory protection, since it's used to display\n * memory in the debugger tui. That's useful, for example, if debugging\n * programs that specify an eXecute-only program header.\n *\n * It's recommended that the caller use:\n *\n *     BEGIN_NO_PAGE_FAULTS;\n *     i64 address = ...;\n *     u8 *pointer = SpyAddress(m, address);\n *     END_NO_PAGE_FAULTS;\n *\n * When calling this function.\n */\nu8 *SpyAddress(struct Machine *m, i64 virt) {\n  return LookupAddress2(m, virt, 0, 0);\n}\n\nu8 *ResolveAddress(struct Machine *m, i64 v) {\n  u8 *r;\n  if ((r = GetAddress(m, v))) return r;\n  ThrowSegmentationFault(m, v);\n}\n\nbool IsValidMemory(struct Machine *m, i64 virt, i64 size, int prot) {\n  i64 p, pe;\n  u64 pte, mask, need;\n  size += virt & 4095;\n  virt &= -4096;\n  unassert(m->mode.omode == XED_MODE_LONG);\n  unassert(prot && !(prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)));\n  need = mask = 0;\n  if (prot & PROT_READ) {\n    mask |= PAGE_U;\n    need |= PAGE_U;\n  }\n  if (prot & PROT_WRITE) {\n    mask |= PAGE_RW;\n    need |= PAGE_RW;\n  }\n  if (prot & PROT_EXEC) {\n    mask |= PAGE_XD;\n  }\n  if (ckd_add(&pe, virt, size)) {\n    eoverflow();\n    return false;\n  }\n  for (p = virt; p < pe; p += 4096) {\n    if (!(pte = FindPageTableEntry(m, p))) {\n      return false;\n    }\n    if ((pte & mask) != need) {\n      errno = EFAULT;\n      return false;\n    }\n  }\n  return true;\n}\n\nint VirtualCopy(struct Machine *m, i64 v, char *r, u64 n, bool d) {\n  u8 *p;\n  u64 k;\n  k = 4096 - (v & 4095);\n  while (n) {\n    k = MIN(k, n);\n    if (!(p = LookupAddress(m, v))) return -1;\n    if (d) {\n      memcpy(r, p, k);\n    } else if (!IsRomAddress(m, p)) {\n      memcpy(p, r, k);\n    }\n    n -= k;\n    r += k;\n    v += k;\n    k = 4096;\n  }\n  return 0;\n}\n\nint CopyFromUser(struct Machine *m, void *dst, i64 src, u64 n) {\n  return VirtualCopy(m, src, (char *)dst, n, true);\n}\n\nint CopyFromUserRead(struct Machine *m, void *dst, i64 addr, u64 n) {\n  if (CopyFromUser(m, dst, addr, n) == -1) return -1;\n  SetReadAddr(m, addr, n);\n  return 0;\n}\n\nint CopyToUser(struct Machine *m, i64 dst, void *src, u64 n) {\n  return VirtualCopy(m, dst, (char *)src, n, false);\n}\n\nint CopyToUserWrite(struct Machine *m, i64 addr, void *src, u64 n) {\n  if (CopyToUser(m, addr, src, n) == -1) return -1;\n  SetWriteAddr(m, addr, n);\n  return 0;\n}\n\nvoid CommitStash(struct Machine *m) {\n  unassert(m->stashaddr);\n  if (m->opcache->writable) {\n    CopyToUser(m, m->stashaddr, m->opcache->stash, m->opcache->stashsize);\n  }\n  m->stashaddr = 0;\n}\n\nu8 *ReserveAddress(struct Machine *m, i64 v, size_t n, bool writable) {\n  long k;\n  u64 mask, need;\n  u8 *res, *p1, *p2;\n  if (writable) {\n    SetWriteAddr(m, v, n);\n  } else {\n    SetReadAddr(m, v, n);\n  }\n  if (HasLinearMapping()) {\n    return ToHost(v);\n  }\n  m->reserving = true;\n  if (Cpl(m) == 3) {\n    if (!writable) {\n      mask = PAGE_U;\n      need = PAGE_U;\n    } else {\n      mask = PAGE_U | PAGE_RW;\n      need = PAGE_U | PAGE_RW;\n    }\n  } else {\n    mask = 0;\n    need = 0;\n  }\n  if ((v & 4095) + n <= 4096) {\n    if ((res = LookupAddress2(m, v, mask, need))) {\n      if (!IsRomAddress(m, res)) return res;\n      p1 = res;\n      m->stashaddr = v;\n      m->opcache->stashsize = n;\n      m->opcache->writable = writable;\n      res = m->opcache->stash;\n      IGNORE_RACES_START();\n      memcpy(res, p1, n);\n      IGNORE_RACES_END();\n      return res;\n    } else {\n      ThrowSegmentationFault(m, v);\n    }\n  }\n  STATISTIC(++page_overlaps);\n  unassert(n <= 4096);\n  m->stashaddr = v;\n  m->opcache->stashsize = n;\n  m->opcache->writable = writable;\n  res = m->opcache->stash;\n  k = 4096 - (v & 4095);\n  if ((p1 = LookupAddress2(m, v, mask, need))) {\n    if ((p2 = LookupAddress2(m, v + k, mask, need))) {\n      IGNORE_RACES_START();\n      memcpy(res, p1, k);\n      memcpy(res + k, p2, n - k);\n      IGNORE_RACES_END();\n      return res;\n    } else {\n      ThrowSegmentationFault(m, v + k);\n    }\n  } else {\n    ThrowSegmentationFault(m, v);\n  }\n}\n\nstatic u8 *AccessRam2(struct Machine *m, i64 v, size_t n, void *p[2], u8 *tmp,\n                      bool copy, bool protect_rom) {\n  u8 *a, *b;\n  unsigned k;\n  unassert(n <= 4096);\n  if ((v & 4095) + n <= 4096) {\n    a = ResolveAddress(m, v);\n    if (!protect_rom || !IsRomAddress(m, a)) return a;\n    if (copy) memcpy(tmp, a, n);\n    return tmp;\n  }\n  STATISTIC(++page_overlaps);\n  k = 4096;\n  k -= v & 4095;\n  unassert(k <= 4096);\n  a = ResolveAddress(m, v);\n  b = ResolveAddress(m, v + k);\n  if (copy) {\n    memcpy(tmp, a, k);\n    memcpy(tmp + k, b, n - k);\n  }\n  if (protect_rom) {\n    if (IsRomAddress(m, a)) a = NULL;\n    if (IsRomAddress(m, b)) b = NULL;\n  }\n  p[0] = a;\n  p[1] = b;\n  return tmp;\n}\n\nu8 *AccessRam(struct Machine *m, i64 v, size_t n, void *p[2], u8 *tmp, bool d) {\n  return AccessRam2(m, v, n, p, tmp, d, !d);\n}\n\nu8 *Load(struct Machine *m, i64 v, size_t n, u8 *b) {\n  void *p[2];\n  SetReadAddr(m, v, n);\n  return AccessRam(m, v, n, p, b, true);\n}\n\nu8 *BeginStore(struct Machine *m, i64 v, size_t n, void *p[2], u8 *b) {\n  SetWriteAddr(m, v, n);\n  return AccessRam(m, v, n, p, b, false);\n}\n\nu8 *BeginStoreNp(struct Machine *m, i64 v, size_t n, void *p[2], u8 *b) {\n  if (!v) return NULL;\n  return BeginStore(m, v, n, p, b);\n}\n\n#if 0\nu8 *BeginLoadStore(struct Machine *m, i64 v, size_t n, void *p[2], u8 *b) {\n  SetWriteAddr(m, v, n);\n  return AccessRam2(m, v, n, p, b, true, true);\n}\n#endif\n\nvoid EndStore(struct Machine *m, i64 v, size_t n, void *p[2], u8 *b) {\n  unsigned k;\n  unassert(n <= 4096);\n  if ((v & 4095) + n <= 4096) return;\n  k = 4096;\n  k -= v & 4095;\n  unassert(n > k);\n#ifdef DISABLE_ROM\n  unassert(p[0]);\n  unassert(p[1]);\n  memcpy(p[0], b, k);\n  memcpy(p[1], b + k, n - k);\n#else\n  if (p[0]) memcpy(p[0], b, k);\n  if (p[1]) memcpy(p[1], b + k, n - k);\n#endif\n}\n\nvoid EndStoreNp(struct Machine *m, i64 v, size_t n, void *p[2], u8 *b) {\n  if (v) EndStore(m, v, n, p, b);\n}\n\nvoid *AddToFreeList(struct Machine *m, void *mem) {\n  int n;\n  void *p;\n  p = m->freelist.p;\n  n = m->freelist.n + 1;\n  if ((p = realloc(p, n * sizeof(*m->freelist.p)))) {\n    STATISTIC(++freelisted);\n    m->freelist.p = (void **)p;\n    m->freelist.n = n;\n    m->freelist.p[n - 1] = mem;\n    return mem;\n  } else {\n    free(mem);\n    return 0;\n  }\n}\n\n// Returns pointer to memory in guest memory. If the memory overlaps a\n// page boundary, then it's copied, and the temporary memory is pushed\n// to the free list. Returns NULL w/ EFAULT or ENOMEM on error.\nvoid *Schlep(struct Machine *m, i64 addr, size_t size, u64 mask, u64 need) {\n  char *copy;\n  size_t have;\n  void *res, *page;\n  if (!size) return 0;\n  if (!(page = LookupAddress2(m, addr, mask, need))) return 0;\n  have = 4096 - (addr & 4095);\n  if (size <= have) {\n    res = page;\n  } else {\n    if (!(copy = (char *)malloc(size))) return 0;\n    memcpy(copy, page, have);\n    for (; have < size; have += 4096) {\n      if (!(page = LookupAddress2(m, addr + have, mask, need))) {\n        free(copy);\n        return 0;\n      }\n      memcpy(copy + have, page, MIN(4096, size - have));\n    }\n    res = AddToFreeList(m, copy);\n  }\n  return res;\n}\n\nvoid *SchlepR(struct Machine *m, i64 addr, size_t size) {\n  SetReadAddr(m, addr, size);\n  return Schlep(m, addr, size, PAGE_U, PAGE_U);\n}\n\nvoid *SchlepW(struct Machine *m, i64 addr, size_t size) {\n  SetWriteAddr(m, addr, size);\n  return Schlep(m, addr, size, PAGE_RW, PAGE_RW);\n}\n\nvoid *SchlepRW(struct Machine *m, i64 addr, size_t size) {\n  SetReadAddr(m, addr, size);\n  SetWriteAddr(m, addr, size);\n  return Schlep(m, addr, size, PAGE_U | PAGE_RW, PAGE_U | PAGE_RW);\n}\n\n// Returns pointer to string in guest memory. If the string overlaps a\n// page boundary, then it's copied, and the temporary memory is pushed\n// to the free list. Returns NULL w/ EFAULT or ENOMEM on error.\nchar *LoadStr(struct Machine *m, i64 addr) {\n  size_t have;\n  char *copy, *page, *p;\n  have = 4096 - (addr & 4095);\n  if (!addr) return 0;\n  if (!(page = (char *)LookupAddress2(m, addr, PAGE_U, PAGE_U))) return 0;\n  if ((p = (char *)memchr(page, '\\0', have))) {\n    SetReadAddr(m, addr, p - page + 1);\n    return page;\n  }\n  if (!(copy = (char *)malloc(have + 4096))) return 0;\n  memcpy(copy, page, have);\n  for (;;) {\n    if (!(page = (char *)LookupAddress2(m, addr + have, PAGE_U, PAGE_U))) break;\n    if ((p = (char *)memccpy(copy + have, page, '\\0', 4096))) {\n      SetReadAddr(m, addr, have + (p - (copy + have)) + 1);\n      return (char *)AddToFreeList(m, copy);\n    }\n    have += 4096;\n    if (!(p = (char *)realloc(copy, have + 4096))) break;\n    copy = p;\n  }\n  free(copy);\n  return 0;\n}\n\n// Copies string from guest memory. The returned memory is pushed to the\n// machine free list. NULL w/ ENOMEM is returned if we're out of memory.\nchar *CopyStr(struct Machine *m, i64 addr) {\n  char *s;\n  if (!(s = LoadStr(m, addr))) return 0;\n  return (char *)AddToFreeList(m, strdup(s));\n}\n\n// Returns fully copied NULL-terminated NUL-terminated string list. All\n// memory allocated by this routine is pushed to the machine free list.\nchar **CopyStrList(struct Machine *m, i64 addr) {\n  int n;\n  u8 b[8];\n  char *s;\n  void *mem;\n  char **list;\n  for (list = 0, n = 0;;) {\n    if ((mem = realloc(list, ++n * sizeof(*list)))) {\n      list = (char **)mem;\n    } else {\n      free(list);\n      return 0;\n    }\n    CopyFromUserRead(m, b, addr + n * 8 - 8, 8);\n    if (Read64(b)) {\n      if ((s = CopyStr(m, Read64(b)))) {\n        list[n - 1] = s;\n      } else {\n        free(list);\n        return 0;\n      }\n    } else {\n      list[n - 1] = 0;\n      return (char **)AddToFreeList(m, list);\n    }\n  }\n}\n"
  },
  {
    "path": "blink/memorymalloc.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/debug.h\"\n#include \"blink/errno.h\"\n#include \"blink/fds.h\"\n#include \"blink/jit.h\"\n#include \"blink/linux.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/pml4t.h\"\n#include \"blink/random.h\"\n#include \"blink/thread.h\"\n#include \"blink/timespec.h\"\n#include \"blink/types.h\"\n#include \"blink/util.h\"\n#include \"blink/x86.h\"\n\nstruct Allocator {\n  pthread_mutex_t_ lock;\n  struct HostPage *pages GUARDED_BY(lock);\n} g_allocator = {\n    PTHREAD_MUTEX_INITIALIZER_,\n};\n\nstruct Machine g_bssmachine;\nstruct HostPages g_hostpages;\n\nstatic void FillPage(void *p, int c) {\n  memset(p, c, 4096);\n}\n\nstatic void ClearPage(void *p) {\n  FillPage(p, 0);\n}\n\nstatic struct HostPage *NewHostPage(void) {\n  return (struct HostPage *)malloc(sizeof(struct HostPage));\n}\n\nstatic void FreeHostPage(struct HostPage *hp) {\n  free(hp);\n}\n\nstatic u64 TrackHostPage(u8 *ptr) {\n  u64 entry;\n  if (HasLinearMapping()) {\n    return (uintptr_t)ptr;\n  } else {\n    if (g_hostpages.n == g_hostpages.c) {\n      g_hostpages.c += 1;\n      g_hostpages.c += g_hostpages.c >> 1;\n      g_hostpages.p =\n          realloc(g_hostpages.p, g_hostpages.c * sizeof(*g_hostpages.p));\n    }\n    entry = g_hostpages.n++;\n    g_hostpages.p[entry] = ptr;\n    return entry << 12;\n  }\n}\n\nvoid FreeAnonymousPage(struct System *s, u8 *page) {\n  struct HostPage *h;\n  unassert((h = NewHostPage()));\n  LOCK(&g_allocator.lock);\n  h->page = page;\n  h->next = g_allocator.pages;\n  g_allocator.pages = h;\n  UNLOCK(&g_allocator.lock);\n}\n\nstatic size_t GetBigSize(size_t n) {\n  unassert(n);\n  long z = FLAG_pagesize;\n  return ROUNDUP(n, z);\n}\n\nstatic void FreeFileMap(struct FileMap *fm) {\n  if (fm) {\n    free(fm->present);\n    free(fm->path);\n    free(fm);\n  }\n}\n\nvoid FreeBig(void *p, size_t n) {\n  if (!p) return;\n  unassert(!Munmap(p, n));\n}\n\nvoid *AllocateBig(size_t n, int prot, int flags, int fd, off_t off) {\n  void *p = Mmap(0, n, prot, flags, fd, off, \"big\");\n  return p != MAP_FAILED ? p : 0;\n}\n\nstatic void FreePageTable(struct System *s, u8 *page) {\n  FreeAnonymousPage(s, page);\n  s->memstat.tables -= 1;\n  s->rss -= 1;\n}\n\nstatic bool FreeEmptyPageTables(struct System *s, u64 pt, long level) {\n  u8 *mi;\n  long i;\n  bool isempty = true;\n  mi = GetPageAddress(s, pt, level == 1);\n  for (i = 0; i < 512; ++i) {\n    if (level == 4) {\n      if (LoadPte(mi + i * 8)) {\n        isempty = false;\n      }\n    } else {\n      pt = LoadPte(mi + i * 8);\n      if (pt & PAGE_V) {\n        if (FreeEmptyPageTables(s, pt, level + 1)) {\n          StorePte(mi + i * 8, 0);\n        } else {\n          isempty = false;\n        }\n      } else {\n        unassert(!pt);\n      }\n    }\n  }\n  if (isempty) {\n    FreePageTable(s, mi);\n  }\n  return isempty;\n}\n\nstatic void FreeHostPages(struct System *s) {\n  if (!s->real && s->cr3) {\n    unassert(!FreeVirtual(s, -0x800000000000, 0x1000000000000));\n    unassert(FreeEmptyPageTables(s, s->cr3, 1));\n#if 0\n    unassert(!s->memstat.committed);\n    unassert(!s->memstat.reserved);\n    unassert(!s->memstat.tables);\n    unassert(!s->vss);\n    unassert(!s->rss);\n#endif\n    s->cr3 = 0;\n  } else if (s->real) {\n    Munmap(s->real, ROUNDUP(kRealSize, FLAG_pagesize));\n  }\n  s->real = 0;\n}\n\nstatic void FreeFileMaps(struct System *s) {\n  struct Dll *e;\n  while ((e = dll_first(s->filemaps))) {\n    dll_remove(&s->filemaps, e);\n    FreeFileMap(FILEMAP_CONTAINER(e));\n  }\n}\n\nvoid CleanseMemory(struct System *s, size_t size) {\n  i64 oldrss;\n  if (s->memchurn >= (s->rss >> 1)) {\n    (void)(oldrss = s->rss);\n    FreeEmptyPageTables(s, s->cr3, 1);\n    MEM_LOGF(\"freed %\" PRId64 \" page tables\", oldrss - s->rss);\n    s->memchurn = 0;\n  }\n}\n\nint GetFileDescriptorLimit(struct System *s) {\n  u64 lim;\n  LOCK(&s->mmap_lock);\n  lim = Read64(s->rlim[RLIMIT_NOFILE_LINUX].cur);\n  UNLOCK(&s->mmap_lock);\n  if (lim > INT_MAX) lim = INT_MAX;\n  return lim;\n}\n\nlong GetMaxVss(struct System *s) {\n  return MIN(kMaxVirtual, Read64(s->rlim[RLIMIT_AS_LINUX].cur)) / 4096;\n}\n\nlong GetMaxRss(struct System *s) {\n  return MIN(kMaxResident, Read64(s->rlim[RLIMIT_AS_LINUX].cur)) / 4096;\n}\n\nstruct System *NewSystem(struct XedMachineMode mode) {\n  long i;\n  struct System *s;\n  unassert(mode.omode == XED_MODE_REAL ||    //\n           mode.omode == XED_MODE_LEGACY ||  //\n           mode.omode == XED_MODE_LONG);\n  unassert(mode.genmode == XED_GEN_MODE_REAL ||  //\n           mode.genmode == XED_GEN_MODE_PROTECTED);\n  if (posix_memalign((void **)&s, _Alignof(struct System), sizeof(*s))) {\n    enomem();\n    return 0;\n  }\n  memset(s, 0, sizeof(*s));\n  s->mode = mode;\n  if (s->mode.omode == XED_MODE_REAL) {\n    u8 *real =\n        Mmap(NULL, ROUNDUP(kRealSize, FLAG_pagesize), PROT_READ | PROT_WRITE,\n             MAP_PRIVATE | MAP_ANONYMOUS_, -1, 0, \"real\");\n    if (!real) {\n      free(s);\n      enomem();\n      return 0;\n    }\n    s->real = real;\n    s->gdt_limit = s->idt_limit = 0xFFFF;\n    s->gdt_base = s->idt_base = 0;\n  }\n#ifdef HAVE_JIT\n  InitJit(&s->jit, (uintptr_t)JitlessDispatch);\n#endif\n  InitFds(&s->fds);\n  unassert(!pthread_mutex_init(&s->sig_lock, 0));\n  unassert(!pthread_mutex_init(&s->mmap_lock, 0));\n  unassert(!pthread_mutex_init(&s->exec_lock, 0));\n  unassert(!pthread_cond_init(&s->machines_cond, 0));\n  unassert(!pthread_mutex_init(&s->machines_lock, 0));\n  unassert(!pthread_cond_init(&s->pagelocks_cond, 0));\n  unassert(!pthread_mutex_init(&s->pagelocks_lock, 0));\n  s->blinksigs = (u64)1 << (SIGSYS_LINUX - 1) |   //\n                 (u64)1 << (SIGILL_LINUX - 1) |   //\n                 (u64)1 << (SIGFPE_LINUX - 1) |   //\n                 (u64)1 << (SIGSEGV_LINUX - 1) |  //\n                 (u64)1 << (SIGBUS_LINUX - 1) |   //\n                 (u64)1 << (SIGPIPE_LINUX - 1) |  //\n                 (u64)1 << (SIGTRAP_LINUX - 1);\n  for (i = 0; i < RLIM_NLIMITS_LINUX; ++i) {\n    Write64(s->rlim[i].cur, RLIM_INFINITY_LINUX);\n    Write64(s->rlim[i].max, RLIM_INFINITY_LINUX);\n  }\n  s->pid = getpid();\n  return s;\n}\n\nstatic void FreeMachineUnlocked(struct Machine *m) {\n  THR_LOGF(\"pid=%d tid=%d FreeMachine\", m->system->pid, m->tid);\n  UnlockRobustFutexes(m);\n  if (IsMakingPath(m)) {\n    AbandonJit(&m->system->jit, m->path.jb);\n  }\n  m->sysdepth = 0;\n  CollectPageLocks(m);\n  CollectGarbage(m, 0);\n  free(m->pagelocks.p);\n  free(m->freelist.p);\n  free(m);\n  if (g_machine == m) {\n    g_machine = 0;\n  }\n}\n\nbool IsOrphan(struct Machine *m) {\n  bool res;\n  LOCK(&m->system->machines_lock);\n  if (m->system->machines == m->system->machines->next &&\n      m->system->machines == m->system->machines->prev) {\n    unassert(m == MACHINE_CONTAINER(m->system->machines));\n    res = true;\n  } else {\n    res = false;\n  }\n  UNLOCK(&m->system->machines_lock);\n  return res;\n}\n\nvoid KillOtherThreads(struct System *s) {\n#ifdef HAVE_THREADS\n  int r, t;\n  struct Dll *e;\n  struct Machine *m;\n  struct timespec deadline;\n  if (atomic_exchange(&s->killer, true)) {\n    FreeMachine(g_machine);\n    pthread_exit(EXIT_SUCCESS);\n  }\nStartOver:\n  unassert(s == g_machine->system);\n  unassert(!dll_is_empty(s->machines));\n  for (t = 0; !IsOrphan(g_machine); ++t) {\n    LOCK(&s->machines_lock);\n    for (e = dll_first(s->machines); e; e = dll_next(s->machines, e)) {\n      if ((m = MACHINE_CONTAINER(e)) != g_machine) {\n        THR_LOGF(\"pid=%d tid=%d is killing tid %d\", s->pid, g_machine->tid,\n                 m->tid);\n        atomic_store_explicit(&m->killed, true, memory_order_release);\n        atomic_store_explicit(&m->attention, true, memory_order_release);\n        if (t < 10) {\n          pthread_kill(m->thread, SIGSYS);\n        } else {\n          LOGF(\"kill9'd thread after 10 tries\");\n          pthread_kill(m->thread, SIGKILL);\n          dll_remove(&s->machines, e);\n          UNLOCK(&s->machines_lock);\n          goto StartOver;\n        }\n      }\n    }\n    deadline = AddTime(GetTime(), FromMilliseconds(kPollingMs));\n    r = pthread_cond_timedwait(&s->machines_cond, &s->machines_lock, &deadline);\n    unassert(r == 0 || r == ETIMEDOUT);\n    UNLOCK(&s->machines_lock);\n  }\n#endif\n}\n\nvoid RemoveOtherThreads(struct System *s) {\n#ifdef HAVE_THREADS\n  struct Dll *e, *g;\n  struct Machine *m;\n  LOCK(&s->machines_lock);\n  for (e = dll_first(s->machines); e; e = g) {\n    g = dll_next(s->machines, e);\n    m = MACHINE_CONTAINER(e);\n    if (m != g_machine) {\n      dll_remove(&s->machines, e);\n      FreeMachineUnlocked(m);\n    }\n  }\n  UNLOCK(&s->machines_lock);\n#endif\n}\n\nvoid FreeSystem(struct System *s) {\n  THR_LOGF(\"pid=%d FreeSystem\", s->pid);\n  unassert(dll_is_empty(s->machines));  // Use KillOtherThreads & FreeMachine\n  FreeHostPages(s);\n  unassert(!pthread_mutex_destroy(&s->machines_lock));\n  unassert(!pthread_cond_destroy(&s->machines_cond));\n  unassert(!pthread_mutex_destroy(&s->pagelocks_lock));\n  unassert(!pthread_cond_destroy(&s->pagelocks_cond));\n  unassert(!pthread_mutex_destroy(&s->exec_lock));\n  unassert(!pthread_mutex_destroy(&s->mmap_lock));\n  // TODO(jart): Figure out why sig_lock sometimes fails to destroy\n  (void)pthread_mutex_destroy(&s->sig_lock);\n  free(s->elf.interpreter);\n  DestroyFds(&s->fds);\n  free(s->elf.execfn);\n  free(s->elf.prog);\n  FreeFileMaps(s);\n#ifdef HAVE_JIT\n  DestroyJit(&s->jit);\n#endif\n  free(s);\n}\n\nstruct Machine *NewMachine(struct System *system, struct Machine *parent) {\n  _Static_assert(IS2POW(kMaxThreadIds), \"\");\n  struct Machine *m;\n  unassert(system);\n  unassert(!parent || system == parent->system);\n  if (posix_memalign((void **)&m, _Alignof(struct Machine), sizeof(*m))) {\n    enomem();\n    return 0;\n  }\n  // TODO(jart): We shouldn't be doing expensive ops in an allocator.\n  LOCK(&system->machines_lock);\n  if (parent) {\n    memcpy(m, parent, sizeof(*m));\n    memset(&m->path, 0, sizeof(m->path));\n    memset(&m->freelist, 0, sizeof(m->freelist));\n    memset(&m->pagelocks, 0, sizeof(m->pagelocks));\n    ResetInstructionCache(m);\n    m->insyscall = false;\n    m->nofault = false;\n    m->sysdepth = 0;\n    m->sigdepth = 0;\n    m->signals = 0;\n  } else {\n    memset(m, 0, sizeof(*m));\n    ResetCpu(m);\n  }\n  m->ctid = 0;\n  m->oplen = 0;\n  m->system = system;\n  m->mode = system->mode;\n  m->thread = pthread_self();\n  Write32(m->sigaltstack.flags, SS_DISABLE_LINUX);\n  if (parent) {\n    m->tid = (system->next_tid++ & (kMaxThreadIds - 1)) + kMinThreadId;\n  } else {\n    // TODO(jart): We shouldn't be doing system calls in an allocator.\n    m->tid = m->system->pid;\n  }\n  dll_init(&m->elem);\n  // TODO(jart): Child thread should add itself to system.\n  dll_make_first(&system->machines, &m->elem);\n  UNLOCK(&system->machines_lock);\n  THR_LOGF(\"new machine thread pid=%d tid=%d\", m->system->pid, m->tid);\n  return m;\n}\n\nvoid CollectGarbage(struct Machine *m, size_t mark) {\n  long i;\n  for (i = mark; i < m->freelist.n; ++i) {\n    free(m->freelist.p[i]);\n  }\n  m->freelist.n = mark;\n}\n\nvoid FreeMachine(struct Machine *m) {\n  bool orphan;\n  struct System *s;\n  if (m) {\n    unassert((s = m->system));\n    m->sysdepth = 0;\n    CollectPageLocks(m);\n    LOCK(&s->machines_lock);\n    dll_remove(&s->machines, &m->elem);\n    if (!(orphan = dll_is_empty(s->machines))) {\n      unassert(!pthread_cond_signal(&s->machines_cond));\n    }\n    UNLOCK(&s->machines_lock);\n    FreeMachineUnlocked(m);\n    if (orphan) {\n      FreeSystem(s);\n    } else {\n      THR_LOGF(\"more threads remain in operation\");\n    }\n  }\n}\n\nu64 AllocateAnonymousPage(struct System *s) {\n  u8 *page;\n  size_t i, n;\n  struct HostPage *h;\n  LOCK(&g_allocator.lock);\n  if ((h = g_allocator.pages)) {\n    g_allocator.pages = h->next;\n    UNLOCK(&g_allocator.lock);\n    page = h->page;\n    FreeHostPage(h);\n    goto Finished;\n  } else {\n    UNLOCK(&g_allocator.lock);\n  }\n  n = 64;\n  page = (u8 *)AllocateBig(n * 4096, PROT_READ | PROT_WRITE,\n                           MAP_ANONYMOUS_ | MAP_PRIVATE, -1, 0);\n  if (!page) return -1;\n  LOCK(&g_allocator.lock);\n  for (i = n; i-- > 1;) {\n    unassert((h = NewHostPage()));\n    h->page = page + i * 4096;\n    h->next = g_allocator.pages;\n    g_allocator.pages = h;\n  }\n  UNLOCK(&g_allocator.lock);\nFinished:\n  s->rss += 1;\n  i = TrackHostPage(page);\n  unassert(!(i & ~PAGE_TA));\n  return i | PAGE_HOST | PAGE_U | PAGE_RW | PAGE_V;\n}\n\nu64 AllocatePageTable(struct System *s) {\n  u64 res;\n  if ((res = AllocateAnonymousPage(s)) != -1) {\n    s->memstat.tables += 1;\n    res &= ~PAGE_U;\n  }\n  return res;\n}\n\nbool IsValidAddrSize(i64 virt, i64 size) {\n  virt = (i64)((u64)virt << 16) >> 16;\n  return size > 0 &&                 //\n         !(virt & 4095) &&           //\n         virt >= -0x800000000000 &&  //\n         virt < 0x800000000000 &&    //\n         size <= 0x1000000000000 &&  //\n         virt + size <= 0x800000000000;\n}\n\nvoid InvalidateSystem(struct System *s, bool tlb, bool icache) {\n  struct Dll *e;\n  struct Machine *m;\n  if (tlb || icache) {\n    LOCK(&s->machines_lock);\n    for (e = dll_first(s->machines); e; e = dll_next(s->machines, e)) {\n      m = MACHINE_CONTAINER(e);\n      if (tlb) {\n        atomic_store_explicit(&m->invalidated, true, memory_order_release);\n      }\n      if (icache) {\n        atomic_store_explicit(&m->opcache->invalidated, true,\n                              memory_order_release);\n      }\n    }\n    UNLOCK(&s->machines_lock);\n  }\n}\n\nstruct FileMap *AddFileMap(struct System *s, i64 virt, i64 size,\n                           const char *path, u64 offset) {\n  struct FileMap *fm;\n  size_t pages, words;\n  if (!path) return 0;\n  if ((fm = (struct FileMap *)calloc(1, sizeof(struct FileMap)))) {\n    fm->virt = virt;\n    fm->size = size;\n    fm->path = strdup(path);\n    fm->offset = offset;\n    pages = ROUNDUP(size, 4096) / 4096;\n    words = ROUNDUP(pages, 64) / 64;\n    if (fm->path && (fm->present = (u64 *)malloc(words * sizeof(u64)))) {\n      memset(fm->present, -1, pages / 64 * sizeof(u64));\n      if (pages % 64) {\n        fm->present[pages / 64] = ((u64)1 << (pages % 64)) - 1;\n      }\n      fm->pages = pages;\n      dll_init(&fm->elem);\n      dll_make_first(&s->filemaps, &fm->elem);\n      ELF_LOGF(\"AddFileMap(%#\" PRIx64 \", %#\" PRIx64 \", %s, %#\" PRIx64 \")\", virt,\n               size, path, offset);\n      return fm;\n    }\n  }\n  FreeFileMap(fm);\n  return 0;\n}\n\nstatic void AddFileMapViaMap(struct System *s, i64 virt, i64 size, int fildes,\n                             u64 offset) {\n  char *path;\n  struct Fd *fd;\n  struct FileMap *fm;\n  LOCK(&s->fds.lock);\n  path = (fd = GetFd(&s->fds, fildes)) ? strdup(fd->path) : 0;\n  UNLOCK(&s->fds.lock);\n  fm = AddFileMap(s, virt, size, path, offset);\n  free(path);\n  if (fm && s->dis && s->onfilemap) {\n    s->onfilemap(s, fm);\n  }\n}\n\nstruct FileMap *GetFileMap(struct System *s, i64 virt) {\n  u64 i;\n  struct Dll *e;\n  struct FileMap *fm;\n  for (e = dll_first(s->filemaps); e; e = dll_next(s->filemaps, e)) {\n    fm = FILEMAP_CONTAINER(e);\n    if (virt >= fm->virt && virt < fm->virt + fm->size) {\n      i = virt - fm->virt;\n      i /= 4096;\n      if (fm->present[i / 64] & ((u64)1 << (i % 64))) {\n        return fm;\n      }\n    }\n  }\n  return 0;\n}\n\nstatic void UnmarkFilePage(struct System *s, i64 virt) {\n  u64 i;\n  bool lru;\n  struct Dll *e;\n  struct FileMap *fm;\n  lru = false;\n  for (e = dll_first(s->filemaps); e; e = dll_next(s->filemaps, e)) {\n    fm = FILEMAP_CONTAINER(e);\n    if (virt >= fm->virt && virt < fm->virt + fm->size) {\n      unassert(fm->pages);\n      i = virt - fm->virt;\n      i /= 4096;\n      if (fm->present[i / 64] & ((u64)1 << (i % 64))) {\n        fm->present[i / 64] &= ~((u64)1 << (i % 64));\n        if (!--fm->pages) {\n          dll_remove(&s->filemaps, e);\n          FreeFileMap(fm);\n        } else if (lru) {\n          dll_remove(&s->filemaps, e);\n          dll_make_first(&s->filemaps, e);\n        }\n        break;\n      }\n    }\n    lru = true;\n  }\n}\n\nstatic void WaitForPageToNotBeLocked(struct System *s, i64 virt, u8 *pte) {\n  unassert(g_machine);\n#ifdef DEBUG\n  unassert(!IsOrphan(g_machine));\n  unassert(!HasPageLock(g_machine, virt & -4096));\n#endif\n  LOCK(&s->pagelocks_lock);\n  while (LoadPte(pte) & PAGE_LOCKS) {\n    unassert(!pthread_cond_wait(&s->pagelocks_cond, &s->pagelocks_lock));\n  }\n  UNLOCK(&s->pagelocks_lock);\n}\n\nstatic bool FreePage(struct System *s, i64 virt, u64 entry, u64 size,\n                     bool *executable_code_was_made_non_executable,\n                     long *rss_delta) {\n  u8 *page;\n  long pagesize;\n  unassert(entry & PAGE_V);\n  if (entry & PAGE_FILE) UnmarkFilePage(s, virt);\n  if (!(entry & PAGE_XD) && !(entry & PAGE_RSRV)) {\n    *executable_code_was_made_non_executable = true;\n#ifndef DISABLE_JIT\n    if (!IsJitDisabled(&s->jit)) {\n      ResetJitPage(&s->jit, virt);\n    }\n#endif\n  }\n  if ((entry & (PAGE_HOST | PAGE_MAP | PAGE_MUG)) == PAGE_HOST) {\n    unassert(~entry & PAGE_RSRV);\n    s->memstat.committed -= 1;\n    ClearPage((page = FindHostPage(entry)));\n    FreeAnonymousPage(s, page);\n    --*rss_delta;\n    return false;\n  } else if ((entry & (PAGE_HOST | PAGE_MAP | PAGE_MUG)) ==\n             (PAGE_HOST | PAGE_MAP | PAGE_MUG)) {\n    u8 *real, *mug;\n    pagesize = FLAG_pagesize;\n    real = mug = FindHostPage(entry);\n    while ((uintptr_t)mug & (pagesize - 1)) mug -= 4096;\n    unassert(!Munmap(mug, real - mug + size));\n    if (entry & PAGE_RSRV) {\n      s->memstat.reserved -= 1;\n    } else {\n      s->memstat.committed -= 1;\n      --*rss_delta;\n    }\n    return false;\n  } else if ((entry & (PAGE_HOST | PAGE_MAP | PAGE_MUG)) ==\n             (PAGE_HOST | PAGE_MAP)) {\n    unassert(!(entry & PAGE_RSRV));\n    s->memstat.committed -= 1;\n    --*rss_delta;\n    return true;  // call is responsible for freeing\n  } else if (entry & PAGE_RSRV) {\n    s->memstat.reserved -= 1;\n    return false;\n  } else {\n    unassert(!\"impossible memory\");\n    return false;\n  }\n}\n\nstatic void AddPageToRanges(struct ContiguousMemoryRanges *ranges, i64 virt,\n                            i64 end) {\n  if (!(ranges->i && ranges->p[ranges->i - 1].b == virt)) {\n    if (ranges->i == ranges->n) {\n      if (ranges->n) {\n        ranges->n += ranges->n >> 1;\n      } else {\n        ranges->n = 8;\n      }\n      unassert(ranges->p = (struct ContiguousMemoryRange *)realloc(\n                   ranges->p, ranges->n * sizeof(*ranges->p)));\n    }\n    ranges->p[ranges->i++].a = virt;\n  }\n  ranges->p[ranges->i - 1].b = virt + MIN(4096, end - virt);\n}\n\n// removes page table entries. anonymous pages will be added to the\n// system's free list. mug pages will be freed one by one. linear pages\n// won't be freed, and will instead have their intervals pooled in the\n// ranges data structure; the caller is responsible for freeing those.\nstatic void RemoveVirtual(struct System *s, i64 virt, i64 size,\n                          struct ContiguousMemoryRanges *ranges,\n                          bool *executable_code_was_made_non_executable,\n                          bool *address_space_was_mutated,  //\n                          long *vss_delta, long *rss_delta) {\n  i64 end;\n  u64 i, pt;\n  u8 *pp, *pde;\n  unsigned pi, p1;\n  unassert(!(virt & 4095));\n  MEM_LOGF(\"RemoveVirtual(%#\" PRIx64 \", %#\" PRIx64 \")\", virt, size);\n  for (pde = 0, end = virt + size; virt < end; virt += (u64)1 << i) {\n    for (pt = s->cr3, i = 39;; i -= 9) {\n      pi = p1 = (virt >> i) & 511;\n      pp = GetPageAddress(s, pt, i == 39) + pi * 8;\n      if (i == 12 + 9) pde = pp;\n      pt = LoadPte(pp);\n      if (i > 12 && !(pt & PAGE_V)) break;\n      if (i > 12) continue;\n    LastLevel:\n      if (pt & PAGE_V) {\n        for (;;) {\n          if (pt & PAGE_LOCKS) {\n            WaitForPageToNotBeLocked(s, virt, pp);\n          } else if (CasPte(pp, pt, 0)) {\n            break;\n          }\n          pt = LoadPte(pp);\n          unassert(pt & PAGE_V);\n        }\n        if (FreePage(s, virt, pt, MIN(4096, end - virt),\n                     executable_code_was_made_non_executable, rss_delta) &&\n            HasLinearMapping()) {\n          AddPageToRanges(ranges, virt, end);\n        }\n        *address_space_was_mutated = true;\n        --*vss_delta;\n      }\n      if (virt + 4096 < end && pi < 511) {\n        pi += 1;\n        pp += 8;\n        pt = LoadPte(pp);\n        virt += 4096;\n        goto LastLevel;\n      } else if (!p1 && pi == 511) {\n        // when more than 512*4096 bytes are being unmapped, we\n        // opportunistically unmap page directories too, if the\n        // requested interval overlaps an entire page table. we\n        // guarantee safety because mmap_lock is held, which is\n        // required to create/remove (but not edit) the entries\n        // therefore if we observed all entries are zero we can\n        // say for certain it's safe to free. the only question\n        // becomes readers like FindPageTableEntry() that still\n        // crawl an old pointer to a free page table. free page\n        // tables may be crawled because they always get zero'd\n        // before being put into a freelist fifo that cools off\n        FreePageTable(s, GetPageAddress(s, LoadPte(pde), i == 39));\n        StorePte(pde, 0);\n      }\n      break;\n    }\n  }\n}\n\n#define EXIT_FAILURE_MMAP_PANIC 250\n\n_Noreturn static void PanicDueToMmap(void) {\n#ifndef NDEBUG\n  WriteErrorString(\n      \"unrecoverable mmap() crisis: see log for further details\\n\");\n#else\n  WriteErrorString(\n      \"unrecoverable mmap() crisis: Blink was built with NDEBUG\\n\");\n#endif\n  exit(EXIT_FAILURE_MMAP_PANIC);\n}\n\nstatic int FailDueToHostAlignment(i64 virt, long pagesize, const char *kind) {\n  LOGF(\"app chose mmap %s (%#\" PRIx64 \") that's not aligned \"\n       \"to the platform page size (%#lx) while using linear mode \"\n       \"(try using `blink -m`)\",\n       kind, virt, pagesize);\n  return einval();\n}\n\nstatic int DetermineHostProtection(int prot) {\n  int sysprot;\n  // blink never executes guest memory on metal\n  sysprot = prot & ~PROT_EXEC;\n  // when memory is being fully virtualized,\n  // blink will check permissions on its own\n  // note we can't force write permission in\n  // some cases such as shared file mappings\n  if (!HasLinearMapping()) {\n    sysprot |= PROT_READ;\n  }\n  return sysprot;\n}\n\ni64 ReserveVirtual(struct System *s, i64 virt, i64 size, u64 flags, int fd,\n                   i64 offset, bool shared, bool fixedmap) {\n  u8 *mi;\n  int demand;\n  int method;\n  i64 result;\n  bool mutated;\n  void *got, *want;\n  long i, pagesize;\n  int prot, sysprot;\n  long vss_delta, rss_delta;\n  i64 ti, pt, end, pages, level, entry;\n  bool executable_code_was_made_non_executable;\n  struct ContiguousMemoryRanges ranges;\n\n  // we determine these\n  unassert(!(flags & PAGE_TA));\n  unassert(!(flags & PAGE_MAP));\n  unassert(!(flags & PAGE_HOST));\n  unassert(!(flags & PAGE_RSRV));\n  unassert(s->mode.omode == XED_MODE_LONG);\n\n  // determine memory protection\n  prot = GetProtection(flags);\n  sysprot = DetermineHostProtection(prot);\n\n  MEM_LOGF(\"ReserveVirtual(%#\" PRIx64 \", %#\" PRIx64 \", %s)\", virt, size,\n           DescribeProt(prot));\n\n  if (!IsValidAddrSize(virt, size)) {\n    LOGF(\"mmap(addr=%#\" PRIx64 \", size=%#\" PRIx64 \") is not a legal mapping\",\n         virt, size);\n    return einval();\n  }\n\n  if (fd != -1 && (offset & 4095)) {\n    LOGF(\"mmap(offset=%#\" PRIx64 \") isn't 4096-byte page aligned\", offset);\n    return einval();\n  }\n\n  pagesize = FLAG_pagesize;\n\n  if (HasLinearMapping()) {\n    if (virt & (pagesize - 1)) {\n      return FailDueToHostAlignment(virt, pagesize, \"address\");\n    }\n    if (offset & (pagesize - 1)) {\n      return FailDueToHostAlignment(offset, pagesize, \"file offset\");\n    }\n  }\n\n  // remove existing mapping\n  vss_delta = 0;\n  rss_delta = 0;\n  mutated = false;\n  executable_code_was_made_non_executable = false;\n  pages = ROUNDUP(size, 4096) / 4096;\n  if (HasLinearMapping() && FLAG_vabits <= 47) {\n    if (fixedmap) {\n      method = MAP_FIXED;\n    } else if (virt) {\n      method = MAP_DEMAND;\n    } else {\n      method = 0;\n    }\n  } else {\n    if (FLAG_vabits <= 47) {\n      demand = MAP_DEMAND;\n    } else {\n      demand = MAP_FIXED;\n    }\n    memset(&ranges, 0, sizeof(ranges));\n    RemoveVirtual(s, virt, size, &ranges,\n                  &executable_code_was_made_non_executable, &mutated,\n                  &vss_delta, &rss_delta);\n    if (ranges.i) {\n      // linear mappings exist within the requested interval\n      if (ranges.i == 1 &&          //\n          ranges.p[0].a == virt &&  //\n          ranges.p[0].b == virt + size) {\n        // it should be 100% safe to let the kernel blow it away\n        method = MAP_FIXED;\n      } else {\n        // holes exist; try to create a greenfield\n        for (i = 0; i < ranges.i; ++i) {\n          Munmap(ToHost(ranges.p[i].a), ranges.p[i].b - ranges.p[i].a);\n          mutated = true;\n        }\n        // errors in Munmap() should propagate to Mmap() below\n        method = demand;\n      }\n      free(ranges.p);\n    } else {\n      // requested interval should be a greenfield\n      method = demand;\n    }\n  }\n\n  if (HasLinearMapping()) {\n    // create a linear mapping. doing this runs the risk of destroying\n    // things the kernel put into our address space that blink doesn't\n    // know about. systems like linux and freebsd have a feature which\n    // lets us report a friendly error to the user, when that happens.\n    // the solution is most likely to rebuild with -Wl,-Ttext-segment=\n    // please note we need to take off the seatbelt after an execve().\n    errno = 0;\n    want = virt ? ToHost(virt) : 0;\n    if ((got = Mmap(want, size, sysprot,                    //\n                    (method |                               //\n                     (fd == -1 ? MAP_ANONYMOUS_ : 0) |      //\n                     (shared ? MAP_SHARED : MAP_PRIVATE)),  //\n                    fd, offset, \"linear\")) != want) {\n      if (got == MAP_FAILED && errno == ENOMEM && !mutated) {\n        LOGF(\"host system returned ENOMEM\");\n        return -1;\n      } else if (got != MAP_FAILED && !want) {\n        virt = ToGuest(got);\n        unassert(IsValidAddrSize(virt, size));\n      } else {\n        ERRF(\"mmap(%#\" PRIx64 \"[%p], %#\" PRIx64 \")\"\n             \" -> %#\" PRIx64 \"[%p] crisis: %s\",\n             virt, want, size, ToGuest(got), got,\n             (method == MAP_DEMAND && errno == MAP_DENIED)\n                 ? \"requested memory overlapped blink image or system memory. \"\n                   \"try using `blink -m` to disable memory optimizations, or \"\n                   \"try compiling blink using -Wl,--image-base=0x23000000 or \"\n                   \"possibly -Wl,-Ttext-segment=0x23000000 in LDFLAGS\"\n                 : DescribeHostErrno(errno));\n        PanicDueToMmap();\n      }\n    }\n    s->memstat.committed += pages;\n    flags |= PAGE_HOST | PAGE_MAP;\n    vss_delta += pages;\n    rss_delta += pages;\n  } else if (fd != -1 || shared) {\n    vss_delta += pages;\n    s->memstat.reserved += pages;\n    flags |= PAGE_HOST | PAGE_MAP | PAGE_MUG | PAGE_RSRV;\n  } else {\n    flags |= PAGE_RSRV;\n    vss_delta += pages;\n    s->memstat.reserved += pages;\n  }\n\n  MEM_LOGF(\"reserving virtual [%#\" PRIx64 \",%#\" PRIx64 \") w/ %\" PRId64 \" kb\",\n           virt, virt + size, size / 1024);\n\n  // create a filemap object\n  if (fd != -1 && !(flags & PAGE_FILE)) {\n    flags |= PAGE_FILE;\n    AddFileMapViaMap(s, virt, size, fd, offset);\n  }\n\n  // add pml4t entries ensuring intermediary tables exist\n  for (result = virt, end = virt + size;;) {\n    for (pt = s->cr3, level = 39; level >= 12; level -= 9) {\n      ti = (virt >> level) & 511;\n      mi = GetPageAddress(s, pt, level == 39) + ti * 8;\n      if (level > 12) {\n        pt = LoadPte(mi);\n        if (!(pt & PAGE_V)) {\n          if ((pt = AllocatePageTable(s)) == -1) {\n            WriteErrorString(\"mmap() crisis: ran out of page table memory\\n\");\n            exit(EXIT_FAILURE_MMAP_PANIC);\n          }\n          StorePte(mi, pt);\n        }\n        continue;\n      }\n      for (;;) {\n        u64 real;\n        if (flags & PAGE_MAP) {\n          if (flags & PAGE_MUG) {\n            u8 *mug;\n            off_t mugoff;\n            int mugflags;\n            long mugsize;\n            long mugskew;\n            mugsize = MIN(4096, end - virt);\n            if (fd != -1) {\n              mugskew = offset - ROUNDDOWN(offset, pagesize);\n              mugoff = ROUNDDOWN(offset, pagesize);\n              mugsize += mugskew;\n            } else {\n              mugoff = 0;\n              mugskew = 0;\n            }\n            mugflags = (shared ? MAP_SHARED : MAP_PRIVATE) |\n                       (fd == -1 ? MAP_ANONYMOUS_ : 0);\n            mug = AllocateBig(mugsize, sysprot, mugflags, fd, mugoff);\n            if (!mug) {\n              ERRF(\"mmap(virt=%\" PRIx64\n                   \", size=%ld, flags=%#x, fd=%d, offset=%#\" PRIx64\n                   \") crisis: %s\",\n                   virt, mugsize, mugflags, fd, (u64)mugoff,\n                   DescribeHostErrno(errno));\n              PanicDueToMmap();\n            }\n            real = TrackHostPage(mug + mugskew);\n            offset += 4096;\n          } else {\n            real = (uintptr_t)ToHost(virt);\n          }\n          unassert(!(real & ~PAGE_TA));\n          entry = real | flags | PAGE_V;\n        } else {\n          entry = flags | PAGE_V;\n        }\n        for (;;) {\n          pt = LoadPte(mi);\n          if (pt & PAGE_LOCKS) {\n            unassert(pt & PAGE_V);\n            WaitForPageToNotBeLocked(s, virt, mi);\n          } else if (CasPte(mi, pt, entry)) {\n            break;\n          }\n        }\n        if (pt & PAGE_V) {\n          FreePage(s, virt, pt, 4096, &executable_code_was_made_non_executable,\n                   &rss_delta);\n        }\n        if ((virt += 4096) >= end) {\n          s->rss += rss_delta;\n          s->vss += vss_delta;\n#ifndef DISABLE_JIT\n          if (HasLinearMapping() && !IsJitDisabled(&s->jit)) {\n            result = ProtectRwxMemory(s, result, result, size, pagesize, prot);\n          }\n#endif\n          InvalidateSystem(s, !!rss_delta,\n                           executable_code_was_made_non_executable);\n          return result;\n        }\n        if (++ti == 512) break;\n        mi += 8;\n      }\n    }\n  }\n}\n\ni64 FindVirtual(struct System *s, i64 virt, i64 size) {\n  u64 i, pt, got, orig_virt = virt;\n  (void)orig_virt;\nStartOver:\n  if (!IsValidAddrSize(virt, size)) {\n    LOGF(\"FindVirtual [%#\" PRIx64 \",%#\" PRIx64 \") -> \"\n         \"[%#\" PRIx64 \",%#\" PRIx64 \") not possible\",\n         orig_virt, orig_virt + size, virt, virt + size);\n    return enomem();\n  }\n  got = 0;\n  do {\n    for (i = 39, pt = s->cr3;; i -= 9) {\n      pt = LoadPte(GetPageAddress(s, pt, i == 39) +\n                   (((virt + got) >> i) & 511) * 8);\n      if (i == 12 || !(pt & PAGE_V)) break;\n    }\n    got += (u64)1 << i;\n    if ((pt & PAGE_V)) {\n      virt += got;\n      goto StartOver;\n    }\n  } while (got < size);\n  return virt;\n}\n\nint FreeVirtual(struct System *s, i64 virt, i64 size) {\n  int rc;\n  long i;\n  bool mutated;\n  long vss_delta, rss_delta;\n  bool executable_code_was_made_non_executable;\n  struct ContiguousMemoryRanges ranges;\n  MEM_LOGF(\"freeing virtual [%#\" PRIx64 \",%#\" PRIx64 \") w/ %\" PRId64 \" kb\",\n           virt, virt + size, size / 1024);\n  if (!IsValidAddrSize(virt, size)) {\n    LOGF(\"invalid addr size\");\n    return einval();\n  }\n  vss_delta = 0;\n  rss_delta = 0;\n  memset(&ranges, 0, sizeof(ranges));\n  executable_code_was_made_non_executable = false;\n  RemoveVirtual(s, virt, size, &ranges,\n                &executable_code_was_made_non_executable, &mutated, &vss_delta,\n                &rss_delta);\n  for (rc = i = 0; i < ranges.i; ++i) {\n    if (Munmap(ToHost(ranges.p[i].a), ranges.p[i].b - ranges.p[i].a)) {\n      LOGF(\"failed to %s subrange\"\n           \" [%\" PRIx64 \",%\" PRIx64 \") within requested range\"\n           \" [%\" PRIx64 \",%\" PRIx64 \"): %s\",\n           \"munmap\", ranges.p[i].a, ranges.p[i].b, virt, virt + size,\n           DescribeHostErrno(errno));\n      rc = einval();\n    }\n  }\n  free(ranges.p);\n  s->vss += vss_delta;\n  s->rss += rss_delta;\n  s->memchurn -= vss_delta;\n  InvalidateSystem(s, !!rss_delta, executable_code_was_made_non_executable);\n  return rc;\n}\n\nint GetProtection(u64 key) {\n  int prot = 0;\n  if (key & PAGE_U) prot |= PROT_READ;\n  if (key & PAGE_RW) prot |= PROT_WRITE;\n  if (!(key & PAGE_XD)) prot |= PROT_EXEC;\n  return prot;\n}\n\nu64 SetProtection(int prot) {\n  u64 key = 0;\n  if (prot & PROT_READ) key |= PAGE_U;\n  if (prot & PROT_WRITE) key |= PAGE_RW;\n  if (~prot & PROT_EXEC) key |= PAGE_XD;\n  return key;\n}\n\nbool IsFullyMapped(struct System *s, i64 virt, i64 size) {\n  u8 *mi;\n  u64 pt;\n  i64 ti, end, level;\n  for (end = virt + size;;) {\n    for (pt = s->cr3, level = 39; level >= 12; level -= 9) {\n      ti = (virt >> level) & 511;\n      mi = GetPageAddress(s, pt, level == 39) + ti * 8;\n      pt = LoadPte(mi);\n      if (level > 12) {\n        if (!(pt & PAGE_V)) {\n          return false;\n        }\n        continue;\n      }\n      for (;;) {\n        if (!(pt & PAGE_V)) {\n          return false;\n        }\n        if ((virt += 4096) >= end) {\n          return true;\n        }\n        if (++ti == 512) break;\n        pt = LoadPte((mi += 8));\n      }\n    }\n  }\n}\n\nbool IsFullyUnmapped(struct System *s, i64 virt, i64 size) {\n  u8 *mi;\n  i64 end;\n  u64 i, pt;\n  for (end = virt + size; virt < end; virt += (u64)1 << i) {\n    for (pt = s->cr3, i = 39;; i -= 9) {\n      mi = GetPageAddress(s, pt, i == 39) + ((virt >> i) & 511) * 8;\n      pt = LoadPte(mi);\n      if (!(pt & PAGE_V)) {\n        break;\n      } else if (i == 12) {\n        return false;\n      }\n    }\n  }\n  return true;\n}\n\nint ProtectVirtual(struct System *s, i64 virt, i64 size, int prot,\n                   bool hostonly) {\n  u8 *mi;\n  int rc;\n  int sysprot;\n  u64 pt, pt2, key;\n  long i, pagesize;\n  i64 a, b, ti, end, level, orig_virt;\n  bool executable_code_was_made_non_executable;\n  struct ContiguousMemoryRanges ranges;\n  MEM_LOGF(\"protecting virtual [%#\" PRIx64 \",%#\" PRIx64 \") w/ %s\", virt,\n           virt + size, DescribeProt(prot));\n  orig_virt = virt;\n  (void)orig_virt;\n  pagesize = FLAG_pagesize;\n  if (!IsValidAddrSize(virt, size)) {\n    return einval();\n  }\n  if (!IsFullyMapped(s, virt, size)) {\n    LOGF(\"mprotect(%#\" PRIx64 \", %#\" PRIx64 \") interval has unmapped pages\",\n         virt, size);\n    return enomem();\n  }\n  key = SetProtection(prot);\n  sysprot = DetermineHostProtection(prot);\n  // in linear mode, the guest might try to do something like\n  // set a 4096 byte guard page to PROT_NONE at the bottom of\n  // its 64kb stack. if the host operating system has a 64 kb\n  // page size, then that would be bad. we can't satisfy prot\n  // unless the guest takes the page size into consideration.\n  if (HasLinearMapping() &&\n      (virt - ROUNDDOWN(virt, pagesize) >= 4096 ||\n       ROUNDUP(virt + size, pagesize) - (virt + size) >= 4096)) {\n    unassert(!hostonly);  // caller should know better\n    sysprot = PROT_READ | PROT_WRITE;\n  }\n  memset(&ranges, 0, sizeof(ranges));\n  executable_code_was_made_non_executable = false;\n  for (rc = 0, end = virt + size;;) {\n    for (pt = s->cr3, level = 39; level >= 12; level -= 9) {\n      ti = (virt >> level) & 511;\n      mi = GetPageAddress(s, pt, level == 39) + ti * 8;\n      pt = LoadPte(mi);\n      if (level > 12) {\n        if (!(pt & PAGE_V)) {\n          goto MemoryDisappeared;\n        }\n        continue;\n      }\n      for (;;) {\n        if (!(pt & PAGE_V)) {\n          goto MemoryDisappeared;\n        }\n        if (HasLinearMapping() && (pt & (PAGE_HOST | PAGE_MAP | PAGE_MUG)) ==\n                                      (PAGE_HOST | PAGE_MAP)) {\n          AddPageToRanges(&ranges, virt, end);\n        } else if ((pt & (PAGE_HOST | PAGE_MAP | PAGE_MUG)) ==\n                   (PAGE_HOST | PAGE_MAP | PAGE_MUG)) {\n          u8 *real = FindHostPage(pt);\n          while ((uintptr_t)real & (pagesize - 1)) real -= 4096;\n          if (Mprotect(real, pagesize, sysprot, \"mug\")) {\n            LOGF(\"mprotect(pt=%#\" PRIx64\n                 \", real=%p, size=%#lx, prot=%d) failed: %s\",\n                 pt, real, pagesize, prot, DescribeHostErrno(errno));\n            rc = -1;\n          }\n        }\n        if (!hostonly) {\n          for (;;) {\n            pt2 = (pt & ~(PAGE_U | PAGE_RW | PAGE_XD)) | key;\n            if (CasPte(mi, pt, pt2)) break;\n            pt = LoadPte(mi);\n            if (!(pt & PAGE_V)) {\n              goto MemoryDisappeared;\n            }\n          }\n          // check for exec -> non-exec\n          if (!(pt & PAGE_XD) && (pt2 & PAGE_XD) && !(pt & PAGE_RSRV)) {\n            executable_code_was_made_non_executable = true;\n#ifdef HAVE_JIT\n            if (!IsJitDisabled(&s->jit)) {\n              ResetJitPage(&s->jit, virt);\n            }\n#endif\n          }\n        }\n        if ((virt += 4096) >= end) {\n          goto FinishedCrawling;\n        }\n        if (++ti == 512) break;\n        pt = LoadPte((mi += 8));\n      }\n    }\n  }\nFinishedCrawling:\n  if (HasLinearMapping()) {\n    for (i = 0; i < ranges.i; ++i) {\n      a = ROUNDDOWN(ranges.p[i].a, pagesize);\n      b = ranges.p[i].b;\n      if (Mprotect(ToHost(a), b - a, sysprot, \"linear\")) {\n        LOGF(\"failed to %s subrange\"\n             \" [%\" PRIx64 \",%\" PRIx64 \") within requested range\"\n             \" [%\" PRIx64 \",%\" PRIx64 \"): %s\",\n             \"mprotect\", a, b, orig_virt, orig_virt + size,\n             DescribeHostErrno(errno));\n        rc = -1;\n      }\n    }\n    free(ranges.p);\n  }\n  if (!hostonly) {\n#ifndef DISABLE_JIT\n    if (HasLinearMapping() && !IsJitDisabled(&s->jit)) {\n      ProtectRwxMemory(s, rc, orig_virt, size, pagesize, prot);\n    }\n#endif\n    InvalidateSystem(s, true, executable_code_was_made_non_executable);\n  }\n  return rc;\nMemoryDisappeared:\n  // mprotect() doesn't lock pages, so a race condition can\n  // occur if the guest fiendishly munmaps this memory from\n  // a different thread. in that case, the main thing we do\n  // care about is not crashing. therefore it should not be\n  // too concerning that this failure could occur after the\n  // address space has been mutated.\n  if (HasLinearMapping()) {\n    free(ranges.p);\n  }\n  return enomem();\n}\n\nint SyncVirtual(struct System *s, i64 virt, i64 size, int sysflags) {\n  int rc;\n  u8 *mi;\n  u64 pt;\n  i64 orig_virt;\n  i64 ti, end, level;\n  long i, skew, pagesize;\n  struct ContiguousMemoryRanges ranges;\n  if (!IsValidAddrSize(virt, size)) {\n    return einval();\n  }\n  orig_virt = virt;\n  (void)orig_virt;\n  pagesize = FLAG_pagesize;\n  if (HasLinearMapping() && (skew = virt & (pagesize - 1))) {\n    size += skew;\n    virt -= skew;\n  }\n  if (!IsFullyMapped(s, virt, size)) {\n    LOGF(\"mprotect(%#\" PRIx64 \", %#\" PRIx64 \") interval has unmapped pages\",\n         virt, size);\n    return enomem();\n  }\n  memset(&ranges, 0, sizeof(ranges));\n  for (rc = 0, end = virt + size;;) {\n    for (pt = s->cr3, level = 39; level >= 12; level -= 9) {\n      ti = (virt >> level) & 511;\n      mi = GetPageAddress(s, pt, level == 39) + ti * 8;\n      pt = LoadPte(mi);\n      if (level > 12) {\n        if (!(pt & PAGE_V)) {\n          goto MemoryDisappeared;\n        }\n        continue;\n      }\n      for (;;) {\n        if (!(pt & PAGE_V)) {\n          goto MemoryDisappeared;\n        }\n        if (HasLinearMapping() && (pt & (PAGE_HOST | PAGE_MAP | PAGE_MUG)) ==\n                                      (PAGE_HOST | PAGE_MAP)) {\n          AddPageToRanges(&ranges, virt, end);\n        } else if ((pt & (PAGE_HOST | PAGE_MAP | PAGE_MUG)) ==\n                   (PAGE_HOST | PAGE_MAP | PAGE_MUG)) {\n          u8 *page, *real;\n          page = real = FindHostPage(pt);\n          while ((uintptr_t)page & (pagesize - 1)) page -= 4096;\n          long lilsize = (real - page) + MIN(4096, end - virt);\n          if (Msync(page, lilsize, sysflags, \"mug\")) {\n            LOGF(\"msync(%p [pt=%#\" PRIx64\n                 \"], size=%#lx, flags=%d) failed: %s\\n%s\",\n                 page, pt, pagesize, sysflags, DescribeHostErrno(errno),\n                 FormatPml4t(g_machine));\n            rc = -1;\n          }\n        }\n        if ((virt += 4096) >= end) {\n          goto FinishedCrawling;\n        }\n        if (++ti == 512) break;\n        pt = LoadPte((mi += 8));\n      }\n    }\n  }\nFinishedCrawling:\n  if (HasLinearMapping()) {\n    for (i = 0; i < ranges.i; ++i) {\n      if (Msync(ToHost(ranges.p[i].a), ranges.p[i].b - ranges.p[i].a, sysflags,\n                \"linear\")) {\n        LOGF(\"failed to %s subrange\"\n             \" [%\" PRIx64 \",%\" PRIx64 \") within requested range\"\n             \" [%\" PRIx64 \",%\" PRIx64 \"): %s\",\n             \"msync\", ranges.p[i].a, ranges.p[i].b, orig_virt, orig_virt + size,\n             DescribeHostErrno(errno));\n        rc = -1;\n      }\n    }\n    free(ranges.p);\n  }\n  return rc;\nMemoryDisappeared:\n  if (HasLinearMapping()) {\n    free(ranges.p);\n  }\n  return enomem();\n}\n\n// @asyncsignalsafe\nstatic i64 FindGuestAddr(struct System *s, uintptr_t hp, u64 pt, long lvl,\n                         u64 *out_pte) {\n  u8 *mi;\n  i64 res;\n  u64 pte, i;\n  if ((mi = GetPageAddress(s, pt, lvl == 1))) {\n    for (i = 0; i < 512; ++i) {\n      if ((pte = LoadPte(mi + i * 8)) & PAGE_V) {\n        if (lvl == 4) {\n          if ((pte & PAGE_HOST) && (uintptr_t)FindHostPage(pte) == hp) {\n            if (out_pte) {\n              *out_pte = pte;\n            }\n            return i << 39;\n          }\n        } else if ((res = FindGuestAddr(s, hp, pte, lvl + 1, out_pte)) != -1) {\n          return i << 39 | res >> 9;\n        }\n      }\n    }\n  }\n  return -1;\n}\n\n// Reverse maps real host address to virtual guest address if exists.\n// On failure the host address is returned and zero is stored in pte.\n// @asyncsignalsafe\ni64 ConvertHostToGuestAddress(struct System *s, void *ha, u64 *out_pte) {\n  i64 g48;\n  uintptr_t base;\n  if (out_pte) *out_pte = 0;\n  if (s->mode.omode != XED_MODE_LONG &&\n      (!(s->cr0 & CR0_PG) || s->mode.genmode == XED_GEN_MODE_REAL)) {\n    return (uintptr_t)ha;\n  }\n  if ((uintptr_t)ha < kNullSize) return (uintptr_t)ha;\n  if (HasLinearMapping() && !out_pte) return ToGuest(ha);\n  base = (uintptr_t)ha & -4096;\n  if ((g48 = FindGuestAddr(s, base, s->cr3, 1, out_pte)) != -1) {\n    return ((i64)((u64)g48 << 16) >> 16) | ((uintptr_t)ha & 4095);\n  } else {\n    return (uintptr_t)ha;\n  }\n}\n"
  },
  {
    "path": "blink/message.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <math.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <wchar.h>\n\n#include \"blink/buffer.h\"\n#include \"blink/lines.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/panel.h\"\n#include \"blink/strwidth.h\"\n#include \"blink/util.h\"\n\nstatic int GetWidthOfLongestLine(struct Lines *lines) {\n  int i, w, m;\n  for (m = i = 0; i < lines->n; ++i) {\n    w = strwidth(lines->p[i], 0);\n    m = MAX(m, w);\n  }\n  return m;\n}\n\nvoid PrintMessageBox(int fd, const char *msg, long tyn, long txn) {\n  struct Buffer b;\n  int i, w, h, x, y;\n  struct Lines *lines;\n  lines = NewLines();\n  AppendLines(lines, msg);\n  h = 3 + lines->n + 3;\n  w = 4 + GetWidthOfLongestLine(lines) + 4;\n  x = rint(txn / 2. - w / 2.);\n  y = rint(tyn / 2. - h / 2.);\n  memset(&b, 0, sizeof(b));\n  AppendFmt(&b, \"\\033[%d;%dH\", y++, x);\n  for (i = 0; i < w; ++i) AppendStr(&b, \" \");\n  AppendFmt(&b, \"\\033[%d;%dH ╔\", y++, x);\n  for (i = 0; i < w - 4; ++i) AppendStr(&b, \"═\");\n  AppendStr(&b, \"╗ \");\n  AppendFmt(&b, \"\\033[%d;%dH ║  %-*s  ║ \", y++, x, w - 8, \"\");\n  for (i = 0; i < lines->n; ++i) {\n    int lw = strwidth(lines->p[i], 0);\n    AppendFmt(&b, \"\\033[%d;%dH ║  %s%-*s  ║ \", y++, x, lines->p[i], w - 8 - lw,\n              \"\");\n  }\n  FreeLines(lines);\n  AppendFmt(&b, \"\\033[%d;%dH ║  %-*s  ║ \", y++, x, w - 8, \"\");\n  AppendFmt(&b, \"\\033[%d;%dH ╚\", y++, x);\n  for (i = 0; i < w - 4; ++i) AppendStr(&b, \"═\");\n  AppendStr(&b, \"╝ \");\n  AppendFmt(&b, \"\\033[%d;%dH\", y++, x);\n  for (i = 0; i < w; ++i) AppendStr(&b, \" \");\n  AppendFmt(&b, \"\\033[%ld;%ldH\", tyn, txn);\n  UninterruptibleWrite(fd, b.p, b.i);\n  free(b.p);\n}\n"
  },
  {
    "path": "blink/metal.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/msr.h\"\n#include \"blink/rde.h\"\n#include \"blink/x86.h\"\n\n#ifndef DISABLE_METAL\n\nstatic relegated const struct DescriptorCache *GetSegment(P, unsigned s) {\n  if (s < 6) {\n    return m->seg + s;\n  } else {\n    OpUdImpl(m);\n  }\n}\n\nstatic relegated u64 GetDescriptorBase(u64 d) {\n  return (d & 0xff00000000000000) >> 32 | (d & 0x000000ffffff0000) >> 16;\n}\n\nstatic struct XedMachineMode GetDescriptorMode(u64 d) {\n  static const struct XedMachineMode kMode[] = {\n      XED_MACHINE_MODE_LEGACY_16, XED_MACHINE_MODE_LONG,\n      XED_MACHINE_MODE_LEGACY_32, XED_MACHINE_MODE_LONG};\n  return kMode[(d & 0x0060000000000000) >> 53];\n}\n\nstatic relegated bool IsProtectedMode(struct Machine *m) {\n  return m->system->cr0 & CR0_PE;\n}\n\nstatic relegated bool IsNullSelector(u16 sel) {\n  return (sel & -4u) == 0;\n}\n\nstatic relegated void ChangeMachineMode(struct Machine *m,\n                                        struct XedMachineMode mode) {\n  if (memcmp(&mode, &m->mode, sizeof(mode)) == 0) return;\n  ResetInstructionCache(m);\n  SetMachineMode(m, mode);\n#ifdef HAVE_JIT\n  if (mode.omode == XED_MODE_LONG && FLAG_wantjit) {\n    EnableJit(&m->system->jit);\n  }\n#endif\n}\n\nstatic relegated void SetSegment(P, unsigned sr, u16 sel, bool jumping) {\n  u64 descriptor;\n  if (sr == SREG_CS && !jumping) OpUdImpl(m);\n  if (!IsProtectedMode(m)) {\n    m->seg[sr].sel = sel;\n    m->seg[sr].base = sel << 4;\n  } else if (GetDescriptor(m, sel, &descriptor) != -1) {\n    m->seg[sr].sel = sel;\n    m->seg[sr].base = GetDescriptorBase(descriptor);\n    if (sr == SREG_CS) {\n      ChangeMachineMode(m, GetDescriptorMode(descriptor));\n    }\n  } else if (IsNullSelector(sel)) {\n    switch (sr) {\n      case SREG_CS:\n        ThrowProtectionFault(m);\n        break;\n      case SREG_SS:\n        if (Cpl(m) == 3) ThrowProtectionFault(m);\n    }\n    m->seg[sr].sel = sel;\n  } else {\n    ThrowProtectionFault(m);\n  }\n}\n\nrelegated void SetCs(P, u16 sel) {\n  SetSegment(A, SREG_CS, sel, true);\n}\n\nrelegated void LongBranch(P, u16 sel, u64 ip) {\n  SetCs(A, sel);\n  m->ip = ip;\n  m->oplen = 0;\n  if (m->system->onlongbranch) {\n    m->system->onlongbranch(m);\n  }\n}\n\nrelegated void OpPushSeg(P) {\n  u8 seg = (Opcode(rde) & 070) >> 3;\n  Push(A, GetSegment(A, seg)->sel);\n}\n\nrelegated void OpPopSeg(P) {\n  u8 seg = (Opcode(rde) & 070) >> 3;\n  SetSegment(A, seg, Pop(A, 0), false);\n}\n\nrelegated void OpMovEvqpSw(P) {\n  WriteRegisterOrMemory(rde, GetModrmRegisterWordPointerWriteOszRexw(A),\n                        GetSegment(A, ModrmReg(rde))->sel);\n}\n\nrelegated void OpMovSwEvqp(P) {\n  u64 x;\n  x = ReadMemory(rde, GetModrmRegisterWordPointerReadOszRexw(A));\n  SetSegment(A, ModrmReg(rde), x, false);\n}\n\nrelegated void OpJmpf(P) {\n  LongBranch(A, uimm0, disp);\n}\n\nstatic void PutEaxAx(P, u32 x) {\n  if (!Osz(rde)) {\n    Put64(m->ax, x);\n  } else {\n    Put16(m->ax, x);\n  }\n}\n\nstatic u32 GetEaxAx(P) {\n  if (!Osz(rde)) {\n    return Get32(m->ax);\n  } else {\n    return Get16(m->ax);\n  }\n}\n\nrelegated void OpInAlImm(P) {\n  Put8(m->ax, OpIn(m, uimm0));\n}\n\nrelegated void OpInAxImm(P) {\n  PutEaxAx(A, OpIn(m, uimm0));\n}\n\nrelegated void OpInAlDx(P) {\n  Put8(m->ax, OpIn(m, Get16(m->dx)));\n}\n\nrelegated void OpInAxDx(P) {\n  PutEaxAx(A, OpIn(m, Get16(m->dx)));\n}\n\nrelegated void OpOutImmAl(P) {\n  OpOut(m, uimm0, Get8(m->ax));\n}\n\nrelegated void OpOutImmAx(P) {\n  OpOut(m, uimm0, GetEaxAx(A));\n}\n\nrelegated void OpOutDxAl(P) {\n  OpOut(m, Get16(m->dx), Get8(m->ax));\n}\n\nrelegated void OpOutDxAx(P) {\n  OpOut(m, Get16(m->dx), GetEaxAx(A));\n}\n\nstatic relegated void LoadFarPointer(P, unsigned sr, bool jumping) {\n  unsigned n;\n  u8 *p;\n  u64 fp;\n  switch (Eamode(rde)) {\n    case XED_MODE_LONG:\n      OpUdImpl(m);\n      break;\n    case XED_MODE_LEGACY:\n    case XED_MODE_REAL:\n      n = 1 << WordLog2(rde);\n      p = ComputeReserveAddressRead(A, n + 2);\n      LockBus(p);\n      fp = Load32(p);\n      if (n >= 4) {\n        fp |= (u64)Load16(p + 4) << 32;\n        SetSegment(A, sr, fp >> 32 & 0x0000ffff, jumping);\n        fp &= 0xffffffff;\n      } else {\n        SetSegment(A, sr, fp >> 16 & 0x0000ffff, jumping);\n        fp &= 0x0000ffff;\n      }\n      UnlockBus(p);\n      if (!jumping) {\n        WriteRegister(rde, RegRexrReg(m, rde), fp);  // offset portion\n      } else {\n        m->ip = fp;\n        m->oplen = 0;\n        if (m->system->onlongbranch) {\n          m->system->onlongbranch(m);\n        }\n      }\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nrelegated void OpLes(P) {\n  LoadFarPointer(A, SREG_ES, false);\n}\n\nrelegated void OpLds(P) {\n  LoadFarPointer(A, SREG_DS, false);\n}\n\nrelegated void OpLss(P) {\n  LoadFarPointer(A, SREG_SS, false);\n}\n\nrelegated void OpLfs(P) {\n  LoadFarPointer(A, SREG_FS, false);\n}\n\nrelegated void OpLgs(P) {\n  LoadFarPointer(A, SREG_GS, false);\n}\n\nrelegated void OpJmpfEq(P) {\n  LoadFarPointer(A, SREG_CS, true);\n}\n\nrelegated void OpCallfEq(P) {\n  Push(A, m->cs.sel);\n  Push(A, m->ip);\n  LoadFarPointer(A, SREG_CS, true);\n}\n\nrelegated void OpClts(P) {\n  if (Cpl(m)) {\n    ThrowProtectionFault(m);\n  } else {\n    m->system->cr0 &= ~(u64)CR0_TS;\n  }\n}\n\nrelegated void OpWrmsr(P) {\n  switch (Get32(m->cx)) {\n    case MSR_IA32_EFER:\n      m->system->efer = Get32(m->ax);\n      break;\n    case MSR_IA32_FS_BASE:\n      m->fs.base = (u64)Read32(m->dx) << 32 | Read32(m->ax);\n      break;\n    case MSR_IA32_GS_BASE:\n      m->gs.base = (u64)Read32(m->dx) << 32 | Read32(m->ax);\n      break;\n    default:\n      LOGF(\"unsupported msr %#x\", Get32(m->cx));\n      break;\n  }\n}\n\nrelegated void OpRdmsr(P) {\n  switch (Get32(m->cx)) {\n    case MSR_IA32_EFER:\n      Put32(m->ax, m->system->efer);\n      break;\n    case MSR_IA32_FS_BASE:\n      Put32(m->dx, m->fs.base >> 32);\n      Put32(m->ax, m->fs.base);\n      break;\n    case MSR_IA32_GS_BASE:\n      Put32(m->dx, m->gs.base >> 32);\n      Put32(m->ax, m->gs.base);\n      break;\n    default:\n      LOGF(\"unsupported msr %#x\", Get32(m->cx));\n      break;\n  }\n}\n\nrelegated void OpMovRqCq(P) {\n  switch (ModrmReg(rde)) {\n    case 0:\n      Put64(RegRexbRm(m, rde), m->system->cr0);\n      break;\n    case 2:\n      Put64(RegRexbRm(m, rde), m->system->cr2);\n      break;\n    case 3:\n      Put64(RegRexbRm(m, rde), m->system->cr3);\n      break;\n    case 4:\n      Put64(RegRexbRm(m, rde), m->system->cr4);\n      break;\n    default:\n      OpUdImpl(m);\n  }\n}\n\nrelegated void OpMovCqRq(P) {\n  u64 cr0;\n  struct XedMachineMode mode;\n  switch (ModrmReg(rde)) {\n    case 0:\n      m->system->cr0 = cr0 = Get64(RegRexbRm(m, rde));\n      mode = m->system->mode;\n      if ((cr0 & CR0_PE)) {\n        mode.genmode = XED_GEN_MODE_PROTECTED;\n      } else {\n        mode.genmode = XED_GEN_MODE_REAL;\n      }\n      ChangeMachineMode(m, mode);\n      break;\n    case 2:\n      m->system->cr2 = Get64(RegRexbRm(m, rde));\n      break;\n    case 3:\n      m->system->cr3 = Get64(RegRexbRm(m, rde));\n      ResetTlb(m);\n      break;\n    case 4:\n      m->system->cr4 = Get64(RegRexbRm(m, rde));\n      ResetTlb(m);\n      break;\n    default:\n      OpUdImpl(m);\n  }\n}\n\n#endif /* DISABLE_METAL */\n"
  },
  {
    "path": "blink/mkfifo.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <fcntl.h>\n#include <sys/stat.h>\n\n#include \"blink/errno.h\"\n#include \"blink/log.h\"\n\nint mkfifo_(const char *ph, mode_t mode) {\n#ifdef HAVE_MKFIFO\n  return mkfifo(ph, mode);\n#else\n  return enosys();\n#endif\n}\n"
  },
  {
    "path": "blink/mkfifoat.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <fcntl.h>\n#include <sys/stat.h>\n\n#include \"blink/errno.h\"\n#include \"blink/log.h\"\n#include \"blink/syscall.h\"\n\nint mkfifoat_(int dirfd, const char *path, mode_t mode) {\n  if (dirfd == AT_FDCWD) {\n    return mkfifo(path, mode);\n  } else {\n    LOGF(\"this platform doesn't have mkfifoat()\");\n    return enosys();\n  }\n}\n"
  },
  {
    "path": "blink/mmx.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n\n#include \"blink/endian.h\"\n#include \"blink/macros.h\"\n#include \"blink/sse.h\"\n\n#ifndef DISABLE_MMX\n\nrelegated void MmxPsubb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] -= y[i];\n  }\n}\n\nrelegated void MmxPaddb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] += y[i];\n  }\n}\n\nrelegated void MmxPavgb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] = (x[i] + y[i] + 1) >> 1;\n  }\n}\n\nrelegated void MmxPabsb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] = ABS((i8)y[i]);\n  }\n}\n\nrelegated void MmxPminub(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] = MIN(x[i], y[i]);\n  }\n}\n\nrelegated void MmxPmaxub(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] = MAX(x[i], y[i]);\n  }\n}\n\nrelegated void MmxPcmpeqb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] = -(x[i] == y[i]);\n  }\n}\n\nrelegated void MmxPcmpgtb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] = -((i8)x[i] > (i8)y[i]);\n  }\n}\n\nrelegated void MmxPsubw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, Get16(x + i * 2) - Get16(y + i * 2));\n  }\n}\n\nrelegated void MmxPaddw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, Get16(x + i * 2) + Get16(y + i * 2));\n  }\n}\n\nrelegated void MmxPaddsw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, MAX(-32768, MIN(32767, ((i16)Get16(x + i * 2) +\n                                             (i16)Get16(y + i * 2)))));\n  }\n}\n\nrelegated void MmxPsubsw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, MAX(-32768, MIN(32767, ((i16)Get16(x + i * 2) -\n                                             (i16)Get16(y + i * 2)))));\n  }\n}\n\nrelegated void MmxPaddusw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, MIN(65535, Get16(x + i * 2) + Get16(y + i * 2)));\n  }\n}\n\nrelegated void MmxPcmpgtw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, -((i16)Get16(x + i * 2) > (i16)Get16(y + i * 2)));\n  }\n}\n\nrelegated void MmxPcmpeqw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, -(Get16(x + i * 2) == Get16(y + i * 2)));\n  }\n}\n\nrelegated void MmxPavgw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, (Get16(x + i * 2) + Get16(y + i * 2) + 1) >> 1);\n  }\n}\n\nrelegated void MmxPmulhw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, ((i16)Get16(x + i * 2) * (i16)Get16(y + i * 2)) >> 16);\n  }\n}\n\nrelegated void MmxPmullw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, (i16)Get16(x + i * 2) * (i16)Get16(y + i * 2));\n  }\n}\n\nstatic relegated int Addition(int x, int y) {\n  return x + y;\n}\n\nstatic relegated int Subtraction(int x, int y) {\n  return x - y;\n}\n\nstatic relegated int Clamp16(int x) {\n  return MAX(-32768, MIN(32767, x));\n}\n\nstatic relegated void Phsw(u8 x[8], const u8 y[8], int Op(int, int)) {\n  u8 t[8];\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    Put16(t + i * 2, Clamp16(Op((i16)Get16(x + (i * 2) * 2),\n                                (i16)Get16(x + (i * 2 + 1) * 2))));\n  }\n  for (i = 0; i < 2; ++i) {\n    Put16(t + (2 + i) * 2, Clamp16(Op((i16)Get16(y + (i * 2) * 2),\n                                      (i16)Get16(y + (i * 2 + 1) * 2))));\n  }\n  memcpy(x, t, 8);\n}\n\nrelegated void MmxPhaddsw(u8 x[8], const u8 y[8]) {\n  Phsw(x, y, Addition);\n}\n\nrelegated void MmxPhsubsw(u8 x[8], const u8 y[8]) {\n  Phsw(x, y, Subtraction);\n}\n\n#endif /* DISABLE_MMX */\n"
  },
  {
    "path": "blink/modrm.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/modrm.h\"\n\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n#include \"blink/x86.h\"\n\nstruct AddrSeg LoadEffectiveAddress(const P) {\n  u64 i = disp;\n  u64 s = m->ds.base;\n  struct AddrSeg res;\n  unassert(!IsModrmRegister(rde));\n  if (Eamode(rde) != XED_MODE_REAL) {\n    if (!SibExists(rde)) {\n      if (IsRipRelative(rde)) {\n        if (Mode(rde) == XED_MODE_LONG) {\n          i += m->ip;\n        }\n      } else {\n        i += Get64(RegRexbRm(m, rde));\n        if (RexbRm(rde) == 4 || RexbRm(rde) == 5) {\n          s = m->ss.base;\n        }\n      }\n    } else {\n      if (SibHasBase(rde)) {\n        i += Get64(RegRexbBase(m, rde));\n        if (RexbBase(rde) == 4 || RexbBase(rde) == 5) {\n          s = m->ss.base;\n        }\n      }\n      if (SibHasIndex(rde)) {\n        i += Get64(RegRexxIndex(m, rde)) << SibScale(rde);\n      }\n    }\n    if (Eamode(rde) == XED_MODE_LEGACY) {\n      i &= 0xffffffff;\n    }\n  } else {\n    switch (ModrmRm(rde)) {\n      case 0:\n        i += Get16(m->bx);\n        i += Get16(m->si);\n        break;\n      case 1:\n        i += Get16(m->bx);\n        i += Get16(m->di);\n        break;\n      case 2:\n        s = m->ss.base;\n        i += Get16(m->bp);\n        i += Get16(m->si);\n        break;\n      case 3:\n        s = m->ss.base;\n        i += Get16(m->bp);\n        i += Get16(m->di);\n        break;\n      case 4:\n        i += Get16(m->si);\n        break;\n      case 5:\n        i += Get16(m->di);\n        break;\n      case 6:\n        if (ModrmMod(rde)) {\n          s = m->ss.base;\n          i += Get16(m->bp);\n        }\n        break;\n      case 7:\n        i += Get16(m->bx);\n        break;\n      default:\n        __builtin_unreachable();\n    }\n    i &= 0xffff;\n  }\n  res.addr = i;\n  res.seg = s;\n  return res;\n}\n\ni64 ComputeAddress(P) {\n  struct AddrSeg ea = LoadEffectiveAddress(A);\n  return AddSegment(A, ea.addr, ea.seg);\n}\n\nu8 *ComputeReserveAddressRead(P, size_t n) {\n  return ReserveAddress(m, ComputeAddress(A), n, false);\n}\n\nu8 *ComputeReserveAddressRead1(P) {\n  return ComputeReserveAddressRead(A, 1);\n}\n\nu8 *ComputeReserveAddressRead4(P) {\n  return ComputeReserveAddressRead(A, 4);\n}\n\nu8 *ComputeReserveAddressRead8(P) {\n  return ComputeReserveAddressRead(A, 8);\n}\n\nu8 *ComputeReserveAddressWrite(P, size_t n) {\n  return ReserveAddress(m, ComputeAddress(A), n, true);\n}\n\nu8 *ComputeReserveAddressWrite1(P) {\n  return ComputeReserveAddressWrite(A, 1);\n}\n\nu8 *ComputeReserveAddressWrite4(P) {\n  return ComputeReserveAddressWrite(A, 4);\n}\n\nu8 *ComputeReserveAddressWrite8(P) {\n  return ComputeReserveAddressWrite(A, 8);\n}\n\nu8 *GetModrmRegisterMmPointerRead(P, size_t n) {\n  if (IsModrmRegister(rde)) {\n    return MmRm(m, rde);\n  } else {\n    return ComputeReserveAddressRead(A, n);\n  }\n}\n\nu8 *GetModrmRegisterMmPointerRead8(P) {\n  return GetModrmRegisterMmPointerRead(A, 8);\n}\n\nu8 *GetModrmRegisterMmPointerWrite(P, size_t n) {\n  if (IsModrmRegister(rde)) {\n    return MmRm(m, rde);\n  } else {\n    return ComputeReserveAddressWrite(A, n);\n  }\n}\n\nu8 *GetModrmRegisterMmPointerWrite8(P) {\n  return GetModrmRegisterMmPointerWrite(A, 8);\n}\n\nu8 *GetModrmRegisterBytePointerRead1(P) {\n  if (IsModrmRegister(rde)) {\n    return ByteRexbRm(m, rde);\n  } else {\n    return ComputeReserveAddressRead1(A);\n  }\n}\n\nu8 *GetModrmRegisterBytePointerWrite1(P) {\n  if (IsModrmRegister(rde)) {\n    return ByteRexbRm(m, rde);\n  } else {\n    return ComputeReserveAddressWrite1(A);\n  }\n}\n\nu8 *GetModrmRegisterWordPointerRead(P, size_t n) {\n  if (IsModrmRegister(rde)) {\n    return RegRexbRm(m, rde);\n  } else {\n    return ComputeReserveAddressRead(A, n);\n  }\n}\n\nu8 *GetModrmRegisterWordPointerRead2(P) {\n  return GetModrmRegisterWordPointerRead(A, 2);\n}\n\nu8 *GetModrmRegisterWordPointerRead4(P) {\n  return GetModrmRegisterWordPointerRead(A, 4);\n}\n\nu8 *GetModrmRegisterWordPointerRead8(P) {\n  return GetModrmRegisterWordPointerRead(A, 8);\n}\n\nu8 *GetModrmRegisterWordPointerReadOsz(P) {\n  if (!Osz(rde)) {\n    return GetModrmRegisterWordPointerRead8(A);\n  } else {\n    return GetModrmRegisterWordPointerRead2(A);\n  }\n}\n\nu8 *GetModrmRegisterWordPointerReadOszRexw(P) {\n  if (Rexw(rde)) {\n    return GetModrmRegisterWordPointerRead8(A);\n  } else if (!Osz(rde)) {\n    return GetModrmRegisterWordPointerRead4(A);\n  } else {\n    return GetModrmRegisterWordPointerRead2(A);\n  }\n}\n\nu8 *GetModrmRegisterWordPointerWrite(P, size_t n) {\n  if (IsModrmRegister(rde)) {\n    return RegRexbRm(m, rde);\n  } else {\n    return ComputeReserveAddressWrite(A, n);\n  }\n}\n\nu8 *GetModrmRegisterWordPointerWrite2(P) {\n  return GetModrmRegisterWordPointerWrite(A, 2);\n}\n\nu8 *GetModrmRegisterWordPointerWrite4(P) {\n  return GetModrmRegisterWordPointerWrite(A, 4);\n}\n\nu8 *GetModrmRegisterWordPointerWrite8(P) {\n  return GetModrmRegisterWordPointerWrite(A, 8);\n}\n\nu8 *GetModrmRegisterWordPointerWriteOszRexw(P) {\n  if (Rexw(rde)) {\n    return GetModrmRegisterWordPointerWrite(A, 8);\n  } else if (!Osz(rde)) {\n    return GetModrmRegisterWordPointerWrite(A, 4);\n  } else {\n    return GetModrmRegisterWordPointerWrite(A, 2);\n  }\n}\n\nu8 *GetModrmRegisterWordPointerWriteOsz(P) {\n  if (!Osz(rde)) {\n    return GetModrmRegisterWordPointerWrite(A, 8);\n  } else {\n    return GetModrmRegisterWordPointerWrite(A, 2);\n  }\n}\n\nstatic u8 *GetModrmRegisterXmmPointerRead(P, size_t n) {\n  if (IsModrmRegister(rde)) {\n    return XmmRexbRm(m, rde);\n  } else {\n    return ComputeReserveAddressRead(A, n);\n  }\n}\n\nu8 *GetModrmRegisterXmmPointerRead4(P) {\n  return GetModrmRegisterXmmPointerRead(A, 4);\n}\n\nu8 *GetModrmRegisterXmmPointerRead8(P) {\n  return GetModrmRegisterXmmPointerRead(A, 8);\n}\n\nu8 *GetModrmRegisterXmmPointerRead16(P) {\n  return GetModrmRegisterXmmPointerRead(A, 16);\n}\n\nstatic u8 *GetModrmRegisterXmmPointerWrite(P, size_t n) {\n  if (IsModrmRegister(rde)) {\n    return XmmRexbRm(m, rde);\n  } else {\n    return ComputeReserveAddressWrite(A, n);\n  }\n}\n\nu8 *GetModrmRegisterXmmPointerWrite4(P) {\n  return GetModrmRegisterXmmPointerWrite(A, 4);\n}\n\nu8 *GetModrmRegisterXmmPointerWrite8(P) {\n  return GetModrmRegisterXmmPointerWrite(A, 8);\n}\n\nu8 *GetModrmRegisterXmmPointerWrite16(P) {\n  return GetModrmRegisterXmmPointerWrite(A, 16);\n}\n\nstatic u8 *GetVectorAddress(P, size_t n) {\n  u8 *p;\n  i64 v;\n  if (IsModrmRegister(rde)) {\n    p = XmmRexbRm(m, rde);\n  } else {\n    v = ComputeAddress(A);\n    SetReadAddr(m, v, n);\n    if ((v & (n - 1)) || !(p = LookupAddress(m, v))) {\n      ThrowSegmentationFault(m, v);\n    }\n  }\n  return p;\n}\n\nu8 *GetMmxAddress(P) {\n  return GetVectorAddress(A, 8);\n}\n\nu8 *GetXmmAddress(P) {\n  return GetVectorAddress(A, 16);\n}\n\nu8 *GetModrmReadBW(P) {\n  int lg2 = RegLog2(rde);\n  if (IsModrmRegister(rde)) {\n    if (!lg2) {\n      return ByteRexbRm(m, rde);\n    } else {\n      return RegRexbRm(m, rde);\n    }\n  } else {\n    return ComputeReserveAddressRead(A, 1 << RegLog2(rde));\n  }\n}\n\nu8 *GetModrmWriteBW(P) {\n  int lg2 = RegLog2(rde);\n  if (IsModrmRegister(rde)) {\n    if (!lg2) {\n      return ByteRexbRm(m, rde);\n    } else {\n      return RegRexbRm(m, rde);\n    }\n  } else {\n    return ComputeReserveAddressWrite(A, 1 << RegLog2(rde));\n  }\n}\n"
  },
  {
    "path": "blink/modrm.h",
    "content": "#ifndef BLINK_MODRM_H_\n#define BLINK_MODRM_H_\n#include \"blink/builtin.h\"\n#include \"blink/machine.h\"\n#include \"blink/rde.h\"\n#include \"blink/thread.h\"\n#include \"blink/x86.h\"\n\n#define RegRexbSrm(m, x)   m->weg[RexbSrm(x)]\n#define AddrByteReg(m, k)  (m->beg + kByteReg[k])\n#define ByteRexrReg(m, x)  AddrByteReg(m, RexRexr(x))\n#define ByteRexbRm(m, x)   AddrByteReg(m, RexRexb(x))\n#define ByteRexbSrm(m, x)  AddrByteReg(m, RexRexbSrm(x))\n#define RegSrm(m, x)       m->weg[Srm(x)]\n#define RegVreg(m, x)      m->weg[Vreg(x)]\n#define RegRexbRm(m, x)    m->weg[RexbRm(x)]\n#define RegRexrReg(m, x)   m->weg[RexrReg(x)]\n#define RegRexbBase(m, x)  m->weg[RexbBase(x)]\n#define RegRexxIndex(m, x) m->weg[Rexx(x) << 3 | SibIndex(x)]\n#define MmRm(m, x)         m->xmm[(x & 00000001600) >> 7]\n#define MmReg(m, x)        m->xmm[(x & 00000000007) >> 0]\n#define XmmRexbRm(m, x)    m->xmm[RexbRm(x)]\n#define XmmRexrReg(m, x)   m->xmm[RexrReg(x)]\n\n#ifdef HAVE_THREADS\n#define Lock(x) ((x & 020000000000) >> 037)\n#else\n#define Lock(x) 0\n#endif\n\n#ifndef DISABLE_METAL\n#define Mode(x)   ((x & 001400000000) >> 032)\n#define Eamode(x) ((x & 000300000000) >> 030)\n#else\n#define Mode(x) XED_MODE_LONG\nstatic inline u32 Eamode(u32 x) {\n  u32 res = (x & 000300000000) >> 030;\n  if (res == XED_MODE_REAL) __builtin_unreachable();\n  return res;\n}\n#endif\n\nstruct AddrSeg {\n  i64 addr;\n  u64 seg;\n};\n\nextern const u8 kByteReg[32];\n\nu8 *GetModrmReadBW(P);\nu8 *GetModrmWriteBW(P);\ni64 ComputeAddress(P);\nstruct AddrSeg LoadEffectiveAddress(const P);\nu8 *ComputeReserveAddressRead(P, size_t);\nu8 *ComputeReserveAddressRead1(P);\nu8 *ComputeReserveAddressRead4(P);\nu8 *ComputeReserveAddressRead8(P);\nu8 *ComputeReserveAddressWrite(P, size_t);\nu8 *ComputeReserveAddressWrite1(P);\nu8 *ComputeReserveAddressWrite4(P);\nu8 *ComputeReserveAddressWrite8(P);\nu8 *GetModrmRegisterBytePointerRead1(P);\nu8 *GetModrmRegisterBytePointerWrite1(P);\nu8 *GetModrmRegisterMmPointerRead(P, size_t);\nu8 *GetModrmRegisterMmPointerRead8(P);\nu8 *GetModrmRegisterMmPointerWrite(P, size_t);\nu8 *GetModrmRegisterMmPointerWrite8(P);\nu8 *GetModrmRegisterWordPointerRead(P, size_t);\nu8 *GetModrmRegisterWordPointerRead2(P);\nu8 *GetModrmRegisterWordPointerRead4(P);\nu8 *GetModrmRegisterWordPointerRead8(P);\nu8 *GetModrmRegisterWordPointerReadOsz(P);\nu8 *GetModrmRegisterWordPointerReadOszRexw(P);\nu8 *GetModrmRegisterWordPointerWrite(P, size_t);\nu8 *GetModrmRegisterWordPointerWrite2(P);\nu8 *GetModrmRegisterWordPointerWrite4(P);\nu8 *GetModrmRegisterWordPointerWrite8(P);\nu8 *GetModrmRegisterWordPointerWriteOsz(P);\nu8 *GetModrmRegisterWordPointerWriteOszRexw(P);\nu8 *GetModrmRegisterXmmPointerRead16(P);\nu8 *GetModrmRegisterXmmPointerRead4(P);\nu8 *GetModrmRegisterXmmPointerRead8(P);\nu8 *GetModrmRegisterXmmPointerWrite16(P);\nu8 *GetModrmRegisterXmmPointerWrite4(P);\nu8 *GetModrmRegisterXmmPointerWrite8(P);\nu8 *GetXmmAddress(P) returnsaligned((16));\nu8 *GetMmxAddress(P) returnsaligned((8));\n\n#endif /* BLINK_MODRM_H_ */\n"
  },
  {
    "path": "blink/msr.h",
    "content": "#ifndef BLINK_MSR_H_\n#define BLINK_MSR_H_\n\n#define MSR_P5_TSC  0x10  // time stamp register\n#define MSR_P5_CESR 0x11  // control and event select register\n#define MSR_P5_CTR0 0x12  // counter #0\n#define MSR_P5_CTR1 0x13  // counter #1\n\n#define MSR_P5_CESR_PC    0x0200  // pin control\n#define MSR_P5_CESR_CC    0x01C0  // counter control mask\n#define MSR_P5_CESR_ES    0x003F  // event control mask\n#define MSR_P5_CESR_SHIFT 16      // shift to get counter 1\n#define MSR_P5_CESR_MASK  (MSR_P5_CESR_PC | MSR_P5_CESR_CC | MSR_P5_CESR_ES)\n\n#define MSR_IA32_EFER     0xC0000080  // extended feature enable register\n#define MSR_IA32_EFER_LMA 0x00000400  // long mode active\n#define MSR_IA32_EFER_LME 0x00000100  // long mode enable\n#define MSR_IA32_EFER_NXE 0x00000800  // no-execute enable\n#define MSR_IA32_EFER_SCE 0x00000001  // syscall/sysret enable\n\n#define MSR_IA32_FS_BASE        0xC0000100\n#define MSR_IA32_GS_BASE        0xC0000101\n#define MSR_IA32_GS_BASE_KERNEL 0xC0000102\n\n#define MSR_CORE_THREAD_COUNT       0x35\n#define MSR_FLEX_RATIO              0x194\n#define MSR_IA32_APERF              0xE8\n#define MSR_IA32_APIC_BASE          0x1b\n#define MSR_IA32_APIC_BASE_BASE     (0xfffff << 12)\n#define MSR_IA32_APIC_BASE_BSP      (1 << 8)\n#define MSR_IA32_APIC_BASE_ENABLE   (1 << 11)\n#define MSR_IA32_APIC_BASE_EXTENDED (1 << 10)\n#define MSR_IA32_BBL_CR_CTL         0x119\n#define MSR_IA32_BIOS_SIGN_ID       0x8b\n#define MSR_IA32_CLOCK_MODULATION   0x19a\n#define MSR_IA32_CORE_C3_RESIDENCY  0x3FC\n#define MSR_IA32_CORE_C6_RESIDENCY  0x3FD\n#define MSR_IA32_CORE_C7_RESIDENCY  0x3FE\n#define MSR_IA32_CR_PAT             0x277\n#define MSR_IA32_CSTAR              0xC0000083\n#define MSR_IA32_DDR_ENERGY_STATUS  0x619\n#define MSR_IA32_DEBUGCTLMSR        0x1d9\n#define MSR_IA32_DS_AREA            0x600\n#define MSR_IA32_EBL_CR_POWERON     0x2a\n\n#define MSR_IA32_EVNTSEL0                    0x186\n#define MSR_IA32_EVNTSEL1                    0x187\n#define MSR_IA32_EVNTSEL2                    0x188\n#define MSR_IA32_EVNTSEL3                    0x189\n#define MSR_IA32_FEATCTL_CSTATE_SMI          (1 << 16)\n#define MSR_IA32_FEATCTL_LOCK                (1 << 0)\n#define MSR_IA32_FEATCTL_VMXON               (1 << 2)\n#define MSR_IA32_FEATCTL_VMXON_SMX           (1 << 1)\n#define MSR_IA32_FEATURE_CONTROL             0x3a\n#define MSR_IA32_FMASK                       0xC0000084\n#define MSR_IA32_GT_PERF_LIMIT_REASONS       0x6B0\n#define MSR_IA32_IA_PERF_LIMIT_REASONS       0x690\n#define MSR_IA32_IA_PERF_LIMIT_REASONS_SKL   0x64F\n#define MSR_IA32_LASTBRANCHFROMIP            0x1db\n#define MSR_IA32_LASTBRANCHTOIP              0x1dc\n#define MSR_IA32_LASTINTFROMIP               0x1dd\n#define MSR_IA32_LASTINTTOIP                 0x1de\n#define MSR_IA32_LLC_FLUSHED_RESIDENCY_TIMER 0x61D\n#define MSR_IA32_LSTAR                       0xC0000082\n#define MSR_IA32_MC0_ADDR                    0x402\n#define MSR_IA32_MC0_CTL                     0x400\n#define MSR_IA32_MC0_MISC                    0x403\n#define MSR_IA32_MC0_STATUS                  0x401\n#define MSR_IA32_MCG_CAP                     0x179\n#define MSR_IA32_MCG_CTL                     0x17b\n#define MSR_IA32_MCG_STATUS                  0x17a\n#define MSR_IA32_MISC_ENABLE                 0x1a0\n#define MSR_IA32_MPERF                       0xE7\n#define MSR_IA32_MTRRCAP                     0xfe\n#define MSR_IA32_MTRR_DEF_TYPE               0x2ff\n#define MSR_IA32_MTRR_FIX16K_80000           0x258\n#define MSR_IA32_MTRR_FIX16K_A0000           0x259\n#define MSR_IA32_MTRR_FIX4K_C0000            0x268\n#define MSR_IA32_MTRR_FIX4K_C8000            0x269\n#define MSR_IA32_MTRR_FIX4K_D0000            0x26a\n#define MSR_IA32_MTRR_FIX4K_D8000            0x26b\n#define MSR_IA32_MTRR_FIX4K_E0000            0x26c\n#define MSR_IA32_MTRR_FIX4K_E8000            0x26d\n#define MSR_IA32_MTRR_FIX4K_F0000            0x26e\n#define MSR_IA32_MTRR_FIX4K_F8000            0x26f\n#define MSR_IA32_MTRR_FIX64K_00000           0x250\n#define MSR_IA32_MTRR_PHYSBASE(n)            (0x200 + 2 * (n))\n#define MSR_IA32_MTRR_PHYSMASK(n)            (0x200 + 2 * (n) + 1)\n#define MSR_IA32_P5_MC_ADDR                  0\n#define MSR_IA32_P5_MC_TYPE                  1\n#define MSR_IA32_PACKAGE_THERM_INTERRUPT     0x1b2\n#define MSR_IA32_PACKAGE_THERM_STATUS        0x1b1\n#define MSR_IA32_PERFCTR0                    0xc1\n#define MSR_IA32_PERFCTR1                    0xc2\n#define MSR_IA32_PERFCTR3                    0xc3\n#define MSR_IA32_PERFCTR4                    0xc4\n#define MSR_IA32_PERF_CTL                    0x199\n#define MSR_IA32_PERF_FIXED_CTR0             0x309\n#define MSR_IA32_PERF_FIXED_CTR_CTRL         0x38D\n#define MSR_IA32_PERF_GLOBAL_CTRL            0x38F\n#define MSR_IA32_PERF_GLOBAL_OVF_CTRL        0x390\n#define MSR_IA32_PERF_GLOBAL_STATUS          0x38E\n#define MSR_IA32_PERF_STS                    0x198\n#define MSR_IA32_PKG_C10_RESIDENCY           0x632\n#define MSR_IA32_PKG_C2_RESIDENCY            0x60D\n#define MSR_IA32_PKG_C3_RESIDENCY            0x3F8\n#define MSR_IA32_PKG_C6_RESIDENCY            0x3F9\n#define MSR_IA32_PKG_C7_RESIDENCY            0x3FA\n#define MSR_IA32_PKG_C8_RESIDENCY            0x630\n#define MSR_IA32_PKG_C9_RESIDENCY            0x631\n#define MSR_IA32_PKG_ENERGY_STATUS           0x611\n#define MSR_IA32_PKG_POWER_SKU_UNIT          0x606\n#define MSR_IA32_PLATFORM_ID                 0x17\n#define MSR_IA32_PP0_ENERGY_STATUS           0x639\n#define MSR_IA32_PP1_ENERGY_STATUS           0x641\n#define MSR_IA32_RING_PERF_STATUS            0x621\n#define MSR_IA32_STAR                        0xC0000081\n#define MSR_IA32_SYSENTER_CS                 0x174\n#define MSR_IA32_SYSENTER_EIP                0x176\n#define MSR_IA32_SYSENTER_ESP                0x175\n#define MSR_IA32_TSC_AUX                     0xC0000103\n#define MSR_IA32_TSC_DEADLINE                0x6e0\n#define MSR_IA32_UCODE_REV                   MSR_IA32_BIOS_SIGN_ID\n#define MSR_IA32_UCODE_WRITE                 MSR_IA32_UPDT_TRIG\n#define MSR_IA32_UPDT_TRIG                   0x79\n\n#define MSR_IA32_VMX_BASE                  0x480\n#define MSR_IA32_VMX_BASIC                 MSR_IA32_VMX_BASE\n#define MSR_IA32_VMX_CR0_FIXED0            MSR_IA32_VMX_BASE + 6\n#define MSR_IA32_VMX_CR0_FIXED1            MSR_IA32_VMX_BASE + 7\n#define MSR_IA32_VMX_CR4_FIXED0            MSR_IA32_VMX_BASE + 8\n#define MSR_IA32_VMX_CR4_FIXED1            MSR_IA32_VMX_BASE + 9\n#define MSR_IA32_VMX_ENTRY_CTLS            MSR_IA32_VMX_BASE + 4\n#define MSR_IA32_VMX_EPT_VPID_CAP          MSR_IA32_VMX_BASE + 12\n#define MSR_IA32_VMX_EPT_VPID_CAP_AD_SHIFT 21\n#define MSR_IA32_VMX_EXIT_CTLS             MSR_IA32_VMX_BASE + 3\n#define MSR_IA32_VMX_MISC                  MSR_IA32_VMX_BASE + 5\n#define MSR_IA32_VMX_PINBASED_CTLS         MSR_IA32_VMX_BASE + 1\n#define MSR_IA32_VMX_PROCBASED_CTLS        MSR_IA32_VMX_BASE + 2\n#define MSR_IA32_VMX_PROCBASED_CTLS2       MSR_IA32_VMX_BASE + 11\n#define MSR_IA32_VMX_TRUE_PINBASED_CTLS    MSR_IA32_VMX_BASE + 13\n#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS   MSR_IA32_VMX_BASE + 14\n#define MSR_IA32_VMX_TRUE_VMENTRY_CTLS     MSR_IA32_VMX_BASE + 16\n#define MSR_IA32_VMX_TRUE_VMEXIT_CTLS      MSR_IA32_VMX_BASE + 15\n#define MSR_IA32_VMX_VMCS_ENUM             MSR_IA32_VMX_BASE + 10\n#define MSR_IA32_VMX_VMFUNC                MSR_IA32_VMX_BASE + 17\n\n#define MSR_P5_CESR_CC_CLOCK   0x0100  // Clock Counting (or Event)\n#define MSR_P5_CESR_CC_CPL     0x00C0  // Count regardless of the CPL\n#define MSR_P5_CESR_CC_CPL012  0x0040  // Count if the CPL == 0, 1, 2\n#define MSR_P5_CESR_CC_CPL3    0x0080  // Count if the CPL == 3\n#define MSR_P5_CESR_CC_DISABLE 0x0000  // Disable counter\n\n#define MSR_P5_CESR_ES_AGI             0x011111  // Stall because of AGI\n#define MSR_P5_CESR_ES_BANK_CONFLICTS  0x001010  // Bank conflicts\n#define MSR_P5_CESR_ES_BRANCHE         0x010010  // Branches\n#define MSR_P5_CESR_ES_BRANCHE_BTB     0x010100  // Taken branch or BTB Hit\n#define MSR_P5_CESR_ES_BREAK_DR0       0x100011  // Breakpoint matches on DR0\n#define MSR_P5_CESR_ES_BREAK_DR1       0x100100  // Breakpoint matches on DR1\n#define MSR_P5_CESR_ES_BREAK_DR2       0x100101  // Breakpoint matches on DR2\n#define MSR_P5_CESR_ES_BREAK_DR3       0x100110  // Breakpoint matches on DR3\n#define MSR_P5_CESR_ES_BTB_HIT         0x010011  // BTB Hits\n#define MSR_P5_CESR_ES_BUS_CYCLE       0x011000  // Clocks while bus cycle\n#define MSR_P5_CESR_ES_CACHE_SNOOP_HIT 0x001000  // Data cache snoop hits\n#define MSR_P5_CESR_ES_CODE_CACHE_MISS 0x001110  // Code Cache miss\n#define MSR_P5_CESR_ES_CODE_READ       0x001100  // Code Read\n#define MSR_P5_CESR_ES_CODE_TLB_MISS   0x001101  // Code TLB miss\n#define MSR_P5_CESR_ES_DATA_CACHE_WB   0x000110  // Cache lines written back\n#define MSR_P5_CESR_ES_DATA_MEM_READ   0x011010  // Pipeline waiting for read\n#define MSR_P5_CESR_ES_DATA_READ       0x000000  // Data Read\n#define MSR_P5_CESR_ES_DATA_READ_MISS  0x000011  // Data Read Miss\n#define MSR_P5_CESR_ES_DATA_RW         0x101000  // Data Read or Write\n#define MSR_P5_CESR_ES_DATA_RW_MISS    0x101001  // Data Read or Write Miss\n#define MSR_P5_CESR_ES_DATA_TLB_MISS   0x000010  // Data TLB Miss\n#define MSR_P5_CESR_ES_DATA_WRITE      0x000001  // Data Write\n#define MSR_P5_CESR_ES_DATA_WRITE_MISS 0x000100  // Data Write Miss\n#define MSR_P5_CESR_ES_EXTERNAL_SNOOP  0x000111  // External Snoop\n#define MSR_P5_CESR_ES_FLOP            0x100010  // Floating Point operations\n#define MSR_P5_CESR_ES_FULL_WRITE_BUF  0x011001  // Clocks while full wrt buf\n#define MSR_P5_CESR_ES_HARDWARE_IT     0x100111  // Hardware interrupts\n#define MSR_P5_CESR_ES_HIT_EM          0x000101  // Write (hit) to M|E state\n#define MSR_P5_CESR_ES_INSTRUCTION     0x010110  // Instruction executed\n#define MSR_P5_CESR_ES_INSTRUCTION_V   0x010111  // Inst. executed (v-pipe)\n#define MSR_P5_CESR_ES_IO_CYCLE        0x011101  // I/O Read or Write cycles\n#define MSR_P5_CESR_ES_LOCKED_CYCLE    0x011100  // Locked bus cycles\n#define MSR_P5_CESR_ES_MEM_ACCESS_PIPE 0x001001  // mem access both pipes\n#define MSR_P5_CESR_ES_MISALIGNED      0x001011  // Misaligned Memory or I/O\n#define MSR_P5_CESR_ES_NON_CACHEABLE   0x011110  // Non-cacheable Mem. read\n#define MSR_P5_CESR_ES_PIPELINE_FLUSH  0x010101  // Pipeline Flushes\n#define MSR_P5_CESR_ES_SEGMENT_LOADED  0x001111  // Any segment reg. loaded\n#define MSR_P5_CESR_ES_WRITE_EM        0x011011  // Stall on write E|M state\n\n#define MSR_PLATFORM_INFO 0xce\n\n#endif /* BLINK_MSR_H_ */\n"
  },
  {
    "path": "blink/name.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/builtin.h\"\n#include \"blink/case.h\"\n#include \"blink/debug.h\"\n\nconst char *DescribeMopcode(int code) {\n  switch (code) {\n    XLAT(0x000, \"OpAlub\");\n    XLAT(0x001, \"OpAluw\");\n    XLAT(0x002, \"OpAlubFlip\");\n    XLAT(0x003, \"OpAluwFlip\");\n    XLAT(0x004, \"OpAluAlIbAdd\");\n    XLAT(0x005, \"OpAluRaxIvds\");\n    XLAT(0x006, \"OpPushSeg\");\n    XLAT(0x007, \"OpPopSeg\");\n    XLAT(0x008, \"OpAlub\");\n    XLAT(0x009, \"OpAluw\");\n    XLAT(0x00A, \"OpAlubFlip\");\n    XLAT(0x00B, \"OpAluwFlip\");\n    XLAT(0x00C, \"OpAluAlIbOr\");\n    XLAT(0x00D, \"OpAluRaxIvds\");\n    XLAT(0x00E, \"OpPushSeg\");\n    XLAT(0x00F, \"OpPopSeg\");\n    XLAT(0x010, \"OpAlub\");\n    XLAT(0x011, \"OpAluw\");\n    XLAT(0x012, \"OpAlubFlip\");\n    XLAT(0x013, \"OpAluwFlip\");\n    XLAT(0x014, \"OpAluAlIbAdc\");\n    XLAT(0x015, \"OpAluRaxIvds\");\n    XLAT(0x016, \"OpPushSeg\");\n    XLAT(0x017, \"OpPopSeg\");\n    XLAT(0x018, \"OpAlub\");\n    XLAT(0x019, \"OpAluw\");\n    XLAT(0x01A, \"OpAlubFlip\");\n    XLAT(0x01B, \"OpAluwFlip\");\n    XLAT(0x01C, \"OpAluAlIbSbb\");\n    XLAT(0x01D, \"OpAluRaxIvds\");\n    XLAT(0x01E, \"OpPushSeg\");\n    XLAT(0x01F, \"OpPopSeg\");\n    XLAT(0x020, \"OpAlub\");\n    XLAT(0x021, \"OpAluw\");\n    XLAT(0x022, \"OpAlubFlip\");\n    XLAT(0x023, \"OpAluwFlip\");\n    XLAT(0x024, \"OpAluAlIbAnd\");\n    XLAT(0x025, \"OpAluRaxIvds\");\n    XLAT(0x026, \"OpPushSeg\");\n    XLAT(0x027, \"OpPopSeg\");\n    XLAT(0x028, \"OpAlub\");\n    XLAT(0x029, \"OpAluw\");\n    XLAT(0x02A, \"OpAlubFlip\");\n    XLAT(0x02B, \"OpAluwFlip\");\n    XLAT(0x02C, \"OpAluAlIbSub\");\n    XLAT(0x02D, \"OpAluRaxIvds\");\n    XLAT(0x02E, \"OpUd\");\n    XLAT(0x02F, \"OpDas\");\n    XLAT(0x030, \"OpAlub\");\n    XLAT(0x031, \"OpAluw\");\n    XLAT(0x032, \"OpAlubFlip\");\n    XLAT(0x033, \"OpAluwFlip\");\n    XLAT(0x034, \"OpAluAlIbXor\");\n    XLAT(0x035, \"OpAluRaxIvds\");\n    XLAT(0x036, \"OpUd\");\n    XLAT(0x037, \"OpAaa\");\n    XLAT(0x038, \"OpAlubCmp\");\n    XLAT(0x039, \"OpAluwCmp\");\n    XLAT(0x03A, \"OpAlubFlipCmp\");\n    XLAT(0x03B, \"OpAluwFlipCmp\");\n    XLAT(0x03C, \"OpCmpAlIb\");\n    XLAT(0x03D, \"OpCmpRaxIvds\");\n    XLAT(0x03E, \"OpUd\");\n    XLAT(0x03F, \"OpAas\");\n    XLAT(0x040, \"OpIncZv\");\n    XLAT(0x041, \"OpIncZv\");\n    XLAT(0x042, \"OpIncZv\");\n    XLAT(0x043, \"OpIncZv\");\n    XLAT(0x044, \"OpIncZv\");\n    XLAT(0x045, \"OpIncZv\");\n    XLAT(0x046, \"OpIncZv\");\n    XLAT(0x047, \"OpIncZv\");\n    XLAT(0x048, \"OpDecZv\");\n    XLAT(0x049, \"OpDecZv\");\n    XLAT(0x04A, \"OpDecZv\");\n    XLAT(0x04B, \"OpDecZv\");\n    XLAT(0x04C, \"OpDecZv\");\n    XLAT(0x04D, \"OpDecZv\");\n    XLAT(0x04E, \"OpDecZv\");\n    XLAT(0x04F, \"OpDecZv\");\n    XLAT(0x050, \"OpPushZvq\");\n    XLAT(0x051, \"OpPushZvq\");\n    XLAT(0x052, \"OpPushZvq\");\n    XLAT(0x053, \"OpPushZvq\");\n    XLAT(0x054, \"OpPushZvq\");\n    XLAT(0x055, \"OpPushZvq\");\n    XLAT(0x056, \"OpPushZvq\");\n    XLAT(0x057, \"OpPushZvq\");\n    XLAT(0x058, \"OpPopZvq\");\n    XLAT(0x059, \"OpPopZvq\");\n    XLAT(0x05A, \"OpPopZvq\");\n    XLAT(0x05B, \"OpPopZvq\");\n    XLAT(0x05C, \"OpPopZvq\");\n    XLAT(0x05D, \"OpPopZvq\");\n    XLAT(0x05E, \"OpPopZvq\");\n    XLAT(0x05F, \"OpPopZvq\");\n    XLAT(0x060, \"OpPusha\");\n    XLAT(0x061, \"OpPopa\");\n    XLAT(0x062, \"OpUd\");\n    XLAT(0x063, \"OpMovsxdGdqpEd\");\n    XLAT(0x064, \"OpUd\");\n    XLAT(0x065, \"OpUd\");\n    XLAT(0x066, \"OpUd\");\n    XLAT(0x067, \"OpUd\");\n    XLAT(0x068, \"OpPushImm\");\n    XLAT(0x069, \"OpImulGvqpEvqpImm\");\n    XLAT(0x06A, \"OpPushImm\");\n    XLAT(0x06B, \"OpImulGvqpEvqpImm\");\n    XLAT(0x06C, \"OpIns\");\n    XLAT(0x06D, \"OpIns\");\n    XLAT(0x06E, \"OpOuts\");\n    XLAT(0x06F, \"OpOuts\");\n    XLAT(0x070, \"OpJo\");\n    XLAT(0x071, \"OpJno\");\n    XLAT(0x072, \"OpJb\");\n    XLAT(0x073, \"OpJae\");\n    XLAT(0x074, \"OpJe\");\n    XLAT(0x075, \"OpJne\");\n    XLAT(0x076, \"OpJbe\");\n    XLAT(0x077, \"OpJa\");\n    XLAT(0x078, \"OpJs\");\n    XLAT(0x079, \"OpJns\");\n    XLAT(0x07A, \"OpJp\");\n    XLAT(0x07B, \"OpJnp\");\n    XLAT(0x07C, \"OpJl\");\n    XLAT(0x07D, \"OpJge\");\n    XLAT(0x07E, \"OpJle\");\n    XLAT(0x07F, \"OpJg\");\n    XLAT(0x080, \"OpAlubiReg\");\n    XLAT(0x081, \"OpAluwiReg\");\n    XLAT(0x082, \"OpAlubiReg\");\n    XLAT(0x083, \"OpAluwiReg\");\n    XLAT(0x084, \"OpAlubTest\");\n    XLAT(0x085, \"OpAluwTest\");\n    XLAT(0x086, \"OpXchgGbEb\");\n    XLAT(0x087, \"OpXchgGvqpEvqp\");\n    XLAT(0x088, \"OpMovEbGb\");\n    XLAT(0x089, \"OpMovEvqpGvqp\");\n    XLAT(0x08A, \"OpMovGbEb\");\n    XLAT(0x08B, \"OpMovGvqpEvqp\");\n    XLAT(0x08C, \"OpMovEvqpSw\");\n    XLAT(0x08D, \"OpLeaGvqpM\");\n    XLAT(0x08E, \"OpMovSwEvqp\");\n    XLAT(0x08F, \"OpPopEvq\");\n    XLAT(0x090, \"OpNop\");\n    XLAT(0x091, \"OpXchgZvqp\");\n    XLAT(0x092, \"OpXchgZvqp\");\n    XLAT(0x093, \"OpXchgZvqp\");\n    XLAT(0x094, \"OpXchgZvqp\");\n    XLAT(0x095, \"OpXchgZvqp\");\n    XLAT(0x096, \"OpXchgZvqp\");\n    XLAT(0x097, \"OpXchgZvqp\");\n    XLAT(0x098, \"OpSax\");\n    XLAT(0x099, \"OpConvert\");\n    XLAT(0x09A, \"OpCallf\");\n    XLAT(0x09B, \"OpFwait\");\n    XLAT(0x09C, \"OpPushf\");\n    XLAT(0x09D, \"OpPopf\");\n    XLAT(0x09E, \"OpSahf\");\n    XLAT(0x09F, \"OpLahf\");\n    XLAT(0x0A0, \"OpMovAlOb\");\n    XLAT(0x0A1, \"OpMovRaxOvqp\");\n    XLAT(0x0A2, \"OpMovObAl\");\n    XLAT(0x0A3, \"OpMovOvqpRax\");\n    XLAT(0x0A4, \"OpMovsb\");\n    XLAT(0x0A5, \"OpMovs\");\n    XLAT(0x0A6, \"OpCmps\");\n    XLAT(0x0A7, \"OpCmps\");\n    XLAT(0x0A8, \"OpTestAlIb\");\n    XLAT(0x0A9, \"OpTestRaxIvds\");\n    XLAT(0x0AA, \"OpStosb\");\n    XLAT(0x0AB, \"OpStos\");\n    XLAT(0x0AC, \"OpLods\");\n    XLAT(0x0AD, \"OpLods\");\n    XLAT(0x0AE, \"OpScas\");\n    XLAT(0x0AF, \"OpScas\");\n    XLAT(0x0B0, \"OpMovZbIb\");\n    XLAT(0x0B1, \"OpMovZbIb\");\n    XLAT(0x0B2, \"OpMovZbIb\");\n    XLAT(0x0B3, \"OpMovZbIb\");\n    XLAT(0x0B4, \"OpMovZbIb\");\n    XLAT(0x0B5, \"OpMovZbIb\");\n    XLAT(0x0B6, \"OpMovZbIb\");\n    XLAT(0x0B7, \"OpMovZbIb\");\n    XLAT(0x0B8, \"OpMovZvqpIvqp\");\n    XLAT(0x0B9, \"OpMovZvqpIvqp\");\n    XLAT(0x0BA, \"OpMovZvqpIvqp\");\n    XLAT(0x0BB, \"OpMovZvqpIvqp\");\n    XLAT(0x0BC, \"OpMovZvqpIvqp\");\n    XLAT(0x0BD, \"OpMovZvqpIvqp\");\n    XLAT(0x0BE, \"OpMovZvqpIvqp\");\n    XLAT(0x0BF, \"OpMovZvqpIvqp\");\n    XLAT(0x0C0, \"OpBsubiImm\");\n    XLAT(0x0C1, \"OpBsuwiImm\");\n    XLAT(0x0C2, \"OpRetIw\");\n    XLAT(0x0C3, \"OpRet\");\n    XLAT(0x0C4, \"OpLes\");\n    XLAT(0x0C5, \"OpLds\");\n    XLAT(0x0C6, \"OpMovEbIb\");\n    XLAT(0x0C7, \"OpMovEvqpIvds\");\n    XLAT(0x0C8, \"OpUd\");\n    XLAT(0x0C9, \"OpLeave\");\n    XLAT(0x0CA, \"OpRetf\");\n    XLAT(0x0CB, \"OpRetf\");\n    XLAT(0x0CC, \"OpInterrupt3\");\n    XLAT(0x0CD, \"OpInterruptImm\");\n    XLAT(0x0CE, \"OpUd\");\n    XLAT(0x0CF, \"OpUd\");\n    XLAT(0x0D0, \"OpBsubi1\");\n    XLAT(0x0D1, \"OpBsuwi1\");\n    XLAT(0x0D2, \"OpBsubiCl\");\n    XLAT(0x0D3, \"OpBsuwiCl\");\n    XLAT(0x0D4, \"OpAam\");\n    XLAT(0x0D5, \"OpAad\");\n    XLAT(0x0D6, \"OpSalc\");\n    XLAT(0x0D7, \"OpXlatAlBbb\");\n    XLAT(0x0D8, \"OpFpu\");\n    XLAT(0x0D9, \"OpFpu\");\n    XLAT(0x0DA, \"OpFpu\");\n    XLAT(0x0DB, \"OpFpu\");\n    XLAT(0x0DC, \"OpFpu\");\n    XLAT(0x0DD, \"OpFpu\");\n    XLAT(0x0DE, \"OpFpu\");\n    XLAT(0x0DF, \"OpFpu\");\n    XLAT(0x0E0, \"OpLoopne\");\n    XLAT(0x0E1, \"OpLoope\");\n    XLAT(0x0E2, \"OpLoop1\");\n    XLAT(0x0E3, \"OpJcxz\");\n    XLAT(0x0E4, \"OpInAlImm\");\n    XLAT(0x0E5, \"OpInAxImm\");\n    XLAT(0x0E6, \"OpOutImmAl\");\n    XLAT(0x0E7, \"OpOutImmAx\");\n    XLAT(0x0E8, \"OpCallJvds\");\n    XLAT(0x0E9, \"OpJmp\");\n    XLAT(0x0EA, \"OpJmpf\");\n    XLAT(0x0EB, \"OpJmp\");\n    XLAT(0x0EC, \"OpInAlDx\");\n    XLAT(0x0ED, \"OpInAxDx\");\n    XLAT(0x0EE, \"OpOutDxAl\");\n    XLAT(0x0EF, \"OpOutDxAx\");\n    XLAT(0x0F0, \"OpUd\");\n    XLAT(0x0F1, \"OpInterrupt1\");\n    XLAT(0x0F2, \"OpUd\");\n    XLAT(0x0F3, \"OpUd\");\n    XLAT(0x0F4, \"OpHlt\");\n    XLAT(0x0F5, \"OpCmc\");\n    XLAT(0x0F6, \"Op0f6\");\n    XLAT(0x0F7, \"Op0f7\");\n    XLAT(0x0F8, \"OpClc\");\n    XLAT(0x0F9, \"OpStc\");\n    XLAT(0x0FA, \"OpCli\");\n    XLAT(0x0FB, \"OpSti\");\n    XLAT(0x0FC, \"OpCld\");\n    XLAT(0x0FD, \"OpStd\");\n    XLAT(0x0FE, \"Op0fe\");\n    XLAT(0x0FF, \"Op0ff\");\n    XLAT(0x100, \"OpUd\");\n    XLAT(0x101, \"Op101\");\n    XLAT(0x102, \"OpUd\");\n    XLAT(0x103, \"OpLsl\");\n    XLAT(0x104, \"OpUd\");\n    XLAT(0x105, \"OpSyscall\");\n    XLAT(0x106, \"OpUd\");\n    XLAT(0x107, \"OpUd\");\n    XLAT(0x108, \"OpUd\");\n    XLAT(0x109, \"OpUd\");\n    XLAT(0x10A, \"OpUd\");\n    XLAT(0x10B, \"OpUd\");\n    XLAT(0x10C, \"OpUd\");\n    XLAT(0x10D, \"OpHintNopEv\");\n    XLAT(0x10E, \"OpUd\");\n    XLAT(0x10F, \"OpUd\");\n    XLAT(0x110, \"OpMov0f10\");\n    XLAT(0x111, \"OpMovWpsVps\");\n    XLAT(0x112, \"OpMov0f12\");\n    XLAT(0x113, \"OpMov0f13\");\n    XLAT(0x114, \"OpUnpcklpsd\");\n    XLAT(0x115, \"OpUnpckhpsd\");\n    XLAT(0x116, \"OpMov0f16\");\n    XLAT(0x117, \"OpMov0f17\");\n    XLAT(0x118, \"OpHintNopEv\");\n    XLAT(0x119, \"OpHintNopEv\");\n    XLAT(0x11A, \"OpHintNopEv\");\n    XLAT(0x11B, \"OpHintNopEv\");\n    XLAT(0x11C, \"OpHintNopEv\");\n    XLAT(0x11D, \"OpHintNopEv\");\n    XLAT(0x11E, \"OpHintNopEv\");\n    XLAT(0x11F, \"OpNopEv\");\n    XLAT(0x120, \"OpMovRqCq\");\n    XLAT(0x121, \"OpUd\");\n    XLAT(0x122, \"OpMovCqRq\");\n    XLAT(0x123, \"OpUd\");\n    XLAT(0x124, \"OpUd\");\n    XLAT(0x125, \"OpUd\");\n    XLAT(0x126, \"OpUd\");\n    XLAT(0x127, \"OpUd\");\n    XLAT(0x128, \"OpMov0f28\");\n    XLAT(0x129, \"OpMovWpsVps\");\n    XLAT(0x12A, \"OpCvt0f2a\");\n    XLAT(0x12B, \"OpMov0f2b\");\n    XLAT(0x12C, \"OpCvtt0f2c\");\n    XLAT(0x12D, \"OpCvt0f2d\");\n    XLAT(0x12E, \"OpComissVsWs\");\n    XLAT(0x12F, \"OpComissVsWs\");\n    XLAT(0x130, \"OpWrmsr\");\n    XLAT(0x131, \"OpRdtsc\");\n    XLAT(0x132, \"OpRdmsr\");\n    XLAT(0x133, \"OpUd\");\n    XLAT(0x134, \"OpUd\");\n    XLAT(0x135, \"OpUd\");\n    XLAT(0x136, \"OpUd\");\n    XLAT(0x137, \"OpUd\");\n    XLAT(0x138, \"OpUd\");\n    XLAT(0x139, \"OpUd\");\n    XLAT(0x13A, \"OpUd\");\n    XLAT(0x13B, \"OpUd\");\n    XLAT(0x13C, \"OpUd\");\n    XLAT(0x13D, \"OpUd\");\n    XLAT(0x13E, \"OpUd\");\n    XLAT(0x13F, \"OpUd\");\n    XLAT(0x140, \"OpCmovo\");\n    XLAT(0x141, \"OpCmovno\");\n    XLAT(0x142, \"OpCmovb\");\n    XLAT(0x143, \"OpCmovae\");\n    XLAT(0x144, \"OpCmove\");\n    XLAT(0x145, \"OpCmovne\");\n    XLAT(0x146, \"OpCmovbe\");\n    XLAT(0x147, \"OpCmova\");\n    XLAT(0x148, \"OpCmovs\");\n    XLAT(0x149, \"OpCmovns\");\n    XLAT(0x14A, \"OpCmovp\");\n    XLAT(0x14B, \"OpCmovnp\");\n    XLAT(0x14C, \"OpCmovl\");\n    XLAT(0x14D, \"OpCmovge\");\n    XLAT(0x14E, \"OpCmovle\");\n    XLAT(0x14F, \"OpCmovg\");\n    XLAT(0x150, \"OpMovmskpsd\");\n    XLAT(0x151, \"OpSqrtpsd\");\n    XLAT(0x152, \"OpRsqrtps\");\n    XLAT(0x153, \"OpRcpps\");\n    XLAT(0x154, \"OpAndpsd\");\n    XLAT(0x155, \"OpAndnpsd\");\n    XLAT(0x156, \"OpOrpsd\");\n    XLAT(0x157, \"OpXorpsd\");\n    XLAT(0x158, \"OpAddpsd\");\n    XLAT(0x159, \"OpMulpsd\");\n    XLAT(0x15A, \"OpCvt0f5a\");\n    XLAT(0x15B, \"OpCvt0f5b\");\n    XLAT(0x15C, \"OpSubpsd\");\n    XLAT(0x15D, \"OpMinpsd\");\n    XLAT(0x15E, \"OpDivpsd\");\n    XLAT(0x15F, \"OpMaxpsd\");\n    XLAT(0x160, \"OpSsePunpcklbw\");\n    XLAT(0x161, \"OpSsePunpcklwd\");\n    XLAT(0x162, \"OpSsePunpckldq\");\n    XLAT(0x163, \"OpSsePacksswb\");\n    XLAT(0x164, \"OpSsePcmpgtb\");\n    XLAT(0x165, \"OpSsePcmpgtw\");\n    XLAT(0x166, \"OpSsePcmpgtd\");\n    XLAT(0x167, \"OpSsePackuswb\");\n    XLAT(0x168, \"OpSsePunpckhbw\");\n    XLAT(0x169, \"OpSsePunpckhwd\");\n    XLAT(0x16A, \"OpSsePunpckhdq\");\n    XLAT(0x16B, \"OpSsePackssdw\");\n    XLAT(0x16C, \"OpSsePunpcklqdq\");\n    XLAT(0x16D, \"OpSsePunpckhqdq\");\n    XLAT(0x16E, \"OpMov0f6e\");\n    XLAT(0x16F, \"OpMov0f6f\");\n    XLAT(0x170, \"OpShuffle\");\n    XLAT(0x171, \"Op171\");\n    XLAT(0x172, \"Op172\");\n    XLAT(0x173, \"Op173\");\n    XLAT(0x174, \"OpSsePcmpeqb\");\n    XLAT(0x175, \"OpSsePcmpeqw\");\n    XLAT(0x176, \"OpSsePcmpeqd\");\n    XLAT(0x177, \"OpEmms\");\n    XLAT(0x178, \"OpUd\");\n    XLAT(0x179, \"OpUd\");\n    XLAT(0x17A, \"OpUd\");\n    XLAT(0x17B, \"OpUd\");\n    XLAT(0x17C, \"OpHaddpsd\");\n    XLAT(0x17D, \"OpHsubpsd\");\n    XLAT(0x17E, \"OpMov0f7e\");\n    XLAT(0x17F, \"OpMov0f7f\");\n    XLAT(0x180, \"OpJo\");\n    XLAT(0x181, \"OpJno\");\n    XLAT(0x182, \"OpJb\");\n    XLAT(0x183, \"OpJae\");\n    XLAT(0x184, \"OpJe\");\n    XLAT(0x185, \"OpJne\");\n    XLAT(0x186, \"OpJbe\");\n    XLAT(0x187, \"OpJa\");\n    XLAT(0x188, \"OpJs\");\n    XLAT(0x189, \"OpJns\");\n    XLAT(0x18A, \"OpJp\");\n    XLAT(0x18B, \"OpJnp\");\n    XLAT(0x18C, \"OpJl\");\n    XLAT(0x18D, \"OpJge\");\n    XLAT(0x18E, \"OpJle\");\n    XLAT(0x18F, \"OpJg\");\n    XLAT(0x190, \"OpSeto\");\n    XLAT(0x191, \"OpSetno\");\n    XLAT(0x192, \"OpSetb\");\n    XLAT(0x193, \"OpSetae\");\n    XLAT(0x194, \"OpSete\");\n    XLAT(0x195, \"OpSetne\");\n    XLAT(0x196, \"OpSetbe\");\n    XLAT(0x197, \"OpSeta\");\n    XLAT(0x198, \"OpSets\");\n    XLAT(0x199, \"OpSetns\");\n    XLAT(0x19A, \"OpSetp\");\n    XLAT(0x19B, \"OpSetnp\");\n    XLAT(0x19C, \"OpSetl\");\n    XLAT(0x19D, \"OpSetge\");\n    XLAT(0x19E, \"OpSetle\");\n    XLAT(0x19F, \"OpSetg\");\n    XLAT(0x1A0, \"OpPushSeg\");\n    XLAT(0x1A1, \"OpPopSeg\");\n    XLAT(0x1A2, \"OpCpuid\");\n    XLAT(0x1A3, \"OpBit\");\n    XLAT(0x1A4, \"OpDoubleShift\");\n    XLAT(0x1A5, \"OpDoubleShift\");\n    XLAT(0x1A6, \"OpUd\");\n    XLAT(0x1A7, \"OpUd\");\n    XLAT(0x1A8, \"OpPushSeg\");\n    XLAT(0x1A9, \"OpPopSeg\");\n    XLAT(0x1AA, \"OpUd\");\n    XLAT(0x1AB, \"OpBit\");\n    XLAT(0x1AC, \"OpDoubleShift\");\n    XLAT(0x1AD, \"OpDoubleShift\");\n    XLAT(0x1AE, \"Op1ae\");\n    XLAT(0x1AF, \"OpImulGvqpEvqp\");\n    XLAT(0x1B0, \"OpCmpxchgEbAlGb\");\n    XLAT(0x1B1, \"OpCmpxchgEvqpRaxGvqp\");\n    XLAT(0x1B2, \"OpLss\");\n    XLAT(0x1B3, \"OpBit\");\n    XLAT(0x1B4, \"OpLfs\");\n    XLAT(0x1B5, \"OpLgs\");\n    XLAT(0x1B6, \"OpMovzbGvqpEb\");\n    XLAT(0x1B7, \"OpMovzwGvqpEw\");\n    XLAT(0x1B8, \"Op1b8\");\n    XLAT(0x1B9, \"OpUd\");\n    XLAT(0x1BA, \"OpBit\");\n    XLAT(0x1BB, \"OpBit\");\n    XLAT(0x1BC, \"OpBsf\");\n    XLAT(0x1BD, \"OpBsr\");\n    XLAT(0x1BE, \"OpMovsbGvqpEb\");\n    XLAT(0x1BF, \"OpMovswGvqpEw\");\n    XLAT(0x1C0, \"OpXaddEbGb\");\n    XLAT(0x1C1, \"OpXaddEvqpGvqp\");\n    XLAT(0x1C2, \"OpCmppsd\");\n    XLAT(0x1C3, \"OpMovntiMdqpGdqp\");\n    XLAT(0x1C4, \"OpPinsrwVdqEwIb\");\n    XLAT(0x1C5, \"OpPextrwGdqpUdqIb\");\n    XLAT(0x1C6, \"OpShufpsd\");\n    XLAT(0x1C7, \"Op1c7\");\n    XLAT(0x1C8, \"OpBswapZvqp\");\n    XLAT(0x1C9, \"OpBswapZvqp\");\n    XLAT(0x1CA, \"OpBswapZvqp\");\n    XLAT(0x1CB, \"OpBswapZvqp\");\n    XLAT(0x1CC, \"OpBswapZvqp\");\n    XLAT(0x1CD, \"OpBswapZvqp\");\n    XLAT(0x1CE, \"OpBswapZvqp\");\n    XLAT(0x1CF, \"OpBswapZvqp\");\n    XLAT(0x1D0, \"OpAddsubpsd\");\n    XLAT(0x1D1, \"OpSsePsrlwv\");\n    XLAT(0x1D2, \"OpSsePsrldv\");\n    XLAT(0x1D3, \"OpSsePsrlqv\");\n    XLAT(0x1D4, \"OpSsePaddq\");\n    XLAT(0x1D5, \"OpSsePmullw\");\n    XLAT(0x1D6, \"OpMov0fD6\");\n    XLAT(0x1D7, \"OpPmovmskbGdqpNqUdq\");\n    XLAT(0x1D8, \"OpSsePsubusb\");\n    XLAT(0x1D9, \"OpSsePsubusw\");\n    XLAT(0x1DA, \"OpSsePminub\");\n    XLAT(0x1DB, \"OpSsePand\");\n    XLAT(0x1DC, \"OpSsePaddusb\");\n    XLAT(0x1DD, \"OpSsePaddusw\");\n    XLAT(0x1DE, \"OpSsePmaxub\");\n    XLAT(0x1DF, \"OpSsePandn\");\n    XLAT(0x1E0, \"OpSsePavgb\");\n    XLAT(0x1E1, \"OpSsePsrawv\");\n    XLAT(0x1E2, \"OpSsePsradv\");\n    XLAT(0x1E3, \"OpSsePavgw\");\n    XLAT(0x1E4, \"OpSsePmulhuw\");\n    XLAT(0x1E5, \"OpSsePmulhw\");\n    XLAT(0x1E6, \"OpCvt0fE6\");\n    XLAT(0x1E7, \"OpMov0fE7\");\n    XLAT(0x1E8, \"OpSsePsubsb\");\n    XLAT(0x1E9, \"OpSsePsubsw\");\n    XLAT(0x1EA, \"OpSsePminsw\");\n    XLAT(0x1EB, \"OpSsePor\");\n    XLAT(0x1EC, \"OpSsePaddsb\");\n    XLAT(0x1ED, \"OpSsePaddsw\");\n    XLAT(0x1EE, \"OpSsePmaxsw\");\n    XLAT(0x1EF, \"OpSsePxor\");\n    XLAT(0x1F0, \"OpLddquVdqMdq\");\n    XLAT(0x1F1, \"OpSsePsllwv\");\n    XLAT(0x1F2, \"OpSsePslldv\");\n    XLAT(0x1F3, \"OpSsePsllqv\");\n    XLAT(0x1F4, \"OpSsePmuludq\");\n    XLAT(0x1F5, \"OpSsePmaddwd\");\n    XLAT(0x1F6, \"OpSsePsadbw\");\n    XLAT(0x1F7, \"OpMaskMovDiXmmRegXmmRm\");\n    XLAT(0x1F8, \"OpSsePsubb\");\n    XLAT(0x1F9, \"OpSsePsubw\");\n    XLAT(0x1FA, \"OpSsePsubd\");\n    XLAT(0x1FB, \"OpSsePsubq\");\n    XLAT(0x1FC, \"OpSsePaddb\");\n    XLAT(0x1FD, \"OpSsePaddw\");\n    XLAT(0x1FE, \"OpSsePaddd\");\n    XLAT(0x1FF, \"OpUd\");\n    XLAT(0x200, \"OpSsePshufb\");\n    XLAT(0x201, \"OpSsePhaddw\");\n    XLAT(0x202, \"OpSsePhaddd\");\n    XLAT(0x203, \"OpSsePhaddsw\");\n    XLAT(0x204, \"OpSsePmaddubsw\");\n    XLAT(0x205, \"OpSsePhsubw\");\n    XLAT(0x206, \"OpSsePhsubd\");\n    XLAT(0x207, \"OpSsePhsubsw\");\n    XLAT(0x208, \"OpSsePsignb\");\n    XLAT(0x209, \"OpSsePsignw\");\n    XLAT(0x20A, \"OpSsePsignd\");\n    XLAT(0x20B, \"OpSsePmulhrsw\");\n    XLAT(0x21c, \"OpSsePabsb\");\n    XLAT(0x21d, \"OpSsePabsw\");\n    XLAT(0x21e, \"OpSsePabsd\");\n    XLAT(0x22a, \"OpMovntdqaVdqMdq\");\n    XLAT(0x240, \"OpSsePmulld\");\n    XLAT(0x30f, \"OpSsePalignr\");\n    XLAT(0x344, \"OpSsePclmulqdq\");\n    default:\n      return \"UNKNOWN\";\n  }\n}\n"
  },
  {
    "path": "blink/ndelay.h",
    "content": "#ifndef BLINK_NDELAY_H_\n#define BLINK_NDELAY_H_\n#include <fcntl.h>\n\n#if !defined(O_NDELAY) && defined(O_NONBLOCK)\n#define O_NDELAY O_NONBLOCK\n#endif\n\n#endif /* BLINK_NDELAY_H_ */\n"
  },
  {
    "path": "blink/oneoff.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/socket.h>\n#include <time.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/linux.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/timespec.h\"\n#include \"blink/types.h\"\n\nint main(int argc, char *argv[]) {\n  return 0;\n}\n"
  },
  {
    "path": "blink/op101.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdio.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/jit.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/time.h\"\n#include \"blink/x86.h\"\n\nstatic void StoreDescriptorTable(P, u16 limit, u64 base) {\n  u64 l;\n  l = ComputeAddress(A);\n  if (l + 10 <= kRealSize) {\n    Write16(m->system->real + l, limit);\n    if (Mode(rde) == XED_MODE_LONG) {\n      Write64(m->system->real + l + 2, base);\n      SetWriteAddr(m, l, 10);\n    } else {\n      Write32(m->system->real + l + 2, base);\n      SetWriteAddr(m, l, 6);\n    }\n  } else {\n    ThrowSegmentationFault(m, l);\n  }\n}\n\nstatic void LoadDescriptorTable(P, u16 *out_limit, u64 *out_base) {\n  u16 limit;\n  u64 l, base;\n  l = ComputeAddress(A);\n  if (l + 10 <= kRealSize) {\n    limit = Read16(m->system->real + l);\n    // Intel Manual Volume 2A:\n    // - \"If the operand-size attribute is 16 bits, a 16-bit limit (lower 2\n    //   bytes) and a 24-bit base address (third, fourth, and fifth byte) are\n    //   loaded.\"\n    // - \"In 64-bit mode, the instruction’s operand size is fixed at 8 + 2\n    //   bytes (an 8-byte base and a 2-byte limit).\"\n    if (Mode(rde) == XED_MODE_LONG) {\n      base = Read64(m->system->real + l + 2);\n      SetReadAddr(m, l, 10);\n    } else if (!Osz(rde)) {\n      base = Read32(m->system->real + l + 2);\n      SetReadAddr(m, l, 6);\n    } else {\n      base = Read32(m->system->real + l + 2) & 0x00ffffff;\n      SetReadAddr(m, l, 6);\n    }\n    *out_limit = limit;\n    *out_base = base;\n  } else {\n    ThrowSegmentationFault(m, l);\n  }\n}\n\nstatic void SgdtMs(P) {\n  StoreDescriptorTable(A, m->system->gdt_limit, m->system->gdt_base);\n}\n\nstatic void LgdtMs(P) {\n  LoadDescriptorTable(A, &m->system->gdt_limit, &m->system->gdt_base);\n}\n\nstatic void SidtMs(P) {\n  StoreDescriptorTable(A, m->system->idt_limit, m->system->idt_base);\n}\n\nstatic void LidtMs(P) {\n  LoadDescriptorTable(A, &m->system->idt_limit, &m->system->idt_base);\n}\n\nstatic void Monitor(P) {\n}\n\nstatic void Mwait(P) {\n}\n\nstatic void Swapgs(P) {\n}\n\nstatic void Vmcall(P) {\n}\n\nstatic void Vmlaunch(P) {\n}\n\nstatic void Vmresume(P) {\n}\n\nstatic void Vmxoff(P) {\n}\n\nstatic void InvlpgM(P) {\n  i64 virt;\n  struct AddrSeg as;\n  // if (Cpl(m)) OpUdImpl(m);\n  as = LoadEffectiveAddress(A);\n  virt = as.seg + as.addr;\n  if (Mode(rde) == XED_MODE_LONG &&\n      !(-0x800000000000 <= virt && virt < 0x800000000000)) {\n    // In 64-bit mode, if the memory address is in non-canonical form,\n    // then INVLPG is the same as a NOP. -Quoth Intel §invlpg\n    return;\n  }\n#ifndef DISABLE_JIT\n  if (!IsJitDisabled(&m->system->jit)) {\n    ResetJitPage(&m->system->jit, virt);\n  }\n#endif\n  InvalidateSystem(m->system, true, true);\n}\n\nstatic void Smsw(P, bool ismem) {\n  if (ismem) {\n    Store16(GetModrmRegisterWordPointerWrite2(A), m->system->cr0);\n  } else if (Rexw(rde)) {\n    Put64(RegRexbRm(m, rde), m->system->cr0);\n  } else if (!Osz(rde)) {\n    Put64(RegRexbRm(m, rde), m->system->cr0 & 0xffffffff);\n  } else {\n    Put16(RegRexbRm(m, rde), m->system->cr0);\n  }\n}\n\nstatic void Lmsw(P) {\n  // Intel V2A § 3.2:  \"Only the low-order 4 bits of the source operand\n  // (which contains the PE, MP, EM, and TS flags) are loaded into CR0.\n  // The PG, CD, NW, AM, WP, NE, and ET flags of CR0 are not affected.\n  // The operand-size attribute has no effect on this instruction.\"\n  m->system->cr0 = (m->system->cr0 & ~(u64)0xf) |\n                   (Read16(GetModrmRegisterWordPointerRead2(A)) & 0xf);\n}\n\nvoid Op101(P) {\n  bool ismem;\n  ismem = !IsModrmRegister(rde);\n  switch (ModrmReg(rde)) {\n#ifndef DISABLE_METAL\n    case 0:\n      if (ismem) {\n        SgdtMs(A);\n      } else {\n        switch (ModrmRm(rde)) {\n          case 1:\n            Vmcall(A);\n            break;\n          case 2:\n            Vmlaunch(A);\n            break;\n          case 3:\n            Vmresume(A);\n            break;\n          case 4:\n            Vmxoff(A);\n            break;\n          default:\n            OpUdImpl(m);\n        }\n      }\n      break;\n    case 1:\n      if (ismem) {\n        SidtMs(A);\n      } else {\n        switch (ModrmRm(rde)) {\n          case 0:\n            Monitor(A);\n            break;\n          case 1:\n            Mwait(A);\n            break;\n          default:\n            OpUdImpl(m);\n        }\n      }\n      break;\n    case 2:\n      if (ismem) {\n        LgdtMs(A);\n      } else {\n        OpUdImpl(m);\n      }\n      break;\n    case 3:\n      if (ismem) {\n        LidtMs(A);\n      } else {\n        OpUdImpl(m);\n      }\n      break;\n    case 4:\n      Smsw(A, ismem);\n      break;\n    case 6:\n      Lmsw(A);\n      break;\n#endif\n    case 7:\n      if (ismem) {\n#ifndef DISABLE_METAL\n        InvlpgM(A);\n#else\n        OpUdImpl(m);\n#endif\n      } else {\n        switch (ModrmRm(rde)) {\n          case 0:\n            Swapgs(A);\n            break;\n          case 1:\n            OpRdtscp(A);\n            break;\n          default:\n            OpUdImpl(m);\n        }\n      }\n      break;\n    default:\n      OpUdImpl(m);\n  }\n}\n"
  },
  {
    "path": "blink/open.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/debug.h\"\n#include \"blink/errno.h\"\n#include \"blink/fds.h\"\n#include \"blink/fspath.h\"\n#include \"blink/log.h\"\n#include \"blink/overlays.h\"\n#include \"blink/random.h\"\n#include \"blink/syscall.h\"\n#include \"blink/thread.h\"\n#include \"blink/vfs.h\"\n#include \"blink/xlat.h\"\n\nstatic int SysTmpfile(struct Machine *m, i32 dirfildes, i64 pathaddr,\n                      i32 oflags, i32 mode) {\n  long i;\n  int lim;\n  u64 rng;\n  int tmpdir;\n  int fildes;\n  int sysflags;\n  char name[13];\n  int supported;\n  int unsupported;\n  sigset_t ss, oldss;\n  sysflags = O_CREAT | O_EXCL | O_CLOEXEC;\n  switch (oflags & O_ACCMODE_LINUX) {\n    case O_RDWR_LINUX:\n      sysflags |= O_RDWR;\n      break;\n    case O_WRONLY_LINUX:\n      sysflags |= O_WRONLY;\n      break;\n    default:\n      LOGF(\"O_TMPFILE must O_WRONLY or O_RDWR\");\n      return einval();\n  }\n  supported =\n      O_ACCMODE_LINUX | O_CLOEXEC_LINUX | O_EXCL_LINUX | O_LARGEFILE_LINUX;\n  if ((unsupported = oflags & ~supported)) {\n    LOGF(\"O_TMPFILE unsupported flags %#x\", unsupported);\n    return einval();\n  }\n  if (!(lim = GetFileDescriptorLimit(m->system))) return emfile();\n  unassert(!sigfillset(&ss));\n  unassert(!pthread_sigmask(SIG_BLOCK, &ss, &oldss));\n  if ((tmpdir = VfsOpen(GetDirFildes(dirfildes), LoadStr(m, pathaddr),\n                        O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0)) != -1) {\n    if (tmpdir >= lim) {\n      VfsClose(tmpdir);\n      fildes = emfile();\n    } else {\n      unassert(GetRandom(&rng, 8, 0) == 8);\n      for (i = 0; i < 12; ++i) {\n        name[i] = \"0123456789abcdefghijklmnopqrstuvwxyz\"[rng % 36];\n        rng /= 36;\n      }\n      name[i] = 0;\n      if ((fildes = VfsOpen(tmpdir, name, sysflags, mode)) != -1) {\n        unassert(!VfsUnlink(tmpdir, name, 0));\n        unassert(VfsDup2(fildes, tmpdir) == tmpdir);\n        fildes = tmpdir;\n        if (oflags & O_CLOEXEC_LINUX) {\n          unassert(!VfsFcntl(fildes, F_SETFD, FD_CLOEXEC));\n        }\n        LOCK(&m->system->fds.lock);\n        unassert(AddFd(&m->system->fds, fildes, oflags));\n        UNLOCK(&m->system->fds.lock);\n      } else {\n        unassert(!VfsClose(tmpdir));\n      }\n    }\n  } else {\n    fildes = -1;\n  }\n  unassert(!pthread_sigmask(SIG_SETMASK, &oldss, 0));\n  return fildes;\n}\n\nint SysOpenat(struct Machine *m, i32 dirfildes, i64 pathaddr, i32 oflags,\n              i32 mode) {\n  int lim;\n  int fildes;\n  int sysflags;\n  struct Fd *fd;\n  const char *path;\n#ifndef O_TMPFILE\n#ifndef DISABLE_NONPOSIX\n  if ((oflags & O_TMPFILE_LINUX) == O_TMPFILE_LINUX) {\n    return SysTmpfile(m, dirfildes, pathaddr, oflags & ~O_TMPFILE_LINUX, mode);\n  }\n#endif\n#endif\n  if ((sysflags = XlatOpenFlags(oflags)) == -1) return -1;\n  if (!(lim = GetFileDescriptorLimit(m->system))) return emfile();\n  if (!(path = LoadStr(m, pathaddr))) return -1;\n  RESTARTABLE(fildes = VfsOpen(GetDirFildes(dirfildes), path, sysflags, mode));\n  if (fildes != -1) {\n    if (fildes >= lim) {\n      close(fildes);\n      fildes = emfile();\n    } else {\n      LOCK(&m->system->fds.lock);\n      unassert(fd = AddFd(&m->system->fds, fildes, sysflags));\n      fd->path = JoinPath(GetDirFildesPath(m->system, dirfildes), path);\n      UNLOCK(&m->system->fds.lock);\n    }\n  } else {\n#ifdef __FreeBSD__\n    // Address FreeBSD divergence from IEEE Std 1003.1-2008 (POSIX.1)\n    // in the case when O_NOFOLLOW is used, but fails due to symlink.\n    if (errno == EMLINK) {\n      errno = ELOOP;\n    }\n#endif\n#ifdef __NetBSD__\n    // Address NetBSD divergence from IEEE Std 1003.1-2008 (POSIX.1)\n    // in the case when O_NOFOLLOW is used but fails due to symlink.\n    if (errno == EFTYPE) {\n      errno = ELOOP;\n    }\n#endif\n  }\n  return fildes;\n}\n"
  },
  {
    "path": "blink/overlays.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/overlays.h\"\n\n#include <errno.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/debug.h\"\n#include \"blink/errno.h\"\n#include \"blink/fspath.h\"\n#include \"blink/likely.h\"\n#include \"blink/log.h\"\n#include \"blink/syscall.h\"\n#include \"blink/thompike.h\"\n#include \"blink/util.h\"\n\n#ifndef DISABLE_OVERLAYS\n\n#define UNREACHABLE \"(unreachable)\"\n\nstatic char **g_overlays;\n\nstatic void FreeStrings(char **ss) {\n  size_t i;\n  if (!ss) return;\n  for (i = 0; ss[i]; ++i) {\n    free(ss[i]);\n  }\n  free(ss);\n}\n\nstatic char **SplitString(const char *s, int c) {\n  size_t n = 0;\n  const char *t;\n  char *e, **g, **r = 0;\n  while (s) {\n    if ((t = strchr(s, c))) {\n      e = strndup(s, t - s);\n    } else {\n      e = strdup(s);\n    }\n    if (!e || !(g = (char **)realloc(r, (n + 2) * sizeof(*r)))) {\n      free(e);\n      FreeStrings(r);\n      return 0;\n    }\n    g[n++] = e;\n    g[n] = 0;\n    s = t ? t + 1 : 0;\n    r = g;\n  }\n  return r;\n}\n\nstatic void FreeOverlays(void) {\n  FreeStrings(g_overlays);\n  g_overlays = 0;\n}\n\n// if the user only specified a single overlay, then we treat it as\n// chroot would unless of course the specified root is the real one\nstatic bool IsRestrictedRoot(char **paths) {\n  return !paths[1] && paths[0][0];\n}\n\nint SetOverlays(const char *config, bool cd_into_chroot) {\n  size_t i, j;\n  static int once;\n  bool has_real_root;\n  char *path, *path2, **paths;\n  if (!config) return efault();\n  if (!(paths = SplitString(config, ':'))) {\n    return -1;\n  }\n  // normalize absolute paths at startup and\n  // remove non-existent paths\n  has_real_root = false;\n  i = j = 0;\n  do {\n    path = paths[i++];\n    if (path) {\n      if (!path[0] || (path[0] == '/' && !path[1])) {\n        path[0] = 0;\n        has_real_root = true;\n      } else {\n        path2 = ExpandUser(path);\n        free(path);\n        path = path2;\n        path2 = (char *)malloc(PATH_MAX + 1);\n        if (!realpath(path, path2)) {\n          free(path);\n          continue;\n        }\n        free(path);\n        path = path2;\n      }\n    }\n    paths[j++] = path;\n  } while (path);\n  if (!paths[0]) {\n    LOGF(\"blink overlays '%s' didn't have a path that exists\", config);\n    FreeStrings(paths);\n    return einval();\n  }\n  if (!has_real_root && paths[1]) {\n    LOGF(\"if multiple overlays are specified, \"\n         \"one of them must be empty string\");\n    FreeStrings(paths);\n    return einval();\n  }\n  if (cd_into_chroot && IsRestrictedRoot(paths)) {\n    if (chdir(paths[0])) {\n      LOGF(\"failed to cd into blink overlay: %s\", DescribeHostErrno(errno));\n      FreeStrings(paths);\n      return -1;\n    }\n  }\n  if (!once) {\n    atexit(FreeOverlays);\n    once = 1;\n  }\n  FreeOverlays();\n  g_overlays = paths;\n  return 0;\n}\n\n// if we get these failures when opening a temporary dirfd of a user\n// supplied overlay path, then it's definitely not a user error, and\n// therefore not safe to continue.\nstatic bool IsUnrecoverableErrno(void) {\n  return errno == EINTR || errno == EMFILE || errno == ENFILE;\n}\n\nchar *OverlaysGetcwd(char *output, size_t size) {\n  size_t n, m;\n  char *cwd, buf[PATH_MAX];\n  if (!(cwd = (getcwd)(buf, sizeof(buf)))) return 0;\n  n = strlen(cwd);\n  if (IsRestrictedRoot(g_overlays)) {\n    m = strlen(g_overlays[0]);\n    if (n == m && !memcmp(cwd, g_overlays[0], n)) {\n      cwd[0] = '/';\n      cwd[1] = 0;\n    } else if (n > m && !memcmp(cwd, g_overlays[0], m) && cwd[m] == '/') {\n      cwd += m;\n    } else if (strlen(UNREACHABLE) + n + 1 < sizeof(buf)) {\n      memmove(cwd + strlen(UNREACHABLE), cwd, n + 1);\n      memcpy(cwd, UNREACHABLE, strlen(UNREACHABLE));\n    } else {\n      return 0;\n    }\n    n = strlen(cwd);\n  }\n  if (n + 1 > size) return 0;\n  memcpy(output, cwd, n + 1);\n  return output;\n}\n\nstatic int Chdir(const char *path) {\n  return chdir(path);\n}\n\nint OverlaysChdir(const char *path) {\n  size_t n, m;\n  char buf[PATH_MAX];\n  if (!path) return efault();\n  if (!path[0]) return enoent();\n  if (IsRestrictedRoot(g_overlays) && path[0] == '/') {\n    if (!path[1]) {\n      return Chdir(g_overlays[0]);\n    } else {\n      n = strlen(g_overlays[0]);\n      m = strlen(path);\n      if (n + m + 1 > sizeof(buf)) {\n        errno = ENAMETOOLONG;\n        return -1;\n      }\n      memcpy(buf, g_overlays[0], n);\n      memcpy(buf + n, path, m);\n      buf[n + m] = 0;\n      return Chdir(buf);\n    }\n  }\n  return Chdir(path);\n}\n\nint OverlaysOpen(int dirfd, const char *path, int flags, int mode) {\n  int fd;\n  size_t i;\n  int err = -1;\n  if (!path) return efault();\n  if (!*path) return enoent();\n  if (path[0] != '/' && path[0]) {\n    return openat(dirfd, path, flags, mode);\n  }\n  for (i = 0; g_overlays[i]; ++i) {\n    if (!*g_overlays[i]) {\n      if ((fd = open(path, flags, mode)) != -1) {\n        return fd;\n      }\n      if (errno != ENOENT && errno != ENOTDIR) {\n        return -1;\n      }\n      if (err == -1) {\n        err = errno;\n      }\n    } else {\n      dirfd = open(g_overlays[i], O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0);\n      if (dirfd == -1) {\n        if (IsUnrecoverableErrno()) {\n          return -1;\n        } else {\n          LOGF(\"bad overlay %s: %s\", g_overlays[i], DescribeHostErrno(errno));\n          continue;\n        }\n      }\n      if ((fd = openat(dirfd, !path[1] ? \".\" : path + 1, flags, mode)) != -1) {\n        unassert(dup2(fd, dirfd) == dirfd);\n        if (flags & O_CLOEXEC) {\n          unassert(!fcntl(dirfd, F_SETFD, FD_CLOEXEC));\n        }\n        unassert(!close(fd));\n        return dirfd;\n      }\n      if (err == -1) {\n        err = errno;\n      }\n      unassert(!close(dirfd));\n      if (errno != ENOENT && errno != ENOTDIR) {\n        return -1;\n      }\n    }\n  }\n  unassert(err != -1);\n  errno = err;\n  return -1;\n}\n\nstatic ssize_t OverlaysGeneric(int dirfd, const char *path, void *args,\n                               ssize_t fgenericat(int, const char *, void *)) {\n  _Static_assert(sizeof(ssize_t) >= sizeof(int), \"\");\n  size_t i;\n  ssize_t rc;\n  int err = -1;\n  if (!path) return efault();\n  if (!*path) return enoent();\n  if (path[0] != '/' && path[0]) {\n    return fgenericat(dirfd, path, args);\n  }\n  for (i = 0; g_overlays[i]; ++i) {\n    if (!*g_overlays[i]) {\n      if ((rc = fgenericat(AT_FDCWD, path, args)) != -1) {\n        return rc;\n      }\n      if (err == -1) {\n        err = errno;\n      }\n      if (err != ENOENT && err != ENOTDIR) {\n        return -1;\n      }\n    } else {\n      dirfd = open(g_overlays[i], O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0);\n      if (dirfd == -1) {\n        if (IsUnrecoverableErrno()) {\n          return -1;\n        } else {\n          LOGF(\"bad overlay %s: %s\", g_overlays[i], DescribeHostErrno(errno));\n          continue;\n        }\n      }\n      if ((rc = fgenericat(dirfd, !path[1] ? \".\" : path + 1, args)) != -1) {\n        unassert(!close(dirfd));\n        return rc;\n      }\n      if (err == -1) {\n        err = errno;\n      }\n      unassert(!close(dirfd));\n      if (errno != ENOENT && errno != ENOTDIR) {\n        return -1;\n      }\n    }\n  }\n  unassert(err != -1);\n  errno = err;\n  return -1;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Stat {\n  struct stat *st;\n  int flags;\n};\n\nstatic ssize_t Stat(int dirfd, const char *path, void *vargs) {\n  struct Stat *args = (struct Stat *)vargs;\n  return fstatat(dirfd, path, args->st, args->flags);\n}\n\nint OverlaysStat(int dirfd, const char *path, struct stat *st, int flags) {\n  struct Stat args = {st, flags};\n  return OverlaysGeneric(dirfd, path, &args, Stat);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Access {\n  mode_t mode;\n  int flags;\n};\n\nstatic ssize_t Access(int dirfd, const char *path, void *vargs) {\n  struct Access *args = (struct Access *)vargs;\n  return faccessat(dirfd, path, args->mode, args->flags);\n}\n\nint OverlaysAccess(int dirfd, const char *path, mode_t mode, int flags) {\n  struct Access args = {mode, flags};\n  return OverlaysGeneric(dirfd, path, &args, Access);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Unlink {\n  int flags;\n};\n\nstatic ssize_t Unlink(int dirfd, const char *path, void *vargs) {\n  struct Unlink *args = (struct Unlink *)vargs;\n  return unlinkat(dirfd, path, args->flags);\n}\n\nint OverlaysUnlink(int dirfd, const char *path, int flags) {\n  struct Unlink args = {flags};\n  return OverlaysGeneric(dirfd, path, &args, Unlink);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Mkdir {\n  mode_t mode;\n};\n\nstatic ssize_t Mkdir(int dirfd, const char *path, void *vargs) {\n  struct Mkdir *args = (struct Mkdir *)vargs;\n  return mkdirat(dirfd, path, args->mode);\n}\n\nint OverlaysMkdir(int dirfd, const char *path, mode_t mode) {\n  struct Mkdir args = {mode};\n  return OverlaysGeneric(dirfd, path, &args, Mkdir);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Mkfifo {\n  mode_t mode;\n};\n\nstatic ssize_t Mkfifo(int dirfd, const char *path, void *vargs) {\n  struct Mkfifo *args = (struct Mkfifo *)vargs;\n  return mkfifoat(dirfd, path, args->mode);\n}\n\nint OverlaysMkfifo(int dirfd, const char *path, mode_t mode) {\n  struct Mkfifo args = {mode};\n  return OverlaysGeneric(dirfd, path, &args, Mkfifo);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Chmod {\n  mode_t mode;\n  int flags;\n};\n\nstatic ssize_t Chmod(int dirfd, const char *path, void *vargs) {\n  struct Chmod *args = (struct Chmod *)vargs;\n  return fchmodat(dirfd, path, args->mode, args->flags);\n}\n\nint OverlaysChmod(int dirfd, const char *path, mode_t mode, int flags) {\n  struct Chmod args = {mode, flags};\n  return OverlaysGeneric(dirfd, path, &args, Chmod);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Chown {\n  uid_t uid;\n  gid_t gid;\n  int flags;\n};\n\nstatic ssize_t Chown(int dirfd, const char *path, void *vargs) {\n  struct Chown *args = (struct Chown *)vargs;\n  return fchownat(dirfd, path, args->uid, args->gid, args->flags);\n}\n\nint OverlaysChown(int dirfd, const char *path, uid_t uid, gid_t gid,\n                  int flags) {\n  struct Chown args = {uid, gid, flags};\n  return OverlaysGeneric(dirfd, path, &args, Chown);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Symlink {\n  const char *target;\n};\n\nstatic ssize_t Symlink(int dirfd, const char *path, void *vargs) {\n  struct Symlink *args = (struct Symlink *)vargs;\n  return symlinkat(args->target, dirfd, path);\n}\n\nint OverlaysSymlink(const char *target, int dirfd, const char *path) {\n  struct Symlink args = {target};\n  return OverlaysGeneric(dirfd, path, &args, Symlink);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Readlink {\n  char *buf;\n  size_t size;\n};\n\nstatic ssize_t Readlink(int dirfd, const char *path, void *vargs) {\n  struct Readlink *args = (struct Readlink *)vargs;\n  return readlinkat(dirfd, path, args->buf, args->size);\n}\n\nssize_t OverlaysReadlink(int dirfd, const char *path, char *buf, size_t size) {\n  struct Readlink args = {buf, size};\n  return OverlaysGeneric(dirfd, path, &args, Readlink);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Utime {\n  const struct timespec *times;\n  int flags;\n};\n\nstatic ssize_t Utime(int dirfd, const char *path, void *vargs) {\n  struct Utime *args = (struct Utime *)vargs;\n  return utimensat(dirfd, path, args->times, args->flags);\n}\n\nint OverlaysUtime(int dirfd, const char *path, const struct timespec times[2],\n                  int flags) {\n  struct Utime args = {times, flags};\n  return OverlaysGeneric(dirfd, path, &args, Utime);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic ssize_t OverlaysGeneric2(int srcdirfd, const char *srcpath, int dstdirfd,\n                                const char *dstpath, void *args,\n                                ssize_t fgenericat(int, const char *, int,\n                                                   const char *, void *)) {\n  ssize_t rc;\n  int err = -1;\n  ssize_t i, j;\n  const char *sp, *dp;\n  int srccloseme, dstcloseme;\n  if (!srcpath || !dstpath) return efault();\n  if (!*srcpath || !*dstpath) return enoent();\n  for (j = 0; j >= 0 && g_overlays[j]; ++j) {\n    if (srcpath[0] != '/' && srcpath[0]) {\n      j = -2;\n      sp = srcpath;\n      srccloseme = -1;\n    } else if (!*g_overlays[j]) {\n      srcdirfd = AT_FDCWD;\n      srccloseme = -1;\n      sp = srcpath;\n    } else {\n      sp = !srcpath[1] ? \".\" : srcpath + 1;\n      srccloseme = srcdirfd =\n          open(g_overlays[j], O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0);\n      if (srcdirfd == -1) {\n        if (IsUnrecoverableErrno()) {\n          return -1;\n        } else {\n          LOGF(\"bad overlay %s: %s\", g_overlays[j], DescribeHostErrno(errno));\n          continue;\n        }\n      }\n    }\n    for (i = 0; i >= 0 && g_overlays[i]; ++i) {\n      if (dstpath[0] != '/' && dstpath[0]) {\n        i = -2;\n        dp = dstpath;\n        dstcloseme = -1;\n      } else if (!*g_overlays[i]) {\n        dstdirfd = AT_FDCWD;\n        dstcloseme = -1;\n        dp = dstpath;\n      } else {\n        dp = !dstpath[1] ? \".\" : dstpath + 1;\n        dstcloseme = dstdirfd =\n            open(g_overlays[i], O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0);\n        if (dstdirfd == -1) {\n          if (IsUnrecoverableErrno()) {\n            if (srccloseme != -1) close(srccloseme);\n            return -1;\n          } else {\n            LOGF(\"bad overlay %s: %s\", g_overlays[i], DescribeHostErrno(errno));\n            continue;\n          }\n        }\n      }\n      if ((rc = fgenericat(srcdirfd, sp, dstdirfd, dp, args)) != -1) {\n        if (dstcloseme != -1) close(dstcloseme);\n        if (srccloseme != -1) close(srccloseme);\n        return rc;\n      }\n      if (err == -1) {\n        err = errno;\n      }\n      if (dstcloseme != -1) close(dstcloseme);\n      if (errno != ENOENT && errno != ENOTDIR) {\n        if (srccloseme != -1) close(srccloseme);\n        return -1;\n      }\n    }\n    if (srccloseme != -1) close(srccloseme);\n  }\n  unassert(err != -1);\n  errno = err;\n  return -1;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic ssize_t Rename(int srcdirfd, const char *srcpath, int dstdirfd,\n                      const char *dstpath, void *vargs) {\n  return renameat(srcdirfd, srcpath, dstdirfd, dstpath);\n}\n\nint OverlaysRename(int srcdirfd, const char *srcpath, int dstdirfd,\n                   const char *dstpath) {\n  return OverlaysGeneric2(srcdirfd, srcpath, dstdirfd, dstpath, 0, Rename);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct Link {\n  int flags;\n};\n\nstatic ssize_t Link(int srcdirfd, const char *srcpath, int dstdirfd,\n                    const char *dstpath, void *vargs) {\n  struct Link *args = (struct Link *)vargs;\n  return linkat(srcdirfd, srcpath, dstdirfd, dstpath, args->flags);\n}\n\nint OverlaysLink(int srcdirfd, const char *srcpath, int dstdirfd,\n                 const char *dstpath, int flags) {\n  struct Link args = {flags};\n  return OverlaysGeneric2(srcdirfd, srcpath, dstdirfd, dstpath, &args, Link);\n}\n\n#endif /* DISABLE_OVERLAYS */\n"
  },
  {
    "path": "blink/overlays.h",
    "content": "#ifndef BLINK_OVERLAYS_H_\n#define BLINK_OVERLAYS_H_\n#include <stdbool.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#define DEFAULT_OVERLAYS \":o\"\n\nint OverlaysChdir(const char *);\nint SetOverlays(const char *, bool);\nchar *OverlaysGetcwd(char *, size_t);\nint OverlaysUnlink(int, const char *, int);\nint OverlaysMkdir(int, const char *, mode_t);\nint OverlaysMkfifo(int, const char *, mode_t);\nint OverlaysOpen(int, const char *, int, int);\nint OverlaysChmod(int, const char *, mode_t, int);\nint OverlaysAccess(int, const char *, mode_t, int);\nint OverlaysSymlink(const char *, int, const char *);\nint OverlaysStat(int, const char *, struct stat *, int);\nint OverlaysChown(int, const char *, uid_t, gid_t, int);\nint OverlaysRename(int, const char *, int, const char *);\nssize_t OverlaysReadlink(int, const char *, char *, size_t);\nint OverlaysLink(int, const char *, int, const char *, int);\nint OverlaysUtime(int, const char *, const struct timespec[2], int);\n\n#endif /* BLINK_OVERLAYS_H_ */\n"
  },
  {
    "path": "blink/panel.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/panel.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/assert.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/buffer.h\"\n#include \"blink/builtin.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/types.h\"\n#include \"blink/util.h\"\n\nstatic int tpdecode(const char *s, wint_t *out) {\n  u32 wc, cb, need, msb, j, i = 0;\n  if ((wc = s[i++] & 255) == -1) return -1;\n  while ((wc & 0300) == 0200) {\n    if ((wc = s[i++] & 255) == -1) return -1;\n  }\n  if (!(0 <= wc && wc <= 0x7F)) {\n    msb = wc < 252 ? bsr(~wc & 0xff) : 1;\n    need = 7 - msb;\n    wc &= ((1u << msb) - 1) | 0003;\n    for (j = 1; j < need; ++j) {\n      if ((cb = s[i++] & 255) == -1) return -1;\n      if ((cb & 0300) == 0200) {\n        wc = wc << 6 | (cb & 077);\n      } else {\n        if (out) *out = 0xFFFD;\n        return -1;\n      }\n    }\n  }\n  if (out) *out = wc;\n  return i;\n}\n\n/**\n * Renders panel div flex boxen inside terminal display for tui.\n *\n * You can use all the UNICODE and ANSI escape sequences you want.\n *\n * @param pn is number of panels\n * @param p is panel list in logically sorted order\n * @param tyn is terminal height in cells\n * @param txn is terminal width in cells\n * @param size optionally receives length of result\n * @return ANSI codes, or null w/ errno\n */\nchar *RenderPanels(long pn, struct Panel *p, long tyn, long txn, size_t *size) {\n  wint_t wc;\n  struct Buffer b, *l;\n  int x, y, i, j, width;\n  enum { kUtf8, kAnsi, kAnsiCsi } s;\n  memset(&b, 0, sizeof(b));\n  AppendStr(&b, \"\\033[H\");\n  for (y = 0; y < tyn; ++y) {\n    if (y) AppendFmt(&b, \"\\033[%dH\", y + 1);\n    for (x = i = 0; i < pn; ++i) {\n      if (p[i].top <= y && y < p[i].bottom) {\n        j = 0;\n        s = kUtf8;\n        l = &p[i].lines[y - p[i].top];\n        while (x + 8 <= p[i].left) {\n          char t[8] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};\n          AppendData(&b, t, 8);\n          x += 8;\n        }\n        while (x < p[i].left) {\n          AppendChar(&b, ' ');\n          x += 1;\n        }\n        while (x < p[i].right || j < l->i) {\n          wc = '\\0';\n          width = 0;\n          if (j < l->i) {\n            wc = l->p[j];\n            switch (s) {\n              case kUtf8:\n                switch (wc & 255) {\n                  case 033:\n                    s = kAnsi;\n                    ++j;\n                    break;\n                  default:\n                    j += abs(tpdecode(l->p + j, &wc));\n                    if (x < p[i].right) {\n                      width = wcwidth(wc);\n                      width = MAX(1, width);\n                    } else {\n                      wc = 0;\n                    }\n                    break;\n                }\n                break;\n              case kAnsi:\n                switch (wc & 255) {\n                  case '[':\n                    s = kAnsiCsi;\n                    ++j;\n                    break;\n                  case '@':\n                  case ']':\n                  case '^':\n                  case '_':\n                  case '\\\\':\n                  case 'A':\n                  case 'B':\n                  case 'C':\n                  case 'D':\n                  case 'E':\n                  case 'F':\n                  case 'G':\n                  case 'H':\n                  case 'I':\n                  case 'J':\n                  case 'K':\n                  case 'L':\n                  case 'M':\n                  case 'N':\n                  case 'O':\n                  case 'P':\n                  case 'Q':\n                  case 'R':\n                  case 'S':\n                  case 'T':\n                  case 'U':\n                  case 'V':\n                  case 'W':\n                  case 'X':\n                  case 'Y':\n                  case 'Z':\n                    s = kUtf8;\n                    ++j;\n                    break;\n                  default:\n                    s = kUtf8;\n                    continue;\n                }\n                break;\n              case kAnsiCsi:\n                switch (wc & 255) {\n                  case ':':\n                  case ';':\n                  case '<':\n                  case '=':\n                  case '>':\n                  case '?':\n                  case '0':\n                  case '1':\n                  case '2':\n                  case '3':\n                  case '4':\n                  case '5':\n                  case '6':\n                  case '7':\n                  case '8':\n                  case '9':\n                    ++j;\n                    break;\n                  case '`':\n                  case '~':\n                  case '^':\n                  case '@':\n                  case '[':\n                  case ']':\n                  case '{':\n                  case '}':\n                  case '_':\n                  case '|':\n                  case '\\\\':\n                  case 'A':\n                  case 'B':\n                  case 'C':\n                  case 'D':\n                  case 'E':\n                  case 'F':\n                  case 'G':\n                  case 'H':\n                  case 'I':\n                  case 'J':\n                  case 'K':\n                  case 'L':\n                  case 'M':\n                  case 'N':\n                  case 'O':\n                  case 'P':\n                  case 'Q':\n                  case 'R':\n                  case 'S':\n                  case 'T':\n                  case 'U':\n                  case 'V':\n                  case 'W':\n                  case 'X':\n                  case 'Y':\n                  case 'Z':\n                  case 'a':\n                  case 'b':\n                  case 'c':\n                  case 'd':\n                  case 'e':\n                  case 'f':\n                  case 'g':\n                  case 'h':\n                  case 'i':\n                  case 'j':\n                  case 'k':\n                  case 'l':\n                  case 'm':\n                  case 'n':\n                  case 'o':\n                  case 'p':\n                  case 'q':\n                  case 'r':\n                  case 's':\n                  case 't':\n                  case 'u':\n                  case 'v':\n                  case 'w':\n                  case 'x':\n                  case 'y':\n                  case 'z':\n                    s = kUtf8;\n                    ++j;\n                    break;\n                  default:\n                    s = kUtf8;\n                    continue;\n                }\n                break;\n              default:\n                __builtin_unreachable();\n            }\n            if (x > p[i].right) {\n              break;\n            }\n          } else if (x < p[i].right) {\n            wc = ' ';\n            width = 1;\n          }\n          if (wc) {\n            x += width;\n            AppendWide(&b, wc);\n          }\n        }\n      }\n    }\n  }\n  unassert(b.p = (char *)realloc(b.p, b.i + 1));\n  if (size) *size = b.i;\n  return b.p;\n}\n"
  },
  {
    "path": "blink/panel.h",
    "content": "#ifndef BLINK_PANEL_H_\n#define BLINK_PANEL_H_\n#include <stddef.h>\n#include <sys/types.h>\n\n#include \"blink/buffer.h\"\n\nstruct Panel {\n  int top;\n  int bottom;\n  int left;\n  int right;\n  struct Buffer *lines;\n  int n;\n};\n\nchar *RenderPanels(long, struct Panel *, long, long, size_t *);\nvoid PrintMessageBox(int, const char *, long, long);\n\n#endif /* BLINK_PANEL_H_ */\n"
  },
  {
    "path": "blink/path.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <fcntl.h>\n#include <stdarg.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/debug.h\"\n#include \"blink/dis.h\"\n#include \"blink/high.h\"\n#include \"blink/jit.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/modrm.h\"\n#include \"blink/overlays.h\"\n#include \"blink/rde.h\"\n#include \"blink/stats.h\"\n#include \"blink/vfs.h\"\n\n#define APPEND(...) o += snprintf(b + o, o > n ? 0 : n - o, __VA_ARGS__)\n\n#ifdef HAVE_JIT\n\nvoid (*AddPath_StartOp_Hook)(P);\n\n#if LOG_COD\nstatic int g_cod;\nstatic struct Dis g_dis;\n#endif\n\nstatic void StartPath(struct Machine *m, i64 pc) {\n  JIX_LOGF(\"%\" PRIx64 \":%\" PRIx64 \" <path>\", GetPc(m), pc);\n}\n\nstatic void DebugOp(struct Machine *m, i64 expected_ip) {\n  if (m->ip != expected_ip) {\n    ERRF(\"IP was %\" PRIx64 \" but it should have been %\" PRIx64, m->ip,\n         expected_ip);\n  }\n  unassert(m->ip == expected_ip);\n}\n\nstatic void StartOp(struct Machine *m, i64 pc) {\n  JIX_LOGF(\"%\" PRIx64 \":%\" PRIx64 \"   <op>\", GetPc(m), pc);\n  JIX_LOGF(\"%\" PRIx64 \":%\" PRIx64 \"     %s\", GetPc(m), pc, DescribeOp(m, pc));\n  unassert(!IsMakingPath(m));\n}\n\nstatic void EndOp(struct Machine *m, i64 pc) {\n  JIX_LOGF(\"%\" PRIx64 \":%\" PRIx64 \"   </op>\", GetPc(m), pc);\n  m->oplen = 0;\n  if (m->stashaddr) {\n    CommitStash(m);\n  }\n}\n\nstatic void EndPath(struct Machine *m, i64 pc) {\n  JIX_LOGF(\"%\" PRIx64 \":%\" PRIx64 \"   %s\", GetPc(m), GetPc(m),\n           DescribeOp(m, GetPc(m)));\n  JIX_LOGF(\"%\" PRIx64 \":%\" PRIx64 \" </path>\", GetPc(m), GetPc(m));\n}\n\nvoid FuseOp(struct Machine *m, i64 pc) {\n  JIX_LOGF(\"%\" PRIx64 \":%\" PRIx64 \"     %s\", GetPc(m), pc, DescribeOp(m, pc));\n  JIX_LOGF(\"%\" PRIx64 \":%\" PRIx64 \"   </op>\", GetPc(m), pc);\n}\n\n#ifdef HAVE_JIT\n#if defined(__x86_64__)\nstatic const u8 kEnter[] = {\n    0x55,                    // push %rbp\n    0x48, 0x89, 0345,        // mov  %rsp,%rbp\n#ifdef __CYGWIN__            //\n    0x48, 0x83, 0354, 0x40,  // sub  $0x40,%rsp\n    0x48, 0x89, 0175, 0xc8,  // mov  %rdi,-0x38(%rbp)\n    0x48, 0x89, 0165, 0xd0,  // mov  %rsi,-0x30(%rbp)\n#else                        //\n    0x48, 0x83, 0354, 0x30,  // sub  $0x30,%rsp\n#endif                       //\n    0x48, 0x89, 0135, 0xd8,  // mov  %rbx,-0x28(%rbp)\n    0x4c, 0x89, 0145, 0xe0,  // mov  %r12,-0x20(%rbp)\n    0x4c, 0x89, 0155, 0xe8,  // mov  %r13,-0x18(%rbp)\n    0x4c, 0x89, 0165, 0xf0,  // mov  %r14,-0x10(%rbp)\n    0x4c, 0x89, 0175, 0xf8,  // mov  %r15,-0x08(%rbp)\n#ifdef __CYGWIN__            //\n    0x48, 0x89, 0313,        // mov  %rcx,%rbx\n#else                        //\n    0x48, 0x89, 0373,        // mov  %rdi,%rbx\n#endif\n};\nstatic const u8 kLeave[] = {\n    0x4c, 0x8b, 0175, 0xf8,  // mov -0x08(%rbp),%r15\n    0x4c, 0x8b, 0165, 0xf0,  // mov -0x10(%rbp),%r14\n    0x4c, 0x8b, 0155, 0xe8,  // mov -0x18(%rbp),%r13\n    0x4c, 0x8b, 0145, 0xe0,  // mov -0x20(%rbp),%r12\n    0x48, 0x8b, 0135, 0xd8,  // mov -0x28(%rbp),%rbx\n#ifdef __CYGWIN__\n    0x48, 0x8b, 0165, 0xd0,  // mov -0x30(%rbp),%rsi\n    0x48, 0x8b, 0175, 0xc8,  // mov -0x38(%rbp),%rdi\n    0x48, 0x83, 0304, 0x40,  // add $0x40,%rsp\n#else\n    0x48, 0x83, 0304, 0x30,  // add $0x30,%rsp\n#endif\n    0x5d,  // pop %rbp\n};\n#elif defined(__aarch64__)\nstatic const u32 kEnter[] = {\n    0xa9bc7bfd,  // stp x29, x30, [sp, #-64]!\n    0x910003fd,  // mov x29, sp\n    0xa90153f3,  // stp x19, x20, [sp, #16]\n    0xa9025bf5,  // stp x21, x22, [sp, #32]\n    0xa90363f7,  // stp x23, x24, [sp, #48]\n    0xaa0003f3,  // mov x19, x0\n};\nstatic const u32 kLeave[] = {\n    0xa94153f3,  // ldp x19, x20, [sp, #16]\n    0xa9425bf5,  // ldp x21, x22, [sp, #32]\n    0xa94363f7,  // ldp x23, x24, [sp, #48]\n    0xa8c47bfd,  // ldp x29, x30, [sp], #64\n};\n#endif /* __x86_64__ */\n#endif /* HAVE_JIT */\n\nlong GetPrologueSize(void) {\n#ifdef HAVE_JIT\n  return sizeof(kEnter);\n#else\n  return 0;\n#endif\n}\n\nvoid(SetupCod)(struct Machine *m) {\n#if LOG_COD\n  m->system->dis = &g_dis;\n  LoadDebugSymbols(m->system);\n  DisLoadElf(&g_dis, &m->system->elf);\n  g_cod = VfsOpen(AT_FDCWD_LINUX, \"/tmp/blink.s\",\n                  O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);\n  g_cod = VfsFcntl(g_cod, F_DUPFD_CLOEXEC, kMinBlinkFd);\n#endif\n}\n\nvoid(LogCodOp)(struct Machine *m, const char *s) {\n#if LOG_COD\n  // FlushCod(m->path.jb);\n  WriteCod(\"/\\t%s\\n\", s);\n#endif\n}\n\nvoid(WriteCod)(const char *fmt, ...) {\n#if LOG_COD\n  int n;\n  va_list va;\n  char buf[256];\n  if (!g_cod) return;\n  va_start(va, fmt);\n  n = vsnprintf(buf, sizeof(buf), fmt, va);\n  va_end(va);\n  write(g_cod, buf, MIN(n, sizeof(buf)));\n#endif\n}\n\nvoid BeginCod(struct Machine *m, i64 pc) {\n#if LOG_COD\n  char b[256];\n  char spec[64];\n  int i, o = 0, n = sizeof(b);\n  if (!g_cod) return;\n  DISABLE_HIGHLIGHT_BEGIN;\n  APPEND(\"/\\t\");\n  unassert(!GetInstruction(m, pc, g_dis.xedd));\n  DisInst(&g_dis, b + o, DisSpec(g_dis.xedd, spec));\n  o = strlen(b);\n  APPEND(\" #\");\n  for (i = 0; i < g_dis.xedd->length; ++i) {\n    APPEND(\" %02x\", g_dis.xedd->bytes[i]);\n  }\n  APPEND(\" @ %\" PRIx64, m->ip);\n  APPEND(\"\\n\");\n  write(g_cod, b, MIN(o, n));\n  DISABLE_HIGHLIGHT_END;\n#endif\n}\n\nvoid FlushCod(struct JitBlock *jb) {\n#if LOG_COD\n  char b[256];\n  char spec[64];\n  if (!g_cod) return;\n  if (jb->index == jb->blocksize + 1) {\n    WriteCod(\"/\\tOOM!\\n\");\n    jb->cod = jb->index;\n    return;\n  }\n  DISABLE_HIGHLIGHT_BEGIN;\n  for (; jb->cod < jb->index; jb->cod += g_dis.xedd->length) {\n    unassert(!DecodeInstruction(g_dis.xedd, jb->addr + jb->cod,\n                                jb->index - jb->cod, XED_MODE_LONG));\n    g_dis.addr = (uintptr_t)jb->addr + jb->cod;\n    DisInst(&g_dis, b, DisSpec(g_dis.xedd, spec));\n    WriteCod(\"\\t%s\\n\", b);\n  }\n  DISABLE_HIGHLIGHT_END;\n#endif\n}\n\nstatic bool IsPure(u64 rde) {\n  switch (Mopcode(rde)) {\n    case 0x004:  // OpAluAlIbAdd\n    case 0x005:  // OpAluRaxIvds\n    case 0x00C:  // OpAluAlIbOr\n    case 0x00D:  // OpAluRaxIvds\n    case 0x014:  // OpAluAlIbAdc\n    case 0x015:  // OpAluRaxIvds\n    case 0x01C:  // OpAluAlIbSbb\n    case 0x01D:  // OpAluRaxIvds\n    case 0x024:  // OpAluAlIbAnd\n    case 0x025:  // OpAluRaxIvds\n    case 0x02C:  // OpAluAlIbSub\n    case 0x02D:  // OpAluRaxIvds\n    case 0x034:  // OpAluAlIbXor\n    case 0x035:  // OpAluRaxIvds\n    case 0x03C:  // OpCmpAlIb\n    case 0x03D:  // OpCmpRaxIvds\n    case 0x090:  // OpNop\n    case 0x091:  // OpXchgZvqp\n    case 0x092:  // OpXchgZvqp\n    case 0x093:  // OpXchgZvqp\n    case 0x094:  // OpXchgZvqp\n    case 0x095:  // OpXchgZvqp\n    case 0x096:  // OpXchgZvqp\n    case 0x097:  // OpXchgZvqp\n    case 0x098:  // OpSax\n    case 0x099:  // OpConvert\n    case 0x09E:  // OpSahf\n    case 0x09F:  // OpLahf\n    case 0x0A1:  // OpMovRaxOvqp\n    case 0x0A3:  // OpMovOvqpRax\n    case 0x0A8:  // OpTestAlIb\n    case 0x0A9:  // OpTestRaxIvds\n    case 0x0B0:  // OpMovZbIb\n    case 0x0B1:  // OpMovZbIb\n    case 0x0B2:  // OpMovZbIb\n    case 0x0B3:  // OpMovZbIb\n    case 0x0B4:  // OpMovZbIb\n    case 0x0B5:  // OpMovZbIb\n    case 0x0B6:  // OpMovZbIb\n    case 0x0B7:  // OpMovZbIb\n    case 0x0B8:  // OpMovZvqpIvqp\n    case 0x0B9:  // OpMovZvqpIvqp\n    case 0x0BA:  // OpMovZvqpIvqp\n    case 0x0BB:  // OpMovZvqpIvqp\n    case 0x0BC:  // OpMovZvqpIvqp\n    case 0x0BD:  // OpMovZvqpIvqp\n    case 0x0BE:  // OpMovZvqpIvqp\n    case 0x0BF:  // OpMovZvqpIvqp\n    case 0x0D6:  // OpSalc\n    case 0x0F5:  // OpCmc\n    case 0x0F8:  // OpClc\n    case 0x0F9:  // OpStc\n    case 0x11F:  // OpNopEv\n    case 0x150:  // OpMovmskpsd\n    case 0x1D7:  // OpPmovmskbGdqpNqUdq\n    case 0x1C8:  // OpBswapZvqp\n    case 0x1C9:  // OpBswapZvqp\n    case 0x1CA:  // OpBswapZvqp\n    case 0x1CB:  // OpBswapZvqp\n    case 0x1CC:  // OpBswapZvqp\n    case 0x1CD:  // OpBswapZvqp\n    case 0x1CE:  // OpBswapZvqp\n    case 0x1CF:  // OpBswapZvqp\n    case 0x050:  // OpPushZvq\n    case 0x051:  // OpPushZvq\n    case 0x052:  // OpPushZvq\n    case 0x053:  // OpPushZvq\n    case 0x054:  // OpPushZvq\n    case 0x055:  // OpPushZvq\n    case 0x056:  // OpPushZvq\n    case 0x057:  // OpPushZvq\n    case 0x058:  // OpPopZvq\n    case 0x059:  // OpPopZvq\n    case 0x05A:  // OpPopZvq\n    case 0x05B:  // OpPopZvq\n    case 0x05C:  // OpPopZvq\n    case 0x05D:  // OpPopZvq\n    case 0x05E:  // OpPopZvq\n    case 0x05F:  // OpPopZvq\n      return true;\n    case 0x000:  // OpAlub\n    case 0x001:  // OpAluw\n    case 0x002:  // OpAlubFlip\n    case 0x003:  // OpAluwFlip\n    case 0x008:  // OpAlub\n    case 0x009:  // OpAluw\n    case 0x00A:  // OpAlubFlip\n    case 0x00B:  // OpAluwFlip\n    case 0x010:  // OpAlub\n    case 0x011:  // OpAluw\n    case 0x012:  // OpAlubFlip\n    case 0x013:  // OpAluwFlip\n    case 0x018:  // OpAlub\n    case 0x019:  // OpAluw\n    case 0x01A:  // OpAlubFlip\n    case 0x01B:  // OpAluwFlip\n    case 0x020:  // OpAlub\n    case 0x021:  // OpAluw\n    case 0x022:  // OpAlubFlip\n    case 0x023:  // OpAluwFlip\n    case 0x028:  // OpAlub\n    case 0x029:  // OpAluw\n    case 0x02A:  // OpAlubFlip\n    case 0x02B:  // OpAluwFlip\n    case 0x030:  // OpAlub\n    case 0x031:  // OpAluw\n    case 0x032:  // OpAlubFlip\n    case 0x033:  // OpAluwFlip\n    case 0x038:  // OpAlubCmp\n    case 0x039:  // OpAluwCmp\n    case 0x03A:  // OpAlubFlipCmp\n    case 0x03B:  // OpAluwFlipCmp\n    case 0x063:  // OpMovsxdGdqpEd\n    case 0x069:  // OpImulGvqpEvqpImm\n    case 0x06B:  // OpImulGvqpEvqpImm\n    case 0x080:  // OpAlubiReg\n    case 0x081:  // OpAluwiReg\n    case 0x082:  // OpAlubiReg\n    case 0x083:  // OpAluwiReg\n    case 0x084:  // OpAlubTest\n    case 0x085:  // OpAluwTest\n    case 0x086:  // OpXchgGbEb\n    case 0x087:  // OpXchgGvqpEvqp\n    case 0x088:  // OpMovEbGb\n    case 0x089:  // OpMovEvqpGvqp\n    case 0x08A:  // OpMovGbEb\n    case 0x08B:  // OpMovGvqpEvqp\n    case 0x0C0:  // OpBsubiImm\n    case 0x0C1:  // OpBsuwiImm\n    case 0x0C6:  // OpMovEbIb\n    case 0x0C7:  // OpMovEvqpIvds\n    case 0x0D0:  // OpBsubi1\n    case 0x0D1:  // OpBsuwi1\n    case 0x0D2:  // OpBsubiCl\n    case 0x0D3:  // OpBsuwiCl\n    case 0x0F6:  // Op0f6\n    case 0x0F7:  // Op0f7\n    case 0x140:  // OpCmovo\n    case 0x141:  // OpCmovno\n    case 0x142:  // OpCmovb\n    case 0x143:  // OpCmovae\n    case 0x144:  // OpCmove\n    case 0x145:  // OpCmovne\n    case 0x146:  // OpCmovbe\n    case 0x147:  // OpCmova\n    case 0x148:  // OpCmovs\n    case 0x149:  // OpCmovns\n    case 0x14A:  // OpCmovp\n    case 0x14B:  // OpCmovnp\n    case 0x14C:  // OpCmovl\n    case 0x14D:  // OpCmovge\n    case 0x14E:  // OpCmovle\n    case 0x14F:  // OpCmovg\n    case 0x190:  // OpSeto\n    case 0x191:  // OpSetno\n    case 0x192:  // OpSetb\n    case 0x193:  // OpSetae\n    case 0x194:  // OpSete\n    case 0x195:  // OpSetne\n    case 0x196:  // OpSetbe\n    case 0x197:  // OpSeta\n    case 0x198:  // OpSets\n    case 0x199:  // OpSetns\n    case 0x19A:  // OpSetp\n    case 0x19B:  // OpSetnp\n    case 0x19C:  // OpSetl\n    case 0x19D:  // OpSetge\n    case 0x19E:  // OpSetle\n    case 0x19F:  // OpSetg\n    case 0x1A3:  // OpBit\n    case 0x1A4:  // OpDoubleShift\n    case 0x1A5:  // OpDoubleShift\n    case 0x1AB:  // OpBit\n    case 0x1AC:  // OpDoubleShift\n    case 0x1AD:  // OpDoubleShift\n    case 0x1AF:  // OpImulGvqpEvqp\n    case 0x1B3:  // OpBit\n    case 0x1B6:  // OpMovzbGvqpEb\n    case 0x1B7:  // OpMovzwGvqpEw\n    case 0x1BA:  // OpBit\n    case 0x1BB:  // OpBit\n    case 0x1BC:  // OpBsf\n    case 0x1BD:  // OpBsr\n    case 0x1BE:  // OpMovsbGvqpEb\n    case 0x1BF:  // OpMovswGvqpEw\n    case 0x110:  // sse moves\n    case 0x111:  // sse moves\n    case 0x112:  // sse moves\n    case 0x113:  // sse moves\n    case 0x114:  // unpcklpsd\n    case 0x115:  // unpckhpsd\n    case 0x116:  // sse moves\n    case 0x117:  // sse moves\n    case 0x128:  // sse moves\n    case 0x129:  // sse moves\n    case 0x12A:  // sse convs\n    case 0x12B:  // sse moves\n    case 0x12C:  // sse convs\n    case 0x12D:  // sse convs\n    case 0x160:  // OpSsePunpcklbw\n    case 0x161:  // OpSsePunpcklwd\n    case 0x162:  // OpSsePunpckldq\n    case 0x163:  // OpSsePacksswb\n    case 0x164:  // OpSsePcmpgtb\n    case 0x165:  // OpSsePcmpgtw\n    case 0x166:  // OpSsePcmpgtd\n    case 0x167:  // OpSsePackuswb\n    case 0x168:  // OpSsePunpckhbw\n    case 0x169:  // OpSsePunpckhwd\n    case 0x16A:  // OpSsePunpckhdq\n    case 0x16B:  // OpSsePackssdw\n    case 0x16C:  // OpSsePunpcklqdq\n    case 0x16D:  // OpSsePunpckhqdq\n    case 0x16E:  // OpMov0f6e\n    case 0x16F:  // OpMov0f6f\n    case 0x170:  // OpShuffle\n    case 0x171:  // Op171\n    case 0x172:  // Op172\n    case 0x173:  // Op173\n    case 0x174:  // OpSsePcmpeqb\n    case 0x175:  // OpSsePcmpeqw\n    case 0x176:  // OpSsePcmpeqd\n    case 0x17E:  // OpMov0f7e\n    case 0x17F:  // OpMov0f7f\n    case 0x1D1:  // OpSsePsrlwv\n    case 0x1D2:  // OpSsePsrldv\n    case 0x1D3:  // OpSsePsrlqv\n    case 0x1D4:  // OpSsePaddq\n    case 0x1D5:  // OpSsePmullw\n    case 0x1D8:  // OpSsePsubusb\n    case 0x1D9:  // OpSsePsubusw\n    case 0x1DA:  // OpSsePminub\n    case 0x1DB:  // OpSsePand\n    case 0x1DC:  // OpSsePaddusb\n    case 0x1DD:  // OpSsePaddusw\n    case 0x1DE:  // OpSsePmaxub\n    case 0x1DF:  // OpSsePandn\n    case 0x1E0:  // OpSsePavgb\n    case 0x1E1:  // OpSsePsrawv\n    case 0x1E2:  // OpSsePsradv\n    case 0x1E3:  // OpSsePavgw\n    case 0x1E4:  // OpSsePmulhuw\n    case 0x1E5:  // OpSsePmulhw\n    case 0x1E8:  // OpSsePsubsb\n    case 0x1E9:  // OpSsePsubsw\n    case 0x1EA:  // OpSsePminsw\n    case 0x1EB:  // OpSsePor\n    case 0x1EC:  // OpSsePaddsb\n    case 0x1ED:  // OpSsePaddsw\n    case 0x1EE:  // OpSsePmaxsw\n    case 0x1EF:  // OpSsePxor\n    case 0x1F1:  // OpSsePsllwv\n    case 0x1F2:  // OpSsePslldv\n    case 0x1F3:  // OpSsePsllqv\n    case 0x1F4:  // OpSsePmuludq\n    case 0x1F5:  // OpSsePmaddwd\n    case 0x1F6:  // OpSsePsadbw\n    case 0x1F8:  // OpSsePsubb\n    case 0x1F9:  // OpSsePsubw\n    case 0x1FA:  // OpSsePsubd\n    case 0x1FB:  // OpSsePsubq\n    case 0x1FC:  // OpSsePaddb\n    case 0x1FD:  // OpSsePaddw\n    case 0x1FE:  // OpSsePaddd\n    case 0x200:  // OpSsePshufb\n    case 0x201:  // OpSsePhaddw\n    case 0x202:  // OpSsePhaddd\n    case 0x203:  // OpSsePhaddsw\n    case 0x204:  // OpSsePmaddubsw\n    case 0x205:  // OpSsePhsubw\n    case 0x206:  // OpSsePhsubd\n    case 0x207:  // OpSsePhsubsw\n    case 0x208:  // OpSsePsignb\n    case 0x209:  // OpSsePsignw\n    case 0x20A:  // OpSsePsignd\n    case 0x20B:  // OpSsePmulhrsw\n    case 0x2F6:  // adcx, adox, mulx\n    case 0x344:  // pclmulqdq\n      return IsModrmRegister(rde);\n    case 0x08D:  // OpLeaGvqpM\n      return !IsRipRelative(rde);\n    case 0x0FF:\n      return IsModrmRegister(rde) &&  //\n             (ModrmReg(rde) == 0 ||   // inc\n              ModrmReg(rde) == 1);    // dec\n    default:\n      return false;\n  }\n}\n\nstatic bool MustUpdateIp(P) {\n  u64 next;\n  if (!IsPure(rde)) return true;\n  next = m->ip + Oplength(rde);\n  if (GetJitHook(&m->system->jit, next)) return true;\n  return false;\n}\n\nstatic void InitPaths(struct System *s) {\n#ifdef HAVE_JIT\n  struct JitBlock *jb;\n  if (!s->ender) {\n    unassert((jb = StartJit(&s->jit, 0)));\n    WriteCod(\"\\nJit_%p:\\n\", jb->addr + jb->index);\n    s->ender = GetJitPc(jb);\n#if LOG_JIX\n    AppendJitMovReg(jb, kJitArg0, kJitSav0);\n    AppendJitCall(jb, (void *)EndPath);\n#endif\n    AppendJit(jb, kLeave, sizeof(kLeave));\n    AppendJitRet(jb);\n    FlushCod(jb);\n    unassert(FinishJit(&s->jit, jb));\n  }\n#endif\n}\n\nbool CreatePath(P) {\n#ifdef HAVE_JIT\n  bool res;\n  i64 pc, jpc;\n  unassert(!IsMakingPath(m));\n  InitPaths(m->system);\n  if (m->path.skip > 0) {\n    --m->path.skip;\n    return false;\n  }\n  if ((pc = GetPc(m))) {\n    if ((m->path.jb = StartJit(&m->system->jit, pc))) {\n      JIP_LOGF(\"starting new path jit_pc:%\" PRIxPTR \" at pc:%\" PRIx64,\n               GetJitPc(m->path.jb), pc);\n      FlushCod(m->path.jb);\n      jpc = (uintptr_t)m->path.jb->addr + m->path.jb->index;\n      (void)jpc;\n      AppendJit(m->path.jb, kEnter, sizeof(kEnter));\n#if LOG_JIX\n      Jitter(A,\n             \"a1i\"  // arg1 = ip\n             \"q\"    // arg0 = machine\n             \"c\"    // call function (StartPath)\n             \"q\",   // arg0 = machine\n             GetPc(m), StartPath);\n#endif\n      WriteCod(\"\\nJit_%\" PRIx64 \"_%\" PRIx64 \":\\n\", pc, jpc);\n      FlushCod(m->path.jb);\n      m->path.start = pc;\n      m->path.elements = 0;\n      res = true;\n    } else {\n      res = false;\n    }\n  } else {\n    res = false;\n  }\n  return res;\n#else\n  return false;\n#endif\n}\n\nvoid CompletePath(P) {\n  unassert(IsMakingPath(m));\n  FlushSkew(A);\n  AppendJitJump(m->path.jb, (void *)m->system->ender);\n  FinishPath(m);\n}\n\nvoid FinishPath(struct Machine *m) {\n  unassert(IsMakingPath(m));\n  FlushCod(m->path.jb);\n  STATISTIC(path_longest_bytes =\n                MAX(path_longest_bytes, m->path.jb->index - m->path.jb->start));\n  STATISTIC(path_longest = MAX(path_longest, m->path.elements));\n  STATISTIC(AVERAGE(path_average_elements, m->path.elements));\n  STATISTIC(AVERAGE(path_average_bytes, m->path.jb->index - m->path.jb->start));\n  if (FinishJit(&m->system->jit, m->path.jb)) {\n    STATISTIC(++path_count);\n    JIP_LOGF(\"staged path to %\" PRIx64, m->path.start);\n  } else {\n    JIP_LOGF(\"path starting at %\" PRIx64 \" couldn't be installed\",\n             m->path.start);\n  }\n  m->path.jb = 0;\n}\n\nvoid AbandonPath(struct Machine *m) {\n  WriteCod(\"/\\tABANDONED\\n\");\n  unassert(IsMakingPath(m));\n  JIP_LOGF(\"abandoning path jit_pc:%\" PRIxPTR \" which started at pc:%\" PRIx64,\n           GetJitPc(m->path.jb), m->path.start);\n  AbandonJit(&m->system->jit, m->path.jb);\n  m->path.skew = 0;\n  m->path.jb = 0;\n}\n\nvoid FlushSkew(P) {\n  unassert(IsMakingPath(m));\n  if (m->path.skew) {\n    JIP_LOGF(\"adding %\" PRId64 \" to ip\", m->path.skew);\n    Jitter(A,\n           \"a1i\"  // arg1 = skew\n           \"q\"    // arg0 = machine\n           \"m\",   // arg0 = machine\n           m->path.skew, AdvanceIp);\n    m->path.skew = 0;\n  }\n}\n\nvoid AddPath_StartOp(P) {\n#if LOG_CPU\n  Jitter(A, \"qmq\", LogCpu);\n#endif\n  BeginCod(m, GetPc(m));\n#ifndef NDEBUG\n  if (FLAG_statistics) {\n    Jitter(A,\n           \"a0i\"  // arg0 = &instructions_jitted\n           \"m\",   // call micro-op (CountOp)\n           &instructions_jitted, CountOp);\n  }\n#endif\n  if (AddPath_StartOp_Hook) {\n    AddPath_StartOp_Hook(A);\n  }\n#if LOG_JIX || defined(DEBUG)\n  Jitter(A,\n         \"a1i\"  // arg1 = m->ip\n         \"q\"    // arg0 = machine\n         \"c\",   // call function (DebugOp)\n         m->ip - m->path.skew, DebugOp);\n#endif\n#if LOG_JIX\n  Jitter(A,\n         \"a1i\"  // arg1 = pc\n         \"q\"    // arg0 = machine\n         \"c\",   // call function (StartOp)\n         m->ip, StartOp);\n#endif\n  if (MustUpdateIp(A)) {\n    if (!m->path.skew) {\n      JIP_LOGF(\"adding %\" PRId64 \" to ip\", Oplength(rde));\n      Jitter(A,\n             \"a1i\"  // arg1 = Oplength(rde)\n             \"q\"    // arg0 = machine\n             \"m\",   // call micro-op (AddIp)\n             Oplength(rde), AddIp);\n    } else {\n      JIP_LOGF(\"adding %\" PRId64 \"+%\" PRId64 \" to ip\", m->path.skew,\n               Oplength(rde));\n      Jitter(A,\n             \"a2i\"  // arg1 = program counter delta\n             \"a1i\"  // arg1 = instruction length\n             \"q\"    // arg0 = machine\n             \"m\",   // call micro-op (SkewIp)\n             m->path.skew + Oplength(rde), Oplength(rde), SkewIp);\n      m->path.skew = 0;\n    }\n  } else {\n    m->path.skew += Oplength(rde);\n  }\n  AppendJitMovReg(m->path.jb, kJitArg0, kJitSav0);\n  m->reserving = false;\n}\n\nvoid AddPath_EndOp(P) {\n  _Static_assert(offsetof(struct Machine, stashaddr) < 128, \"\");\n  if (m->reserving) {\n    WriteCod(\"/\\tflush reserve\\n\");\n  }\n#if !LOG_JIX && defined(__x86_64__)\n  if (m->reserving) {\n    AppendJitMovReg(m->path.jb, kJitArg0, kJitSav0);\n    u8 sa = offsetof(struct Machine, stashaddr);\n    u8 code[] = {\n        // cmpq $0x0,0x18(%rdi)\n        0x48 | (kJitArg0 > 7 ? kAmdRexb : 0),\n        0x83,\n        0170 | (kJitArg0 & 7),\n        sa,\n        0x00,\n        // jz +5\n        0x74,\n        0x05,\n    };\n    AppendJit(m->path.jb, code, sizeof(code));\n    AppendJitCall(m->path.jb, (void *)(uintptr_t)CommitStash);\n  }\n#elif !LOG_JIX && defined(__aarch64__)\n  if (m->reserving) {\n    AppendJitMovReg(m->path.jb, kJitArg0, kJitSav0);\n    u32 sa = offsetof(struct Machine, stashaddr);\n    u32 code[] = {\n        0xf9400001 | (sa / 8) << 10,  // ldr x1, [x0, #stashaddr]\n        0xb4000001 | 2 << 5,          // cbz x1, +2\n    };\n    AppendJit(m->path.jb, code, sizeof(code));\n    AppendJitCall(m->path.jb, (void *)(uintptr_t)CommitStash);\n  }\n#else\n  Jitter(A,\n         \"a1i\"  // arg1 = pc\n         \"q\"    // arg0 = machine\n         \"c\",   // call function (EndOp)\n         m->ip, EndOp);\n#endif\n  FlushCod(m->path.jb);\n}\n\nbool AddPath(P) {\n  unassert(IsMakingPath(m));\n  Jitter(A,\n         \"a3i\"  // arg2 = uimm0\n         \"a2i\"  // arg2 = disp\n         \"a1i\"  // arg1 = rde\n         \"c\",   // call function\n         uimm0, disp, rde, GetOp(Mopcode(rde)));\n  return true;\n}\n\n#endif /* HAVE_JIT */\n"
  },
  {
    "path": "blink/pipe.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <fcntl.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/endian.h\"\n#include \"blink/errno.h\"\n#include \"blink/fds.h\"\n#include \"blink/log.h\"\n#include \"blink/ndelay.h\"\n#include \"blink/syscall.h\"\n#include \"blink/thread.h\"\n#include \"blink/vfs.h\"\n#include \"blink/xlat.h\"\n\nint SysPipe2(struct Machine *m, i64 pipefds_addr, i32 flags) {\n  int rc;\n  int lim;\n  int fds[2];\n  int oflags;\n  int supported;\n  u8 fds_linux[2][4];\n  supported = O_CLOEXEC_LINUX | O_NDELAY_LINUX;\n  if (flags & ~supported) {\n    LOGF(\"%s() unsupported flags: %d\", \"pipe2\", flags & ~supported);\n    return einval();\n  }\n  if (!IsValidMemory(m, pipefds_addr, sizeof(fds_linux), PROT_WRITE)) {\n    return efault();\n  }\n  if (!(lim = GetFileDescriptorLimit(m->system))) return emfile();\n#ifdef HAVE_PIPE2\n  if ((rc = VfsPipe2(fds, (oflags = XlatOpenFlags(flags)))) != -1) {\n#else\n  if (flags) LOCK(&m->system->exec_lock);\n  if (VfsPipe(fds) != -1) {\n    oflags = 0;\n    if (flags & O_CLOEXEC_LINUX) {\n      oflags |= O_CLOEXEC;\n      unassert(!VfsFcntl(fds[0], F_SETFD, FD_CLOEXEC));\n      unassert(!VfsFcntl(fds[1], F_SETFD, FD_CLOEXEC));\n    }\n    if (flags & O_NDELAY_LINUX) {\n      oflags |= O_NDELAY;\n      unassert(!VfsFcntl(fds[0], F_SETFL, O_NDELAY));\n      unassert(!VfsFcntl(fds[1], F_SETFL, O_NDELAY));\n    }\n#endif\n    if (fds[0] >= lim || fds[1] >= lim) {\n      close(fds[0]);\n      close(fds[1]);\n      rc = emfile();\n    } else {\n      LOCK(&m->system->fds.lock);\n      unassert(AddFd(&m->system->fds, fds[0], O_RDONLY | oflags));\n      unassert(AddFd(&m->system->fds, fds[1], O_WRONLY | oflags));\n      UNLOCK(&m->system->fds.lock);\n      Write32(fds_linux[0], fds[0]);\n      Write32(fds_linux[1], fds[1]);\n      unassert(!CopyToUserWrite(m, pipefds_addr, fds_linux, sizeof(fds_linux)));\n      rc = 0;\n    }\n  } else {\n    rc = -1;\n  }\n#ifndef HAVE_PIPE2\n  if (flags) UNLOCK(&m->system->exec_lock);\n#endif\n  return rc;\n}\n"
  },
  {
    "path": "blink/pml4t.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/pml4t.h\"\n\n#include <stdlib.h>\n\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n#include \"blink/x86.h\"\n\nstatic void AppendContiguousMemoryRange(struct ContiguousMemoryRanges *ranges,\n                                        i64 a, i64 b) {\n  ranges->p = (struct ContiguousMemoryRange *)realloc(\n      ranges->p, ++ranges->i * sizeof(*ranges->p));\n  ranges->p[ranges->i - 1].a = a;\n  ranges->p[ranges->i - 1].b = b;\n}\n\nstatic void FindContiguousMemoryRangesImpl(\n    struct Machine *m, struct ContiguousMemoryRanges *ranges, i64 addr,\n    unsigned level, u64 pt, i64 a, i64 b) {\n  u64 entry;\n  i64 i, page;\n  for (i = a; i < b; ++i) {\n    entry = Load64(GetPageAddress(m->system, pt, level == 39) + i * 8);\n    if (!(entry & PAGE_V)) continue;\n    page = (addr | i << level) << 16 >> 16;\n    if (level == 12) {\n      if (ranges->i && page == ranges->p[ranges->i - 1].b) {\n        ranges->p[ranges->i - 1].b += 4096;\n      } else {\n        AppendContiguousMemoryRange(ranges, page, page + 4096);\n      }\n    } else {\n      FindContiguousMemoryRangesImpl(m, ranges, page, level - 9, entry, 0, 512);\n    }\n  }\n}\n\nint FindContiguousMemoryRanges(struct Machine *m,\n                               struct ContiguousMemoryRanges *ranges) {\n  u64 cr3;\n  ranges->i = 0;\n  if (m->mode.omode == XED_MODE_LONG) {\n    cr3 = m->system->cr3;\n    FindContiguousMemoryRangesImpl(m, ranges, 0, 39, cr3, 256, 512);\n    FindContiguousMemoryRangesImpl(m, ranges, 0, 39, cr3, 0, 256);\n  } else {\n    AppendContiguousMemoryRange(ranges, 0, kRealSize);\n  }\n  return 0;\n}\n"
  },
  {
    "path": "blink/pml4t.h",
    "content": "#ifndef BLINK_PML4T_H_\n#define BLINK_PML4T_H_\n#include \"blink/machine.h\"\n\nstruct ContiguousMemoryRange {\n  i64 a;\n  i64 b;\n};\n\nstruct ContiguousMemoryRanges {\n  unsigned i, n;\n  struct ContiguousMemoryRange *p;\n};\n\nint FindContiguousMemoryRanges(struct Machine *,\n                               struct ContiguousMemoryRanges *);\n\n#endif /* BLINK_PML4T_H_ */\n"
  },
  {
    "path": "blink/pml4tfmt.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <inttypes.h>\n#include <math.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/assert.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/flag.h\"\n#include \"blink/high.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/pml4t.h\"\n#include \"blink/rde.h\"\n#include \"blink/thread.h\"\n#include \"blink/util.h\"\n#include \"blink/x86.h\"\n\n#define INTERESTING_FLAGS (PAGE_U | PAGE_RW | PAGE_XD | PAGE_FILE)\n\n#define BYTES 16384\n#define APPEND(...) \\\n  u->o += snprintf(u->b + u->o, u->o > BYTES ? 0 : BYTES - u->o, __VA_ARGS__)\n\nstruct MapMaker {\n  bool t;\n  int o;\n  int count;\n  int committed;\n  long lines;\n  char *b;\n  i64 start;\n  u64 flags;\n  struct FileMap *fm;\n};\n\nstatic bool IsStackRead(long mop) {\n  switch (mop) {\n    case 0x007:  // OpPopSeg\n    case 0x00F:  // OpPopSeg\n    case 0x017:  // OpPopSeg\n    case 0x01F:  // OpPopSeg\n    case 0x058:  // OpPopZvq\n    case 0x059:  // OpPopZvq\n    case 0x05A:  // OpPopZvq\n    case 0x05B:  // OpPopZvq\n    case 0x05C:  // OpPopZvq\n    case 0x05D:  // OpPopZvq\n    case 0x05E:  // OpPopZvq\n    case 0x05F:  // OpPopZvq\n    case 0x061:  // OpPopa\n    case 0x08F:  // OpPopEvq\n    case 0x09D:  // OpPopf\n    case 0x1A1:  // OpPopSeg\n    case 0x1A9:  // OpPopSeg\n    case 0x0C2:  // OpRetIw\n    case 0x0C3:  // OpRet\n    case 0x0CA:  // OpRetf\n    case 0x0CB:  // OpRetf\n    case 0x0C9:  // OpLeave\n      return true;\n    default:\n      return false;\n  }\n}\n\nstatic bool IsStackWrite(long mop) {\n  switch (mop) {\n    case 0x006:  // OpPushSeg\n    case 0x00E:  // OpPushSeg\n    case 0x016:  // OpPushSeg\n    case 0x01E:  // OpPushSeg\n    case 0x050:  // OpPushZvq\n    case 0x051:  // OpPushZvq\n    case 0x052:  // OpPushZvq\n    case 0x053:  // OpPushZvq\n    case 0x054:  // OpPushZvq\n    case 0x055:  // OpPushZvq\n    case 0x056:  // OpPushZvq\n    case 0x057:  // OpPushZvq\n    case 0x060:  // OpPusha\n    case 0x068:  // OpPushImm\n    case 0x06A:  // OpPushImm\n    case 0x09C:  // OpPushf\n    case 0x1A0:  // OpPushSeg\n    case 0x1A8:  // OpPushSeg\n    case 0x0C9:  // OpLeave\n    case 0x09A:  // OpCallf\n    case 0x0E8:  // OpCallJvds\n      return true;\n    default:\n      return false;\n  }\n}\n\nstatic i64 MakeAddress(u16 a[4]) {\n  u64 x;\n  x = 0;\n  x |= a[0];\n  x <<= 9;\n  x |= a[1];\n  x <<= 9;\n  x |= a[2];\n  x <<= 9;\n  x |= a[3];\n  x <<= 12;\n  return x;\n}\n\nstatic void FormatStartPage(struct Machine *m, struct MapMaker *u, i64 start) {\n  u->t = true;\n  u->start = start;\n  u->count = 0;\n  u->committed = 0;\n  u->fm = GetFileMap(m->system, start);\n}\n\nstatic void FormatEndPage(struct Machine *m, struct MapMaker *u, i64 end) {\n  int i;\n  char size[16];\n  bool isreading, iswriting, isexecuting, isfault;\n  u->t = false;\n  if (u->lines++) APPEND(\"\\n\");\n  isexecuting = m->xedd && MAX(u->start, m->ip) <\n                               MIN(m->ip + Oplength(m->xedd->op.rde), end);\n  isreading =\n      MAX(u->start, m->readaddr) < MIN(m->readaddr + m->readsize, end) ||\n      (m->xedd && IsStackRead(Mopcode(m->xedd->op.rde)) &&\n       MAX(u->start, Read64(m->sp)) < MIN(Read64(m->sp) - 8, end));\n  iswriting =\n      MAX(u->start, m->writeaddr) < MIN(m->writeaddr + m->writesize, end) ||\n      (m->xedd && IsStackWrite(Mopcode(m->xedd->op.rde)) &&\n       MAX(u->start, Read64(m->sp)) < MIN(Read64(m->sp) + 8, end));\n  isfault = MAX(u->start, m->faultaddr) < MIN(m->faultaddr + 1, end);\n  if (g_high.enabled) {\n    if (isexecuting) APPEND(\"\\033[7m\");\n    if (isreading) APPEND(\"\\033[1m\");\n    if (iswriting) APPEND(\"\\033[31m\");\n  }\n  APPEND(\"%012\" PRIx64 \"-%012\" PRIx64, u->start, end - 1);\n  if (g_high.enabled && (isreading || iswriting || isexecuting)) {\n    APPEND(\"\\033[0m\");\n  }\n  FormatSize(size, end - u->start, 1024);\n  APPEND(\"%c%5s \", isfault ? '*' : ' ', size);\n  if (FLAG_nolinear) {\n    APPEND(\"%3d%% \", (int)ceil((double)u->committed / u->count * 100));\n  }\n  i = 0;\n  if (u->flags & PAGE_U) {\n    APPEND(\"r\");\n    ++i;\n  }\n  if (u->flags & PAGE_RW) {\n    APPEND(\"w\");\n    ++i;\n  }\n  if (~u->flags & PAGE_XD) {\n    APPEND(\"x\");\n    ++i;\n  }\n  while (i++ < 4) {\n    APPEND(\" \");\n  }\n  if (u->fm) {\n    APPEND(\"%s\", u->fm->path);\n  }\n}\n\nstatic void FormatPdeOrPte(struct Machine *m, struct MapMaker *u, u64 entry,\n                           u16 a[4], int n) {\n  i64 addr;\n  addr = MakeAddress(a);\n  if (u->t && u->flags != (entry & INTERESTING_FLAGS)) {\n    FormatEndPage(m, u, addr);\n  }\n  if (!u->t) {\n    FormatStartPage(m, u, addr);\n    u->flags = entry & INTERESTING_FLAGS;\n  }\n  u->count += n;\n  if (~entry & PAGE_RSRV) {\n    u->committed += n;\n  }\n}\n\nstatic u8 *GetPt(struct Machine *m, u64 entry, bool is_cr3) {\n  return GetPageAddress(m->system, entry, is_cr3);\n}\n\nchar *FormatPml4t(struct Machine *m) {\n  _Thread_local static char b[BYTES];\n  if (m->metal)\n    // TODO(jart): fix pml4t viz in metal mode\n    return b;\n  u8 *pd[4];\n  u64 entry;\n  u16 i, a[4];\n  struct MapMaker u = {.b = b};\n  u16 range[][2] = {{256, 512}, {0, 256}};\n  b[0] = 0;\n  if (m->mode.omode != XED_MODE_LONG) return b;\n  unassert(m->system->cr3);\n  pd[0] = GetPt(m, m->system->cr3, true);\n  for (i = 0; i < ARRAYLEN(range); ++i) {\n    a[0] = range[i][0];\n    do {\n      a[1] = a[2] = a[3] = 0;\n      entry = LoadPte(pd[0] + a[0] * 8);\n      if (!(entry & PAGE_V)) {\n        if (u.t) FormatEndPage(m, &u, MakeAddress(a));\n      } else if (entry & PAGE_PS) {\n        FormatPdeOrPte(m, &u, entry, a, 1 << 27);\n      } else {\n        pd[1] = GetPt(m, entry, false);\n        do {\n          a[2] = a[3] = 0;\n          entry = LoadPte(pd[1] + a[1] * 8);\n          if (!(entry & PAGE_V)) {\n            if (u.t) FormatEndPage(m, &u, MakeAddress(a));\n          } else if (entry & PAGE_PS) {\n            FormatPdeOrPte(m, &u, entry, a, 1 << 18);\n          } else {\n            pd[2] = GetPt(m, entry, false);\n            do {\n              a[3] = 0;\n              entry = LoadPte(pd[2] + a[2] * 8);\n              if (!(entry & PAGE_V)) {\n                if (u.t) FormatEndPage(m, &u, MakeAddress(a));\n              } else if (entry & PAGE_PS) {\n                FormatPdeOrPte(m, &u, entry, a, 1 << 9);\n              } else {\n                pd[3] = GetPt(m, entry, false);\n                do {\n                  entry = LoadPte(pd[3] + a[3] * 8);\n                  if (~entry & PAGE_V) {\n                    if (u.t) FormatEndPage(m, &u, MakeAddress(a));\n                  } else {\n                    FormatPdeOrPte(m, &u, entry, a, 1);\n                  }\n                } while (++a[3] != 512);\n              }\n            } while (++a[2] != 512);\n          }\n        } while (++a[1] != 512);\n      }\n    } while (++a[0] != range[i][1]);\n  }\n  if (u.t) {\n    FormatEndPage(m, &u, 0x800000000000);\n  }\n  return b;\n}\n"
  },
  {
    "path": "blink/popcount.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/bitscan.h\"\n\nint(popcount)(u64 x) {\n  x = x - ((x >> 1) & 0x5555555555555555);\n  x = ((x >> 2) & 0x3333333333333333) + (x & 0x3333333333333333);\n  x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;\n  x = (x + (x >> 32)) & 0xffffffff;\n  x = x + (x >> 16);\n  x = (x + (x >> 8)) & 0x7f;\n  return x;\n}\n"
  },
  {
    "path": "blink/ppc.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/machine.h\"\n\n// @asyncsignalsafe\nint FixPpcSignal(struct Machine *m, int sig, siginfo_t *si) {\n  u64 pte;\n  // let's help qemu-ppc64le pass readonly_test\n  if (HasLinearMapping() && sig == SIGSEGV && si->si_code == SEGV_MAPERR) {\n    ConvertHostToGuestAddress(m->system, si->si_addr, &pte);\n    if ((pte & PAGE_V) &&\n        ((pte & (PAGE_U | PAGE_RW)) != (PAGE_U | PAGE_RW) ||\n         (pte & (PAGE_U | PAGE_RW | PAGE_XD)) == (PAGE_U | PAGE_RW))) {\n      si->si_code = SEGV_ACCERR;\n    }\n  }\n  return sig;\n}\n"
  },
  {
    "path": "blink/preadv.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/preadv.h\"\n\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"blink/errno.h\"\n#include \"blink/iovs.h\"\n#include \"blink/limits.h\"\n#include \"blink/macros.h\"\n\n// preadv() and pwritev() need MacOS 11+ c. 2020\n\nssize_t preadv_(int fd, const struct iovec *iov, int iovcnt, off_t offset) {\n  int i;\n  char *p;\n  ssize_t rc;\n  size_t j, n, m, t;\n  if (offset < 0 || iovcnt <= 0 || iovcnt > GetIovMax()) {\n    return einval();\n  }\n  for (n = 0, i = 0; i < iovcnt; ++i) {\n    t = n + iov[i].iov_len;\n    if (t < n || n > NUMERIC_MAX(ssize_t)) {\n      return einval();\n    }\n    n = t;\n  }\n  if (!(p = (char *)malloc(n))) {\n    return enomem();\n  }\n  if ((rc = pread(fd, p, n, offset)) != -1) {\n    for (j = 0, i = 0; i < iovcnt && j < rc; ++i, j += m) {\n      m = MIN(iov[i].iov_len, rc - j);\n      memcpy(iov[i].iov_base, p + j, m);\n    }\n  }\n  free(p);\n  return rc;\n}\n\nssize_t pwritev_(int fd, const struct iovec *iov, int iovcnt, off_t offset) {\n  int i;\n  char *p;\n  ssize_t rc;\n  size_t j, n, m, t;\n  if (offset < 0 || iovcnt <= 0 || iovcnt > GetIovMax()) {\n    return einval();\n  }\n  for (n = 0, i = 0; i < iovcnt; ++i) {\n    t = n + iov[i].iov_len;\n    if (t < n || n > NUMERIC_MAX(ssize_t)) {\n      return einval();\n    }\n    n = t;\n  }\n  if (!(p = (char *)malloc(n))) {\n    return enomem();\n  }\n  for (j = 0, i = 0; i < iovcnt && j < n; ++i, j += m) {\n    m = MIN(iov[i].iov_len, n - j);\n    memcpy(p + j, iov[i].iov_base, m);\n  }\n  rc = pwrite(fd, p, n, offset);\n  free(p);\n  return rc;\n}\n"
  },
  {
    "path": "blink/preadv.h",
    "content": "#ifndef BLINK_PREADV_H_\n#define BLINK_PREADV_H_\n#include <sys/types.h>\n#include <sys/uio.h>\n\n#include \"blink/builtin.h\"\n\nssize_t preadv_(int, const struct iovec *, int, off_t);\nssize_t pwritev_(int, const struct iovec *, int, off_t);\n\n#ifndef HAVE_PREADV\n#ifdef preadv\n#undef preadv\n#endif\n#ifdef pwritev\n#undef pwritev\n#endif\n#define preadv  preadv_\n#define pwritev pwritev_\n#endif\n\n#endif /* BLINK_PREADV_H_ */\n"
  },
  {
    "path": "blink/procfs.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Trung Nguyen                                                  │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/procfs.h\"\n\n#include <fcntl.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/atomic.h\"\n#include \"blink/errno.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/timespec.h\"\n#include \"blink/vfs.h\"\n\n#ifdef __EMSCRIPTEN__\n#include <emscripten.h>\n#endif\n\n#ifdef __CYGWIN__\n#include <windows.h>\n#include <winternl.h>\n#endif\n\n#if defined(__APPLE__) || defined(__NetBSD__)\n#define st_atim st_atimespec\n#define st_ctim st_ctimespec\n#define st_mtim st_mtimespec\n#endif\n\n#ifndef DISABLE_VFS\n\n#define PROCFS_NAME_MAX 16\n#define PROCFS_READ_LEN 4096\n#define PROCFS_DELETED  \" (deleted)\"\n\nstruct ProcfsInfo {\n  u64 ino;\n  u32 mode;\n  u32 uid;\n  u32 gid;\n  u32 type;\n  char name[PROCFS_NAME_MAX];\n  struct timespec time;\n  union {\n    _Atomic(struct ProcfsOpenFile *) openfile;\n    _Atomic(struct ProcfsOpenDir *) opendir;\n  };\n  union {\n    int (*readdir)(struct VfsInfo *, struct dirent *);\n    ssize_t (*readlink)(struct VfsInfo *, char **);\n    int (*read)(struct VfsInfo *, struct ProcfsOpenFile *);\n  };\n};\n\nstruct ProcfsOpenFile {\n  pthread_mutex_t_ lock;\n  size_t index;\n  off_t offset;\n  int openflags;\n  size_t readbufstart;\n  size_t readbufend;\n  char readbuf[PROCFS_READ_LEN];\n};\n\nstruct ProcfsOpenDir {\n  pthread_mutex_t_ lock;\n  size_t index;\n};\n\nstruct ProcfsDevice {\n  struct timespec mounttime;\n};\n\nenum {\n  PROCFS_NULL_INO,\n  PROCFS_ROOT_INO,\n  PROCFS_FILESYSTEMS_INO,\n  PROCFS_MEMINFO_INO,\n  PROCFS_MOUNTS_INO,\n  PROCFS_SELF_INO,\n  PROCFS_SYS_INO,\n  PROCFS_UPTIME_INO,\n\n  PROCFS_FIRST_PID_INO\n};\n\nenum {\n  PROCFS_ROOT_TYPE,\n  PROCFS_MEMINFO_TYPE,\n  PROCFS_FILESYSTEMS_TYPE,\n  PROCFS_MOUNTS_TYPE,\n  PROCFS_SELF_TYPE,\n  PROCFS_SYS_TYPE,\n  PROCFS_UPTIME_TYPE,\n\n  PROCFS_PIDDIR_TYPE,\n  PROCFS_PIDDIR_EXE_TYPE,\n  PROCFS_PIDDIR_CWD_TYPE,\n  PROCFS_PIDDIR_ROOT_TYPE,\n  PROCFS_PIDDIR_MOUNTS_TYPE,\n  PROCFS_PIDDIR_FDDIR_TYPE,\n  PROCFS_PIDDIR_LAST_TYPE = PROCFS_PIDDIR_FDDIR_TYPE\n};\n\nstatic int ProcfsRootReaddir(struct VfsInfo *, struct dirent *);\nstatic ssize_t ProcfsSelfReadlink(struct VfsInfo *, char **);\nstatic ssize_t ProcfsToSelfReadlink(struct VfsInfo *, char **);\nstatic int ProcfsMeminfoRead(struct VfsInfo *, struct ProcfsOpenFile *);\nstatic int ProcfsUptimeRead(struct VfsInfo *, struct ProcfsOpenFile *);\nstatic int ProcfsFilesystemsRead(struct VfsInfo *, struct ProcfsOpenFile *);\n\nstatic int ProcfsPiddirReaddir(struct VfsInfo *, struct dirent *);\nstatic ssize_t ProcfsPiddirExeReadlink(struct VfsInfo *, char **);\nstatic ssize_t ProcfsPiddirCwdReadlink(struct VfsInfo *, char **);\nstatic ssize_t ProcfsPiddirRootReadlink(struct VfsInfo *, char **);\nstatic int ProcfsPiddirMountsRead(struct VfsInfo *, struct ProcfsOpenFile *);\n\nstatic struct ProcfsInfo g_defaultinfos[] = {\n    [PROCFS_ROOT_INO] = {PROCFS_ROOT_INO, S_IFDIR | 0555, 0, 0,\n                         PROCFS_ROOT_TYPE, \"\", .readdir = ProcfsRootReaddir},\n    [PROCFS_FILESYSTEMS_INO] = {PROCFS_FILESYSTEMS_INO, S_IFREG | 0444, 0, 0,\n                                PROCFS_FILESYSTEMS_TYPE, \"filesystems\",\n                                .read = ProcfsFilesystemsRead},\n    [PROCFS_MEMINFO_INO] = {PROCFS_MEMINFO_INO, S_IFREG | 0444, 0, 0,\n                            PROCFS_MEMINFO_TYPE, \"meminfo\",\n                            .read = ProcfsMeminfoRead},\n    [PROCFS_MOUNTS_INO] = {PROCFS_MOUNTS_INO, S_IFLNK | 0777, 0, 0,\n                           PROCFS_MOUNTS_TYPE, \"mounts\",\n                           .readlink = ProcfsToSelfReadlink},\n    [PROCFS_SELF_INO] = {PROCFS_SELF_INO, S_IFLNK | 0777, 0, 0,\n                         PROCFS_SELF_TYPE, \"self\",\n                         .readlink = ProcfsSelfReadlink},\n    [PROCFS_SYS_INO] = {PROCFS_SYS_INO, S_IFDIR | 0555, 0, 0, PROCFS_SYS_TYPE,\n                        \"sys\"},\n    [PROCFS_UPTIME_INO] = {PROCFS_UPTIME_INO, S_IFREG | 0444, 0, 0,\n                           PROCFS_UPTIME_TYPE, \"uptime\",\n                           .read = ProcfsUptimeRead},\n};\n\nstatic struct ProcfsInfo g_piddirinfos[] = {\n    [PROCFS_PIDDIR_TYPE -\n     PROCFS_PIDDIR_TYPE] = {0, S_IFDIR | 0555, 0, 0, PROCFS_PIDDIR_TYPE, \"\",\n                            .readdir = ProcfsPiddirReaddir},\n    [PROCFS_PIDDIR_EXE_TYPE -\n        PROCFS_PIDDIR_TYPE] = {0, S_IFLNK | 0777, 0, 0, PROCFS_PIDDIR_EXE_TYPE,\n                               \"exe\", .readlink = ProcfsPiddirExeReadlink},\n    [PROCFS_PIDDIR_CWD_TYPE -\n        PROCFS_PIDDIR_TYPE] = {0, S_IFLNK | 0777, 0, 0, PROCFS_PIDDIR_CWD_TYPE,\n                               \"cwd\", .readlink = ProcfsPiddirCwdReadlink},\n    [PROCFS_PIDDIR_ROOT_TYPE -\n        PROCFS_PIDDIR_TYPE] = {0, S_IFLNK | 0777, 0, 0, PROCFS_PIDDIR_ROOT_TYPE,\n                               \"root\", .readlink = ProcfsPiddirRootReadlink},\n    [PROCFS_PIDDIR_MOUNTS_TYPE -\n        PROCFS_PIDDIR_TYPE] = {0, S_IFREG | 0444, 0, 0,\n                               PROCFS_PIDDIR_MOUNTS_TYPE, \"mounts\",\n                               .read = ProcfsPiddirMountsRead},\n    [PROCFS_PIDDIR_FDDIR_TYPE - PROCFS_PIDDIR_TYPE] = {0, S_IFDIR | 0555, 0, 0,\n                                                       PROCFS_PIDDIR_FDDIR_TYPE,\n                                                       \"fd\"},\n};\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsCreateInfo(struct ProcfsInfo **info) {\n  *info = malloc(sizeof(struct ProcfsInfo));\n  if (*info == NULL) {\n    return enomem();\n  }\n  (*info)->ino = 0;\n  (*info)->mode = 0;\n  (*info)->type = 0;\n  (*info)->name[0] = '\\0';\n  (*info)->openfile = NULL;\n  return 0;\n}\n\nstatic int ProcfsCreateDefaultInfo(struct ProcfsInfo **info,\n                                   struct ProcfsDevice *device, u64 ino) {\n  *info = malloc(sizeof(struct ProcfsInfo));\n  if (*info == NULL) {\n    return enomem();\n  }\n  **info = g_defaultinfos[ino];\n  (*info)->time = device->mounttime;\n  return 0;\n}\n\nstatic int ProcfsCreatePiddirInfo(struct ProcfsInfo **info,\n                                  struct ProcfsInfo *parent, i32 pid,\n                                  u32 type) {\n  *info = malloc(sizeof(struct ProcfsInfo));\n  if (*info == NULL) {\n    return enomem();\n  }\n  if (parent == NULL) {\n    **info = g_piddirinfos[0];\n    // TODO(trungnt): This should be dynamically allocated when we support\n    // more processes.\n    (*info)->ino = PROCFS_FIRST_PID_INO;\n    sprintf((*info)->name, \"%d\", pid);\n    // TODO(trungnt): On Linux, the UID and GID of these files\n    // are set to the ones of the user who created the process.\n    (*info)->uid = getuid();\n    (*info)->gid = getgid();\n    (*info)->time = GetTime();\n  } else {\n    **info = g_piddirinfos[type - PROCFS_PIDDIR_TYPE];\n    (*info)->ino = parent->ino + (type - PROCFS_PIDDIR_TYPE);\n    (*info)->uid = parent->uid;\n    (*info)->gid = parent->gid;\n    (*info)->time = GetTime();\n  }\n  return 0;\n}\n\nstatic int ProcfsFreeInfo(void *info) {\n  if (info == NULL) {\n    return 0;\n  }\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info;\n  if (S_ISDIR(procinfo->mode)) {\n    free(procinfo->opendir);\n  } else if (S_ISREG(procinfo->mode)) {\n    free(procinfo->openfile);\n  }\n  free(info);\n  return 0;\n}\n\nstatic int ProcfsFreeDevice(void *device) {\n  free(device);\n  return 0;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsInit(const char *source, u64 flags, const void *data,\n                      struct VfsDevice **device, struct VfsMount **mount) {\n  struct ProcfsDevice *procdevice = NULL;\n  struct ProcfsInfo *procinfo = NULL;\n  procdevice = malloc(sizeof(struct ProcfsDevice));\n  if (procdevice == NULL) {\n    return enomem();\n  }\n  procdevice->mounttime = GetTime();\n  *device = NULL;\n  if (VfsCreateDevice(device) == -1) {\n    goto cleananddie;\n  }\n  (*device)->data = procdevice;\n  (*device)->ops = &g_procfs.ops;\n  *mount = malloc(sizeof(struct VfsMount));\n  if (*mount == NULL) {\n    goto cleananddie;\n  }\n  if (ProcfsCreateDefaultInfo(&procinfo, procdevice, PROCFS_ROOT_INO) == -1) {\n    goto cleananddie;\n  }\n  if (VfsCreateInfo(&(*mount)->root) == -1) {\n    goto cleananddie;\n  }\n  unassert(!VfsAcquireDevice(*device, &(*mount)->root->device));\n  (*mount)->root->data = procinfo;\n  (*mount)->root->mode = S_IFDIR;\n  (*mount)->root->ino = 1;\n  // Weak reference.\n  (*device)->root = (*mount)->root;\n  VFS_LOGF(\"Mounted a procfs device\");\n  return 0;\ncleananddie:\n  if (*device) {\n    unassert(!VfsFreeDevice(*device));\n  } else {\n    free(procdevice);\n  }\n  if (*mount) {\n    if ((*mount)->root) {\n      unassert(!VfsFreeInfo((*mount)->root));\n    } else {\n      unassert(!ProcfsFreeInfo(procinfo));\n    }\n    free(*mount);\n  }\n  return -1;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsReadmountentry(struct VfsDevice *device, char **spec,\n                                char **type, char **mntops) {\n  *spec = strdup(\"proc\");\n  if (*spec == NULL) {\n    return enomem();\n  }\n  *type = strdup(\"proc\");\n  if (*type == NULL) {\n    free(*spec);\n    return enomem();\n  }\n  *mntops = NULL;\n  return 0;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsFinddir(struct VfsInfo *parent, const char *name,\n                         struct VfsInfo **output) {\n  struct ProcfsInfo *procparent = (struct ProcfsInfo *)parent->data;\n  struct ProcfsInfo *procoutput = NULL;\n  int i, pid;\n  VFS_LOGF(\"ProcfsFinddir(parent=%p (%s), name=\\\"%s\\\", output=%p)\", parent,\n           parent->name, name, output);\n  if (strcmp(name, \".\") == 0) {\n    unassert(!VfsAcquireInfo(parent, output));\n    return 0;\n  }\n  *output = NULL;\n  switch (procparent->type) {\n    case PROCFS_ROOT_TYPE:\n      for (i = PROCFS_ROOT_INO + 1; i < PROCFS_FIRST_PID_INO; ++i) {\n        if (!strcmp(name, g_defaultinfos[i].name)) {\n          if (ProcfsCreateDefaultInfo(\n                  &procoutput, (struct ProcfsDevice *)parent->device->data,\n                  i) == -1) {\n            goto cleananddie;\n          }\n          break;\n        }\n      }\n      if (procoutput == NULL) {\n        pid = -1;\n        sscanf(name, \"%d\", &pid);\n        if (pid == getpid()) {\n          if (ProcfsCreatePiddirInfo(&procoutput, NULL, pid,\n                                     PROCFS_PIDDIR_ROOT_TYPE) == -1) {\n            goto cleananddie;\n          }\n        }\n      }\n      // TODO(trungnt): PID-specific directories of other processes.\n      break;\n    case PROCFS_PIDDIR_TYPE:\n      for (i = 1; i <= PROCFS_PIDDIR_LAST_TYPE - PROCFS_PIDDIR_TYPE; ++i) {\n        if (!strcmp(name, g_piddirinfos[i].name)) {\n          if (ProcfsCreatePiddirInfo(&procoutput, procparent, -1,\n                                     i + PROCFS_PIDDIR_TYPE) == -1) {\n            goto cleananddie;\n          }\n          break;\n        }\n      }\n      break;\n  }\n  if (procoutput == NULL) {\n    enoent();\n    goto cleananddie;\n  }\n  if (VfsCreateInfo(output) == -1) {\n    goto cleananddie;\n  }\n  (*output)->data = procoutput;\n  (*output)->ino = procoutput->ino;\n  (*output)->mode = procoutput->mode;\n  unassert(!VfsAcquireDevice(parent->device, &(*output)->device));\n  unassert(!VfsAcquireInfo(parent, &(*output)->parent));\n  (*output)->name = strdup(procoutput->name);\n  if ((*output)->name == NULL) {\n    goto cleananddie;\n  }\n  (*output)->namelen = strlen((*output)->name);\n  return 0;\ncleananddie:\n  if (*output) {\n    unassert(!VfsFreeInfo(*output));\n  } else {\n    unassert(!ProcfsFreeInfo(procoutput));\n  }\n  return -1;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic ssize_t ProcfsReadlink(struct VfsInfo *info, char **output) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  VFS_LOGF(\"ProcfsReadlink(info=%p (%s), output=%p)\", info, info->name, output);\n  if (!S_ISLNK(procinfo->mode)) {\n    return einval();\n  }\n  if (!procinfo->readlink) {\n    return eperm();\n  }\n  return procinfo->readlink(info, output);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsAccessImpl(struct ProcfsInfo *procinfo, mode_t mode) {\n  uid_t uid;\n  gid_t gid;\n  int ret = 0;\n  if (procinfo->ino < PROCFS_FIRST_PID_INO) {\n    // Get fresher info as some files might have been chmod/chown'ed.\n    procinfo = &g_defaultinfos[procinfo->ino];\n  }\n  if (mode != F_OK) {\n    uid = getuid();\n    // This implementation is incomplete as a user can be in multiple groups.\n    gid = getgid();\n    if (mode & R_OK) {\n      if (uid == 0) {\n        if (!(procinfo->mode & (S_IRUSR | S_IRGRP | S_IROTH))) {\n          ret = eacces();\n        }\n      } else if (uid == procinfo->uid) {\n        if (!(procinfo->mode & S_IRUSR)) {\n          ret = eacces();\n        }\n      } else if (gid == procinfo->gid) {\n        if (!(procinfo->mode & S_IRGRP)) {\n          ret = eacces();\n        }\n      } else if (!(procinfo->mode & S_IROTH)) {\n        ret = eacces();\n      }\n    }\n    if (mode & W_OK) {\n      if (uid == 0) {\n        if (!(procinfo->mode & (S_IWUSR | S_IWGRP | S_IWOTH))) {\n          ret = eacces();\n        }\n      } else if (uid == procinfo->uid) {\n        if (!(procinfo->mode & S_IWUSR)) {\n          ret = eacces();\n        }\n      } else if (gid == procinfo->gid) {\n        if (!(procinfo->mode & S_IWGRP)) {\n          ret = eacces();\n        }\n      } else if (!(procinfo->mode & S_IWOTH)) {\n        ret = eacces();\n      }\n    }\n    if (mode & X_OK) {\n      if (uid == 0) {\n        if (!(procinfo->mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {\n          ret = eacces();\n        }\n      } else if (uid == procinfo->uid) {\n        if (!(procinfo->mode & S_IXUSR)) {\n          ret = eacces();\n        }\n      } else if (gid == procinfo->gid) {\n        if (!(procinfo->mode & S_IXGRP)) {\n          ret = eacces();\n        }\n      } else if (!(procinfo->mode & S_IXOTH)) {\n        ret = eacces();\n      }\n    }\n  }\n  return ret;\n}\n\nstatic int ProcfsAccess(struct VfsInfo *parent, const char *name, mode_t mode,\n                        int flags) {\n  struct VfsInfo *info = NULL;\n  struct ProcfsInfo *procinfo;\n  int ret = 0;\n  if (ProcfsFinddir(parent, name, &info) == -1) {\n    return -1;\n  }\n  procinfo = (struct ProcfsInfo *)info->data;\n  ret = ProcfsAccessImpl(procinfo, mode);\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsOpen(struct VfsInfo *parent, const char *name, int flags,\n                      int mode, struct VfsInfo **output) {\n  struct ProcfsInfo *procoutput = NULL;\n  if (ProcfsFinddir(parent, name, output) == -1) {\n    return -1;\n  }\n  procoutput = (struct ProcfsInfo *)(*output)->data;\n  if (S_ISDIR(procoutput->mode)) {\n    procoutput->opendir = malloc(sizeof(struct ProcfsOpenDir));\n    if (procoutput->opendir == NULL) {\n      enomem();\n      goto cleananddie;\n    }\n    procoutput->opendir->index = 0;\n    unassert(!pthread_mutex_init(&procoutput->opendir->lock, NULL));\n  } else if (S_ISREG(procoutput->mode)) {\n    if (flags & O_RDWR || flags & O_RDONLY) {\n      if (ProcfsAccessImpl(procoutput, R_OK) == -1) {\n        goto cleananddie;\n      }\n    }\n    if (flags & O_RDWR || flags & O_WRONLY) {\n      if (ProcfsAccessImpl(procoutput, W_OK) == -1) {\n        goto cleananddie;\n      }\n    }\n    procoutput->openfile = malloc(sizeof(struct ProcfsOpenFile));\n    if (procoutput->openfile == NULL) {\n      enomem();\n      goto cleananddie;\n    }\n    procoutput->openfile->offset = 0;\n    procoutput->openfile->index = 0;\n    procoutput->openfile->openflags = flags;\n    procoutput->openfile->readbufstart = procoutput->openfile->readbufend = 0;\n    unassert(!pthread_mutex_init(&procoutput->openfile->lock, NULL));\n  } else {\n    einval();\n    goto cleananddie;\n  }\n  return 0;\ncleananddie:\n  if (procoutput) {\n    if (S_ISDIR(procoutput->mode)) {\n      free(procoutput->opendir);\n      procoutput->opendir = NULL;\n    } else if (S_ISREG(procoutput->mode)) {\n      free(procoutput->openfile);\n      procoutput->openfile = NULL;\n    }\n  }\n  unassert(!VfsFreeInfo(*output));\n  return -1;\n}\n\nstatic int ProcfsClose(struct VfsInfo *info) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  void *opendata;\n  if (S_ISDIR(procinfo->mode)) {\n    opendata = atomic_exchange(&procinfo->opendir, NULL);\n  } else if (S_ISREG(procinfo->mode)) {\n    opendata = atomic_exchange(&procinfo->openfile, NULL);\n  } else {\n    return 0;\n  }\n  LOCK((pthread_mutex_t_ *)opendata);\n  UNLOCK((pthread_mutex_t_ *)opendata);\n  unassert(!pthread_mutex_destroy((pthread_mutex_t_ *)opendata));\n  free(opendata);\n  return 0;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsStatImpl(struct VfsDevice *device, struct ProcfsInfo *info,\n                          struct stat *st) {\n  st->st_dev = device->dev;\n  st->st_ino = info->ino;\n  st->st_mode = info->mode;\n  st->st_nlink = 1;\n  if (info->ino < PROCFS_FIRST_PID_INO) {\n    st->st_uid = g_defaultinfos[info->type].uid;\n    st->st_gid = g_defaultinfos[info->type].gid;\n  } else {\n    st->st_uid = info->uid;\n    st->st_gid = info->gid;\n  }\n  st->st_uid = info->uid;\n  st->st_gid = info->gid;\n  st->st_rdev = 0;\n  st->st_size = 0;\n  st->st_blksize = PROCFS_READ_LEN;\n  st->st_blocks = 0;\n  st->st_atim = st->st_mtim = st->st_ctim = info->time;\n  return 0;\n}\n\nstatic int ProcfsStat(struct VfsInfo *parent, const char *name, struct stat *st,\n                      int flags) {\n  struct VfsInfo *info;\n  int ret;\n  if (ProcfsFinddir(parent, name, &info) == -1) {\n    return -1;\n  }\n  ret = ProcfsStatImpl(parent->device, (struct ProcfsInfo *)info->data, st);\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nstatic int ProcfsFstat(struct VfsInfo *parent, struct stat *st) {\n  return ProcfsStatImpl(parent->device, (struct ProcfsInfo *)parent->data, st);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\n// On Linux, it is actually possible to chmod/chown some files in procfs.\n// It is NOT possible to do so for files in pid-specific directories.\n// We try to emulate it here, but this emulation suffers from the same\n// limitations as the mount tables at the time of writing: It does not\n// propagate to sibling and parent processes.\n\nstatic int ProcfsFchmod(struct VfsInfo *info, mode_t mode) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  if (procinfo->ino >= PROCFS_FIRST_PID_INO) {\n    return eperm();\n  } else {\n    procinfo->mode = (procinfo->mode & ~07777) | (mode & 07777);\n    g_defaultinfos[procinfo->type].mode = procinfo->mode;\n    return 0;\n  }\n}\n\nstatic int ProcfsChmod(struct VfsInfo *parent, const char *name, mode_t mode,\n                       int flags) {\n  struct VfsInfo *info;\n  int ret;\n  // When we reach here all necessary symlink dereferences have already been\n  // conducted.\n  if (ProcfsFinddir(parent, name, &info) == -1) {\n    return -1;\n  }\n  ret = ProcfsFchmod(info, mode);\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nstatic int ProcfsFchown(struct VfsInfo *info, uid_t uid, gid_t gid) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  if (procinfo->ino >= PROCFS_FIRST_PID_INO) {\n    return eperm();\n  } else {\n    if (uid != -1) {\n      procinfo->uid = uid;\n      g_defaultinfos[procinfo->type].uid = uid;\n    }\n    if (gid != -1) {\n      procinfo->gid = gid;\n      g_defaultinfos[procinfo->type].gid = gid;\n    }\n    return 0;\n  }\n}\n\nstatic int ProcfsChown(struct VfsInfo *parent, const char *name, uid_t uid,\n                       gid_t gid, int flags) {\n  struct VfsInfo *info;\n  int ret;\n  if (ProcfsFinddir(parent, name, &info) == -1) {\n    return -1;\n  }\n  ret = ProcfsFchown(info, uid, gid);\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic ssize_t ProcfsReadImpl(struct VfsInfo *info, void *buf, size_t len,\n                              off_t off, bool copy) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  struct ProcfsOpenFile tmpopenfile = *(procinfo->openfile);\n  ssize_t ret = 0;\n  size_t bytestoread = 0;\n  if (off != -1) {\n    tmpopenfile.readbufstart = tmpopenfile.readbufend = 0;\n    tmpopenfile.index = 0;\n    tmpopenfile.offset = 0;\n  }\n  while ((off > 0 || len > 0) &&\n         tmpopenfile.readbufend <= sizeof(tmpopenfile.readbuf)) {\n    // All bytes from the buffer has been consumed.\n    if (tmpopenfile.readbufstart == tmpopenfile.readbufend) {\n      if (!procinfo->read) {\n        ret = eperm();\n        break;\n      }\n      if (procinfo->read(info, &tmpopenfile) == -1) {\n        ret = -1;\n        break;\n      }\n    }\n    if (off > 0) {\n      bytestoread = MIN(off, tmpopenfile.readbufend - tmpopenfile.readbufstart);\n      tmpopenfile.readbufstart += bytestoread;\n      tmpopenfile.offset += bytestoread;\n      off -= bytestoread;\n    } else {\n      bytestoread = MIN(len, tmpopenfile.readbufend - tmpopenfile.readbufstart);\n      memcpy(buf, tmpopenfile.readbuf + tmpopenfile.readbufstart, bytestoread);\n      tmpopenfile.readbufstart += bytestoread;\n      tmpopenfile.offset += bytestoread;\n      buf = (void *)((char *)buf + bytestoread);\n      len -= bytestoread;\n      ret += bytestoread;\n    }\n  }\n  if (copy || (off == -1 && ret != -1)) {\n    *(procinfo->openfile) = tmpopenfile;\n  }\n  return ret;\n}\n\nstatic ssize_t ProcfsPreadv(struct VfsInfo *info, const struct iovec *iov,\n                            int iovcnt, off_t off) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  size_t len = 0;\n  ssize_t ret;\n  if (!S_ISREG(procinfo->mode) || procinfo->openfile == NULL) {\n    return einval();\n  }\n  if (off < 0) return einval();\n  LOCK(&procinfo->openfile->lock);\n  for (int i = 0; i < iovcnt; ++i) {\n    len += iov[i].iov_len;\n    if (len > SSIZE_MAX) return einval();\n  }\n  len = 0;\n  for (int i = 0; i < iovcnt; ++i) {\n    ret = ProcfsReadImpl(info, iov[i].iov_base, iov[i].iov_len, off, false);\n    if (ret == -1) {\n      if (len == 0) len = -1;\n      break;\n    }\n    len += ret;\n    off += ret;\n    procinfo->openfile->offset += ret;\n    if (ret < iov[i].iov_len) {\n      break;\n    }\n  }\n  UNLOCK(&procinfo->openfile->lock);\n  return len;\n}\n\nstatic ssize_t ProcfsReadv(struct VfsInfo *info, const struct iovec *iov,\n                           int iovcnt) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  size_t len = 0;\n  ssize_t ret;\n  if (!S_ISREG(procinfo->mode) || procinfo->openfile == NULL) {\n    return einval();\n  }\n  LOCK(&procinfo->openfile->lock);\n  for (int i = 0; i < iovcnt; ++i) {\n    len += iov[i].iov_len;\n    if (len > SSIZE_MAX) return einval();\n  }\n  len = 0;\n  for (int i = 0; i < iovcnt; ++i) {\n    ret = ProcfsReadImpl(info, iov[i].iov_base, iov[i].iov_len, -1, false);\n    if (ret == -1) {\n      if (len == 0) len = -1;\n      break;\n    }\n    len += ret;\n    if (ret < iov[i].iov_len) {\n      break;\n    }\n  }\n  UNLOCK(&procinfo->openfile->lock);\n  return len;\n}\n\nstatic ssize_t ProcfsPread(struct VfsInfo *info, void *buf, size_t len,\n                           off_t off) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  ssize_t ret;\n  if (!S_ISREG(procinfo->mode) || procinfo->openfile == NULL) {\n    return einval();\n  }\n  if (off < 0) return einval();\n  LOCK(&procinfo->openfile->lock);\n  ret = ProcfsReadImpl(info, buf, len, off, false);\n  UNLOCK(&procinfo->openfile->lock);\n  return ret;\n}\n\nstatic ssize_t ProcfsRead(struct VfsInfo *info, void *buf, size_t len) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  ssize_t ret;\n  if (!S_ISREG(procinfo->mode) || procinfo->openfile == NULL) {\n    return einval();\n  }\n  LOCK(&procinfo->openfile->lock);\n  ret = ProcfsReadImpl(info, buf, len, -1, false);\n  UNLOCK(&procinfo->openfile->lock);\n  return ret;\n}\n\nstatic ssize_t ProcfsWrite(struct VfsInfo *, const void *, size_t);\nstatic ssize_t ProcfsPwrite(struct VfsInfo *, const void *, size_t, off_t);\nstatic ssize_t ProcfsWritev(struct VfsInfo *, const struct iovec *, int);\nstatic ssize_t ProcfsPwritev(struct VfsInfo *, const struct iovec *, int,\n                             off_t);\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic off_t ProcfsSeekImpl(struct VfsInfo *info, off_t off, int whence) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  off_t newoff = 0;\n  if (S_ISDIR(procinfo->mode)) {\n    if (procinfo->opendir == NULL) {\n      return einval();\n    }\n    switch (whence) {\n      case SEEK_SET:\n        if (off < 0) return einval();\n        procinfo->opendir->index = off;\n        break;\n      case SEEK_CUR:\n        if (off < 0 && -off > procinfo->opendir->index) return einval();\n        procinfo->opendir->index += off;\n        break;\n      case SEEK_END:\n        return einval();\n    }\n    return procinfo->opendir->index;\n  } else if (S_ISREG(procinfo->mode)) {\n    if (procinfo->openfile == NULL) {\n      return einval();\n    }\n    switch (whence) {\n      case SEEK_SET:\n        newoff = off;\n        break;\n      case SEEK_CUR:\n        newoff = procinfo->openfile->offset + off;\n        break;\n      case SEEK_END:\n        return einval();\n    }\n    if (newoff < 0) {\n      return einval();\n    }\n    if (procinfo->openfile->readbufend <= sizeof(procinfo->openfile->readbuf) &&\n        procinfo->openfile->offset / PROCFS_READ_LEN ==\n            newoff / PROCFS_READ_LEN) {\n      // We're still in the cached region.\n      procinfo->openfile->readbufstart += newoff - procinfo->openfile->offset;\n      procinfo->openfile->offset = newoff;\n    } else {\n      if ((procinfo->openfile->offset / PROCFS_READ_LEN >\n           newoff / PROCFS_READ_LEN) ||\n          (procinfo->openfile->readbufend >\n           sizeof(procinfo->openfile->readbuf))) {\n        // Reset the file if it has already ended or we're going back before the\n        // buffer.\n        procinfo->openfile->index = 0;\n        procinfo->openfile->offset = 0;\n        procinfo->openfile->readbufstart = procinfo->openfile->readbufend = 0;\n      }\n      ProcfsReadImpl(info, NULL, 0, newoff - procinfo->openfile->offset, true);\n      procinfo->openfile->offset = newoff;\n    }\n    return procinfo->openfile->offset;\n  } else {\n    return einval();\n  }\n  return einval();\n}\n\nstatic off_t ProcfsSeek(struct VfsInfo *info, off_t off, int whence) {\n  off_t ret;\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  LOCK(&procinfo->openfile->lock);\n  ret = ProcfsSeekImpl(info, off, whence);\n  UNLOCK(&procinfo->openfile->lock);\n  return ret;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsDup(struct VfsInfo *info, struct VfsInfo **newinfo) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data, *newprocinfo;\n  u32 openflags = 0;\n  *newinfo = NULL;\n  if (S_ISREG(info->mode)) {\n    openflags = procinfo->openfile->openflags & ~(O_CREAT | O_EXCL | O_TRUNC);\n  } else if (S_ISDIR(info->mode)) {\n    openflags = O_DIRECTORY;\n  } else {\n    return einval();\n  }\n  if (ProcfsOpen(info->parent, info->name, openflags, 0, newinfo) == -1) {\n    return -1;\n  }\n  newprocinfo = (struct ProcfsInfo *)(*newinfo)->data;\n  if (S_ISDIR(info->mode)) {\n    memcpy(newprocinfo->opendir, procinfo->opendir,\n           sizeof(*newprocinfo->opendir));\n  } else if (S_ISREG(info->mode)) {\n    memcpy(newprocinfo->openfile, procinfo->openfile,\n           sizeof(*newprocinfo->openfile));\n  }\n  unassert(!pthread_mutex_init((pthread_mutex_t *)newprocinfo->openfile, NULL));\n  return 0;\n}\n\n#ifdef HAVE_DUP3\nstatic int ProcfsDup3(struct VfsInfo *info, struct VfsInfo **newinfo, int wut) {\n  // O_CLOEXEC is already handled by the syscall layer.\n  return ProcfsDup(info, newinfo);\n}\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsOpendir(struct VfsInfo *info, struct VfsInfo **output) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  if (!S_ISDIR(procinfo->mode) && !procinfo->opendir) {\n    return einval();\n  }\n  unassert(!VfsAcquireInfo(info, output));\n  return 0;\n}\n\nstatic void ProcfsSeekdir(struct VfsInfo *info, long offset) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  if (!S_ISDIR(procinfo->mode) && !procinfo->opendir) {\n    einval();\n    return;\n  }\n  procinfo->opendir->index = offset;\n}\n\n#ifdef HAVE_SEEKDIR\nstatic long ProcfsTelldir(struct VfsInfo *info) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  if (!S_ISDIR(procinfo->mode) && !procinfo->opendir) {\n    return einval();\n  }\n  return procinfo->opendir->index;\n}\n#endif\n\nstatic struct dirent *ProcfsReaddir(struct VfsInfo *info) {\n  static _Thread_local char buf[sizeof(struct dirent) + VFS_NAME_MAX];\n  struct dirent *de = (struct dirent *)buf;\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  if (!S_ISDIR(procinfo->mode) && !procinfo->opendir) {\n    einval();\n    return NULL;\n  }\n  if (procinfo->readdir) {\n    if (procinfo->readdir(info, de) == -1) {\n      return NULL;\n    }\n    return de;\n  }\n  return NULL;\n}\n\nstatic void ProcfsRewinddir(struct VfsInfo *info) {\n  ProcfsSeekdir(info, 0);\n}\n\nstatic int ProcfsClosedir(struct VfsInfo *info) {\n  unassert(!VfsFreeInfo(info));\n  return ProcfsClose(info);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsUtime(struct VfsInfo *info, const char *name,\n                       const struct timespec times[2], int flags) {\n  return einval();\n}\n\nstatic int ProcfsFutime(struct VfsInfo *info, const struct timespec times[2]) {\n  return einval();\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct VfsInfo *g_selfexeinfo = NULL;\n\nint ProcfsRegisterExe(i32 pid, const char *path) {\n  struct VfsInfo *newinfo, *tmp;\n  unassert(pid == getpid());\n  unassert(!VfsTraverse(path, &newinfo, true));\n  tmp = g_selfexeinfo;\n  g_selfexeinfo = newinfo;\n  unassert(!VfsFreeInfo(tmp));\n  return 0;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsInfoToDirent(struct ProcfsInfo *info, struct dirent *de) {\n  de->d_ino = info->ino;\n#ifdef DT_UNKNOWN\n  if (S_ISDIR(info->mode)) {\n    de->d_type = DT_DIR;\n  } else if (S_ISREG(info->mode)) {\n    de->d_type = DT_REG;\n  } else if (S_ISLNK(info->mode)) {\n    de->d_type = DT_LNK;\n  } else {\n    de->d_type = DT_UNKNOWN;\n  }\n#endif\n  strcpy(de->d_name, info->name);\n  return 0;\n}\n\nstatic int ProcfsRootReaddir(struct VfsInfo *info, struct dirent *de) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  struct ProcfsOpenDir *dir = procinfo->opendir;\n  int ret = 0;\n  LOCK(&dir->lock);\n  // The index value reserves two numbers for .. and .\n  // The PROCFS_*_INO on the other hand uses the first two numbers\n  // for the NULL node and the ROOT node.\n  if (dir->index == 0) {\n    de->d_ino = info->parent->ino;\n#ifdef DT_DIR\n    de->d_type = DT_DIR;\n#endif\n    strcpy(de->d_name, \"..\");\n    ret = 0;\n  } else if (dir->index == 1) {\n    de->d_ino = info->ino;\n#ifdef DT_DIR\n    de->d_type = DT_DIR;\n#endif\n    strcpy(de->d_name, \".\");\n    ret = 0;\n  } else if (dir->index >= PROCFS_FIRST_PID_INO) {\n    if (dir->index == PROCFS_FIRST_PID_INO) {\n      // In the limited version, there's only one PID visible here.\n      // For the complete implementation, we have to query the PID table.\n      de->d_ino = PROCFS_FIRST_PID_INO;\n#ifdef DT_DIR\n      de->d_type = DT_DIR;\n#endif\n      sprintf(de->d_name, \"%d\", getpid());\n    } else {\n      // TODO(trungnt): PID-specific directories for other processes\n      ret = enoent();\n    }\n  } else {\n    if (ProcfsInfoToDirent(&g_defaultinfos[dir->index], de) == -1) {\n      ret = -1;\n    }\n    ret = 0;\n  }\n  ++dir->index;\n  UNLOCK(&dir->lock);\n  return ret;\n}\n\nstatic int ProcfsPiddirReaddir(struct VfsInfo *info, struct dirent *de) {\n  struct ProcfsInfo *procinfo = (struct ProcfsInfo *)info->data;\n  struct ProcfsOpenDir *dir = procinfo->opendir;\n  int ret = 0;\n  LOCK(&dir->lock);\n  if (dir->index == 0) {\n    de->d_ino = info->parent->ino;\n#ifdef DT_DIR\n    de->d_type = DT_DIR;\n#endif\n    strcpy(de->d_name, \"..\");\n    ret = 0;\n  } else if (dir->index == 1) {\n    de->d_ino = info->ino;\n#ifdef DT_DIR\n    de->d_type = DT_DIR;\n#endif\n    strcpy(de->d_name, \".\");\n    ret = 0;\n  } else if ((dir->index - 1) >\n             (PROCFS_PIDDIR_LAST_TYPE - PROCFS_PIDDIR_TYPE)) {\n    ret = enoent();\n  } else {\n    if (ProcfsInfoToDirent(&g_piddirinfos[dir->index - 1], de) == -1) {\n      ret = -1;\n    }\n    ret = 0;\n  }\n  ++dir->index;\n  UNLOCK(&dir->lock);\n  return ret;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic ssize_t ProcfsSelfReadlink(struct VfsInfo *info, char **buf) {\n  *buf = malloc(16);\n  if (!*buf) {\n    return enomem();\n  }\n  snprintf(*buf, 16, \"%d\", getpid());\n  return strlen(*buf);\n}\n\nstatic ssize_t ProcfsToSelfReadlink(struct VfsInfo *info, char **buf) {\n  size_t len = strlen(info->name) + sizeof(\"self/\");\n  *buf = malloc(len);\n  if (!*buf) {\n    return enomem();\n  }\n  strcpy(*buf, \"self/\");\n  strcpy(*buf + sizeof(\"self/\") - 1, info->name);\n  return len - 1;\n}\n\nstatic ssize_t ProcfsPiddirExeReadlink(struct VfsInfo *info, char **buf) {\n  ssize_t len;\n  char *tmp;\n  struct stat st;\n  VFS_LOGF(\"ProcfsPiddirExeReadlink(%p (%s), %p)\", info, info->name, buf);\n  if ((len = VfsPathBuildFull(g_selfexeinfo, NULL, buf)) == -1) {\n    return -1;\n  }\n  if (VfsStat(AT_FDCWD, *buf, &st, 0) == -1) {\n    len += sizeof(PROCFS_DELETED) - 1;\n    tmp = realloc(*buf, len + 1);\n    if (!tmp) {\n      free(*buf);\n      return enomem();\n    }\n    *buf = tmp;\n    memcpy(*buf + len, PROCFS_DELETED, sizeof(PROCFS_DELETED));\n  }\n  return len;\n}\n\nstatic ssize_t ProcfsPiddirCwdReadlink(struct VfsInfo *info, char **buf) {\n  return VfsPathBuildFull(g_cwdinfo, NULL, buf);\n}\n\nstatic ssize_t ProcfsPiddirRootReadlink(struct VfsInfo *info, char **buf) {\n  return VfsPathBuildFull(g_rootinfo, g_actualrootinfo, buf);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int ProcfsMeminfoRead(struct VfsInfo *info,\n                             struct ProcfsOpenFile *openfile) {\n#ifdef __linux__\n  int fd = open(\"/proc/meminfo\", O_RDONLY);\n  ssize_t bytesread;\n  int ret = 0;\n  if (fd == -1) {\n    return -1;\n  }\n  if ((bytesread = pread(fd, openfile->readbuf, sizeof(openfile->readbuf),\n                         openfile->index)) == -1) {\n    ret = -1;\n  }\n  close(fd);\n  if (ret != -1) {\n    if (bytesread != 0) {\n      openfile->index += bytesread;\n      openfile->readbufstart = 0;\n      openfile->readbufend = bytesread;\n    } else {\n      openfile->readbufstart = sizeof(openfile->readbuf) + 1;\n      openfile->readbufend = sizeof(openfile->readbuf) + 1;\n    }\n  }\n  return ret;\n#else\n  u64 memtotal = 0, memfree = 0;\n  if (openfile->index > 0) {\n    openfile->readbufstart = sizeof(openfile->readbuf) + 1;\n    openfile->readbufend = sizeof(openfile->readbuf) + 1;\n    return 0;\n  }\n#if defined(__CYGWIN__)\n  MEMORYSTATUSEX memstat;\n  memstat.dwLength = sizeof(memstat);\n  if (!GlobalMemoryStatusEx(&memstat)) {\n    return -1;\n  }\n  memtotal = memstat.ullTotalPhys;\n  memfree = memstat.ullAvailPhys;\n#elif defined(__EMSCRIPTEN__)\n  // WASM is 32-bit so on a RAM-efficient browser running on a\n  // device with a lot of RAM, we can reach the 4GB limit.\n  memtotal = 4 * 1024 * 1024;\n  memfree = memtotal - EM_ASM_INT(return HEAP8.length);\n#endif\n  openfile->readbufstart = 0;\n  openfile->readbufend = snprintf(openfile->readbuf, sizeof(openfile->readbuf),\n                                  \"MemTotal: %llu kB\\nMemFree: %llu kB\\n\",\n                                  (unsigned long long)(memtotal / 1024),\n                                  (unsigned long long)(memfree / 1024));\n  openfile->index = 1;\n  return 0;\n#endif\n}\n\nstatic int ProcfsUptimeRead(struct VfsInfo *info,\n                            struct ProcfsOpenFile *openfile) {\n  double uptime = 0, idletime = 0;\n  int ret = 0;\n  if (openfile->index > 0) {\n    openfile->readbufstart = sizeof(openfile->readbuf) + 1;\n    openfile->readbufend = sizeof(openfile->readbuf) + 1;\n    return 0;\n  }\n#ifdef __linux__\n  FILE *fp = fopen(\"/proc/uptime\", \"r\");\n  if (!fp) {\n    return -1;\n  }\n  if (!fp) {\n    return -1;\n  }\n  if (fscanf(fp, \"%lf %lf\", &uptime, &idletime) != 2) {\n    ret = -1;\n  }\n  fclose(fp);\n#elif defined(__CYGWIN__)\n  SYSTEM_PERFORMANCE_INFORMATION spi;\n  SYSTEM_TIMEOFDAY_INFORMATION sti;\n  if (!NT_SUCCESS(NtQuerySystemInformation(SystemPerformanceInformation, &spi,\n                                           sizeof(spi), NULL))) {\n    ret = -1;\n  } else if (!NT_SUCCESS(NtQuerySystemInformation(SystemTimeOfDayInformation,\n                                                  &sti, sizeof(sti), NULL))) {\n    ret = -1;\n  } else {\n    uptime = (sti.CurrentTime.QuadPart - sti.BootTime.QuadPart) / 10000000.0;\n    idletime = spi.IdleTime.QuadPart / 10000000.0;\n  }\n#elif defined(__EMSCRIPTEN__)\n  uptime = EM_ASM_DOUBLE(return performance.now() / 1000);\n#endif\n  if (ret != -1) {\n    openfile->readbufstart = 0;\n    openfile->readbufend =\n        snprintf(openfile->readbuf, sizeof(openfile->readbuf), \"%lf %lf\\n\",\n                 uptime, idletime);\n    openfile->index = 1;\n  }\n  return ret;\n}\n\nstatic int ProcfsFilesystemsRead(struct VfsInfo *info,\n                                 struct ProcfsOpenFile *openfile) {\n  size_t byteswritten = 0;\n  size_t bytesleft = sizeof(openfile->readbuf);\n  size_t ret;\n  struct Dll *e = NULL;\n  int i;\n  if (openfile->readbufend > sizeof(openfile->readbuf)) {\n    return 0;\n  }\n  LOCK(&g_vfs.lock);\n  for (i = 0, e = dll_first(g_vfs.systems); e;\n       e = dll_next(g_vfs.systems, e), ++i) {\n    struct VfsSystem *system = VFS_SYSTEM_CONTAINER(e);\n    if (i < openfile->index) continue;\n    ret = snprintf(openfile->readbuf + byteswritten, bytesleft, \"%-8s%s\\n\",\n                   system->nodev ? \"nodev\" : \"\", system->name);\n    if (ret > bytesleft) {\n      break;\n    }\n    byteswritten += ret;\n    bytesleft -= ret;\n    ++openfile->index;\n  }\n  UNLOCK(&g_vfs.lock);\n  if (e == NULL && byteswritten == 0) {\n    openfile->readbufstart = sizeof(openfile->readbuf) + 1;\n    openfile->readbufend = sizeof(openfile->readbuf) + 1;\n  } else {\n    openfile->readbufstart = 0;\n    openfile->readbufend = byteswritten;\n  }\n  return 0;\n}\n\nstatic int ProcfsMountsStringEscape(char **str) {\n  size_t len, len1;\n  char *tmp;\n  for (len = 0, len1 = 0; (*str)[len]; ++len) {\n    len1 += ((*str)[len] == ' ') || ((*str)[len] == '\\t');\n  }\n  if (len1) {\n    len1 = len + len1 * 3;\n    tmp = realloc((*str), len1 + 1);\n    if (!tmp) {\n      return enomem();\n    }\n    (*str) = tmp;\n    tmp = NULL;\n    (*str)[len1] = '\\0';\n    for (; len > 0; --len) {\n      if ((*str)[len - 1] == ' ') {\n        (*str)[len1 - 1] = '0';\n        (*str)[len1 - 2] = '4';\n        (*str)[len1 - 3] = '0';\n        (*str)[len1 - 4] = '\\\\';\n        len1 -= 4;\n      } else if ((*str)[len - 1] == '\\t') {\n        (*str)[len1 - 1] = '1';\n        (*str)[len1 - 2] = '1';\n        (*str)[len1 - 3] = '0';\n        (*str)[len1 - 4] = '\\\\';\n        len1 -= 4;\n      } else {\n        (*str)[len1 - 1] = (*str)[len - 1];\n        --len1;\n      }\n    }\n  }\n  return 0;\n}\n\nstatic int ProcfsPiddirMountsRead(struct VfsInfo *info,\n                                  struct ProcfsOpenFile *openfile) {\n  size_t byteswritten = 0;\n  size_t bytesleft = sizeof(openfile->readbuf);\n  size_t ret, len, len1;\n  struct Dll *e = NULL;\n  char *spec, *file, *vfstype, *mntops, *mntops1, *tmp;\n  int freq = 0, passno = 0;\n  int i;\n  if (openfile->readbufend > sizeof(openfile->readbuf)) {\n    return 0;\n  }\n  LOCK(&g_vfs.lock);\n  for (i = 0, e = dll_first(g_vfs.devices); e;\n       e = dll_next(g_vfs.devices, e), ++i) {\n    struct VfsDevice *device = VFS_DEVICE_CONTAINER(e);\n    if (i < openfile->index) continue;\n    spec = file = vfstype = mntops = mntops1 = tmp = NULL;\n    ret = 0;\n    // Probably the root device.\n    if (device->root == NULL) {\n      goto cleanandcontinue;\n    }\n    if (VfsPathBuildFull(device->root, NULL, &file) == -1) {\n      goto cleanandcontinue;\n    }\n    mntops = strdup(\"defaults\");\n    if (!mntops) {\n      goto cleanandcontinue;\n    }\n    if (!device->ops->Readmountentry ||\n        device->ops->Readmountentry(device, &spec, &vfstype, &mntops1) == -1) {\n      goto cleanandcontinue;\n    }\n    if (mntops1) {\n      len = strlen(mntops);\n      len1 = strlen(mntops1);\n      tmp = realloc(mntops, len + 1 + len1 + 1);\n      if (!tmp) {\n        goto cleanandcontinue;\n      }\n      mntops = tmp;\n      tmp = NULL;\n      mntops[len] = ',';\n      memcpy(mntops + len + 1, mntops1, len1 + 1);\n    }\n    if (spec) {\n      if (ProcfsMountsStringEscape(&spec) == -1) {\n        goto cleanandcontinue;\n      }\n    }\n    if (file) {\n      if (ProcfsMountsStringEscape(&file) == -1) {\n        goto cleanandcontinue;\n      }\n    }\n    ret = snprintf(openfile->readbuf + byteswritten, bytesleft,\n                   \"%s %s %s %s %d %d\\n\", spec, file, vfstype, mntops, freq,\n                   passno);\n  cleanandcontinue:\n    free(spec);\n    free(file);\n    free(vfstype);\n    free(mntops);\n    free(mntops1);\n    free(tmp);\n    if (ret > bytesleft) {\n      break;\n    }\n    byteswritten += ret;\n    bytesleft -= ret;\n    ++openfile->index;\n  }\n  UNLOCK(&g_vfs.lock);\n  if (e == NULL && byteswritten == 0) {\n    openfile->readbufstart = sizeof(openfile->readbuf) + 1;\n    openfile->readbufend = sizeof(openfile->readbuf) + 1;\n  } else {\n    openfile->readbufstart = 0;\n    openfile->readbufend = byteswritten;\n  }\n  return 0;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstruct VfsSystem g_procfs = {.name = \"proc\",\n                             .nodev = true,\n                             .ops = {\n                                 .Init = ProcfsInit,\n                                 .Freeinfo = ProcfsFreeInfo,\n                                 .Freedevice = ProcfsFreeDevice,\n                                 .Readmountentry = ProcfsReadmountentry,\n                                 .Finddir = ProcfsFinddir,\n                                 .Readlink = ProcfsReadlink,\n                                 .Mkdir = NULL,\n                                 .Mkfifo = NULL,\n                                 .Open = ProcfsOpen,\n                                 .Access = ProcfsAccess,\n                                 .Stat = ProcfsStat,\n                                 .Fstat = ProcfsFstat,\n                                 .Chmod = ProcfsChmod,\n                                 .Fchmod = ProcfsFchmod,\n                                 .Chown = ProcfsChown,\n                                 .Fchown = ProcfsFchown,\n                                 .Ftruncate = NULL,\n                                 .Close = ProcfsClose,\n                                 .Link = NULL,\n                                 .Unlink = NULL,\n                                 .Read = ProcfsRead,\n                                 //.Write = ProcfsWrite,\n                                 .Pread = ProcfsPread,\n                                 //.Pwrite = ProcfsPwrite,\n                                 .Readv = ProcfsReadv,\n                                 //.Writev = ProcfsWritev,\n                                 .Preadv = ProcfsPreadv,\n                                 //.Pwritev = ProcfsPwritev,\n                                 .Seek = ProcfsSeek,\n                                 .Fsync = NULL,\n                                 .Fdatasync = NULL,\n                                 .Flock = NULL,\n                                 .Dup = ProcfsDup,\n#ifdef HAVE_DUP3\n                                 .Dup3 = ProcfsDup3,\n#endif\n                                 .Poll = NULL,\n                                 .Opendir = ProcfsOpendir,\n#ifdef HAVE_SEEKDIR\n                                 .Seekdir = ProcfsSeekdir,\n                                 .Telldir = ProcfsTelldir,\n#endif\n                                 .Readdir = ProcfsReaddir,\n                                 .Rewinddir = ProcfsRewinddir,\n                                 .Closedir = ProcfsClosedir,\n                                 .Bind = NULL,\n                                 .Connect = NULL,\n                                 .Connectunix = NULL,\n                                 .Accept = NULL,\n                                 .Listen = NULL,\n                                 .Shutdown = NULL,\n                                 .Recvmsg = NULL,\n                                 .Sendmsg = NULL,\n                                 .Recvmsgunix = NULL,\n                                 .Sendmsgunix = NULL,\n                                 .Getsockopt = NULL,\n                                 .Setsockopt = NULL,\n                                 .Getsockname = NULL,\n                                 .Getpeername = NULL,\n                                 .Rename = NULL,\n                                 .Utime = ProcfsUtime,\n                                 .Futime = ProcfsFutime,\n                                 .Symlink = NULL,\n                                 .Mmap = NULL,\n                                 .Munmap = NULL,\n                                 .Mprotect = NULL,\n                                 .Msync = NULL,\n                                 .Pipe = NULL,\n#ifdef HAVE_PIPE2\n                                 .Pipe2 = NULL,\n#endif\n                                 .Socket = NULL,\n                                 .Socketpair = NULL,\n                                 .Tcgetattr = NULL,\n                                 .Tcsetattr = NULL,\n                                 .Tcflush = NULL,\n                                 .Tcdrain = NULL,\n                                 .Tcsendbreak = NULL,\n                                 .Tcflow = NULL,\n                                 .Tcgetsid = NULL,\n                                 .Tcgetpgrp = NULL,\n                                 .Tcsetpgrp = NULL,\n#ifdef HAVE_SOCKATMARK\n                                 .Sockatmark = NULL,\n#endif\n                                 .Fexecve = NULL,\n                             }};\n\n#endif /* DISABLE_VFS */\n"
  },
  {
    "path": "blink/procfs.h",
    "content": "#ifndef BLINK_PROCFS_H_\n#define BLINK_PROCFS_H_\n\n#include \"blink/vfs.h\"\n\nextern struct VfsSystem g_procfs;\n\nint ProcfsRegisterExe(i32 pid, const char *path);\n\n#endif  // BLINK_PROCFS_H_\n"
  },
  {
    "path": "blink/prog.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/log.h\"\n\nchar *g_progname;\n"
  },
  {
    "path": "blink/pte32.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/thread.h\"\n\n/**\n * @fileoverview page table ops for 32-bit hosts\n */\n\npthread_mutex_t_ g_ptelock = PTHREAD_MUTEX_INITIALIZER_;\n\nu64 LoadPte32_(const u8 *pte) {\n  u64 res;\n  LOCK(&g_ptelock);\n  res = Read64(pte);\n  UNLOCK(&g_ptelock);\n  return res;\n}\n\nvoid StorePte32_(u8 *pte, u64 val) {\n  LOCK(&g_ptelock);\n  Write64(pte, val);\n  UNLOCK(&g_ptelock);\n}\n\nbool CasPte32_(u8 *pte, u64 oldval, u64 newval) {\n  bool res;\n  LOCK(&g_ptelock);\n  if (Read64(pte) == oldval) {\n    Write64(pte, newval);\n    res = true;\n  } else {\n    res = false;\n  }\n  UNLOCK(&g_ptelock);\n  return res;\n}\n"
  },
  {
    "path": "blink/pty.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/pty.h\"\n\n#include <ctype.h>\n#include <errno.h>\n#include <limits.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <wchar.h>\n\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/macros.h\"\n#include \"blink/thompike.h\"\n#include \"blink/util.h\"\n\n#ifdef IUTF8\n#define CURSOR L'▂'\n#else\n#define CURSOR '_'\n#endif\n\n/**\n * @fileoverview Pseudoteletypewriter\n *\n *   \\t                                  TAB\n *   \\a                                  BELL\n *   \\177                                BACKSPACE\n *   \\r                                  CURSOR START\n *   \\b                                  CURSOR LEFT OR CURSOR REWIND\n *   \\n                                  CURSOR DOWN AND START IF OPOST\n *   \\f                                  CURSOR DOWN AND START IF OPOST\n *   \\v                                  CURSOR DOWN AND START OR \\e[H\\e[J\n *   \\eE                                 CURSOR DOWN AND START\n *   \\eD                                 CURSOR DOWN\n *   \\eM                                 CURSOR UP\n *   \\ec                                 FULL RESET\n *   \\e7                                 SAVE CURSOR POSITION\n *   \\e8                                 RESTORE CURSOR POSITION\n *   \\e(0                                DEC SPECIAL GRAPHICS\n *   \\e(B                                USAS X3.4-1967\n *   \\e#5                                SINGLE WIDTH\n *   \\e#6                                DOUBLE WIDTH\n *   \\e#8                                SO MANY E\n *   \\eZ → \\e/Z                          REPORT IDENTITY\n *   \\e[𝑛A                               CURSOR UP             [CLAMPED]\n *   \\e[𝑛B                               CURSOR DOWN           [CLAMPED]\n *   \\e[𝑛C                               CURSOR RIGHT          [CLAMPED]\n *   \\e[𝑛D                               CURSOR LEFT           [CLAMPED]\n *   \\e[𝑦;𝑥H                             SET CURSOR POSITION   [CLAMPED]\n *   \\e[𝑥G                               SET CURSOR COLUMN     [CLAMPED]\n *   \\e[𝑦d                               SET CURSOR ROW        [CLAMPED]\n *   \\e[𝑛E                               CURSOR DOWN AND START [CLAMPED]\n *   \\e[𝑛F                               CURSOR UP AND START   [CLAMPED]\n *   \\e[𝑛S                               SCROLL UP\n *   \\e[𝑛T                               SCROLL DOWN\n *   \\e[𝑛@                               INSERT CELLS\n *   \\e[𝑛P                               DELETE CELLS\n *   \\e[𝑛L                               INSERT LINES\n *   \\e[𝑛M                               DELETE LINES\n *   \\e[J                                ERASE DISPLAY FORWARDS\n *   \\e[1J                               ERASE DISPLAY BACKWARDS\n *   \\e[2J                               ERASE DISPLAY\n *   \\e[K                                ERASE LINE FORWARD\n *   \\e[1K                               ERASE LINE BACKWARD\n *   \\e[2K                               ERASE LINE\n *   \\e[𝑛X                               ERASE CELLS\n *   \\e[0m                               RESET\n *   \\e[1m                               BOLD\n *   \\e[2m                               FAINT\n *   \\e[3m                               ITALIC\n *   \\e[4m                               UNDER\n *   \\e[5m                               BLINK\n *   \\e[7m                               INVERT\n *   \\e[8m                               CONCEAL\n *   \\e[9m                               STRIKE\n *   \\e[20m                              FRAKTUR\n *   \\e[21m                              DUNDER\n *   \\e[22m                              RESET BOLD & FAINT\n *   \\e[23m                              RESET ITALIC & FRAKTUR\n *   \\e[24m                              RESET UNDER & DUNDER\n *   \\e[25m                              RESET BLINK\n *   \\e[27m                              RESET INVERT\n *   \\e[28m                              RESET CONCEAL\n *   \\e[29m                              RESET STRIKE\n *   \\e[39m                              RESET FOREGROUND\n *   \\e[49m                              RESET BACKGROUND\n *   \\e[30m                              BLACK FOREGROUND\n *   \\e[31m                              RED FOREGROUND\n *   \\e[32m                              GREEN FOREGROUND\n *   \\e[33m                              YELLOW FOREGROUND\n *   \\e[34m                              BLUE FOREGROUND\n *   \\e[35m                              MAGENTA FOREGROUND\n *   \\e[36m                              CYAN FOREGROUND\n *   \\e[37m                              WHITE FOREGROUND\n *   \\e[40m                              BLACK BACKGROUND\n *   \\e[41m                              RED BACKGROUND\n *   \\e[42m                              GREEN BACKGROUND\n *   \\e[44m                              YELLOW BACKGROUND\n *   \\e[44m                              BLUE BACKGROUND\n *   \\e[45m                              MAGENTA BACKGROUND\n *   \\e[46m                              CYAN BACKGROUND\n *   \\e[47m                              WHITE BACKGROUND\n *   \\e[90m                              BRIGHT BLACK FOREGROUND\n *   \\e[91m                              BRIGHT RED FOREGROUND\n *   \\e[92m                              BRIGHT GREEN FOREGROUND\n *   \\e[93m                              BRIGHT YELLOW FOREGROUND\n *   \\e[94m                              BRIGHT BLUE FOREGROUND\n *   \\e[95m                              BRIGHT MAGENTA FOREGROUND\n *   \\e[96m                              BRIGHT CYAN FOREGROUND\n *   \\e[97m                              BRIGHT WHITE FOREGROUND\n *   \\e[100m                             BRIGHT BLACK BACKGROUND\n *   \\e[101m                             BRIGHT RED BACKGROUND\n *   \\e[102m                             BRIGHT GREEN BACKGROUND\n *   \\e[103m                             BRIGHT YELLOW BACKGROUND\n *   \\e[104m                             BRIGHT BLUE BACKGROUND\n *   \\e[105m                             BRIGHT MAGENTA BACKGROUND\n *   \\e[106m                             BRIGHT CYAN BACKGROUND\n *   \\e[107m                             BRIGHT WHITE BACKGROUND\n *   \\e[38;5;𝑥m                          XTERM256 FOREGROUND\n *   \\e[48;5;𝑥m                          XTERM256 BACKGROUND\n *   \\e[38;2;𝑟;𝑔;𝑏m                      RGB FOREGROUND\n *   \\e[48;2;𝑟;𝑔;𝑏m                      RGB BACKGROUND\n *   \\e[?25h                             SHOW CURSOR\n *   \\e[?25l                             HIDE CURSOR\n *   \\e[s                                SAVE CURSOR POSITION\n *   \\e[u                                RESTORE CURSOR POSITION\n *   \\e[?5h ... \\e[?5l                   REVERSE VIDEO EPILEPSY\n *   \\e[0q                               RESET LEDS\n *   \\e[1q                               TURN ON FIRST LED\n *   \\e[2q                               TURN ON SECOND LED\n *   \\e[3q                               TURN ON THIRD LED\n *   \\e[4q                               TURN ON FOURTH LED\n *   \\e[c → \\e[?1;0c                     REPORT DEVICE TYPE\n *   \\e[5n → \\e[0n                       REPORT DEVICE STATUS\n *   \\e[6n → \\e[𝑦;𝑥R                     REPORT CURSOR POSITION\n *   \\e7\\e[9979;9979H\\e[6n\\e8 → \\e[𝑦;𝑥R  REPORT DISPLAY DIMENSIONS\n *\n * @see https://vt100.net/docs/vt220-rm/chapter4.html\n * @see https://invisible-island.net/xterm/\n * @see ANSI X3.64-1979\n * @see ISO/IEC 6429\n * @see FIPS-86\n * @see ECMA-48\n */\n\nstruct Pty *NewPty(void) {\n  struct Pty *pty;\n  if ((pty = (struct Pty *)calloc(1, sizeof(*pty)))) {\n    PtyResize(pty, 25, 80);\n    PtyFullReset(pty);\n    PtyErase(pty, 0, pty->yn * pty->xn);\n  }\n  return pty;\n}\n\nstatic void FreePtyPlanes(struct Pty *pty) {\n  free(pty->wcs);\n  free(pty->fgs);\n  free(pty->bgs);\n  free(pty->prs);\n}\n\nvoid FreePty(struct Pty *pty) {\n  if (pty) {\n    FreePtyPlanes(pty);\n    free(pty);\n  }\n}\n\nstatic wchar_t *GetXlatAscii(void) {\n  unsigned i;\n  static bool once;\n  static wchar_t xlat[128];\n  if (!once) {\n    for (i = 0; i < 128; ++i) {\n      xlat[i] = i;\n    }\n    once = true;\n  }\n  return xlat;\n}\n\nstatic wchar_t *GetXlatLineDrawing(void) {\n  unsigned i;\n  static bool once;\n  static wchar_t xlat[128];\n  if (!once) {\n    for (i = 0; i < 128; ++i) {\n      if (0x5F <= i && i <= 0x7E) {\n        xlat[i] = L\" ◆▒␉␌␍␊°±␤␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π≠£·\"[i - 0x5F];\n      } else {\n        xlat[i] = i;\n      }\n    }\n    once = true;\n  }\n  return xlat;\n}\n\nstatic void XlatAlphabet(wchar_t xlat[128], int a, int b) {\n  unsigned i;\n  for (i = 0; i < 128; ++i) {\n    if ('a' <= i && i <= 'z') {\n      xlat[i] = i - 'a' + a;\n    } else if ('A' <= i && i <= 'Z') {\n      xlat[i] = i - 'A' + b;\n    } else {\n      xlat[i] = i;\n    }\n  }\n}\n\nstatic wchar_t *GetXlatItalic(void) {\n  static bool once;\n  static wchar_t xlat[128];\n  if (!once) {\n#if WCHAR_MAX > 0x10000\n    XlatAlphabet(xlat, L'𝑎', L'𝐴');\n#else\n    XlatAlphabet(xlat, L'a', L'A');\n#endif\n    once = true;\n  }\n  return xlat;\n}\n\nstatic wchar_t *GetXlatBoldItalic(void) {\n  static bool once;\n  static wchar_t xlat[128];\n  if (!once) {\n#if WCHAR_MAX > 0x10000\n    XlatAlphabet(xlat, L'𝒂', L'𝑨');\n#else\n    XlatAlphabet(xlat, L'a', L'A');\n#endif\n    once = true;\n  }\n  return xlat;\n}\n\nstatic wchar_t *GetXlatBoldFraktur(void) {\n  static bool once;\n  static wchar_t xlat[128];\n  if (!once) {\n#if WCHAR_MAX > 0x10000\n    XlatAlphabet(xlat, L'𝖆', L'𝕬');\n#else\n    XlatAlphabet(xlat, L'a', L'A');\n#endif\n    once = true;\n  }\n  return xlat;\n}\n\nstatic wchar_t *GetXlatFraktur(void) {\n  unsigned i;\n  static bool once;\n  static wchar_t xlat[128];\n  if (!once) {\n#if WCHAR_MAX > 0x10000\n    for (i = 0; i < ARRAYLEN(xlat); ++i) {\n      if ('A' <= i && i <= 'Z') {\n        xlat[i] = L\"𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ\"[i - 'A'];\n      } else if ('a' <= i && i <= 'z') {\n        xlat[i] = i - 'a' + L'𝔞';\n      } else {\n        xlat[i] = i;\n      }\n    }\n#else\n    XlatAlphabet(xlat, L'a', L'A');\n#endif\n    once = true;\n  }\n  return xlat;\n}\n\nstatic wchar_t *GetXlatDoubleWidth(void) {\n  unsigned i;\n  static bool once;\n  static wchar_t xlat[128];\n  if (!once) {\n    for (i = 0; i < ARRAYLEN(xlat); ++i) {\n      if ('!' <= i && i <= '~') {\n        xlat[i] = -(i - '!' + L'！');\n      } else {\n        xlat[i] = i;\n      }\n    }\n    once = true;\n  }\n  return xlat;\n}\n\nstatic wchar_t *GetXlatSgr(struct Pty *pty) {\n  switch (!!(pty->pr & kPtyFraktur) << 2 | !!(pty->pr & kPtyItalic) << 1 |\n          !!(pty->pr & kPtyBold) << 0) {\n    case 4:\n    case 6:\n      return GetXlatFraktur();\n    case 5:\n    case 7:\n      return GetXlatBoldFraktur();\n    case 3:\n      return GetXlatBoldItalic();\n    case 2:\n      return GetXlatItalic();\n    default:\n      return GetXlatAscii();\n  }\n}\n\nstatic void PtySetXlat(struct Pty *pty, wchar_t *xlat) {\n  pty->xlat = xlat;\n  pty->pr &= ~(kPtyItalic | kPtyFraktur);\n}\n\nstatic void PtySetCodepage(struct Pty *pty, char id) {\n  switch (id) {\n    default:\n    case 'B':\n      PtySetXlat(pty, GetXlatAscii());\n      break;\n    case '0':\n      PtySetXlat(pty, GetXlatLineDrawing());\n      break;\n  }\n}\n\nstatic u32 *u32set(u32 *p, u32 c, size_t n) {\n  size_t i;\n  for (i = 0; i < n; ++i) {\n    p[i] = c;\n  }\n  return p;\n}\n\nvoid PtyErase(struct Pty *pty, long dst, long n) {\n  unassert(dst + n <= pty->yn * pty->xn);\n  u32set(pty->wcs + dst, ' ', n);\n  u32set(pty->prs + dst, 0, n);\n}\n\nvoid PtyMemmove(struct Pty *pty, long dst, long src, long n) {\n  unassert(src + n <= pty->yn * pty->xn);\n  unassert(dst + n <= pty->yn * pty->xn);\n  memmove(pty->wcs + dst, pty->wcs + src, n * 4);\n  memmove(pty->fgs + dst, pty->fgs + src, n * 4);\n  memmove(pty->bgs + dst, pty->bgs + src, n * 4);\n  memmove(pty->prs + dst, pty->prs + src, n * 4);\n}\n\nvoid PtyFullReset(struct Pty *pty) {\n  pty->y = 0;\n  pty->x = 0;\n  pty->pr = 0;\n  pty->u8 = 0;\n  pty->n8 = 0;\n  pty->conf = 0;\n  pty->save = 0;\n  pty->esc.i = 0;\n  pty->input.i = 0;\n  pty->state = kPtyAscii;\n  pty->xlat = GetXlatAscii();\n  PtyErase(pty, 0, pty->yn * pty->xn);\n}\n\nvoid PtySetY(struct Pty *pty, int y) {\n  pty->conf &= ~kPtyRedzone;\n  pty->y = MAX(0, MIN(pty->yn - 1, y));\n}\n\nvoid PtySetX(struct Pty *pty, int x) {\n  pty->conf &= ~kPtyRedzone;\n  pty->x = MAX(0, MIN(pty->xn - 1, x));\n}\n\nvoid PtyResize(struct Pty *pty, int yn, int xn) {\n  unsigned y, ym, xm, y0;\n  u32 *wcs, *fgs, *bgs, *prs;\n  if (xn < 80) xn = 80;\n  if (yn < 25) yn = 25;\n  if (xn == pty->xn && yn == pty->yn) return;\n  wcs = (u32 *)calloc(yn * xn, 4);\n  fgs = (u32 *)calloc(yn * xn, 4);\n  bgs = (u32 *)calloc(yn * xn, 4);\n  prs = (u32 *)calloc(yn * xn, 4);\n  y0 = yn > pty->y + 1 ? 0 : pty->y + 1 - yn;\n  ym = MIN(yn, pty->yn) + y0;\n  xm = MIN(xn, pty->xn);\n  for (y = y0; y < ym; ++y) {\n    memcpy(wcs + y * xn, pty->wcs + y * pty->xn, xm * 4);\n    memcpy(fgs + y * xn, pty->fgs + y * pty->xn, xm * 4);\n    memcpy(bgs + y * xn, pty->bgs + y * pty->xn, xm * 4);\n    memcpy(prs + y * xn, pty->prs + y * pty->xn, xm * 4);\n  }\n  FreePtyPlanes(pty);\n  pty->wcs = wcs;\n  pty->fgs = fgs;\n  pty->bgs = bgs;\n  pty->prs = prs;\n  pty->yn = yn;\n  pty->xn = xn;\n  PtySetY(pty, pty->y);\n  PtySetX(pty, pty->x);\n}\n\nstatic void PtyConcatInput(struct Pty *pty, const char *data, size_t n) {\n  AppendData(&pty->input, data, n);\n}\n\nstatic void PtyScroll(struct Pty *pty) {\n  PtyMemmove(pty, 0, pty->xn, pty->xn * (pty->yn - 1));\n  PtyErase(pty, pty->xn * (pty->yn - 1), pty->xn);\n}\n\nstatic void PtyReverse(struct Pty *pty) {\n  PtyMemmove(pty, pty->xn, 0, pty->xn * (pty->yn - 1));\n  PtyErase(pty, 0, pty->xn);\n}\n\nstatic void PtyIndex(struct Pty *pty) {\n  if (pty->y < pty->yn - 1) {\n    ++pty->y;\n  } else {\n    PtyScroll(pty);\n  }\n}\n\nstatic void PtyReverseIndex(struct Pty *pty) {\n  if (pty->y) {\n    --pty->y;\n  } else {\n    PtyReverse(pty);\n  }\n}\n\nstatic void PtyCarriageReturn(struct Pty *pty) {\n  PtySetX(pty, 0);\n}\n\nstatic void PtyNewline(struct Pty *pty) {\n  PtyIndex(pty);\n  if (!(pty->conf & kPtyNoopost)) {\n    PtyCarriageReturn(pty);\n  }\n}\n\nstatic void PtyAdvance(struct Pty *pty) {\n  unassert(pty->xn - 1 == pty->x);\n  unassert(pty->conf & kPtyRedzone);\n  pty->conf &= ~kPtyRedzone;\n  pty->x = 0;\n  if (pty->y < pty->yn - 1) {\n    ++pty->y;\n  } else {\n    PtyScroll(pty);\n  }\n}\n\nstatic void PtyWriteGlyph(struct Pty *pty, wint_t wc, int w) {\n  u32 i;\n  unassert(!(0x00 <= wc && wc <= 0x1F));\n  unassert(!(0x7F <= wc && wc <= 0x9F));\n  if (w < 1) wc = ' ', w = 1;\n  if ((pty->conf & kPtyRedzone) || pty->x + w > pty->xn) {\n    PtyAdvance(pty);\n  }\n  i = pty->y * pty->xn + pty->x;\n  pty->wcs[i] = wc;\n  if ((pty->prs[i] = pty->pr) & (kPtyFg | kPtyBg)) {\n    pty->fgs[i] = pty->fg;\n    pty->bgs[i] = pty->bg;\n  }\n  if ((pty->x += w) >= pty->xn) {\n    pty->x = pty->xn - 1;\n    pty->conf |= kPtyRedzone;\n  }\n}\n\nstatic void PtyWriteTab(struct Pty *pty) {\n  unsigned x, x2;\n  if (pty->conf & kPtyRedzone) {\n    PtyAdvance(pty);\n  }\n  x2 = MIN(pty->xn, ROUNDUP(pty->x + 1, 8));\n  for (x = pty->x; x < x2; ++x) {\n    pty->wcs[pty->y * pty->xn + x] = ' ';\n  }\n  if (x2 < pty->xn) {\n    pty->x = x2;\n  } else {\n    pty->x = pty->xn - 1;\n    pty->conf |= kPtyRedzone;\n  }\n}\n\nint PtyAtoi(const char *s, const char **e) {\n  int i;\n  for (i = 0; isdigit(*s); ++s) i *= 10, i += *s - '0';\n  if (e) *e = s;\n  return i;\n}\n\nstatic int PtyGetMoveParam(struct Pty *pty) {\n  int x = PtyAtoi(pty->esc.s, NULL);\n  if (x < 1) x = 1;\n  return x;\n}\n\nstatic void PtySetCursorPosition(struct Pty *pty) {\n  int row, col;\n  const char *s = pty->esc.s;\n  row = PtyAtoi(s, &s);\n  row = MAX(1, row);\n  if (*s == ';') ++s;\n  col = PtyAtoi(s, &s);\n  col = MAX(1, col);\n  PtySetY(pty, row - 1);\n  PtySetX(pty, col - 1);\n}\n\nstatic void PtySetCursorRow(struct Pty *pty) {\n  PtySetY(pty, PtyGetMoveParam(pty) - 1);\n}\n\nstatic void PtySetCursorColumn(struct Pty *pty) {\n  PtySetX(pty, PtyGetMoveParam(pty) - 1);\n}\n\nstatic void PtyMoveCursor(struct Pty *pty, int dy, int dx) {\n  int n = PtyGetMoveParam(pty);\n  PtySetY(pty, pty->y + dy * n);\n  PtySetX(pty, pty->x + dx * n);\n}\n\nstatic void PtyScrollUp(struct Pty *pty) {\n  int n = PtyGetMoveParam(pty);\n  while (n--) PtyScroll(pty);\n}\n\nstatic void PtyScrollDown(struct Pty *pty) {\n  int n = PtyGetMoveParam(pty);\n  while (n--) PtyReverse(pty);\n}\n\nstatic void PtySetCursorStatus(struct Pty *pty, bool status) {\n  if (status) {\n    pty->conf &= ~kPtyNocursor;\n  } else {\n    pty->conf |= kPtyNocursor;\n  }\n}\n\nstatic void PtySetMode(struct Pty *pty, bool status) {\n  const char *p = pty->esc.s;\n  switch (*p++) {\n    case '?':\n      while (isdigit(*p)) {\n        switch (PtyAtoi(p, &p)) {\n          case 25:\n            PtySetCursorStatus(pty, status);\n            break;\n          default:\n            break;\n        }\n        if (*p == ';') {\n          ++p;\n        }\n      }\n      break;\n    default:\n      break;\n  }\n}\n\nstatic void PtySaveCursorPosition(struct Pty *pty) {\n  pty->save = (pty->y & 0x7FFF) | (pty->x & 0x7FFF) << 16;\n}\n\nstatic void PtyRestoreCursorPosition(struct Pty *pty) {\n  PtySetY(pty, (pty->save & 0x00007FFF) >> 000);\n  PtySetX(pty, (pty->save & 0x7FFF0000) >> 020);\n}\n\nstatic void PtyEraseDisplay(struct Pty *pty) {\n  switch (PtyAtoi(pty->esc.s, NULL)) {\n    case 0:\n      PtyErase(pty, pty->y * pty->xn + pty->x,\n               pty->yn * pty->xn - (pty->y * pty->xn + pty->x));\n      break;\n    case 1:\n      PtyErase(pty, 0, pty->y * pty->xn + pty->x);\n      break;\n    case 2:\n    case 3:\n      PtyErase(pty, 0, pty->yn * pty->xn);\n      break;\n    default:\n      break;\n  }\n}\n\nstatic void PtyEraseLine(struct Pty *pty) {\n  switch (PtyAtoi(pty->esc.s, NULL)) {\n    case 0:\n      PtyErase(pty, pty->y * pty->xn + pty->x, pty->xn - pty->x);\n      break;\n    case 1:\n      PtyErase(pty, pty->y * pty->xn, pty->x);\n      break;\n    case 2:\n      PtyErase(pty, pty->y * pty->xn, pty->xn);\n      break;\n    default:\n      break;\n  }\n}\n\nstatic void PtyEraseCells(struct Pty *pty) {\n  int i, n, x;\n  i = pty->y * pty->xn + pty->x;\n  n = pty->yn * pty->xn;\n  x = PtyAtoi(pty->esc.s, NULL);\n  x = MIN(MAX(x, 1), n - i);\n  PtyErase(pty, i, x);\n}\n\nstatic int PtyArg1(struct Pty *pty) {\n  int x = PtyAtoi(pty->esc.s, NULL);\n  return MAX(1, x);\n}\n\nstatic void PtyInsertCells(struct Pty *pty) {\n  int n = PtyArg1(pty);\n  n = MIN(pty->xn - pty->x, n);\n  PtyMemmove(pty, pty->y * pty->xn + pty->x + n, pty->y * pty->xn + pty->x,\n             pty->xn - (pty->x + n));\n  PtyErase(pty, pty->y * pty->xn + pty->x, n);\n}\n\nstatic void PtyInsertLines(struct Pty *pty) {\n  int n = PtyArg1(pty);\n  n = MIN(pty->yn - pty->y, n);\n  PtyMemmove(pty, (pty->y + n) * pty->xn, pty->y * pty->xn,\n             (pty->yn - pty->y - n) * pty->xn);\n  PtyErase(pty, pty->y * pty->xn, n * pty->xn);\n}\n\nstatic void PtyDeleteCells(struct Pty *pty) {\n  int n = PtyArg1(pty);\n  n = MIN(pty->xn - pty->x, n);\n  PtyMemmove(pty, pty->y * pty->xn + pty->x, pty->y * pty->xn + pty->x + n,\n             pty->xn - (pty->x + n));\n  PtyErase(pty, pty->y * pty->xn + pty->x, n);\n}\n\nstatic void PtyDeleteLines(struct Pty *pty) {\n  int n = PtyArg1(pty);\n  n = MIN(pty->yn - pty->y, n);\n  PtyMemmove(pty, pty->y * pty->xn, (pty->y + n) * pty->xn,\n             (pty->yn - pty->y - n) * pty->xn);\n  PtyErase(pty, (pty->y + n) * pty->xn, n * pty->xn);\n}\n\nstatic void PtyReportDeviceStatus(struct Pty *pty) {\n  PtyWriteInput(pty, \"\\033[0n\", 4);\n}\n\nstatic void PtyReportPreferredVtType(struct Pty *pty) {\n  PtyWriteInput(pty, \"\\033[?1;0c\", 4);\n}\n\nstatic void PtyReportPreferredVtIdentity(struct Pty *pty) {\n  PtyWriteInput(pty, \"\\033/Z\", 4);\n}\n\nstatic void PtyBell(struct Pty *pty) {\n  pty->conf |= kPtyBell;\n}\n\nstatic void PtyLed(struct Pty *pty) {\n  switch (PtyAtoi(pty->esc.s, NULL)) {\n    case 0:\n      pty->conf &= ~kPtyLed1;\n      pty->conf &= ~kPtyLed2;\n      pty->conf &= ~kPtyLed3;\n      pty->conf &= ~kPtyLed4;\n      break;\n    case 1:\n      pty->conf |= kPtyLed1;\n      break;\n    case 2:\n      pty->conf |= kPtyLed2;\n      break;\n    case 3:\n      pty->conf |= kPtyLed3;\n      break;\n    case 4:\n      pty->conf |= kPtyLed4;\n      break;\n    default:\n      break;\n  }\n}\n\nstatic void PtyReportCursorPosition(struct Pty *pty) {\n  char buf[2 + 10 + 1 + 10 + 1];\n  PtyWriteInput(pty, buf,\n                sprintf(buf, \"\\033[%d;%dR\", (pty->y + 1) & 0x7fff,\n                        (pty->x + 1) & 0x7fff));\n}\n\nstatic void PtyCsiN(struct Pty *pty) {\n  switch (PtyAtoi(pty->esc.s, NULL)) {\n    case 5:\n      PtyReportDeviceStatus(pty);\n      break;\n    case 6:\n      PtyReportCursorPosition(pty);\n      break;\n    default:\n      break;\n  }\n}\n\nstatic void PtySelectGraphicsRendition(struct Pty *pty) {\n  char *p, c;\n  unsigned x;\n  u8 code[4];\n  enum Sgr {\n    kSgr,\n    kSgrFg = 010,\n    kSgrFgTrue = 012,\n    kSgrFgXterm = 015,\n    kSgrBg = 020,\n    kSgrBgTrue = 022,\n    kSgrBgXterm = 025,\n  } t;\n  x = 0;\n  t = kSgr;\n  p = pty->esc.s;\n  memset(code, 0, sizeof(code));\n  for (;;) {\n    c = *p++;\n    switch (c) {\n      case '\\0':\n        return;\n      case '0':\n      case '1':\n      case '2':\n      case '3':\n      case '4':\n      case '5':\n      case '6':\n      case '7':\n      case '8':\n      case '9':\n        x *= 10;\n        x += c - '0';\n        break;\n      case ';':\n      case 'm':\n        code[code[3]] = x;\n        x = 0;\n        switch (t) {\n          case kSgr:\n            switch (code[0]) {\n              case 38:\n                t = kSgrFg;\n                break;\n              case 48:\n                t = kSgrBg;\n                break;\n              case 0:\n                pty->pr = 0;\n                pty->xlat = GetXlatSgr(pty);\n                break;\n              case 1:\n                pty->pr |= kPtyBold;\n                pty->xlat = GetXlatSgr(pty);\n                break;\n              case 2:\n                pty->pr |= kPtyFaint;\n                break;\n              case 3:\n                pty->pr |= kPtyItalic;\n                pty->xlat = GetXlatSgr(pty);\n                break;\n              case 4:\n                pty->pr |= kPtyUnder;\n                break;\n              case 5:\n                pty->pr |= kPtyBlink;\n                break;\n              case 7:\n                pty->pr |= kPtyFlip;\n                break;\n              case 8:\n                pty->pr |= kPtyConceal;\n                break;\n              case 9:\n                pty->pr |= kPtyStrike;\n                break;\n              case 20:\n                pty->pr |= kPtyFraktur;\n                pty->xlat = GetXlatSgr(pty);\n                break;\n              case 21:\n                pty->pr |= kPtyUnder | kPtyDunder;\n                break;\n              case 22:\n                pty->pr &= ~(kPtyFaint | kPtyBold);\n                pty->xlat = GetXlatSgr(pty);\n                break;\n              case 23:\n                pty->pr &= ~kPtyItalic;\n                pty->xlat = GetXlatSgr(pty);\n                break;\n              case 24:\n                pty->pr &= ~(kPtyUnder | kPtyDunder);\n                break;\n              case 25:\n                pty->pr &= ~kPtyBlink;\n                break;\n              case 27:\n                pty->pr &= ~kPtyFlip;\n                break;\n              case 28:\n                pty->pr &= ~kPtyConceal;\n                break;\n              case 29:\n                pty->pr &= ~kPtyStrike;\n                break;\n              case 39:\n                pty->pr &= ~kPtyFg;\n                break;\n              case 49:\n                pty->pr &= ~kPtyBg;\n                break;\n              case 90:\n              case 91:\n              case 92:\n              case 93:\n              case 94:\n              case 95:\n              case 96:\n              case 97:\n                code[0] -= 90 - 30;\n                code[0] += 8;\n                /* fallthrough */\n              case 30:\n              case 31:\n              case 32:\n              case 33:\n              case 34:\n              case 35:\n              case 36:\n              case 37:\n                pty->fg = code[0] - 30;\n                pty->pr |= kPtyFg;\n                pty->pr &= ~kPtyTrue;\n                break;\n              case 100:\n              case 101:\n              case 102:\n              case 103:\n              case 104:\n              case 105:\n              case 106:\n              case 107:\n                code[0] -= 100 - 40;\n                code[0] += 8;\n                /* fallthrough */\n              case 40:\n              case 41:\n              case 42:\n              case 43:\n              case 44:\n              case 45:\n              case 46:\n              case 47:\n                pty->bg = code[0] - 40;\n                pty->pr |= kPtyBg;\n                pty->pr &= ~kPtyTrue;\n                break;\n              default:\n                break;\n            }\n            break;\n          case kSgrFg:\n          case kSgrBg:\n            switch (code[0]) {\n              case 2:\n              case 5:\n                t = (enum Sgr)((int)t + code[0]);\n                break;\n              default:\n                t = kSgr;\n                break;\n            }\n            break;\n          case kSgrFgTrue:\n            if (++code[3] == 3) {\n              code[3] = 0;\n              t = kSgr;\n              pty->fg = Read32(code);\n              pty->pr |= kPtyFg;\n              pty->pr |= kPtyTrue;\n            }\n            break;\n          case kSgrBgTrue:\n            if (++code[3] == 3) {\n              code[3] = 0;\n              t = kSgr;\n              pty->bg = Read32(code);\n              pty->pr |= kPtyBg;\n              pty->pr |= kPtyTrue;\n            }\n            break;\n          case kSgrFgXterm:\n            t = kSgr;\n            pty->fg = code[0];\n            pty->pr |= kPtyFg;\n            pty->pr &= ~kPtyTrue;\n            break;\n          case kSgrBgXterm:\n            t = kSgr;\n            pty->bg = code[0];\n            pty->pr |= kPtyBg;\n            pty->pr &= ~kPtyTrue;\n            break;\n          default:\n            Abort();\n        }\n        break;\n      default:\n        break;\n    }\n  }\n}\n\nstatic void PtyCsi(struct Pty *pty) {\n  switch (pty->esc.s[pty->esc.i - 1]) {\n    case 'f':\n    case 'H':\n      PtySetCursorPosition(pty);\n      break;\n    case 'G':\n      PtySetCursorColumn(pty);\n      break;\n    case 'd':\n      PtySetCursorRow(pty);\n      break;\n    case 'F':\n      pty->x = 0;\n      /* fallthrough */\n    case 'A':\n      PtyMoveCursor(pty, -1, +0);\n      break;\n    case 'E':\n      pty->x = 0;\n      /* fallthrough */\n    case 'B':\n      PtyMoveCursor(pty, +1, +0);\n      break;\n    case 'C':\n      PtyMoveCursor(pty, +0, +1);\n      break;\n    case 'D':\n      PtyMoveCursor(pty, +0, -1);\n      break;\n    case 'S':\n      PtyScrollUp(pty);\n      break;\n    case 'T':\n      PtyScrollDown(pty);\n      break;\n    case '@':\n      PtyInsertCells(pty);\n      break;\n    case 'P':\n      PtyDeleteCells(pty);\n      break;\n    case 'L':\n      PtyInsertLines(pty);\n      break;\n    case 'M':\n      PtyDeleteLines(pty);\n      break;\n    case 'J':\n      PtyEraseDisplay(pty);\n      break;\n    case 'K':\n      PtyEraseLine(pty);\n      break;\n    case 'X':\n      PtyEraseCells(pty);\n      break;\n    case 's':\n      PtySaveCursorPosition(pty);\n      break;\n    case 'u':\n      PtyRestoreCursorPosition(pty);\n      break;\n    case 'n':\n      PtyCsiN(pty);\n      break;\n    case 'm':\n      PtySelectGraphicsRendition(pty);\n      break;\n    case 'h':\n      PtySetMode(pty, true);\n      break;\n    case 'l':\n      PtySetMode(pty, false);\n      break;\n    case 'c':\n      PtyReportPreferredVtType(pty);\n      break;\n    case 'q':\n      PtyLed(pty);\n      break;\n    default:\n      break;\n  }\n}\n\nstatic void PtyScreenAlignmentDisplay(struct Pty *pty) {\n  u32set(pty->wcs, 'E', pty->yn * pty->xn);\n}\n\nstatic void PtyEscHash(struct Pty *pty) {\n  switch (pty->esc.s[1]) {\n    case '5':\n      PtySetXlat(pty, GetXlatAscii());\n      break;\n    case '6':\n      PtySetXlat(pty, GetXlatDoubleWidth());\n      break;\n    case '8':\n      PtyScreenAlignmentDisplay(pty);\n      break;\n    default:\n      break;\n  }\n}\n\nstatic void PtyEsc(struct Pty *pty) {\n  switch (pty->esc.s[0]) {\n    case 'c':\n      PtyFullReset(pty);\n      break;\n    case '7':\n      PtySaveCursorPosition(pty);\n      break;\n    case '8':\n      PtyRestoreCursorPosition(pty);\n      break;\n    case 'E':\n      pty->x = 0;\n    case 'D':\n      PtyIndex(pty);\n      break;\n    case 'M':\n      PtyReverseIndex(pty);\n      break;\n    case 'Z':\n      PtyReportPreferredVtIdentity(pty);\n      break;\n    case '(':\n      PtySetCodepage(pty, pty->esc.s[1]);\n      break;\n    case '#':\n      PtyEscHash(pty);\n      break;\n    default:\n      break;\n  }\n}\n\nstatic void PtyCntrl(struct Pty *pty, int c01) {\n  switch (c01) {\n    case '\\a':\n      PtyBell(pty);\n      break;\n    case 0205:\n    case '\\f':\n    case '\\v':\n    case '\\n':\n      PtyNewline(pty);\n      break;\n    case '\\r':\n      PtyCarriageReturn(pty);\n      break;\n    case '\\t':\n      PtyWriteTab(pty);\n      break;\n    case '\\b':\n    case 0177:\n      pty->x = MAX(0, pty->x - 1);\n      break;\n    case 033:\n      pty->state = kPtyEsc;\n      pty->esc.i = 0;\n      break;\n    case 0204:\n      PtyIndex(pty);\n      break;\n    case 0215:\n      PtyReverseIndex(pty);\n      break;\n    case 0233:\n      pty->state = kPtyCsi;\n      break;\n    default:\n      break;\n  }\n}\n\nstatic void PtyEscAppend(struct Pty *pty, char c) {\n  pty->esc.i = MIN(pty->esc.i + 1, ARRAYLEN(pty->esc.s) - 1);\n  pty->esc.s[pty->esc.i - 1] = c;\n  pty->esc.s[pty->esc.i - 0] = 0;\n}\n\nssize_t PtyWrite(struct Pty *pty, const void *data, size_t n) {\n  int i;\n  wchar_t wc;\n  const u8 *p;\n  for (p = (const u8 *)data, i = 0; i < n; ++i) {\n    switch (pty->state) {\n      case kPtyAscii:\n        if (0x00 <= p[i] && p[i] <= 0x7F) {\n          if (0x20 <= p[i] && p[i] <= 0x7E) {\n            if ((wc = pty->xlat[p[i]]) >= 0) {\n              PtyWriteGlyph(pty, wc, 1);\n            } else {\n              PtyWriteGlyph(pty, -wc, 2);\n            }\n          } else {\n            PtyCntrl(pty, p[i]);\n          }\n        } else if (!ThomPikeCont(p[i])) {\n          pty->state = kPtyUtf8;\n          pty->u8 = ThomPikeByte(p[i]);\n          pty->n8 = ThomPikeLen(p[i]) - 1;\n        }\n        break;\n      case kPtyUtf8:\n        if (ThomPikeCont(p[i])) {\n          pty->u8 = ThomPikeMerge(pty->u8, p[i]);\n          if (--pty->n8) break;\n        }\n        wc = pty->u8;\n        if ((0x00 <= wc && wc <= 0x1F) || (0x7F <= wc && wc <= 0x9F)) {\n          PtyCntrl(pty, wc);\n        } else {\n          PtyWriteGlyph(pty, wc, wcwidth(wc));\n        }\n        pty->state = kPtyAscii;\n        pty->u8 = 0;\n        --i;\n        break;\n      case kPtyEsc:\n        if (p[i] == '[') {\n          pty->state = kPtyCsi;\n        } else if (0x30 <= p[i] && p[i] <= 0x7E) {\n          PtyEscAppend(pty, p[i]);\n          PtyEsc(pty);\n          pty->state = kPtyAscii;\n        } else if (0x20 <= p[i] && p[i] <= 0x2F) {\n          PtyEscAppend(pty, p[i]);\n        } else {\n          pty->state = kPtyAscii;\n        }\n        break;\n      case kPtyCsi:\n        PtyEscAppend(pty, p[i]);\n        switch (p[i]) {\n          case ':':\n          case ';':\n          case '<':\n          case '=':\n          case '>':\n          case '?':\n          case '0':\n          case '1':\n          case '2':\n          case '3':\n          case '4':\n          case '5':\n          case '6':\n          case '7':\n          case '8':\n          case '9':\n            break;\n          case '`':\n          case '~':\n          case '^':\n          case '@':\n          case '[':\n          case ']':\n          case '{':\n          case '}':\n          case '_':\n          case '|':\n          case '\\\\':\n          case 'a':\n          case 'b':\n          case 'c':\n          case 'd':\n          case 'e':\n          case 'f':\n          case 'g':\n          case 'h':\n          case 'i':\n          case 'j':\n          case 'k':\n          case 'l':\n          case 'm':\n          case 'n':\n          case 'o':\n          case 'p':\n          case 'q':\n          case 'r':\n          case 's':\n          case 't':\n          case 'u':\n          case 'v':\n          case 'w':\n          case 'x':\n          case 'y':\n          case 'z':\n          case 'A':\n          case 'B':\n          case 'C':\n          case 'D':\n          case 'E':\n          case 'F':\n          case 'G':\n          case 'H':\n          case 'I':\n          case 'J':\n          case 'K':\n          case 'L':\n          case 'M':\n          case 'N':\n          case 'O':\n          case 'P':\n          case 'Q':\n          case 'R':\n          case 'S':\n          case 'T':\n          case 'U':\n          case 'V':\n          case 'W':\n          case 'X':\n          case 'Y':\n          case 'Z':\n            PtyCsi(pty);\n            pty->state = kPtyAscii;\n            break;\n          default:\n            pty->state = kPtyAscii;\n            continue;\n        }\n        break;\n      default:\n        __builtin_unreachable();\n    }\n  }\n  return n;\n}\n\nssize_t PtyWriteInput(struct Pty *pty, const void *data, size_t n) {\n  int c;\n  bool cr;\n  char *p;\n  const char *q;\n  size_t i, j, m;\n  q = (char *)data;\n  p = pty->input.p;\n  i = pty->input.i;\n  m = pty->input.n;\n  if (i + n * 2 + 1 > m) {\n    m = MAX(m, 8);\n    do m += m >> 1;\n    while (i + n * 2 + 1 > m);\n    if (!(p = (char *)realloc(p, m))) {\n      return -1;\n    }\n    pty->input.p = p;\n    pty->input.n = m;\n  }\n  // TODO(jart): Figure out how translation settings for these work.\n  cr = i && p[i - 1] == '\\r';\n  for (j = 0; j < n; ++j) {\n    c = q[j] & 255;\n    if (c == '\\r') {\n      cr = true;\n    } else if (cr) {\n      if (c != '\\n') {\n        p[i++] = '\\n';\n      }\n      cr = false;\n    }\n    p[i++] = c;\n  }\n  /* if (cr) { */\n  /*   p[i++] = '\\n'; */\n  /* } */\n  if (!(pty->conf & kPtyNoecho)) {\n    PtyWrite(pty, p + pty->input.i, i - pty->input.i);\n  }\n  pty->input.i = i;\n  return n;\n}\n\nssize_t PtyRead(struct Pty *pty, void *buf, size_t size) {\n  char *p;\n  size_t n;\n  n = MIN(size, pty->input.i);\n  if (!(pty->conf & kPtyNocanon)) {\n    if ((p = (char *)memchr(pty->input.p, '\\n', n))) {\n      n = MIN(n, pty->input.p - p + 1);\n    } else {\n      n = 0;\n    }\n  }\n  memcpy(buf, pty->input.p, n);\n  memcpy(pty->input.p, pty->input.p + n, pty->input.i - n);\n  pty->input.i -= n;\n  return n;\n}\n\nstatic char *PtyEncodeRgb(char *p, int rgb) {\n  return p + sprintf(p, \"2;%u;%u;%u\", (rgb & 0x0000ff) >> 000,\n                     (rgb & 0x00ff00) >> 010, (rgb & 0xff0000) >> 020);\n}\n\nstatic char *PtyEncodeXterm256(char *p, int xt) {\n  return p + sprintf(p, \"5;%u\", xt);\n}\n\nchar *PtyEncodeStyle(char *p, u32 xr, u32 pr, u32 fg, u32 bg) {\n  *p++ = 033;\n  *p++ = '[';\n  if (pr & (kPtyBold | kPtyFaint | kPtyFlip | kPtyUnder | kPtyDunder |\n            kPtyBlink | kPtyStrike | kPtyFg | kPtyBg)) {\n    if (xr & (kPtyBold | kPtyFaint)) {\n      if ((xr & (kPtyBold | kPtyFaint)) ^ (pr & (kPtyBold | kPtyFaint))) {\n        *p++ = '2';\n        *p++ = '2';\n        *p++ = ';';\n      }\n      if (pr & kPtyBold) {\n        *p++ = '1';\n        *p++ = ';';\n      }\n      if (pr & kPtyFaint) {\n        *p++ = '2';\n        *p++ = ';';\n      }\n    }\n    if (xr & (kPtyUnder | kPtyDunder)) {\n      if ((xr & (kPtyUnder | kPtyDunder)) ^ (pr & (kPtyUnder | kPtyDunder))) {\n        *p++ = '2';\n        *p++ = '4';\n        *p++ = ';';\n      }\n      if (pr & kPtyUnder) {\n        *p++ = '4';\n        *p++ = ';';\n      }\n      if (pr & kPtyDunder) {\n        *p++ = '2';\n        *p++ = '1';\n        *p++ = ';';\n      }\n    }\n    if (xr & (kPtyFlip | kPtyBlink | kPtyStrike)) {\n      if (xr & kPtyFlip) {\n        if (!(pr & kPtyFlip)) *p++ = '2';\n        *p++ = '7';\n        *p++ = ';';\n      }\n      if (xr & kPtyBlink) {\n        if (!(pr & kPtyBlink)) *p++ = '2';\n        *p++ = '5';\n        *p++ = ';';\n      }\n      if (xr & kPtyStrike) {\n        if (!(pr & kPtyStrike)) *p++ = '2';\n        *p++ = '9';\n        *p++ = ';';\n      }\n    }\n    if (xr & (kPtyFg | kPtyTrue)) {\n      *p++ = '3';\n      if (pr & kPtyFg) {\n        *p++ = '8';\n        *p++ = ';';\n        if (pr & kPtyTrue) {\n          p = PtyEncodeRgb(p, fg);\n        } else {\n          p = PtyEncodeXterm256(p, fg);\n        }\n      } else {\n        *p++ = '9';\n      }\n      *p++ = ';';\n    }\n    if (xr & (kPtyBg | kPtyTrue)) {\n      *p++ = '4';\n      if (pr & kPtyBg) {\n        *p++ = '8';\n        *p++ = ';';\n        if (pr & kPtyTrue) {\n          p = PtyEncodeRgb(p, bg);\n        } else {\n          p = PtyEncodeXterm256(p, bg);\n        }\n      } else {\n        *p++ = '9';\n      }\n      *p++ = ';';\n    }\n    unassert(';' == p[-1]);\n    p[-1] = 'm';\n  } else {\n    *p++ = '0';\n    *p++ = 'm';\n  }\n  return p;\n}\n\nint PtyAppendLine(struct Pty *pty, struct Buffer *buf, unsigned y) {\n  u64 u;\n  char *p, *pb;\n  u32 i, j, n, wc, np, xp, pr, fg, bg, ci;\n  int w;\n  if (y >= pty->yn) {\n    errno = EINVAL;\n    return -1;\n  }\n  n = buf->i + pty->xn * 60; /* torture character length */\n  if (n > buf->n) {\n    if (!(p = (char *)realloc(buf->p, n))) return -1;\n    buf->p = p;\n    buf->n = n;\n  }\n  i = y * pty->xn;\n  j = (y + 1) * pty->xn;\n  pb = buf->p + buf->i;\n  ci = !(pty->conf & kPtyNocursor) && y == pty->y ? i + pty->x : -1;\n  for (pr = 0; i < j; i += w) {\n    np = pty->prs[i];\n    if (!(np & kPtyConceal)) {\n      wc = pty->wcs[i];\n      unassert(!(0x00 <= wc && wc <= 0x1F));\n      unassert(!(0x7F <= wc && wc <= 0x9F));\n      if (0x20 <= wc && wc <= 0x7E) {\n        u = wc;\n        w = 1;\n      } else {\n        u = tpenc(wc);\n        w = wcwidth(wc);\n        w = MAX(1, w);\n      }\n    } else {\n      u = ' ';\n      w = 1;\n    }\n    if (i == ci) {\n      if (u != ' ') {\n        np ^= kPtyFlip;\n      } else {\n        u = tpenc(CURSOR);\n        if (pty->conf & kPtyBlinkcursor) {\n          np |= kPtyBlink;\n        }\n      }\n    }\n    fg = bg = -1;\n    xp = pr ^ np;\n    if (np & (kPtyFg | kPtyBg)) {\n      if (np & kPtyFg) {\n        if (pty->fgs[i] != fg) xp |= kPtyFg;\n        fg = pty->fgs[i];\n      }\n      if (np & kPtyBg) {\n        if (pty->bgs[i] != bg) xp |= kPtyBg;\n        bg = pty->bgs[i];\n      }\n    }\n    p = pb;\n    if (xp) {\n      pr = np;\n      p = PtyEncodeStyle(p, xp, pr, fg, bg);\n    }\n    do {\n      *p++ = u & 0xFF;\n      u >>= 8;\n    } while (u);\n    unassert(p - pb <= 60);\n    pb = p;\n  }\n  unassert(pb - buf->p <= buf->n);\n  buf->i = pb - buf->p;\n  return 0;\n}\n"
  },
  {
    "path": "blink/pty.h",
    "content": "#ifndef BLINK_PTY_H_\n#define BLINK_PTY_H_\n#include \"blink/buffer.h\"\n#include \"blink/types.h\"\n\n#define kPtyFg      0x0001\n#define kPtyBg      0x0002\n#define kPtyBold    0x0004\n#define kPtyFlip    0x0008\n#define kPtyFaint   0x0010\n#define kPtyUnder   0x0020\n#define kPtyDunder  0x0040\n#define kPtyTrue    0x0080\n#define kPtyBlink   0x0100\n#define kPtyItalic  0x0200\n#define kPtyFraktur 0x0400\n#define kPtyStrike  0x0800\n#define kPtyConceal 0x1000\n\n#define kPtyBell        0x001\n#define kPtyRedzone     0x002\n#define kPtyNocursor    0x004\n#define kPtyBlinkcursor 0x008\n#define kPtyNocanon     0x010\n#define kPtyNoecho      0x020\n#define kPtyNoopost     0x040\n#define kPtyLed1        0x080\n#define kPtyLed2        0x100\n#define kPtyLed3        0x200\n#define kPtyLed4        0x400\n\nenum PtyState {\n  kPtyAscii,\n  kPtyUtf8,\n  kPtyEsc,\n  kPtyCsi,\n};\n\nstruct PtyEsc {\n  unsigned i;\n  char s[64];\n};\n\nstruct Pty {\n  int y;\n  int x;\n  int yn;\n  int xn;\n  u32 u8;\n  u32 n8;\n  u32 pr;\n  u32 fg;\n  u32 bg;\n  u32 conf;\n  u32 save;\n  u32 *wcs;\n  u32 *prs;\n  u32 *fgs;\n  u32 *bgs;\n  wchar_t *xlat;\n  enum PtyState state;\n  struct PtyEsc esc;\n  struct Buffer input;\n};\n\nvoid FreePty(struct Pty *);\nstruct Pty *NewPty(void);\nvoid PtyResize(struct Pty *, int, int);\nssize_t PtyRead(struct Pty *, void *, size_t);\nssize_t PtyWrite(struct Pty *, const void *, size_t);\nssize_t PtyWriteInput(struct Pty *, const void *, size_t);\nint PtyAppendLine(struct Pty *, struct Buffer *, unsigned);\nvoid PtyFullReset(struct Pty *);\nvoid PtyMemmove(struct Pty *, long, long, long);\nvoid PtyErase(struct Pty *, long, long);\nvoid PtySetY(struct Pty *, int);\nvoid PtySetX(struct Pty *, int);\n\n#endif /* BLINK_PTY_H_ */\n"
  },
  {
    "path": "blink/pun.h",
    "content": "#ifndef BLINK_PUN_H_\n#define BLINK_PUN_H_\n#include \"blink/types.h\"\n\nunion FloatPun {\n  float f;\n  u32 i;\n};\n\nunion DoublePun {\n  double f;\n  u64 i;\n};\n\nunion FloatVectorPun {\n  union FloatPun u[4];\n  float f[4];\n};\n\nunion DoubleVectorPun {\n  union DoublePun u[2];\n  double f[2];\n};\n\n#endif /* BLINK_PUN_H_ */\n"
  },
  {
    "path": "blink/random.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/random.h\"\n\n#include <errno.h>\n#include <fcntl.h>\n#include <stdbool.h>\n#include <sys/types.h>\n#include <time.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/errno.h\"\n#include \"blink/linux.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/types.h\"\n#include \"blink/util.h\"\n\n#ifdef HAVE_KERN_ARND\n#include <sys/sysctl.h>\n#endif\n\n#ifdef HAVE_SYS_GETRANDOM\n#include <sys/syscall.h>\n#endif\n\n#ifdef HAVE_RTLGENRANDOM\n#include <w32api/_mingw.h>\nbool __stdcall SystemFunction036(void *, __LONG32);\n#endif\n\n#if !defined(HAVE_SYS_GETRANDOM) && \\\n    (defined(HAVE_GETRANDOM) || defined(HAVE_SYS_GETENTROPY))\n#include <sys/random.h>\n#endif\n\n#ifdef HAVE_DEV_URANDOM\nstatic ssize_t GetDevRandom(char *p, size_t n) {\n  int fd;\n  ssize_t rc;\n  if ((fd = open(\"/dev/urandom\", O_RDONLY | O_CLOEXEC)) == -1) return -1;\n  rc = read(fd, p, n);\n  close(fd);\n  return rc;\n}\n#endif\n\n#ifdef HAVE_KERN_ARND\nstatic ssize_t GetKernArnd(char *p, size_t n) {\n  size_t m, i = 0;\n  int cmd[2] = {CTL_KERN, KERN_ARND};\n  for (;;) {\n    m = n - i;\n    if (sysctl(cmd, 2, p + i, &m, 0, 0) != -1) {\n      if ((i += m) == n) {\n        return n;\n      }\n    } else {\n      return i ? i : -1;\n    }\n  }\n}\n#endif\n\nstatic ssize_t GetWeakRandom(char *p, size_t n) {\n  u64 word;\n  size_t i, j;\n  static bool once;\n  static u64 state;\n  if (!once) {\n    LOGF(\"generating weak random data\");\n    state = time(0);\n    once = true;\n  }\n  for (i = 0; i < n;) {\n    word = Vigna(&state);\n    for (j = 0; j < 8 && i < n; ++i, ++j) {\n      p[i] = word;\n      word >>= 8;\n    }\n  }\n  return n;\n}\n\n// \"The user of getrandom() must always check the return value, to\n// determine whether either an error occurred or fewer bytes than\n// requested were returned. In the case where GRND_RANDOM is not\n// specified and buflen is less than or equal to 256, a return of fewer\n// bytes than requested should never happen, but the careful programmer\n// will check for this anyway!\" -Quoth the Linux Programmer's Manual §\n// getrandom().\n\nssize_t GetRandom(void *p, size_t n, int flags) {\n#ifdef GRND_RANDOM\n  _Static_assert(GRND_RANDOM == GRND_RANDOM_LINUX, \"\");\n#endif\n#ifdef GRND_NONBLOCK\n  _Static_assert(GRND_NONBLOCK == GRND_NONBLOCK_LINUX, \"\");\n#endif\n#ifdef HAVE_SYS_GETRANDOM\n  // we need to favor SYS_getrandom right now since our ./configure\n  // script isn't smart enough to accommodate our bundled toolchain\n  return syscall(SYS_getrandom, p, n, flags);\n#elif defined(HAVE_GETRANDOM)\n  return getrandom(p, n, flags);\n#elif defined(HAVE_RTLGENRANDOM)\n  return SystemFunction036(p, n) ? n : -1;\n#elif defined(HAVE_GETENTROPY) || defined(HAVE_SYS_GETENTROPY)\n  return !getentropy((char *)p, MIN(256, n)) ? n : -1;\n#elif defined(HAVE_KERN_ARND)\n  return GetKernArnd((char *)p, n);\n#elif defined(HAVE_DEV_URANDOM)\n  return GetDevRandom((char *)p, n);\n#else\n  return GetWeakRandom((char *)p, n);\n#endif\n}\n"
  },
  {
    "path": "blink/random.h",
    "content": "#ifndef BLINK_RANDOM_H_\n#define BLINK_RANDOM_H_\n#include <sys/types.h>\n\nssize_t GetRandom(void *, size_t, int);\n\n#endif /* BLINK_RANDOM_H_ */\n"
  },
  {
    "path": "blink/rde.h",
    "content": "#ifndef BLINK_RDE_H_\n#define BLINK_RDE_H_\n\n#define kRexbRmMask 000000003600\n#define RexbRm(x)   ((x & kRexbRmMask) >> 007)\n\n#define kRexrRegMask 000000000017\n#define RexrReg(x)   ((x & kRexrRegMask) >> 000)\n\n#define kOplengthMask 00007400000000000000000\n#define Oplength(x)   ((x & kOplengthMask) >> 065)\n\n#define kRegRexbSrmMask 00000170000\n#define RexbSrm(x)      ((x & kRegRexbSrmMask) >> 014)\n\n#define Rex(x)        ((x & 000000000020) >> 004)\n#define Osz(x)        ((x & 000000000040) >> 005)\n#define Asz(x)        ((x & 000010000000) >> 025)\n#define Srm(x)        ((x & 000000070000) >> 014)\n#define Rexr(x)       ((x & 000000000010) >> 003)\n#define Rexw(x)       ((x & 000000000100) >> 006)\n#define Rexx(x)       ((x & 000000400000) >> 021)\n#define Rexb(x)       ((x & 000000002000) >> 012)\n#define Sego(x)       ((x & 000007000000) >> 022)\n#define Ymm(x)        ((x & 010000000000) >> 036)\n#define RegLog2(x)    ((x & 006000000000) >> 034)\n#define ModrmRm(x)    ((x & 000000001600) >> 007)\n#define ModrmReg(x)   ((x & 000000000007) >> 000)\n#define ModrmSrm(x)   ((x & 000000070000) >> 014)\n#define ModrmMod(x)   ((x & 000060000000) >> 026)\n#define RexRexr(x)    ((x & 000000000037) >> 000)\n#define RexRexb(x)    ((x & 000000007600) >> 007)\n#define RexRexbSrm(x) ((x & 000000370000) >> 014)\n#define Modrm(x)      (ModrmMod(x) << 6 | ModrmReg(x) << 3 | ModrmRm(x))\n\n#define SibBase(x)  ((x & 00000000000340000000000) >> 040)\n#define SibIndex(x) ((x & 00000000003400000000000) >> 043)\n#define SibScale(x) ((x & 00000000014000000000000) >> 046)\n#define Opcode(x)   ((x & 00000007760000000000000) >> 050)\n#define Opmap(x)    ((x & 00000070000000000000000) >> 060)\n#define Mopcode(x)  ((x & 00000077760000000000000) >> 050)\n#define Rep(x)      ((x & 00000300000000000000000) >> 063)\n#define WordLog2(x) ((x & 00030000000000000000000) >> 071)\n#define Vreg(x)     ((x & 01700000000000000000000) >> 074)\n\n#define Bite(x)     (~ModrmSrm(x) & 1)\n#define RexbBase(x) (Rexb(x) << 3 | SibBase(x))\n\n#define IsByteOp(x)        (~Srm(rde) & 1)\n#define SibExists(x)       (ModrmRm(x) == 4)\n#define IsModrmRegister(x) (ModrmMod(x) == 3)\n#define SibHasIndex(x)     (SibIndex(x) != 4 || Rexx(x))\n#define SibHasBase(x)      (SibBase(x) != 5 || ModrmMod(x))\n#define SibIsAbsolute(x)   (!SibHasBase(x) && !SibHasIndex(x))\n#define IsRipRelative(x)   (Eamode(x) && ModrmRm(x) == 5 && !ModrmMod(x))\n\n#endif /* BLINK_RDE_H_ */\n"
  },
  {
    "path": "blink/rdrand.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/assert.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/random.h\"\n#include \"blink/thread.h\"\n#include \"blink/util.h\"\n\n#define RESEED_INTERVAL 16\n\nstatic struct Rdrand {\n  pthread_mutex_t_ lock;\n  u64 state;\n  unsigned count;\n} g_rdrand = {\n    .lock = PTHREAD_MUTEX_INITIALIZER_,\n};\n\nstatic void OpRand(P, u64 x) {\n  WriteRegister(rde, RegRexbRm(m, rde), x);\n  m->flags = SetFlag(m->flags, FLAGS_CF, true);\n}\n\nvoid OpRdrand(P) {\n  LOCK(&g_rdrand.lock);\n  if (!(g_rdrand.count++ % RESEED_INTERVAL)) {\n    unassert(GetRandom(&g_rdrand.state, 8, 0) == 8);\n  }\n  OpRand(A, Vigna(&g_rdrand.state));\n  UNLOCK(&g_rdrand.lock);\n}\n\nvoid OpRdseed(P) {\n  u64 x;\n  unassert(GetRandom(&x, 8, 0) == 8);\n  OpRand(A, x);\n}\n"
  },
  {
    "path": "blink/readansi.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <ctype.h>\n#include <errno.h>\n#include <poll.h>\n#include <unistd.h>\n\n#ifdef __EMSCRIPTEN__\n#include <emscripten.h>\n#endif\n\n#include \"blink/builtin.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/thompike.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n\nssize_t readansi(int fd, char *buf, size_t size) {\n  u8 c;\n  int rc, i, j;\n  enum { kAscii, kUtf8, kEsc, kCsi, kSs } t;\n  if (size) buf[0] = 0;\n  for (j = i = 0, t = kAscii;;) {\n    if (i + 2 >= size) {\n      errno = ENOMEM;\n      return -1;\n    }\n    if ((rc = VfsRead(fd, &c, 1)) != 1) {\n      if (rc == -1 && errno == EINTR && i) {\n        continue;\n      }\n      if (rc == -1 && errno == EAGAIN) {\n#ifdef __EMSCRIPTEN__\n        emscripten_sleep(50);\n#else\n        struct pollfd pfd;\n        pfd.fd = fd;\n        pfd.events = POLLIN;\n        VfsPoll(&pfd, 1, 0);\n#endif\n        continue;\n      }\n      return rc;\n    }\n    buf[i++] = c;\n    buf[i] = 0;\n    switch (t) {\n      case kAscii:\n        if (c < 0200) {\n          if (c == 033) {\n            t = kEsc;\n          } else {\n            return i;\n          }\n        } else if (c >= 0300) {\n          t = kUtf8;\n          j = ThomPikeLen(c) - 1;\n        }\n        break;\n      case kUtf8:\n        if (!--j) return i;\n        break;\n      case kEsc:\n        switch (c) {\n          case '[':\n            t = kCsi;\n            break;\n          case 'N':\n          case 'O':\n            t = kSs;\n            break;\n          case 0x20:\n          case 0x21:\n          case 0x22:\n          case 0x23:\n          case 0x24:\n          case 0x25:\n          case 0x26:\n          case 0x27:\n          case 0x28:\n          case 0x29:\n          case 0x2A:\n          case 0x2B:\n          case 0x2C:\n          case 0x2D:\n          case 0x2E:\n          case 0x2F:\n            break;\n          default:\n            return i;\n        }\n        break;\n      case kCsi:\n        switch (c) {\n          case ':':\n          case ';':\n          case '<':\n          case '=':\n          case '>':\n          case '?':\n          case '0':\n          case '1':\n          case '2':\n          case '3':\n          case '4':\n          case '5':\n          case '6':\n          case '7':\n          case '8':\n          case '9':\n            break;\n          default:\n            return i;\n        }\n        break;\n      case kSs:\n        return i;\n      default:\n        __builtin_unreachable();\n    }\n  }\n}\n"
  },
  {
    "path": "blink/realpath.c",
    "content": "/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8   -*-│\n│ vi: set noet ft=c ts=8 tw=8 fenc=utf-8                                   :vi │\n╚──────────────────────────────────────────────────────────────────────────────╝\n│                                                                              │\n│  Musl Libc                                                                   │\n│  Copyright © 2005-2014 Rich Felker, et al.                                   │\n│                                                                              │\n│  Permission is hereby granted, free of charge, to any person obtaining       │\n│  a copy of this software and associated documentation files (the             │\n│  \"Software\"), to deal in the Software without restriction, including         │\n│  without limitation the rights to use, copy, modify, merge, publish,         │\n│  distribute, sublicense, and/or sell copies of the Software, and to          │\n│  permit persons to whom the Software is furnished to do so, subject to       │\n│  the following conditions:                                                   │\n│                                                                              │\n│  The above copyright notice and this permission notice shall be              │\n│  included in all copies or substantial portions of the Software.             │\n│                                                                              │\n│  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,             │\n│  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF          │\n│  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.      │\n│  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY        │\n│  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,        │\n│  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE           │\n│  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                      │\n│                                                                              │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"blink/limits.h\"\n#include \"blink/util.h\"\n\n// clang-format off\n\nstatic size_t slash_len(const char *s)\n{\n\tconst char *s0 = s;\n\twhile (*s == '/') s++;\n\treturn s-s0;\n}\n\nchar *realpath_(const char *filename, char *resolved)\n{\n\tssize_t k;\n\tchar stack[PATH_MAX+1];\n\tchar output[PATH_MAX];\n\tsize_t p, q, l, l0, cnt=0, nup=0;\n\tint check_dir=0;\n\n\tif (!filename) {\n\t\terrno = EINVAL;\n\t\treturn 0;\n\t}\n\tl = strnlen(filename, sizeof stack);\n\tif (!l) {\n\t\terrno = ENOENT;\n\t\treturn 0;\n\t}\n\tif (l >= PATH_MAX) goto toolong;\n\tp = sizeof stack - l - 1;\n\tq = 0;\n\tmemcpy(stack+p, filename, l+1);\n\n\t/* Main loop. Each iteration pops the next part from stack of\n\t * remaining path components and consumes any slashes that follow.\n\t * If not a link, it's moved to output; if a link, contents are\n\t * pushed to the stack. */\nrestart:\n\tfor (; ; p+=slash_len(stack+p)) {\n\t\t/* If stack starts with /, the whole component is / or //\n\t\t * and the output state must be reset. */\n\t\tif (stack[p] == '/') {\n\t\t\tcheck_dir=0;\n\t\t\tnup=0;\n\t\t\tq=0;\n\t\t\toutput[q++] = '/';\n\t\t\tp++;\n\t\t\t/* Initial // is special. */\n\t\t\tif (stack[p] == '/' && stack[p+1] != '/')\n\t\t\t\toutput[q++] = '/';\n\t\t\tcontinue;\n\t\t}\n\n\t\tchar *z = strchrnul(stack+p, '/');\n\t\tl0 = l = z-(stack+p);\n\n\t\tif (!l && !check_dir) break;\n\n\t\t/* Skip any . component but preserve check_dir status. */\n\t\tif (l==1 && stack[p]=='.') {\n\t\t\tp += l;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* Copy next component onto output at least temporarily, to\n\t\t * call readlink, but wait to advance output position until\n\t\t * determining it's not a link. */\n\t\tif (q && output[q-1] != '/') {\n\t\t\tif (!p) goto toolong;\n\t\t\tstack[--p] = '/';\n\t\t\tl++;\n\t\t}\n\t\tif (q+l >= PATH_MAX) goto toolong;\n\t\tmemcpy(output+q, stack+p, l);\n\t\toutput[q+l] = 0;\n\t\tp += l;\n\n\t\tint up = 0;\n\t\tif (l0==2 && stack[p-2]=='.' && stack[p-1]=='.') {\n\t\t\tup = 1;\n\t\t\t/* Any non-.. path components we could cancel start\n\t\t\t * after nup repetitions of the 3-byte string \"../\";\n\t\t\t * if there are none, accumulate .. components to\n\t\t\t * later apply to cwd, if needed. */\n\t\t\tif (q <= 3*nup) {\n\t\t\t\tnup++;\n\t\t\t\tq += l;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t/* When previous components are already known to be\n\t\t\t * directories, processing .. can skip readlink. */\n\t\t\tif (!check_dir) goto skip_readlink;\n\t\t}\n\t\tk = readlink(output, stack, p);\n\t\tif (k==p) goto toolong;\n\t\tif (!k) {\n\t\t\terrno = ENOENT;\n\t\t\treturn 0;\n\t\t}\n\t\tif (k<0) {\n\t\t\tif (errno != EINVAL) return 0;\nskip_readlink:\n\t\t\tcheck_dir = 0;\n\t\t\tif (up) {\n\t\t\t\twhile(q && output[q-1]!='/') q--;\n\t\t\t\tif (q>1 && (q>2 || output[0]!='/')) q--;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (l0) q += l;\n\t\t\tcheck_dir = stack[p];\n\t\t\tcontinue;\n\t\t}\n\t\tif (++cnt == GetSymloopMax()) {\n\t\t\terrno = ELOOP;\n\t\t\treturn 0;\n\t\t}\n\n\t\t/* If link contents end in /, strip any slashes already on\n\t\t * stack to avoid /->// or //->/// or spurious toolong. */\n\t\tif (stack[k-1]=='/') while (stack[p]=='/') p++;\n\t\tp -= k;\n\t\tmemmove(stack+p, stack, k);\n\n\t\t/* Skip the stack advancement in case we have a new\n\t\t * absolute base path. */\n\t\tgoto restart;\n\t}\n\n \toutput[q] = 0;\n\n\tif (output[0] != '/') {\n\t\tif (!getcwd(stack, sizeof stack)) return 0;\n\t\tl = strlen(stack);\n\t\t/* Cancel any initial .. components. */\n\t\tp = 0;\n\t\twhile (nup--) {\n\t\t\twhile(l>1 && stack[l-1]!='/') l--;\n\t\t\tif (l>1) l--;\n\t\t\tp += 2;\n\t\t\tif (p<q) p++;\n\t\t}\n\t\tif (q-p && stack[l-1]!='/') stack[l++] = '/';\n\t\tif (l + (q-p) + 1 >= PATH_MAX) goto toolong;\n\t\tmemmove(output + l, output + p, q - p + 1);\n\t\tmemcpy(output, stack, l);\n\t\tq = l + q-p;\n\t}\n\n\tif (resolved) {\n\t\treturn (char *)memcpy(resolved, output, q+1);\n\t}\n\telse return strdup(output);\n\ntoolong:\n\terrno = ENAMETOOLONG;\n\treturn 0;\n}\n"
  },
  {
    "path": "blink/reset.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <math.h>\n#include <string.h>\n\n#include \"blink/flags.h\"\n#include \"blink/machine.h\"\n#include \"blink/stats.h\"\n\n#define LDBL 3\n#define RINT 0\n\nstatic void ResetFpu(struct Machine *m) {\n#ifndef DISABLE_X87\n  long i;\n  for (i = 0; i < 8; ++i) {\n    m->fpu.st[i] = -NAN;\n  }\n  m->fpu.sw = 0;\n  m->fpu.tw = -1;\n#endif\n  // We diverge from System V ABI here since we don't have long double\n  // support yet. We only support double precision when using x87 fpu.\n  //\n  //\t8087 FPU Control Word\n  //\t IM: Invalid Operation ───────────────┐\n  //\t DM: Denormal Operand ───────────────┐│\n  //\t ZM: Zero Divide ───────────────────┐││\n  //\t OM: Overflow ─────────────────────┐│││\n  //\t UM: Underflow ───────────────────┐││││\n  //\t PM: Precision ──────────────────┐│││││\n  //\t PC: Precision Control ───────┐  ││││││\n  //\t  {float,∅,double,long double}│  ││││││\n  //\t RC: Rounding Control ──────┐ │  ││││││\n  //\t  {even, →-∞, →+∞, →0}      │┌┤  ││││││\n  //\t                           ┌┤││  ││││││\n  //\t                          d││││rr││││││\n  //          0b0000000000000000000001001111111\n  m->fpu.cw = 0x027f;\n}\n\nstatic void ResetSse(struct Machine *m) {\n  // SSE CONTROL AND STATUS REGISTER\n  // IE: Invalid Operation Flag ──────────────┐\n  // DE: Denormal Flag ──────────────────────┐│\n  // ZE: Divide-by-Zero Flag ───────────────┐││\n  // OE: Overflow Flag ────────────────────┐│││\n  // UE: Underflow Flag ──────────────────┐││││\n  // PE: Precision Flag ─────────────────┐│││││\n  // DAZ: Denormals Are Zeros ──────────┐││││││\n  // IM: Invalid Operation Mask ───────┐│││││││\n  // DM: Denormal Operation Mask ─────┐││││││││\n  // ZM: Divide-by-Zero Mask ────────┐│││││││││\n  // OM: Overflow Mask ─────────────┐││││││││││\n  // UM: Underflow Mask ───────────┐│││││││││││\n  // PM: Precision Mask ──────────┐││││││││││││\n  // RC: Rounding Control ───────┐│││││││││││││\n  //   {even, →-∞, →+∞, →0}      ││││││││││││││\n  //                            ┌┤│││││││││││││\n  //           ┌───────────────┐│││││││││││││││\n  //           │   reserved    ││││││││││││││││\n  //         0b00000000000000000001111110000000\n  m->mxcsr = 0x1f80;\n  memset(m->xmm, 0, sizeof(m->xmm));\n}\n\nvoid ResetCpu(struct Machine *m) {\n  m->faultaddr = 0;\n  m->opcache->stashsize = 0;\n  m->stashaddr = 0;\n  m->writeaddr = 0;\n  m->readaddr = 0;\n  m->writesize = 0;\n  m->readsize = 0;\n  m->flags = 0;\n  m->flags = SetFlag(m->flags, FLAGS_VF, 1);\n  m->flags = SetFlag(m->flags, FLAGS_IOPL, 3);\n  memset(m->beg, 0, sizeof(m->beg));\n  memset(m->bofram, 0, sizeof(m->bofram));\n  memset(&m->freelist, 0, sizeof(m->freelist));\n  ResetSse(m);\n  ResetFpu(m);\n}\n\nvoid ResetTlb(struct Machine *m) {\n  STATISTIC(++tlb_resets);\n  memset(m->tlb, 0, sizeof(m->tlb));\n  m->opcache->codevirt = 0;\n  m->opcache->codehost = 0;\n}\n\nvoid ResetInstructionCache(struct Machine *m) {\n  STATISTIC(++icache_resets);\n  memset(m->opcache->icache, 0, sizeof(m->opcache->icache));\n  m->opcache->codevirt = 0;\n  m->opcache->codehost = 0;\n}\n"
  },
  {
    "path": "blink/signal.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/signal.h\"\n\n#include <signal.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/endian.h\"\n#include \"blink/ldbl.h\"\n#include \"blink/linux.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/syscall.h\"\n#include \"blink/thread.h\"\n#include \"blink/util.h\"\n#include \"blink/xlat.h\"\n\nstruct SignalFrame {\n  u8 ret[8];\n  struct siginfo_linux si;\n  struct ucontext_linux uc;\n  struct fpstate_linux fp;\n};\n\nbool IsSignalIgnoredByDefault(int sig) {\n  return sig == SIGURG_LINUX ||   //\n         sig == SIGCONT_LINUX ||  //\n         sig == SIGCHLD_LINUX ||  //\n         sig == SIGWINCH_LINUX;\n}\n\nbool IsSignalSerious(int sig) {\n  return sig == SIGFPE_LINUX ||   //\n         sig == SIGILL_LINUX ||   //\n         sig == SIGBUS_LINUX ||   //\n         sig == SIGQUIT_LINUX ||  //\n         sig == SIGTRAP_LINUX ||  //\n         sig == SIGSEGV_LINUX ||  //\n         sig == SIGSTOP_LINUX ||  //\n         sig == SIGKILL_LINUX;\n}\n\nvoid DeliverSignal(struct Machine *m, int sig, int code) {\n  u64 sp;\n  struct SignalFrame sf;\n  if (IsMakingPath(g_machine)) AbandonPath(g_machine);\n  memset(&sf, 0, sizeof(sf));\n  // capture the current state of the machine\n  Write32(sf.si.signo, sig);\n  Write32(sf.si.code, code);\n  if (sig == SIGILL_LINUX ||   //\n      sig == SIGFPE_LINUX ||   //\n      sig == SIGSEGV_LINUX ||  //\n      sig == SIGBUS_LINUX ||   //\n      sig == SIGTRAP_LINUX) {\n    Write64(sf.si.addr, m->faultaddr);\n    SYS_LOGF(\"delivering %s {.si_code = %d, .si_addr = %#\" PRIx64 \"}\",\n             DescribeSignal(sig), code, m->faultaddr);\n  } else {\n    SYS_LOGF(\"delivering %s, {.si_code = %d}\", DescribeSignal(sig), code);\n    if (sig == SIGTRAP_LINUX) {\n      Write64(sf.uc.trapno, m->trapno);\n    }\n  }\n  Write64(sf.uc.sigmask, m->sigmask);\n  memcpy(sf.uc.r8, m->r8, 8);\n  memcpy(sf.uc.r9, m->r9, 8);\n  memcpy(sf.uc.r10, m->r10, 8);\n  memcpy(sf.uc.r11, m->r11, 8);\n  memcpy(sf.uc.r12, m->r12, 8);\n  memcpy(sf.uc.r13, m->r13, 8);\n  memcpy(sf.uc.r14, m->r14, 8);\n  memcpy(sf.uc.r15, m->r15, 8);\n  memcpy(sf.uc.rdi, m->di, 8);\n  memcpy(sf.uc.rsi, m->si, 8);\n  memcpy(sf.uc.rbp, m->bp, 8);\n  memcpy(sf.uc.rbx, m->bx, 8);\n  memcpy(sf.uc.rdx, m->dx, 8);\n  memcpy(sf.uc.rax, m->ax, 8);\n  memcpy(sf.uc.rcx, m->cx, 8);\n  memcpy(sf.uc.rsp, m->sp, 8);\n  Write64(sf.uc.rip, m->ip);\n  Write64(sf.uc.eflags, m->flags);\n  Write16(sf.fp.cwd, m->fpu.cw);\n#ifndef DISABLE_X87\n  Write16(sf.fp.swd, m->fpu.sw);\n  Write16(sf.fp.ftw, m->fpu.tw);\n  Write16(sf.fp.fop, m->fpu.op);\n  Write64(sf.fp.rip, m->fpu.ip);\n  Write64(sf.fp.rdp, m->fpu.dp);\n  {\n    int i;\n    for (i = 0; i < 8; ++i) {\n      SerializeLdbl(sf.fp.st[i], m->fpu.st[i]);\n    }\n  }\n#endif\n  memcpy(sf.fp.xmm, m->xmm, sizeof(sf.fp.xmm));\n  // set the thread signal mask to the one specified by the signal\n  // handler. by default, the signal being delivered will be added\n  // within the mask unless the guest program specifies SA_NODEFER\n  m->sigmask |= Read64(m->system->hands[sig - 1].mask);\n  if (~Read64(m->system->hands[sig - 1].flags) & SA_NODEFER_LINUX) {\n    m->sigmask |= (u64)1 << (sig - 1);\n  }\n  SIG_LOGF(\"sigmask deliver %\" PRIx64, m->sigmask);\n  // if the guest setup a sigaltstack() and the signal handler used\n  // SA_ONSTACK then use that alternative stack for signal handling\n  // otherwise use the current stack, and do not touch the red zone\n  // because gcc assumes that it owns the 128 bytes underneath rsp.\n  if ((Read64(m->system->hands[sig - 1].flags) & SA_ONSTACK_LINUX) &&\n      !(Read32(m->sigaltstack.flags) & SS_DISABLE_LINUX)) {\n    sp = Read64(m->sigaltstack.sp) + Read64(m->sigaltstack.size);\n    if (Read32(m->sigaltstack.flags) & SS_AUTODISARM_LINUX) {\n      Write32(m->sigaltstack.flags,\n              Read32(m->sigaltstack.flags) & ~SS_AUTODISARM_LINUX);\n    }\n  } else {\n    sp = Read64(m->sp);\n    sp -= kRedzoneSize;\n  }\n  // put signal and machine state on the stack. the guest may change\n  // these values to edit the program's non-signal handler cpu state\n  _Static_assert(!(sizeof(struct siginfo_linux) & 15), \"\");\n  _Static_assert(!(sizeof(struct fpstate_linux) & 15), \"\");\n  _Static_assert(!(sizeof(struct ucontext_linux) & 15), \"\");\n  _Static_assert((sizeof(struct SignalFrame) & 15) == 8, \"\");\n  sp = ROUNDDOWN(sp, 16);\n  sp -= sizeof(sf);\n  unassert((sp & 15) == 8);\n  SIG_LOGF(\"restorer is %\" PRIx64, Read64(m->system->hands[sig - 1].restorer));\n  memcpy(sf.ret, m->system->hands[sig - 1].restorer, 8);\n  Write64(sf.uc.fpstate, sp + offsetof(struct SignalFrame, fp));\n  SIG_LOGF(\"delivering signal @ %\" PRIx64, sp);\n  if (CopyToUserWrite(m, sp, &sf, sizeof(sf)) == -1) {\n    LOGF(\"stack overflow delivering signal\");\n    TerminateSignal(m, SIGSEGV_LINUX, m->segvcode);\n  }\n  // finally, call the signal handler using the sigaction arguments\n  Put64(m->sp, sp);\n  Put64(m->di, sig);\n  Put64(m->si, sp + offsetof(struct SignalFrame, si));\n  Put64(m->dx, sp + offsetof(struct SignalFrame, uc));\n  SIG_LOGF(\"handler is %\" PRIx64, Read64(m->system->hands[sig - 1].handler));\n  m->ip = Read64(m->system->hands[sig - 1].handler);\n}\n\nvoid SigRestore(struct Machine *m) {\n  struct SignalFrame sf;\n  // when the guest returns from the signal handler, it'll call a\n  // pointer to the sa_restorer trampoline which is assumed to be\n  //\n  //   __restore_rt:\n  //     mov $15,%rax\n  //     syscall\n  //\n  // which doesn't change SP, thus we can restore the SignalFrame\n  // and load any change that the guest made to the machine state\n  SYS_LOGF(\"rt_sigreturn(%#\" PRIx64 \")\", Read64(m->sp) - 8);\n  unassert(!CopyFromUserRead(m, &sf, Read64(m->sp) - 8, sizeof(sf)));\n  m->ip = Read64(sf.uc.rip);\n  m->flags = Read64(sf.uc.eflags);\n  m->sigmask = Read64(sf.uc.sigmask);\n  SIG_LOGF(\"sigmask restore %\" PRIx64, m->sigmask);\n  memcpy(m->r8, sf.uc.r8, 8);\n  memcpy(m->r9, sf.uc.r9, 8);\n  memcpy(m->r10, sf.uc.r10, 8);\n  memcpy(m->r11, sf.uc.r11, 8);\n  memcpy(m->r12, sf.uc.r12, 8);\n  memcpy(m->r13, sf.uc.r13, 8);\n  memcpy(m->r14, sf.uc.r14, 8);\n  memcpy(m->r15, sf.uc.r15, 8);\n  memcpy(m->di, sf.uc.rdi, 8);\n  memcpy(m->si, sf.uc.rsi, 8);\n  memcpy(m->bp, sf.uc.rbp, 8);\n  memcpy(m->bx, sf.uc.rbx, 8);\n  memcpy(m->dx, sf.uc.rdx, 8);\n  memcpy(m->ax, sf.uc.rax, 8);\n  memcpy(m->cx, sf.uc.rcx, 8);\n  m->fpu.cw = Read16(sf.fp.cwd);\n  memcpy(m->sp, sf.uc.rsp, 8);\n#ifndef DISABLE_X87\n  m->fpu.sw = Read16(sf.fp.swd);\n  m->fpu.tw = Read16(sf.fp.ftw);\n  m->fpu.op = Read16(sf.fp.fop);\n  m->fpu.ip = Read64(sf.fp.rip);\n  m->fpu.dp = Read64(sf.fp.rdp);\n  {\n    int i;\n    for (i = 0; i < 8; ++i) {\n      m->fpu.st[i] = DeserializeLdbl(sf.fp.st[i]);\n    }\n  }\n#endif\n  memcpy(m->xmm, sf.fp.xmm, sizeof(sf.fp.xmm));\n  m->restored = true;\n  atomic_store_explicit(&m->attention, true, memory_order_release);\n}\n\nstatic int ConsumeSignalImpl(struct Machine *m, int *delivered, bool *restart) {\n  int sig;\n  i64 handler;\n  u64 signals;\n  if (delivered) *delivered = 0;\n  if (restart) *restart = true;\n  // look for a pending signal that isn't currently masked\n  while ((signals = m->signals & ~m->sigmask)) {\n    sig = bsr(signals) + 1;\n    m->signals &= ~((u64)1 << (sig - 1));\n    handler = Read64(m->system->hands[sig - 1].handler);\n    if (handler == SIG_DFL_LINUX) {\n      if (IsSignalIgnoredByDefault(sig)) {\n        SYS_LOGF(\"ignoring %s\", DescribeSignal(sig));\n        return 0;\n      } else {\n        SIG_LOGF(\"default action is to terminate upon signal %s\",\n                 DescribeSignal(sig));\n        return sig;\n      }\n    } else if (handler == SIG_IGN_LINUX) {\n      SYS_LOGF(\"explicitly ignoring %s\", DescribeSignal(sig));\n      return 0;\n    }\n    if (delivered) {\n      *delivered = sig;\n    }\n    if (restart) {\n      *restart = !!(Read64(m->system->hands[sig - 1].flags) & SA_RESTART_LINUX);\n    }\n    DeliverSignal(m, sig, SI_KERNEL_LINUX);\n    return 0;\n  }\n  return 0;\n}\n\nint ConsumeSignal(struct Machine *m, int *delivered, bool *restart) {\n  int rc;\n  if (m->metal) return 0;\n  LOCK(&m->system->sig_lock);\n  rc = ConsumeSignalImpl(m, delivered, restart);\n  UNLOCK(&m->system->sig_lock);\n  return rc;\n}\n\nvoid EnqueueSignal(struct Machine *m, int sig) {\n  if (m && (1 <= sig && sig <= 64)) {\n    m->signals |= 1ul << (sig - 1);\n    if ((m->signals & ~m->sigmask)) {\n      atomic_store_explicit(&m->attention, true, memory_order_release);\n    }\n  }\n}\n\nvoid CheckForSignals(struct Machine *m) {\n  int sig;\n  if (atomic_load_explicit(&m->killed, memory_order_acquire)) {\n    SysExit(m, 0);\n#ifndef DISABLE_JIT\n  } else if (m->selfmodifying) {\n    FlushSmcQueue(m);\n    m->selfmodifying = false;\n#endif\n  } else if (m->signals & ~m->sigmask) {\n    if ((sig = ConsumeSignal(m, 0, 0))) {\n      TerminateSignal(m, sig, 0);\n    }\n  } else {\n    atomic_store_explicit(&m->attention, false, memory_order_relaxed);\n  }\n}\n"
  },
  {
    "path": "blink/signal.h",
    "content": "#ifndef BLINK_SIGNAL_H_\n#define BLINK_SIGNAL_H_\n#include \"blink/machine.h\"\n\nbool IsSignalSerious(int);\nbool IsSignalQueueable(int);\nvoid SigRestore(struct Machine *);\nbool IsSignalIgnoredByDefault(int);\nvoid OnSignal(int, siginfo_t *, void *);\nvoid EnqueueSignal(struct Machine *, int);\nvoid DeliverSignal(struct Machine *, int, int);\nvoid TerminateSignal(struct Machine *, int, int);\nint ConsumeSignal(struct Machine *, int *, bool *);\nvoid DeliverSignalToUser(struct Machine *, int, int);\n\n#endif /* BLINK_SIGNAL_H_ */\n"
  },
  {
    "path": "blink/sigwinch.h",
    "content": "#ifndef BLINK_SIGWINCH_H_\n#define BLINK_SIGWINCH_H_\n#include <signal.h>\n\n#ifndef SIGWINCH\n// SIGWINCH has the same magic number on all platforms. Yet for some\n// reason, platforms are stubborn about defining it in their headers\n#define SIGWINCH 28\n#endif\n\n#endif /* BLINK_SIGWINCH_H_ */\n"
  },
  {
    "path": "blink/smc.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/flag.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/stats.h\"\n#include \"blink/tunables.h\"\n#include \"blink/util.h\"\n#include \"blink/xlat.h\"\n\n#ifndef DISABLE_JIT\n\n// @asyncsignalsafe\nstatic int ProtectHostPages(struct System *s, i64 vaddr, i64 size, int prot) {\n  i64 a, b;\n  unassert(HasLinearMapping());\n  a = ROUNDDOWN(vaddr, FLAG_pagesize);\n  b = ROUNDUP(vaddr + size, FLAG_pagesize);\n  return mprotect(ToHost(a), b - a, prot);\n}\n\nstatic int ProtectSelfModifyingCode(struct System *s, i64 vaddr, i64 size) {\n  MEM_LOGF(\"ProtectSelfModifyingCode(%#\" PRIx64 \", %#\" PRIx64 \")\", vaddr, size);\n  return ProtectHostPages(s, vaddr, size, PROT_READ);\n}\n\n// @asyncsignalsafe\nstatic int UnprotectSelfModifyingCode(struct System *s, i64 vaddr, i64 size) {\n  MEM_LOGF(\"UnprotectSelfModifyingCode(%#\" PRIx64 \", %#\" PRIx64 \")\", vaddr,\n           size);\n  return ProtectHostPages(s, vaddr, size, PROT_READ | PROT_WRITE);\n}\n\n// @asyncsignalsafe\nbool IsPageInSmcQueue(struct Machine *m, i64 page) {\n  int i;\n  i64 tmp;\n  page &= -4096;\n  STATISTIC(++smc_checks);\n  for (i = 0; i < kSmcQueueSize; ++i) {\n    if ((tmp = m->smcqueue.p[i]) == page) {\n      if (i) {\n        m->smcqueue.p[i - 0] = m->smcqueue.p[i - 1];\n        m->smcqueue.p[i - 1] = tmp;\n      }\n      return true;\n    }\n  }\n  return false;\n}\n\n// @asyncsignalsafe\nvoid AddPageToSmcQueue(struct Machine *m, i64 page) {\n  int i;\n  page &= -4096;\n  for (i = 0; i < kSmcQueueSize; ++i) {\n    if (!m->smcqueue.p[i]) {\n      STATISTIC(++smc_enqueued);\n      m->smcqueue.p[i] = page;\n      m->selfmodifying = true;\n      atomic_store_explicit(&m->attention, true, memory_order_release);\n      return;\n    }\n  }\n  ERRF(\"self-modifying code page queue exhausted\");\n  Abort();\n}\n\nvoid FlushSmcQueue(struct Machine *m) {\n  int i;\n  i64 page;\n  unassert(m->selfmodifying);\n  STATISTIC(++smc_flushes);\n  for (i = 0; i < kSmcQueueSize; ++i) {\n    if ((page = m->smcqueue.p[i])) {\n      m->smcqueue.p[i] = 0;\n      if (!IsJitDisabled(&m->system->jit)) {\n        if (HasLinearMapping()) {\n          unassert(!ProtectSelfModifyingCode(m->system, page, 1));\n        }\n        ResetJitPage(&m->system->jit, page);\n      }\n      if (IsMakingPath(m) && (m->path.start & -4096) == (page & -4096)) {\n        AbandonPath(m);\n      }\n    }\n  }\n}\n\ni64 ProtectRwxMemory(struct System *s, i64 rc, i64 virt, i64 size,\n                     long pagesize, int prot) {\n  i64 a, b;\n  unassert(HasLinearMapping());\n  unassert(!IsJitDisabled(&s->jit));\n  if (rc == -1) return -1;\n  if (prot == (PROT_READ | PROT_WRITE | PROT_EXEC)) {\n    a = ROUNDDOWN(virt, 4096);\n    b = ROUNDUP(virt + size, 4096);\n    // we can only do proper smc invalidation on the host page aligned\n    // subset of the mmap()'d or mprotect()'d executable memory region\n    a = ROUNDUP(a, pagesize);\n    b = ROUNDDOWN(b, pagesize);\n    if (b > a) {\n      unassert(!ProtectSelfModifyingCode(s, a, b - a));\n    }\n  }\n  return rc;\n}\n\n// @asyncsignalsafe\nbool IsSelfModifyingCodeSegfault(struct Machine *m, const siginfo_t *si) {\n  u64 pte;\n  i64 vaddr;\n  SIG_LOGF(\"IsSelfModifyingCodeSegfault()\");\n  unassert(m->system->loaded);\n  if (si->si_signo != SIGSEGV) return false;\n  if (si->si_code != SEGV_ACCERR) return false;\n  vaddr = ConvertHostToGuestAddress(m->system, si->si_addr, &pte);\n  SIG_LOGF(\"ConvertHostToGuestAddress(%p) -> %#\" PRIx64, si->si_addr, vaddr);\n  if ((pte & (PAGE_V | PAGE_U | PAGE_RW | PAGE_XD)) !=\n      (PAGE_V | PAGE_U | PAGE_RW)) {\n    return false;\n  }\n  STATISTIC(++smc_segfaults);\n  if (UnprotectSelfModifyingCode(m->system, vaddr, 1)) {\n    ERRF(\"failed to unprotect self modifying code\");\n    return false;\n  }\n  if (!IsPageInSmcQueue(m, vaddr)) {\n    AddPageToSmcQueue(m, vaddr);\n  }\n  return true;\n}\n\n#endif /* DISABLE_JIT */\n"
  },
  {
    "path": "blink/sse.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/sse.h\"\n\n#include <string.h>\n\n#include \"blink/case.h\"\n#include \"blink/endian.h\"\n#include \"blink/intrin.h\"\n#include \"blink/likely.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n\nstatic void MmxPaddusb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] = MIN(255, x[i] + y[i]);\n  }\n}\n\nstatic void MmxPsubusb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] = MIN(255, MAX(0, x[i] - y[i]));\n  }\n}\n\nstatic void MmxPsubsb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] = MAX(-128, MIN(127, (i8)x[i] - (i8)y[i]));\n  }\n}\n\nstatic void MmxPaddsb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 8; ++i) {\n    x[i] = MAX(-128, MIN(127, (i8)x[i] + (i8)y[i]));\n  }\n}\n\nstatic void MmxPmulhrsw(u8 x[8], const u8 y[8]) {\n  i16 a, b;\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    a = Get16(x + i * 2);\n    b = Get16(y + i * 2);\n    Put16(x + i * 2, (((a * b) >> 14) + 1) >> 1);\n  }\n}\n\nstatic void MmxPmaddubsw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2,\n          MAX(-32768, MIN(32767, (x[i * 2 + 0] * (i8)y[i * 2 + 0] +\n                                  x[i * 2 + 1] * (i8)y[i * 2 + 1]))));\n  }\n}\n\nstatic void MmxPsraw(u8 x[8], unsigned k) {\n  unsigned i;\n  if (k > 15) k = 15;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, (i16)Get16(x + i * 2) >> k);\n  }\n}\n\nstatic void MmxPsrad(u8 x[8], unsigned k) {\n  unsigned i;\n  if (k > 31) k = 31;\n  for (i = 0; i < 2; ++i) {\n    Put32(x + i * 4, (i32)Get32(x + i * 4) >> k);\n  }\n}\n\nstatic void MmxPsrlw(u8 x[8], unsigned k) {\n  unsigned i;\n  if (k < 16) {\n    for (i = 0; i < 4; ++i) {\n      Put16(x + i * 2, Get16(x + i * 2) >> k);\n    }\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPsllw(u8 x[8], unsigned k) {\n  unsigned i;\n  if (k <= 15) {\n    for (i = 0; i < 4; ++i) {\n      Put16(x + i * 2, Get16(x + i * 2) << k);\n    }\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPsrld(u8 x[8], unsigned k) {\n  unsigned i;\n  if (k <= 31) {\n    for (i = 0; i < 2; ++i) {\n      Put32(x + i * 4, Get32(x + i * 4) >> k);\n    }\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPslld(u8 x[8], unsigned k) {\n  unsigned i;\n  if (k <= 31) {\n    for (i = 0; i < 2; ++i) {\n      Put32(x + i * 4, Get32(x + i * 4) << k);\n    }\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPsrlq(u8 x[8], unsigned k) {\n  if (k <= 63) {\n    Put64(x, Get64(x) >> k);\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPsllq(u8 x[8], unsigned k) {\n  if (k <= 63) {\n    Put64(x, Get64(x) << k);\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPslldq(u8 x[8], unsigned k) {\n  u8 t[8];\n  unsigned i;\n  if (k > 8) k = 8;\n  for (i = 0; i < k; ++i) t[i] = 0;\n  for (i = 0; i < 8 - k; ++i) t[k + i] = x[i];\n  memcpy(x, t, 8);\n}\n\nstatic void MmxPsrldq(u8 x[8], unsigned k) {\n  u8 t[8];\n  if (k > 8) k = 8;\n  memcpy(t, x + k, 8 - k);\n  memset(t + (8 - k), 0, k);\n  memcpy(x, t, 8);\n}\n\nstatic void MmxPalignr(u8 x[8], const u8 y[8], unsigned k) {\n  u8 t[24];\n  memcpy(t, y, 8);\n  memcpy(t + 8, x, 8);\n  memset(t + 16, 0, 8);\n  memcpy(x, t + MIN(k, 16), 8);\n}\n\nstatic void MmxPsubd(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    Put32(x + i * 4, Get32(x + i * 4) - Get32(y + i * 4));\n  }\n}\n\nstatic void MmxPaddd(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    Put32(x + i * 4, Get32(x + i * 4) + Get32(y + i * 4));\n  }\n}\n\nstatic void MmxPaddq(u8 x[8], const u8 y[8]) {\n  Put64(x, Get64(x) + Get64(y));\n}\n\nstatic void MmxPsubq(u8 x[8], const u8 y[8]) {\n  Put64(x, Get64(x) - Get64(y));\n}\n\nstatic void MmxPsubusw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, MIN(65535, MAX(0, Get16(x + i * 2) - Get16(y + i * 2))));\n  }\n}\n\nstatic void MmxPminsw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, MIN((i16)Get16(x + i * 2), (i16)Get16(y + i * 2)));\n  }\n}\n\nstatic void MmxPmaxsw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, MAX((i16)Get16(x + i * 2), (i16)Get16(y + i * 2)));\n  }\n}\n\nstatic void MmxPackuswb(u8 x[8], const u8 y[8]) {\n  u8 t[8];\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    t[i + 0] = MIN(255, MAX(0, (i16)Get16(x + i * 2)));\n  }\n  for (i = 0; i < 4; ++i) {\n    t[i + 4] = MIN(255, MAX(0, (i16)Get16(y + i * 2)));\n  }\n  memcpy(x, t, 8);\n}\n\nstatic void MmxPacksswb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  u8 t[8];\n  for (i = 0; i < 4; ++i) {\n    t[i + 0] = MAX(-128, MIN(127, (i16)Get16(x + i * 2)));\n  }\n  for (i = 0; i < 4; ++i) {\n    t[i + 4] = MAX(-128, MIN(127, (i16)Get16(y + i * 2)));\n  }\n  memcpy(x, t, 8);\n}\n\nstatic void MmxPackssdw(u8 x[8], const u8 y[8]) {\n  u8 t[8];\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    Put16(t + i * 2 + 0, MAX(-32768, MIN(32767, (i32)Get32(x + i * 4))));\n  }\n  for (i = 0; i < 2; ++i) {\n    Put16(t + i * 2 + 4, MAX(-32768, MIN(32767, (i32)Get32(y + i * 4))));\n  }\n  memcpy(x, t, 8);\n}\n\nstatic void MmxPcmpgtd(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    Put32(x + i * 4, -((i32)Get32(x + i * 4) > (i32)Get32(y + i * 4)));\n  }\n}\n\nstatic void MmxPcmpeqd(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    Put32(x + i * 4, -(Get32(x + i * 4) == Get32(y + i * 4)));\n  }\n}\n\nstatic void MmxPsrawv(u8 x[8], const u8 y[8]) {\n  u64 k;\n  unsigned i;\n  k = Get64(y);\n  if (k > 15) k = 15;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, (i16)Get16(x + i * 2) >> k);\n  }\n}\n\nstatic void MmxPsradv(u8 x[8], const u8 y[8]) {\n  u64 k;\n  unsigned i;\n  k = Get64(y);\n  if (k > 31) k = 31;\n  for (i = 0; i < 2; ++i) {\n    Put32(x + i * 4, (i32)Get32(x + i * 4) >> k);\n  }\n}\n\nstatic void MmxPsrlwv(u8 x[8], const u8 y[8]) {\n  u64 k;\n  unsigned i;\n  k = Get64(y);\n  if (k < 16) {\n    for (i = 0; i < 4; ++i) {\n      Put16(x + i * 2, Get16(x + i * 2) >> k);\n    }\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPsllwv(u8 x[8], const u8 y[8]) {\n  u64 k;\n  unsigned i;\n  k = Get64(y);\n  if (k < 16) {\n    for (i = 0; i < 4; ++i) {\n      Put16(x + i * 2, Get16(x + i * 2) << k);\n    }\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPsrldv(u8 x[8], const u8 y[8]) {\n  u64 k;\n  unsigned i;\n  k = Get64(y);\n  if (k < 32) {\n    for (i = 0; i < 2; ++i) {\n      Put32(x + i * 4, Get32(x + i * 4) >> k);\n    }\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPslldv(u8 x[8], const u8 y[8]) {\n  u64 k;\n  unsigned i;\n  k = Get64(y);\n  if (k < 32) {\n    for (i = 0; i < 2; ++i) {\n      Put32(x + i * 4, Get32(x + i * 4) << k);\n    }\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPsrlqv(u8 x[8], const u8 y[8]) {\n  u64 k;\n  k = Get64(y);\n  if (k < 64) {\n    Put64(x, Get64(x) >> k);\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPsllqv(u8 x[8], const u8 y[8]) {\n  u64 k;\n  k = Get64(y);\n  if (k < 64) {\n    Put64(x, Get64(x) << k);\n  } else {\n    memset(x, 0, 8);\n  }\n}\n\nstatic void MmxPsadbw(u8 x[8], const u8 y[8]) {\n  unsigned i, s, t;\n  for (s = i = 0; i < 4; ++i) {\n    s += ABS(x[i] - y[i]);\n  }\n  for (t = 0; i < 8; ++i) {\n    t += ABS(x[i] - y[i]);\n  }\n  Put32(x + 0, s);\n  Put32(x + 4, t);\n}\n\nstatic void MmxPmaddwd(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    Put32(x + i * 4, ((i16)Get16(x + i * 4 + 0) * (i16)Get16(y + i * 4 + 0) +\n                      (i16)Get16(x + i * 4 + 2) * (i16)Get16(y + i * 4 + 2)));\n  }\n}\n\nstatic void MmxPmulhuw(u8 x[8], const u8 y[8]) {\n  u32 v;\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    v = Get16(x + i * 2);\n    v *= Get16(y + i * 2);\n    v >>= 16;\n    Put16(x + i * 2, v);\n  }\n}\n\nstatic void MmxPmuludq(u8 x[8], const u8 y[8]) {\n  Put64(x, (u64)Get32(x) * Get32(y));\n}\n\nstatic void MmxPmulld(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    Put32(x + i * 4, Get32(x + i * 4) * Get32(y + i * 4));\n  }\n}\n\nstatic void MmxPshufb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  u8 t[8];\n  for (i = 0; i < 8; ++i) {\n    t[i] = (y[i] & 128) ? 0 : x[y[i] & 7];\n  }\n  memcpy(x, t, 8);\n}\n\nstatic void MmxPsignb(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  int v;\n  for (i = 0; i < 8; ++i) {\n    v = (i8)y[i];\n    if (!v) {\n      x[i] = 0;\n    } else if (v < 0) {\n      x[i] = -(i8)x[i];\n    }\n  }\n}\n\nstatic void MmxPsignw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  int v;\n  for (i = 0; i < 4; ++i) {\n    v = (i16)Get16(y + i * 2);\n    if (!v) {\n      Put16(x + i * 2, 0);\n    } else if (v < 0) {\n      Put16(x + i * 2, -(i16)Get16(x + i * 2));\n    }\n  }\n}\n\nstatic void MmxPsignd(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  i32 v;\n  for (i = 0; i < 2; ++i) {\n    v = Get32(y + i * 4);\n    if (!v) {\n      Put32(x + i * 4, 0);\n    } else if (v < 0) {\n      Put32(x + i * 4, -Get32(x + i * 4));\n    }\n  }\n}\n\nstatic void MmxPabsw(u8 x[8], const u8 y[8]) {\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put16(x + i * 2, ABS((i16)Get16(y + i * 2)));\n  }\n}\n\nstatic void MmxPabsd(u8 x[8], const u8 y[8]) {\n  i32 v;\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    v = Get32(y + i * 4);\n    Put32(x + i * 4, v >= 0 ? v : -(u32)v);\n  }\n}\n\nstatic void MmxPhaddw(u8 x[8], const u8 y[8]) {\n  u8 t[8];\n  Put16(t + 0 * 2, Get16(x + 0 * 2) + Get16(x + 1 * 2));\n  Put16(t + 1 * 2, Get16(x + 2 * 2) + Get16(x + 3 * 2));\n  Put16(t + 2 * 2, Get16(y + 0 * 2) + Get16(y + 1 * 2));\n  Put16(t + 3 * 2, Get16(y + 2 * 2) + Get16(y + 3 * 2));\n  memcpy(x, t, 8);\n}\n\nstatic void MmxPhsubw(u8 x[8], const u8 y[8]) {\n  u8 t[8];\n  Put16(t + 0 * 2, Get16(x + 0 * 2) - Get16(x + 1 * 2));\n  Put16(t + 1 * 2, Get16(x + 2 * 2) - Get16(x + 3 * 2));\n  Put16(t + 2 * 2, Get16(y + 0 * 2) - Get16(y + 1 * 2));\n  Put16(t + 3 * 2, Get16(y + 2 * 2) - Get16(y + 3 * 2));\n  memcpy(x, t, 8);\n}\n\nstatic void MmxPhaddd(u8 x[8], const u8 y[8]) {\n  u8 t[8];\n  Put32(t + 0 * 4, Get32(x + 0 * 4) + Get32(x + 1 * 4));\n  Put32(t + 1 * 4, Get32(y + 0 * 4) + Get32(y + 1 * 4));\n  memcpy(x, t, 8);\n}\n\nstatic void MmxPhsubd(u8 x[8], const u8 y[8]) {\n  u8 t[8];\n  Put32(t + 0 * 4, Get32(x + 0 * 4) - Get32(x + 1 * 4));\n  Put32(t + 1 * 4, Get32(y + 0 * 4) - Get32(y + 1 * 4));\n  memcpy(x, t, 8);\n}\n\nstatic void MmxPunpcklbw(u8 x[8], const u8 y[8]) {\n  x[7] = y[3];\n  x[6] = x[3];\n  x[5] = y[2];\n  x[4] = x[2];\n  x[3] = y[1];\n  x[2] = x[1];\n  x[1] = y[0];\n  x[0] = x[0];\n}\n\nstatic void MmxPunpckhbw(u8 x[8], const u8 y[8]) {\n  x[0] = x[4];\n  x[1] = y[4];\n  x[2] = x[5];\n  x[3] = y[5];\n  x[4] = x[6];\n  x[5] = y[6];\n  x[6] = x[7];\n  x[7] = y[7];\n}\n\nstatic void MmxPunpcklwd(u8 x[8], const u8 y[8]) {\n  x[6] = y[2];\n  x[7] = y[3];\n  x[4] = x[2];\n  x[5] = x[3];\n  x[2] = y[0];\n  x[3] = y[1];\n  x[0] = x[0];\n  x[1] = x[1];\n}\n\nstatic void MmxPunpckldq(u8 x[8], const u8 y[8]) {\n  x[4] = y[0];\n  x[5] = y[1];\n  x[6] = y[2];\n  x[7] = y[3];\n  x[0] = x[0];\n  x[1] = x[1];\n  x[2] = x[2];\n  x[3] = x[3];\n}\n\nstatic void MmxPunpckhwd(u8 x[8], const u8 y[8]) {\n  x[0] = x[4];\n  x[1] = x[5];\n  x[2] = y[4];\n  x[3] = y[5];\n  x[4] = x[6];\n  x[5] = x[7];\n  x[6] = y[6];\n  x[7] = y[7];\n}\n\nstatic void MmxPunpckhdq(u8 x[8], const u8 y[8]) {\n  x[0] = x[4];\n  x[1] = x[5];\n  x[2] = x[6];\n  x[3] = x[7];\n  x[4] = y[4];\n  x[5] = y[5];\n  x[6] = y[6];\n  x[7] = y[7];\n}\n\nstatic void MmxPunpcklqdq(u8 x[8], const u8 y[8]) {\n}\n\nstatic void MmxPunpckhqdq(u8 x[8], const u8 y[8]) {\n}\n\nstatic void SsePslldq(u8 x[16], unsigned k) {\n  u8 t[16];\n  unsigned i;\n  if (k > 16) k = 16;\n  for (i = 0; i < k; ++i) t[i] = 0;\n  for (i = 0; i < 16 - k; ++i) t[k + i] = x[i];\n  memcpy(x, t, 16);\n}\n\nstatic void SsePsrldq(u8 x[16], unsigned k) {\n  u8 t[16];\n  if (k > 16) k = 16;\n  memcpy(t, x + k, 16 - k);\n  memset(t + (16 - k), 0, k);\n  memcpy(x, t, 16);\n}\n\nstatic void SsePalignr(u8 x[16], const u8 y[16], unsigned k) {\n  u8 t[48];\n  memcpy(t, y, 16);\n  memcpy(t + 16, x, 16);\n  memset(t + 32, 0, 16);\n  memcpy(x, t + MIN(k, 32), 16);\n}\n\nstatic void SsePsubd(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psubd\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put32(x + i * 4, Get32(x + i * 4) - Get32(y + i * 4));\n  }\n#endif\n}\n\nstatic void SsePaddd(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"paddd\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  for (i = 0; i < 4; ++i) {\n    Put32(x + i * 4, Get32(x + i * 4) + Get32(y + i * 4));\n  }\n#endif\n}\n\nstatic void SsePaddq(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"paddq\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    Put64(x + i * 8, Get64(x + i * 8) + Get64(y + i * 8));\n  }\n#endif\n}\n\nstatic void SsePsubq(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psubq\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    Put64(x + i * 8, Get64(x + i * 8) - Get64(y + i * 8));\n  }\n#endif\n}\n\nstatic void SsePackuswb(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"packuswb\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  u8 t[16];\n  for (i = 0; i < 8; ++i) {\n    t[i + 0] = MIN(255, MAX(0, (i16)Get16(x + i * 2)));\n  }\n  for (i = 0; i < 8; ++i) {\n    t[i + 8] = MIN(255, MAX(0, (i16)Get16(y + i * 2)));\n  }\n  memcpy(x, t, 16);\n#endif\n}\n\nstatic void SsePacksswb(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"packsswb\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  u8 t[16];\n  for (i = 0; i < 8; ++i) {\n    t[i + 0] = MAX(-128, MIN(127, (i16)Get16(x + i * 2)));\n  }\n  for (i = 0; i < 8; ++i) {\n    t[i + 8] = MAX(-128, MIN(127, (i16)Get16(y + i * 2)));\n  }\n  memcpy(x, t, 16);\n#endif\n}\n\nstatic void SsePackssdw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"packssdw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  u8 t[16];\n  for (i = 0; i < 4; ++i) {\n    Put16(t + i * 2 + 0, MAX(-32768, MIN(32767, (i32)Get32(x + i * 4))));\n  }\n  for (i = 0; i < 4; ++i) {\n    Put16(t + i * 2 + 8, MAX(-32768, MIN(32767, (i32)Get32(y + i * 4))));\n  }\n  memcpy(x, t, 16);\n#endif\n}\n\nstatic void SsePsadbw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psadbw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i, s, t;\n  for (s = i = 0; i < 8; ++i) s += ABS(x[i] - y[i]);\n  for (t = 0; i < 16; ++i) t += ABS(x[i] - y[i]);\n  Put64(x + 0, s);\n  Put64(x + 8, t);\n#endif\n}\n\nstatic void SsePmuludq(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pmuludq\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  for (i = 0; i < 2; ++i) {\n    Put64(x + i * 8, (u64)Get32(x + i * 8) * Get32(y + i * 8));\n  }\n#endif\n}\n\nstatic void SsePshufb(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pshufb\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  u8 t[16];\n  unsigned i;\n  for (i = 0; i < 16; ++i) {\n    t[i] = (y[i] & 128) ? 0 : x[y[i] & 15];\n  }\n  memcpy(x, t, 16);\n#endif\n}\n\nstatic void SsePhaddd(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"phaddd\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  u8 t[16];\n  Put32(t + 0 * 4, Get32(x + 0 * 4) + Get32(x + 1 * 4));\n  Put32(t + 1 * 4, Get32(x + 2 * 4) + Get32(x + 3 * 4));\n  Put32(t + 2 * 4, Get32(y + 0 * 4) + Get32(y + 1 * 4));\n  Put32(t + 3 * 4, Get32(y + 2 * 4) + Get32(y + 3 * 4));\n  memcpy(x, t, 16);\n#endif\n}\n\nstatic void SsePhsubd(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"phsubd\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  u8 t[16];\n  Put32(t + 0 * 4, Get32(x + 0 * 4) - Get32(x + 1 * 4));\n  Put32(t + 1 * 4, Get32(x + 2 * 4) - Get32(x + 3 * 4));\n  Put32(t + 2 * 4, Get32(y + 0 * 4) - Get32(y + 1 * 4));\n  Put32(t + 3 * 4, Get32(y + 2 * 4) - Get32(y + 3 * 4));\n  memcpy(x, t, 16);\n#endif\n}\n\nstatic void SsePhaddw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"phaddw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  u8 t[16];\n  Put16(t + 0 * 2, Get16(x + 0 * 2) + Get16(x + 1 * 2));\n  Put16(t + 1 * 2, Get16(x + 2 * 2) + Get16(x + 3 * 2));\n  Put16(t + 2 * 2, Get16(x + 4 * 2) + Get16(x + 5 * 2));\n  Put16(t + 3 * 2, Get16(x + 6 * 2) + Get16(x + 7 * 2));\n  Put16(t + 4 * 2, Get16(y + 0 * 2) + Get16(y + 1 * 2));\n  Put16(t + 5 * 2, Get16(y + 2 * 2) + Get16(y + 3 * 2));\n  Put16(t + 6 * 2, Get16(y + 4 * 2) + Get16(y + 5 * 2));\n  Put16(t + 7 * 2, Get16(y + 6 * 2) + Get16(y + 7 * 2));\n  memcpy(x, t, 16);\n#endif\n}\n\nstatic void SsePhsubw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"phsubw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  u8 t[16];\n  Put16(t + 0 * 2, Get16(x + 0 * 2) - Get16(x + 1 * 2));\n  Put16(t + 1 * 2, Get16(x + 2 * 2) - Get16(x + 3 * 2));\n  Put16(t + 2 * 2, Get16(x + 4 * 2) - Get16(x + 5 * 2));\n  Put16(t + 3 * 2, Get16(x + 6 * 2) - Get16(x + 7 * 2));\n  Put16(t + 4 * 2, Get16(y + 0 * 2) - Get16(y + 1 * 2));\n  Put16(t + 5 * 2, Get16(y + 2 * 2) - Get16(y + 3 * 2));\n  Put16(t + 6 * 2, Get16(y + 4 * 2) - Get16(y + 5 * 2));\n  Put16(t + 7 * 2, Get16(y + 6 * 2) - Get16(y + 7 * 2));\n  memcpy(x, t, 16);\n#endif\n}\n\nstatic void SsePunpcklbw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"punpcklbw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  x[0xf] = y[0x7];\n  x[0xe] = x[0x7];\n  x[0xd] = y[0x6];\n  x[0xc] = x[0x6];\n  x[0xb] = y[0x5];\n  x[0xa] = x[0x5];\n  x[0x9] = y[0x4];\n  x[0x8] = x[0x4];\n  x[0x7] = y[0x3];\n  x[0x6] = x[0x3];\n  x[0x5] = y[0x2];\n  x[0x4] = x[0x2];\n  x[0x3] = y[0x1];\n  x[0x2] = x[0x1];\n  x[0x1] = y[0x0];\n  x[0x0] = x[0x0];\n#endif\n}\n\nstatic void SsePunpckhbw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"punpckhbw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  x[0x0] = x[0x8];\n  x[0x1] = y[0x8];\n  x[0x2] = x[0x9];\n  x[0x3] = y[0x9];\n  x[0x4] = x[0xa];\n  x[0x5] = y[0xa];\n  x[0x6] = x[0xb];\n  x[0x7] = y[0xb];\n  x[0x8] = x[0xc];\n  x[0x9] = y[0xc];\n  x[0xa] = x[0xd];\n  x[0xb] = y[0xd];\n  x[0xc] = x[0xe];\n  x[0xd] = y[0xe];\n  x[0xe] = x[0xf];\n  x[0xf] = y[0xf];\n#endif\n}\n\nstatic void SsePunpcklwd(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"punpcklwd\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  x[0xe] = y[0x6];\n  x[0xf] = y[0x7];\n  x[0xc] = x[0x6];\n  x[0xd] = x[0x7];\n  x[0xa] = y[0x4];\n  x[0xb] = y[0x5];\n  x[0x8] = x[0x4];\n  x[0x9] = x[0x5];\n  x[0x6] = y[0x2];\n  x[0x7] = y[0x3];\n  x[0x4] = x[0x2];\n  x[0x5] = x[0x3];\n  x[0x2] = y[0x0];\n  x[0x3] = y[0x1];\n  x[0x0] = x[0x0];\n  x[0x1] = x[0x1];\n#endif\n}\n\nstatic void SsePunpckldq(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"punpckldq\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  x[0xc] = y[0x4];\n  x[0xd] = y[0x5];\n  x[0xe] = y[0x6];\n  x[0xf] = y[0x7];\n  x[0x8] = x[0x4];\n  x[0x9] = x[0x5];\n  x[0xa] = x[0x6];\n  x[0xb] = x[0x7];\n  x[0x4] = y[0x0];\n  x[0x5] = y[0x1];\n  x[0x6] = y[0x2];\n  x[0x7] = y[0x3];\n  x[0x0] = x[0x0];\n  x[0x1] = x[0x1];\n  x[0x2] = x[0x2];\n  x[0x3] = x[0x3];\n#endif\n}\n\nstatic void SsePunpckhwd(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"punpckhwd\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  x[0x0] = x[0x8];\n  x[0x1] = x[0x9];\n  x[0x2] = y[0x8];\n  x[0x3] = y[0x9];\n  x[0x4] = x[0xa];\n  x[0x5] = x[0xb];\n  x[0x6] = y[0xa];\n  x[0x7] = y[0xb];\n  x[0x8] = x[0xc];\n  x[0x9] = x[0xd];\n  x[0xa] = y[0xc];\n  x[0xb] = y[0xd];\n  x[0xc] = x[0xe];\n  x[0xd] = x[0xf];\n  x[0xe] = y[0xe];\n  x[0xf] = y[0xf];\n#endif\n}\n\nstatic void SsePunpckhdq(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"punpckhdq\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  x[0x0] = x[0x8];\n  x[0x1] = x[0x9];\n  x[0x2] = x[0xa];\n  x[0x3] = x[0xb];\n  x[0x4] = y[0x8];\n  x[0x5] = y[0x9];\n  x[0x6] = y[0xa];\n  x[0x7] = y[0xb];\n  x[0x8] = x[0xc];\n  x[0x9] = x[0xd];\n  x[0xa] = x[0xe];\n  x[0xb] = x[0xf];\n  x[0xc] = y[0xc];\n  x[0xd] = y[0xd];\n  x[0xe] = y[0xe];\n  x[0xf] = y[0xf];\n#endif\n}\n\nstatic void SsePunpcklqdq(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"punpcklqdq\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  x[0x8] = y[0x0];\n  x[0x9] = y[0x1];\n  x[0xa] = y[0x2];\n  x[0xb] = y[0x3];\n  x[0xc] = y[0x4];\n  x[0xd] = y[0x5];\n  x[0xe] = y[0x6];\n  x[0xf] = y[0x7];\n  x[0x0] = x[0x0];\n  x[0x1] = x[0x1];\n  x[0x2] = x[0x2];\n  x[0x3] = x[0x3];\n  x[0x4] = x[0x4];\n  x[0x5] = x[0x5];\n  x[0x6] = x[0x6];\n  x[0x7] = x[0x7];\n#endif\n}\n\nstatic void SsePunpckhqdq(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"punpckhqdq\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  x[0x0] = x[0x8];\n  x[0x1] = x[0x9];\n  x[0x2] = x[0xa];\n  x[0x3] = x[0xb];\n  x[0x4] = x[0xc];\n  x[0x5] = x[0xd];\n  x[0x6] = x[0xe];\n  x[0x7] = x[0xf];\n  x[0x8] = y[0x8];\n  x[0x9] = y[0x9];\n  x[0xa] = y[0xa];\n  x[0xb] = y[0xb];\n  x[0xc] = y[0xc];\n  x[0xd] = y[0xd];\n  x[0xe] = y[0xe];\n  x[0xf] = y[0xf];\n#endif\n}\n\nstatic void SsePsrlw(u8 x[16], unsigned k) {\n  MmxPsrlw(x + 0, k);\n  MmxPsrlw(x + 8, k);\n}\n\nstatic void SsePsraw(u8 x[16], unsigned k) {\n  MmxPsraw(x + 0, k);\n  MmxPsraw(x + 8, k);\n}\n\nstatic void SsePsllw(u8 x[16], unsigned k) {\n  MmxPsllw(x + 0, k);\n  MmxPsllw(x + 8, k);\n}\n\nstatic void SsePsrld(u8 x[16], unsigned k) {\n  MmxPsrld(x + 0, k);\n  MmxPsrld(x + 8, k);\n}\n\nstatic void SsePsrad(u8 x[16], unsigned k) {\n  MmxPsrad(x + 0, k);\n  MmxPsrad(x + 8, k);\n}\n\nstatic void SsePslld(u8 x[16], unsigned k) {\n  MmxPslld(x + 0, k);\n  MmxPslld(x + 8, k);\n}\n\nstatic void SsePsrlq(u8 x[16], unsigned k) {\n  MmxPsrlq(x + 0, k);\n  MmxPsrlq(x + 8, k);\n}\n\nstatic void SsePsllq(u8 x[16], unsigned k) {\n  MmxPsllq(x + 0, k);\n  MmxPsllq(x + 8, k);\n}\n\nstatic void SsePsubsb(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psubsb\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = MAX(-128, MIN(127, X[i] - Y[i]));\n  }\n  memcpy(x, X, 16);\n#endif\n}\n\nstatic void SsePaddsb(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"paddsb\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = MAX(-128, MIN(127, X[i] + Y[i]));\n  }\n  memcpy(x, X, 16);\n#endif\n}\n\nstatic void SsePaddusb(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"paddusb\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  u8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = MIN(255, X[i] + Y[i]);\n  }\n  memcpy(x, X, 16);\n#endif\n}\n\nstatic void SsePsubusb(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psubusb\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  u8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = MIN(255, MAX(0, X[i] - Y[i]));\n  }\n  memcpy(x, X, 16);\n#endif\n}\n\nstatic void SsePsubusw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psubusw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPsubusw(x + 0, y + 0);\n  MmxPsubusw(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePminsw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pminsw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPminsw(x + 0, y + 0);\n  MmxPminsw(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePmaxsw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pmaxsw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPmaxsw(x + 0, y + 0);\n  MmxPmaxsw(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePsignb(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psignb\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPsignb(x + 0, y + 0);\n  MmxPsignb(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePsignw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psignw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPsignw(x + 0, y + 0);\n  MmxPsignw(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePsignd(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psignd\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPsignd(x + 0, y + 0);\n  MmxPsignd(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePmulhrsw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pmulhrsw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPmulhrsw(x + 0, y + 0);\n  MmxPmulhrsw(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePabsw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pabsw\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPabsw(x + 0, y + 0);\n  MmxPabsw(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePabsd(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pabsd\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPabsd(x + 0, y + 0);\n  MmxPabsd(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePcmpgtd(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pcmpgtd\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPcmpgtd(x + 0, y + 0);\n  MmxPcmpgtd(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePcmpeqd(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pcmpeqd\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPcmpeqd(x + 0, y + 0);\n  MmxPcmpeqd(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePsrawv(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psraw\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPsrawv(x + 0, y);\n  MmxPsrawv(x + 8, y);\n#endif\n}\n\nstatic void SsePsradv(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psrad\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPsradv(x + 0, y);\n  MmxPsradv(x + 8, y);\n#endif\n}\n\nstatic void SsePsrlwv(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psrlw\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPsrlwv(x + 0, y);\n  MmxPsrlwv(x + 8, y);\n#endif\n}\n\nstatic void SsePsllwv(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psllw\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPsllwv(x + 0, y);\n  MmxPsllwv(x + 8, y);\n#endif\n}\n\nstatic void SsePsrldv(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psrld\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPsrldv(x + 0, y);\n  MmxPsrldv(x + 8, y);\n#endif\n}\n\nstatic void SsePslldv(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pslld\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPslldv(x + 0, y);\n  MmxPslldv(x + 8, y);\n#endif\n}\n\nstatic void SsePsrlqv(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psrlq\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPsrlqv(x + 0, y);\n  MmxPsrlqv(x + 8, y);\n#endif\n}\n\nstatic void SsePsllqv(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psllq\\t%1,%0\" : \"+x\"(*(char_xmma_t *)x) : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPsllqv(x + 0, y);\n  MmxPsllqv(x + 8, y);\n#endif\n}\n\nstatic void SsePmaddwd(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pmaddwd\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPmaddwd(x + 0, y + 0);\n  MmxPmaddwd(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePmulhuw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pmulhuw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPmulhuw(x + 0, y + 0);\n  MmxPmulhuw(x + 8, y + 8);\n#endif\n}\n\nstatic void SsePmulld(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pmulld\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  int i;\n  u32 X[4] = {Get32(x), Get32(x + 4), Get32(x + 8), Get32(x + 12)};\n  u32 Y[4] = {Get32(y), Get32(y + 4), Get32(y + 8), Get32(y + 12)};\n  for (i = 0; i < 4; ++i) {\n    X[i] *= Y[i];\n  }\n  for (i = 0; i < 4; ++i) {\n    Put32(x + i * 4, X[i]);\n  }\n#endif\n}\n\nstatic void SsePmaddubsw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pmaddubsw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  MmxPmaddubsw(x + 0, y + 0);\n  MmxPmaddubsw(x + 8, y + 8);\n#endif\n}\n\n#ifdef DISABLE_MMX\nrelegated void NoMmx(u8 x[8], const u8 y[8]) {\n  OpUdImpl(g_machine);\n}\nstatic void NoMmxK(u8 x[8], unsigned k) {\n  OpUdImpl(g_machine);\n}\n#define MmxKernel     NoMmx\n#define MmxPabsd      NoMmx\n#define MmxPabsw      NoMmx\n#define MmxPackssdw   NoMmx\n#define MmxPacksswb   NoMmx\n#define MmxPackuswb   NoMmx\n#define MmxPaddd      NoMmx\n#define MmxPaddq      NoMmx\n#define MmxPaddsb     NoMmx\n#define MmxPaddusb    NoMmx\n#define MmxPalignr    NoMmx\n#define MmxPcmpeqd    NoMmx\n#define MmxPcmpgtd    NoMmx\n#define MmxPhaddd     NoMmx\n#define MmxPhaddw     NoMmx\n#define MmxPhsubd     NoMmx\n#define MmxPhsubw     NoMmx\n#define MmxPmaddubsw  NoMmx\n#define MmxPmaddwd    NoMmx\n#define MmxPmaxsw     NoMmx\n#define MmxPminsw     NoMmx\n#define MmxPmulhrsw   NoMmx\n#define MmxPmulhuw    NoMmx\n#define MmxPmulld     NoMmx\n#define MmxPmuludq    NoMmx\n#define MmxPsadbw     NoMmx\n#define MmxPshufb     NoMmx\n#define MmxPsignb     NoMmx\n#define MmxPsignd     NoMmx\n#define MmxPsignw     NoMmx\n#define MmxPslld      NoMmxK\n#define MmxPslldq     NoMmxK\n#define MmxPslldv     NoMmx\n#define MmxPsllq      NoMmxK\n#define MmxPsllqv     NoMmx\n#define MmxPsllw      NoMmxK\n#define MmxPsllwv     NoMmx\n#define MmxPsrad      NoMmxK\n#define MmxPsradv     NoMmx\n#define MmxPsraw      NoMmxK\n#define MmxPsrawv     NoMmx\n#define MmxPsrld      NoMmxK\n#define MmxPsrldq     NoMmxK\n#define MmxPsrldv     NoMmx\n#define MmxPsrlq      NoMmxK\n#define MmxPsrlqv     NoMmx\n#define MmxPsrlw      NoMmxK\n#define MmxPsrlwv     NoMmx\n#define MmxPsubd      NoMmx\n#define MmxPsubq      NoMmx\n#define MmxPsubsb     NoMmx\n#define MmxPsubusb    NoMmx\n#define MmxPsubusw    NoMmx\n#define MmxPunpckhbw  NoMmx\n#define MmxPunpckhdq  NoMmx\n#define MmxPunpckhqdq NoMmx\n#define MmxPunpckhwd  NoMmx\n#define MmxPunpcklbw  NoMmx\n#define MmxPunpckldq  NoMmx\n#define MmxPunpcklqdq NoMmx\n#define MmxPunpcklwd  NoMmx\n#endif\n\nstatic void OpPsb(P, void MmxKernel(u8[8], unsigned),\n                  void SseKernel(u8[16], unsigned)) {\n  if (Osz(rde)) {\n    SseKernel(XmmRexbRm(m, rde), uimm0);\n  } else {\n    MmxKernel(XmmRexbRm(m, rde), uimm0);\n  }\n}\n\noptimizesize void Op171(P) {\n  switch (ModrmReg(rde)) {\n    case 2:\n      OpPsb(A, MmxPsrlw, SsePsrlw);\n      break;\n    case 4:\n      OpPsb(A, MmxPsraw, SsePsraw);\n      break;\n    case 6:\n      OpPsb(A, MmxPsllw, SsePsllw);\n      break;\n    default:\n      OpUdImpl(m);\n  }\n}\n\noptimizesize void Op172(P) {\n  switch (ModrmReg(rde)) {\n    case 2:\n      OpPsb(A, MmxPsrld, SsePsrld);\n      break;\n    case 4:\n      OpPsb(A, MmxPsrad, SsePsrad);\n      break;\n    case 6:\n      OpPsb(A, MmxPslld, SsePslld);\n      break;\n    default:\n      OpUdImpl(m);\n  }\n}\n\noptimizesize void Op173(P) {\n  switch (ModrmReg(rde)) {\n    case 2:\n      OpPsb(A, MmxPsrlq, SsePsrlq);\n      break;\n    case 3:\n      OpPsb(A, MmxPsrldq, SsePsrldq);\n      break;\n    case 6:\n      OpPsb(A, MmxPsllq, SsePsllq);\n      break;\n    case 7:\n      OpPsb(A, MmxPslldq, SsePslldq);\n      break;\n    default:\n      OpUdImpl(m);\n  }\n}\n\nvoid OpSsePalignr(P) {\n  if (Osz(rde)) {\n    SsePalignr(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead16(A), uimm0);\n  } else {\n#ifndef DISABLE_MMX\n    MmxPalignr(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead8(A), uimm0);\n#else\n    OpUdImpl(m);\n#endif\n  }\n}\n\nvoid OpSse(P, void MmxKernel(u8[8], const u8[8]),\n           void SseKernel(u8[16], const u8[16])) {\n  IGNORE_RACES_START();\n  if (Osz(rde)) {\n    SseKernel(XmmRexrReg(m, rde), GetXmmAddress(A));\n  } else {\n#ifndef DISABLE_MMX\n    MmxKernel(XmmRexrReg(m, rde), GetMmxAddress(A));\n#else\n    OpUdImpl(m);\n#endif\n  }\n  IGNORE_RACES_END();\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"z4P\"    // res0 = GetXmmOrMemPointer(RexbRm)\n           \"r0s1=\"  // sav1 = res0\n           \"z4Q\"    // res0 = GetXmmPointer(RexrReg)\n           \"s1a1=\"  // arg1 = sav1\n           \"t\"      // arg0 = res0\n           \"c\",     // call function\n           Osz(rde) ? SseKernel : MmxKernel);\n  }\n}\n\n// clang-format off\nvoid OpSsePunpcklbw(P) { OpSse(A, MmxPunpcklbw, SsePunpcklbw); }\nvoid OpSsePunpcklwd(P) { OpSse(A, MmxPunpcklwd, SsePunpcklwd); }\nvoid OpSsePunpckldq(P) { OpSse(A, MmxPunpckldq, SsePunpckldq); }\nvoid OpSsePacksswb(P) { OpSse(A, MmxPacksswb, SsePacksswb); }\nvoid OpSsePcmpgtd(P) { OpSse(A, MmxPcmpgtd, SsePcmpgtd); }\nvoid OpSsePackuswb(P) { OpSse(A, MmxPackuswb, SsePackuswb); }\nvoid OpSsePunpckhbw(P) { OpSse(A, MmxPunpckhbw, SsePunpckhbw); }\nvoid OpSsePunpckhwd(P) { OpSse(A, MmxPunpckhwd, SsePunpckhwd); }\nvoid OpSsePunpckhdq(P) { OpSse(A, MmxPunpckhdq, SsePunpckhdq); }\nvoid OpSsePackssdw(P) { OpSse(A, MmxPackssdw, SsePackssdw); }\nvoid OpSsePunpcklqdq(P) { OpSse(A, MmxPunpcklqdq, SsePunpcklqdq); }\nvoid OpSsePunpckhqdq(P) { OpSse(A, MmxPunpckhqdq, SsePunpckhqdq); }\nvoid OpSsePcmpeqd(P) { OpSse(A, MmxPcmpeqd, SsePcmpeqd); }\nvoid OpSsePsrlwv(P) { OpSse(A, MmxPsrlwv, SsePsrlwv); }\nvoid OpSsePsrldv(P) { OpSse(A, MmxPsrldv, SsePsrldv); }\nvoid OpSsePsrlqv(P) { OpSse(A, MmxPsrlqv, SsePsrlqv); }\nvoid OpSsePaddq(P) { OpSse(A, MmxPaddq, SsePaddq); }\nvoid OpSsePsubusb(P) { OpSse(A, MmxPsubusb, SsePsubusb); }\nvoid OpSsePsubusw(P) { OpSse(A, MmxPsubusw, SsePsubusw); }\nvoid OpSsePaddusb(P) { OpSse(A, MmxPaddusb, SsePaddusb); }\nvoid OpSsePsrawv(P) { OpSse(A, MmxPsrawv, SsePsrawv); }\nvoid OpSsePsradv(P) { OpSse(A, MmxPsradv, SsePsradv); }\nvoid OpSsePmulhuw(P) { OpSse(A, MmxPmulhuw, SsePmulhuw); }\nvoid OpSsePsubsb(P) { OpSse(A, MmxPsubsb, SsePsubsb); }\nvoid OpSsePminsw(P) { OpSse(A, MmxPminsw, SsePminsw); }\nvoid OpSsePaddsb(P) { OpSse(A, MmxPaddsb, SsePaddsb); }\nvoid OpSsePmaxsw(P) { OpSse(A, MmxPmaxsw, SsePmaxsw); }\nvoid OpSsePsllwv(P) { OpSse(A, MmxPsllwv, SsePsllwv); }\nvoid OpSsePslldv(P) { OpSse(A, MmxPslldv, SsePslldv); }\nvoid OpSsePsllqv(P) { OpSse(A, MmxPsllqv, SsePsllqv); }\nvoid OpSsePmuludq(P) { OpSse(A, MmxPmuludq, SsePmuludq); }\nvoid OpSsePmaddwd(P) { OpSse(A, MmxPmaddwd, SsePmaddwd); }\nvoid OpSsePsadbw(P) { OpSse(A, MmxPsadbw, SsePsadbw); }\nvoid OpSsePsubd(P) { OpSse(A, MmxPsubd, SsePsubd); }\nvoid OpSsePsubq(P) { OpSse(A, MmxPsubq, SsePsubq); }\nvoid OpSsePaddd(P) { OpSse(A, MmxPaddd, SsePaddd); }\nvoid OpSsePshufb(P) { OpSse(A, MmxPshufb, SsePshufb); }\nvoid OpSsePhaddw(P) { OpSse(A, MmxPhaddw, SsePhaddw); }\nvoid OpSsePhaddd(P) { OpSse(A, MmxPhaddd, SsePhaddd); }\nvoid OpSsePmaddubsw(P) { OpSse(A, MmxPmaddubsw, SsePmaddubsw); }\nvoid OpSsePhsubw(P) { OpSse(A, MmxPhsubw, SsePhsubw); }\nvoid OpSsePhsubd(P) { OpSse(A, MmxPhsubd, SsePhsubd); }\nvoid OpSsePsignb(P) { OpSse(A, MmxPsignb, SsePsignb); }\nvoid OpSsePsignw(P) { OpSse(A, MmxPsignw, SsePsignw); }\nvoid OpSsePsignd(P) { OpSse(A, MmxPsignd, SsePsignd); }\nvoid OpSsePmulhrsw(P) { OpSse(A, MmxPmulhrsw, SsePmulhrsw); }\nvoid OpSsePabsw(P) { OpSse(A, MmxPabsw, SsePabsw); }\nvoid OpSsePabsd(P) { OpSse(A, MmxPabsd, SsePabsd); }\nvoid OpSsePmulld(P) { OpSse(A, MmxPmulld, SsePmulld); }\n"
  },
  {
    "path": "blink/sse.h",
    "content": "#ifndef BLINK_SSE_H_\n#define BLINK_SSE_H_\n#include \"blink/builtin.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/tsan.h\"\n\nvoid OpSsePabsb(P);\nvoid OpSsePabsd(P);\nvoid OpSsePabsw(P);\nvoid OpSsePackssdw(P);\nvoid OpSsePacksswb(P);\nvoid OpSsePackuswb(P);\nvoid OpSsePaddb(P);\nvoid OpSsePaddd(P);\nvoid OpSsePaddq(P);\nvoid OpSsePaddsb(P);\nvoid OpSsePaddsw(P);\nvoid OpSsePaddusb(P);\nvoid OpSsePaddusw(P);\nvoid OpSsePaddw(P);\nvoid OpSsePalignr(P);\nvoid OpSsePand(P);\nvoid OpSsePandn(P);\nvoid OpSsePavgb(P);\nvoid OpSsePavgw(P);\nvoid OpSsePcmpeqb(P);\nvoid OpSsePcmpeqd(P);\nvoid OpSsePcmpeqw(P);\nvoid OpSsePcmpgtb(P);\nvoid OpSsePcmpgtd(P);\nvoid OpSsePcmpgtw(P);\nvoid OpSsePhaddd(P);\nvoid OpSsePhaddsw(P);\nvoid OpSsePhaddw(P);\nvoid OpSsePhsubd(P);\nvoid OpSsePhsubsw(P);\nvoid OpSsePhsubw(P);\nvoid OpSsePmaddubsw(P);\nvoid OpSsePmaddwd(P);\nvoid OpSsePmaxsw(P);\nvoid OpSsePmaxub(P);\nvoid OpSsePminsw(P);\nvoid OpSsePminub(P);\nvoid OpSsePmulhrsw(P);\nvoid OpSsePmulhuw(P);\nvoid OpSsePmulhw(P);\nvoid OpSsePmulld(P);\nvoid OpSsePmullw(P);\nvoid OpSsePmuludq(P);\nvoid OpSsePor(P);\nvoid OpSsePsadbw(P);\nvoid OpSsePshufb(P);\nvoid OpSsePsignb(P);\nvoid OpSsePsignd(P);\nvoid OpSsePsignw(P);\nvoid OpSsePslldv(P);\nvoid OpSsePsllqv(P);\nvoid OpSsePsllwv(P);\nvoid OpSsePsradv(P);\nvoid OpSsePsrawv(P);\nvoid OpSsePsrldv(P);\nvoid OpSsePsrlqv(P);\nvoid OpSsePsrlwv(P);\nvoid OpSsePsubb(P);\nvoid OpSsePsubd(P);\nvoid OpSsePsubq(P);\nvoid OpSsePsubsb(P);\nvoid OpSsePsubsw(P);\nvoid OpSsePsubusb(P);\nvoid OpSsePsubusw(P);\nvoid OpSsePsubw(P);\nvoid OpSsePunpckhbw(P);\nvoid OpSsePunpckhdq(P);\nvoid OpSsePunpckhqdq(P);\nvoid OpSsePunpckhwd(P);\nvoid OpSsePunpcklbw(P);\nvoid OpSsePunpckldq(P);\nvoid OpSsePunpcklqdq(P);\nvoid OpSsePunpcklwd(P);\nvoid OpSsePxor(P);\n\nvoid MmxPcmpgtb(u8[8], const u8[8]);\nvoid MmxPcmpgtw(u8[8], const u8[8]);\nvoid MmxPcmpeqb(u8[8], const u8[8]);\nvoid MmxPcmpeqw(u8[8], const u8[8]);\nvoid MmxPmullw(u8[8], const u8[8]);\nvoid MmxPminub(u8[8], const u8[8]);\nvoid MmxPaddusw(u8[8], const u8[8]);\nvoid MmxPmaxub(u8[8], const u8[8]);\nvoid MmxPavgb(u8[8], const u8[8]);\nvoid MmxPavgw(u8[8], const u8[8]);\nvoid MmxPmulhw(u8[8], const u8[8]);\nvoid MmxPsubsw(u8[8], const u8[8]);\nvoid MmxPaddsw(u8[8], const u8[8]);\nvoid MmxPsubb(u8[8], const u8[8]);\nvoid MmxPsubw(u8[8], const u8[8]);\nvoid MmxPaddb(u8[8], const u8[8]);\nvoid MmxPaddw(u8[8], const u8[8]);\nvoid MmxPhaddsw(u8[8], const u8[8]);\nvoid MmxPhsubsw(u8[8], const u8[8]);\nvoid MmxPabsb(u8[8], const u8[8]);\n\nvoid OpSse(P, void (*)(u8[8], const u8[8]), void (*)(u8[16], const u8[16]));\n\n#endif /* BLINK_SSE_H_ */\n"
  },
  {
    "path": "blink/sse2.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n\n#include \"blink/endian.h\"\n#include \"blink/intrin.h\"\n#include \"blink/macros.h\"\n#include \"blink/sse.h\"\n\n/**\n * @fileoverview SSE operations that compilers are good at vectoring.\n */\n\n#define COPY16_X_Y_FROM_x_y(T)                                   \\\n  T X[8] = {(T)Get16(x),      (T)Get16(x + 2), (T)Get16(x + 4),  \\\n            (T)Get16(x + 6),  (T)Get16(x + 8), (T)Get16(x + 10), \\\n            (T)Get16(x + 12), (T)Get16(x + 14)};                 \\\n  T Y[8] = {(T)Get16(y),      (T)Get16(y + 2), (T)Get16(y + 4),  \\\n            (T)Get16(y + 6),  (T)Get16(y + 8), (T)Get16(y + 10), \\\n            (T)Get16(y + 12), (T)Get16(y + 14)}\n\n#define COPY16_x_FROM_X     \\\n  for (i = 0; i < 8; ++i) { \\\n    Put16(x + i * 2, X[i]); \\\n  }\n\nstatic void MmxPor(u8 x[8], const u8 y[8]) {\n  *(u64 *)x |= *(u64 *)y;\n}\n\nstatic void MmxPxor(u8 x[8], const u8 y[8]) {\n  *(u64 *)x ^= *(u64 *)y;\n}\n\nstatic void MmxPand(u8 x[8], const u8 y[8]) {\n  *(u64 *)x &= *(u64 *)y;\n}\n\nstatic void MmxPandn(u8 x[8], const u8 y[8]) {\n  *(u64 *)x = ~*(u64 *)x & *(u64 *)y;\n}\n\nstatic void SsePsubw(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(u16);\n  for (i = 0; i < 8; ++i) {\n    X[i] -= Y[i];\n  }\n  COPY16_x_FROM_X;\n}\n\nstatic void SsePaddw(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(u16);\n  for (i = 0; i < 8; ++i) {\n    X[i] += Y[i];\n  }\n  COPY16_x_FROM_X;\n}\n\nstatic void SsePaddusw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"paddusw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(u16);\n  for (i = 0; i < 8; ++i) {\n    X[i] = MIN(65535, X[i] + Y[i]);\n  }\n  COPY16_x_FROM_X;\n#endif\n}\n\nstatic void SsePhaddsw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"phaddsw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  i16 t[8];\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(i16);\n  for (i = 0; i < 4; ++i) {\n    t[i] = MAX(-32768, MIN(32767, X[i * 2] + X[i * 2 + 1]));\n  }\n  for (i = 0; i < 4; ++i) {\n    t[i + 4] = MAX(-32768, MIN(32767, Y[i * 2] + Y[i * 2 + 1]));\n  }\n  memcpy(X, t, 16);\n  COPY16_x_FROM_X;\n#endif\n}\n\nstatic void SsePhsubsw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"phsubsw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  i16 t[8];\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(i16);\n  for (i = 0; i < 4; ++i) {\n    t[i] = MAX(-32768, MIN(32767, X[i * 2] - X[i * 2 + 1]));\n  }\n  for (i = 0; i < 4; ++i) {\n    t[i + 4] = MAX(-32768, MIN(32767, Y[i * 2] - Y[i * 2 + 1]));\n  }\n  memcpy(X, t, 16);\n  COPY16_x_FROM_X;\n#endif\n}\n\nstatic void SsePsubsw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"psubsw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(i16);\n  for (i = 0; i < 8; ++i) {\n    X[i] = MAX(-32768, MIN(32767, X[i] - Y[i]));\n  }\n  COPY16_x_FROM_X;\n#endif\n}\n\nstatic void SsePaddsw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"paddsw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(i16);\n  for (i = 0; i < 8; ++i) {\n    X[i] = MAX(-32768, MIN(32767, X[i] + Y[i]));\n  }\n  COPY16_x_FROM_X;\n#endif\n}\n\nstatic void SsePcmpgtw(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(i16);\n  for (i = 0; i < 8; ++i) {\n    X[i] = -(X[i] > Y[i]);\n  }\n  COPY16_x_FROM_X;\n}\n\nstatic void SsePcmpeqw(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(i16);\n  for (i = 0; i < 8; ++i) {\n    X[i] = -(X[i] == Y[i]);\n  }\n  COPY16_x_FROM_X;\n}\n\nstatic void SsePavgw(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(u16);\n  for (i = 0; i < 8; ++i) {\n    X[i] = (X[i] + Y[i] + 1) >> 1;\n  }\n  COPY16_x_FROM_X;\n}\n\nstatic void SsePmulhw(u8 x[16], const u8 y[16]) {\n#if X86_INTRINSICS\n  asm(\"pmulhw\\t%1,%0\"\n      : \"+x\"(*(char_xmma_t *)x)\n      : \"xm\"(*(const char_xmma_t *)y));\n#else\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(i16);\n  for (i = 0; i < 8; ++i) {\n    X[i] = (X[i] * Y[i]) >> 16;\n  }\n  COPY16_x_FROM_X;\n#endif\n}\n\nstatic void SsePmullw(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  COPY16_X_Y_FROM_x_y(i16);\n  for (i = 0; i < 8; ++i) {\n    X[i] *= Y[i];\n  }\n  COPY16_x_FROM_X;\n}\n\nstatic void SsePsubsb(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = MAX(-128, MIN(127, X[i] - Y[i]));\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePaddsb(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = MAX(-128, MIN(127, X[i] + Y[i]));\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePaddusb(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  u8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = MIN(255, X[i] + Y[i]);\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePsubusb(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  u8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = MIN(255, MAX(0, X[i] - Y[i]));\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePsubb(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] -= Y[i];\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePaddb(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] += Y[i];\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePor(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] |= Y[i];\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePxor(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] ^= Y[i];\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePand(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] &= Y[i];\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePandn(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = ~X[i] & Y[i];\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePcmpeqb(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = -(X[i] == Y[i]);\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePcmpgtb(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = -(X[i] > Y[i]);\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePavgb(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  u8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = (X[i] + Y[i] + 1) >> 1;\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePabsb(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  i8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = ABS((i8)Y[i]);\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePminub(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  u8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = MIN(X[i], Y[i]);\n  }\n  memcpy(x, X, 16);\n}\n\nstatic void SsePmaxub(u8 x[16], const u8 y[16]) {\n  unsigned i;\n  u8 X[16], Y[16];\n  memcpy(X, x, 16);\n  memcpy(Y, y, 16);\n  for (i = 0; i < 16; ++i) {\n    X[i] = MAX(X[i], Y[i]);\n  }\n  memcpy(x, X, 16);\n}\n\n#ifdef DISABLE_MMX\nvoid NoMmx(u8[8], const u8[8]) relegated;\n#define MmxPor     NoMmx\n#define MmxPxor    NoMmx\n#define MmxPand    NoMmx\n#define MmxPandn   NoMmx\n#define MmxPcmpgtb NoMmx\n#define MmxPcmpgtw NoMmx\n#define MmxPcmpeqb NoMmx\n#define MmxPcmpeqw NoMmx\n#define MmxPmullw  NoMmx\n#define MmxPminub  NoMmx\n#define MmxPand    NoMmx\n#define MmxPaddusw NoMmx\n#define MmxPmaxub  NoMmx\n#define MmxPandn   NoMmx\n#define MmxPavgb   NoMmx\n#define MmxPavgw   NoMmx\n#define MmxPmulhw  NoMmx\n#define MmxPsubsw  NoMmx\n#define MmxPor     NoMmx\n#define MmxPaddsw  NoMmx\n#define MmxPxor    NoMmx\n#define MmxPsubb   NoMmx\n#define MmxPsubw   NoMmx\n#define MmxPaddb   NoMmx\n#define MmxPaddw   NoMmx\n#define MmxPhaddsw NoMmx\n#define MmxPhsubsw NoMmx\n#define MmxPabsb   NoMmx\n#endif\n\n// clang-format off\nvoid OpSsePcmpgtb(P) { OpSse(A, MmxPcmpgtb, SsePcmpgtb); }\nvoid OpSsePcmpgtw(P) { OpSse(A, MmxPcmpgtw, SsePcmpgtw); }\nvoid OpSsePcmpeqb(P) { OpSse(A, MmxPcmpeqb, SsePcmpeqb); }\nvoid OpSsePcmpeqw(P) { OpSse(A, MmxPcmpeqw, SsePcmpeqw); }\nvoid OpSsePmullw(P) { OpSse(A, MmxPmullw, SsePmullw); }\nvoid OpSsePminub(P) { OpSse(A, MmxPminub, SsePminub); }\nvoid OpSsePand(P) { OpSse(A, MmxPand, SsePand); }\nvoid OpSsePaddusw(P) { OpSse(A, MmxPaddusw, SsePaddusw); }\nvoid OpSsePmaxub(P) { OpSse(A, MmxPmaxub, SsePmaxub); }\nvoid OpSsePandn(P) { OpSse(A, MmxPandn, SsePandn); }\nvoid OpSsePavgb(P) { OpSse(A, MmxPavgb, SsePavgb); }\nvoid OpSsePavgw(P) { OpSse(A, MmxPavgw, SsePavgw); }\nvoid OpSsePmulhw(P) { OpSse(A, MmxPmulhw, SsePmulhw); }\nvoid OpSsePsubsw(P) { OpSse(A, MmxPsubsw, SsePsubsw); }\nvoid OpSsePor(P) { OpSse(A, MmxPor, SsePor); }\nvoid OpSsePaddsw(P) { OpSse(A, MmxPaddsw, SsePaddsw); }\nvoid OpSsePxor(P) { OpSse(A, MmxPxor, SsePxor); }\nvoid OpSsePsubb(P) { OpSse(A, MmxPsubb, SsePsubb); }\nvoid OpSsePsubw(P) { OpSse(A, MmxPsubw, SsePsubw); }\nvoid OpSsePaddb(P) { OpSse(A, MmxPaddb, SsePaddb); }\nvoid OpSsePaddw(P) { OpSse(A, MmxPaddw, SsePaddw); }\nvoid OpSsePhaddsw(P) { OpSse(A, MmxPhaddsw, SsePhaddsw); }\nvoid OpSsePhsubsw(P) { OpSse(A, MmxPhsubsw, SsePhsubsw); }\nvoid OpSsePabsb(P) { OpSse(A, MmxPabsb, SsePabsb); }\n"
  },
  {
    "path": "blink/ssefloat.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <math.h>\n#include <string.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/fpu.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/modrm.h\"\n#include \"blink/pun.h\"\n#include \"blink/stats.h\"\n#include \"blink/tsan.h\"\n\nstatic void pshufw(i16 b[4], const i16 a[4], int m) {\n  i16 t[4];\n  t[0] = a[(m & 0003) >> 0];\n  t[1] = a[(m & 0014) >> 2];\n  t[2] = a[(m & 0060) >> 4];\n  t[3] = a[(m & 0300) >> 6];\n  b[0] = t[0];\n  b[1] = t[1];\n  b[2] = t[2];\n  b[3] = t[3];\n}\n\nstatic void pshufd(i32 b[4], const i32 a[4], int m) {\n  i32 t[4];\n  t[0] = a[(m & 0003) >> 0];\n  t[1] = a[(m & 0014) >> 2];\n  t[2] = a[(m & 0060) >> 4];\n  t[3] = a[(m & 0300) >> 6];\n  b[0] = t[0];\n  b[1] = t[1];\n  b[2] = t[2];\n  b[3] = t[3];\n}\n\nstatic void pshuflw(i16 b[8], const i16 a[8], int m) {\n  i16 t[4];\n  t[0] = a[(m & 0003) >> 0];\n  t[1] = a[(m & 0014) >> 2];\n  t[2] = a[(m & 0060) >> 4];\n  t[3] = a[(m & 0300) >> 6];\n  b[0] = t[0];\n  b[1] = t[1];\n  b[2] = t[2];\n  b[3] = t[3];\n  b[4] = a[4];\n  b[5] = a[5];\n  b[6] = a[6];\n  b[7] = a[7];\n}\n\nstatic void pshufhw(i16 b[8], const i16 a[8], int m) {\n  i16 t[4];\n  t[0] = a[4 + ((m & 0003) >> 0)];\n  t[1] = a[4 + ((m & 0014) >> 2)];\n  t[2] = a[4 + ((m & 0060) >> 4)];\n  t[3] = a[4 + ((m & 0300) >> 6)];\n  b[0] = a[0];\n  b[1] = a[1];\n  b[2] = a[2];\n  b[3] = a[3];\n  b[4] = t[0];\n  b[5] = t[1];\n  b[6] = t[2];\n  b[7] = t[3];\n}\n\nvoid OpUnpcklpsd(P) {\n  u8 *a, *b;\n  a = XmmRexrReg(m, rde);\n  b = GetModrmRegisterXmmPointerRead8(A);\n  IGNORE_RACES_START();\n  if (Osz(rde)) {\n    memcpy(a + 8, b, 8);\n  } else {\n    memcpy(a + 4 * 3, b + 4, 4);\n    memcpy(a + 4 * 2, a + 4, 4);\n    memcpy(a + 4 * 1, b + 0, 4);\n  }\n  IGNORE_RACES_END();\n}\n\nvoid OpUnpckhpsd(P) {\n  u8 *a, *b;\n  a = XmmRexrReg(m, rde);\n  b = GetModrmRegisterXmmPointerRead16(A);\n  IGNORE_RACES_START();\n  if (Osz(rde)) {\n    memcpy(a + 0, b + 8, 8);\n    memcpy(a + 8, b + 8, 8);\n  } else {\n    memcpy(a + 4 * 0, a + 4 * 2, 4);\n    memcpy(a + 4 * 1, b + 4 * 2, 4);\n    memcpy(a + 4 * 2, a + 4 * 3, 4);\n    memcpy(a + 4 * 3, b + 4 * 3, 4);\n  }\n  IGNORE_RACES_END();\n}\n\nvoid OpPextrwGdqpUdqIb(P) {\n  u8 i;\n  i = uimm0;\n  i &= Osz(rde) ? 7 : 3;\n  Put16(RegRexrReg(m, rde), Get16(XmmRexbRm(m, rde) + i * 2));\n}\n\nvoid OpPinsrwVdqEwIb(P) {\n  u8 i;\n  i = uimm0;\n  i &= Osz(rde) ? 7 : 3;\n  IGNORE_RACES_START();\n  Put16(XmmRexrReg(m, rde) + i * 2,\n        Read16(GetModrmRegisterWordPointerRead2(A)));\n  IGNORE_RACES_END();\n}\n\nvoid OpShuffle(P) {\n  i16 q16[4];\n  void *kernel;\n  IGNORE_RACES_START();\n  switch (Rep(rde) | Osz(rde)) {\n    case 0:\n      memcpy(q16, GetModrmRegisterXmmPointerRead8(A), 8);\n      pshufw(q16, q16, uimm0);\n      memcpy(XmmRexrReg(m, rde), q16, 8);\n      kernel = 0;\n      break;\n    case 1:\n      pshufd((i32 *)XmmRexrReg(m, rde),\n             (i32 *)GetModrmRegisterXmmPointerRead16(A), uimm0);\n      kernel = (void *)(uintptr_t)pshufd;\n      break;\n    case 2:\n      pshuflw((i16 *)XmmRexrReg(m, rde),\n              (i16 *)GetModrmRegisterXmmPointerRead16(A), uimm0);\n      kernel = (void *)(uintptr_t)pshuflw;\n      break;\n    case 3:\n      pshufhw((i16 *)XmmRexrReg(m, rde),\n              (i16 *)GetModrmRegisterXmmPointerRead16(A), uimm0);\n      kernel = (void *)(uintptr_t)pshufhw;\n      break;\n    default:\n      __builtin_unreachable();\n  }\n  IGNORE_RACES_END();\n  if (IsMakingPath(m) && kernel) {\n    Jitter(A,\n           \"z4P\"    // res0 = GetXmmOrMemPointer(RexbRm)\n           \"r0s1=\"  // sav1 = res0\n           \"z4Q\"    // res0 = GetXmmPointer(RexrReg)\n           \"a2i\"    // arg2 = uimm0\n           \"s1a1=\"  // arg1 = sav1\n           \"t\"      // arg0 = res0\n           \"c\",     // call function\n           uimm0, kernel);\n  }\n}\n\nstatic void Shufps(P) {\n  u8 *p;\n  union FloatPun x[4], y[4], z[4];\n  p = GetModrmRegisterXmmPointerRead16(A);\n  IGNORE_RACES_START();\n  y[0].i = Read32(p + 0 * 4);\n  y[1].i = Read32(p + 1 * 4);\n  y[2].i = Read32(p + 2 * 4);\n  y[3].i = Read32(p + 3 * 4);\n  p = XmmRexrReg(m, rde);\n  x[0].i = Read32(p + 0 * 4);\n  x[1].i = Read32(p + 1 * 4);\n  x[2].i = Read32(p + 2 * 4);\n  x[3].i = Read32(p + 3 * 4);\n  z[0].f = x[(uimm0 & 0003) >> 0].f;\n  z[1].f = x[(uimm0 & 0014) >> 2].f;\n  z[2].f = y[(uimm0 & 0060) >> 4].f;\n  z[3].f = y[(uimm0 & 0300) >> 6].f;\n  Write32(p + 0 * 4, z[0].i);\n  Write32(p + 1 * 4, z[1].i);\n  Write32(p + 2 * 4, z[2].i);\n  Write32(p + 3 * 4, z[3].i);\n  IGNORE_RACES_END();\n}\n\nstatic void Shufpd(P) {\n  u8 *p;\n  union DoublePun x[2], y[2], z[2];\n  p = GetModrmRegisterXmmPointerRead16(A);\n  IGNORE_RACES_START();\n  y[0].i = Read64(p + 0 * 8);\n  y[1].i = Read64(p + 1 * 8);\n  p = XmmRexrReg(m, rde);\n  x[0].i = Read64(p + 0 * 8);\n  x[1].i = Read64(p + 1 * 8);\n  z[0].f = x[(uimm0 & 0001) >> 0].f;\n  z[1].f = y[(uimm0 & 0002) >> 1].f;\n  Write64(p + 0 * 8, z[0].i);\n  Write64(p + 1 * 8, z[1].i);\n  IGNORE_RACES_END();\n}\n\nvoid OpShufpsd(P) {\n  if (Osz(rde)) {\n    Shufpd(A);\n  } else {\n    Shufps(A);\n  }\n}\n\nstatic void Movmskps(P) {\n  u8 *p = GetModrmRegisterXmmPointerRead16(A);\n  IGNORE_RACES_START();\n  Put64(RegRexrReg(m, rde), (!!(p[15] & 0x80) << 3 | !!(p[11] & 0x80) << 2 |\n                             !!(p[7] & 0x80) << 1 | !!(p[3] & 0x80)));\n  IGNORE_RACES_END();\n}\n\nstatic void Movmskpd(P) {\n  u8 *p = GetModrmRegisterXmmPointerRead16(A);\n  IGNORE_RACES_START();\n  Put64(RegRexrReg(m, rde), !!(p[15] & 0x80) << 1 | !!(p[7] & 0x80));\n  IGNORE_RACES_END();\n}\n\nvoid OpMovmskpsd(P) {\n  if (Osz(rde)) {\n    Movmskpd(A);\n  } else {\n    Movmskps(A);\n  }\n}\n\nvoid OpSqrtpsd(P) {\n  IGNORE_RACES_START();\n  switch (Rep(rde) | Osz(rde)) {\n    case 0: {\n      int i;\n      u8 *p;\n      union FloatPun u[4];\n      p = GetModrmRegisterXmmPointerRead16(A);\n      u[0].i = Read32(p + 0 * 4);\n      u[1].i = Read32(p + 1 * 4);\n      u[2].i = Read32(p + 2 * 4);\n      u[3].i = Read32(p + 3 * 4);\n      for (i = 0; i < 4; ++i) u[i].f = sqrtf(u[i].f);\n      p = XmmRexrReg(m, rde);\n      Write32(p + 0 * 4, u[0].i);\n      Write32(p + 1 * 4, u[1].i);\n      Write32(p + 2 * 4, u[2].i);\n      Write32(p + 3 * 4, u[3].i);\n      break;\n    }\n    case 1: {\n      int i;\n      u8 *p;\n      union DoublePun u[2];\n      p = GetModrmRegisterXmmPointerRead16(A);\n      u[0].i = Read32(p + 0 * 8);\n      u[1].i = Read32(p + 1 * 8);\n      for (i = 0; i < 2; ++i) u[i].f = sqrt(u[i].f);\n      p = XmmRexrReg(m, rde);\n      Write32(p + 0 * 8, u[0].i);\n      Write32(p + 1 * 8, u[1].i);\n      break;\n    }\n    case 2: {\n      union DoublePun u;\n      u.i = Read64(GetModrmRegisterXmmPointerRead8(A));\n      u.f = sqrt(u.f);\n      Write64(XmmRexrReg(m, rde), u.i);\n      break;\n    }\n    case 3: {\n      union FloatPun u;\n      u.i = Read32(GetModrmRegisterXmmPointerRead4(A));\n      u.f = sqrtf(u.f);\n      Write32(XmmRexrReg(m, rde), u.i);\n      break;\n    }\n    default:\n      __builtin_unreachable();\n  }\n  IGNORE_RACES_END();\n}\n\nvoid OpRsqrtps(P) {\n  IGNORE_RACES_START();\n  if (Rep(rde) != 3) {\n    int i;\n    u8 *p;\n    union FloatPun u[4];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    u[0].i = Read32(p + 0 * 4);\n    u[1].i = Read32(p + 1 * 4);\n    u[2].i = Read32(p + 2 * 4);\n    u[3].i = Read32(p + 3 * 4);\n    for (i = 0; i < 4; ++i) u[i].f = 1.f / sqrtf(u[i].f);\n    p = XmmRexrReg(m, rde);\n    Write32(p + 0 * 4, u[0].i);\n    Write32(p + 1 * 4, u[1].i);\n    Write32(p + 2 * 4, u[2].i);\n    Write32(p + 3 * 4, u[3].i);\n  } else {\n    union FloatPun u;\n    u.i = Read32(GetModrmRegisterXmmPointerRead4(A));\n    u.f = 1.f / sqrtf(u.f);\n    Write32(XmmRexrReg(m, rde), u.i);\n  }\n  IGNORE_RACES_END();\n}\n\nvoid OpRcpps(P) {\n  IGNORE_RACES_START();\n  if (Rep(rde) != 3) {\n    int i;\n    u8 *p;\n    union FloatPun u[4];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    u[0].i = Read32(p + 0 * 4);\n    u[1].i = Read32(p + 1 * 4);\n    u[2].i = Read32(p + 2 * 4);\n    u[3].i = Read32(p + 3 * 4);\n    for (i = 0; i < 4; ++i) u[i].f = 1.f / u[i].f;\n    p = XmmRexrReg(m, rde);\n    Write32(p + 0 * 4, u[0].i);\n    Write32(p + 1 * 4, u[1].i);\n    Write32(p + 2 * 4, u[2].i);\n    Write32(p + 3 * 4, u[3].i);\n  } else {\n    union FloatPun u;\n    u.i = Read32(GetModrmRegisterXmmPointerRead4(A));\n    u.f = 1.f / u.f;\n    Write32(XmmRexrReg(m, rde), u.i);\n  }\n  IGNORE_RACES_END();\n}\n\nstatic void ComissKernel(const u8 rxr[8], const u8 reg[8], struct Machine *m) {\n  bool zf, cf;\n  union DoublePun xd, yd;\n  m->mxcsr &= ~kMxcsrIe;\n  xd.i = Read64(rxr);\n  yd.i = Read64(reg);\n  if (!isunordered(xd.f, yd.f)) {\n    zf = xd.f == yd.f;\n    cf = xd.f < yd.f;\n    m->flags = SetFlag(m->flags, FLAGS_ZF, zf);\n    m->flags = SetFlag(m->flags, FLAGS_CF, cf);\n    m->flags = SetFlag(m->flags, FLAGS_PF, false);\n    m->flags = SetFlag(m->flags, FLAGS_SF, false);\n    m->flags = SetFlag(m->flags, FLAGS_OF, false);\n  } else {\n    m->flags = SetFlag(m->flags, FLAGS_ZF, true);\n    m->flags = SetFlag(m->flags, FLAGS_CF, true);\n    m->flags = SetFlag(m->flags, FLAGS_PF, true);\n    m->flags = SetFlag(m->flags, FLAGS_SF, false);\n    m->flags = SetFlag(m->flags, FLAGS_OF, false);\n    m->mxcsr |= kMxcsrIe;\n    if (!(m->mxcsr & kMxcsrIm)) {\n      HaltMachine(m, kMachineSimdException);\n    }\n  }\n}\n\nvoid OpComissVsWs(P) {\n  bool isucomiss;\n  u8 zf, cf, pf, ie;\n  isucomiss = ~Opcode(rde) & 1;\n  IGNORE_RACES_START();\n  if (!Osz(rde)) {\n    union FloatPun xf, yf;\n    xf.i = Read32(XmmRexrReg(m, rde));\n    yf.i = Read32(GetModrmRegisterXmmPointerRead4(A));\n    if (!isunordered(xf.f, yf.f)) {\n      zf = xf.f == yf.f;\n      cf = xf.f < yf.f;\n      pf = false;\n      ie = false;\n    } else {\n      zf = cf = pf = ie = true;\n    }\n  } else {\n    union DoublePun xd, yd;\n    xd.i = Read64(XmmRexrReg(m, rde));\n    yd.i = Read64(GetModrmRegisterXmmPointerRead8(A));\n    if (!isunordered(xd.f, yd.f)) {\n      zf = xd.f == yd.f;\n      cf = xd.f < yd.f;\n      pf = false;\n      ie = false;\n    } else {\n      zf = cf = pf = ie = true;\n    }\n    if (IsMakingPath(m) && !isucomiss) {\n      Jitter(A,\n             \"z4P\"    // res0 = GetXmmOrMemPointer(RexbRm)\n             \"r0s1=\"  // sav1 = res0\n             \"z4Q\"    // res0 = GetXmmPointer(RexrReg)\n             \"s0a2=\"  // arg2 = sav0 (machine)\n             \"s1a1=\"  // arg1 = sav1\n             \"t\"      // arg0 = res0\n             \"c\",     // call function\n             ComissKernel);\n    }\n  }\n  m->flags = SetFlag(m->flags, FLAGS_ZF, zf);\n  m->flags = SetFlag(m->flags, FLAGS_PF, pf);\n  m->flags = SetFlag(m->flags, FLAGS_CF, cf);\n  m->flags = SetFlag(m->flags, FLAGS_SF, false);\n  m->flags = SetFlag(m->flags, FLAGS_OF, false);\n  if (!isucomiss) {\n    m->mxcsr &= ~kMxcsrIe;\n    if (ie) {\n      m->mxcsr |= kMxcsrIe;\n      if (!(m->mxcsr & kMxcsrIm)) {\n        HaltMachine(m, kMachineSimdException);\n      }\n    }\n  }\n  IGNORE_RACES_END();\n}\n\nstatic void OpPsd(P, float fs(float x, float y), double fd(double x, double y),\n                  void s1(u8 *, struct Machine *, long),\n                  void d1(u8 *, struct Machine *, long)) {\n  IGNORE_RACES_START();\n  if (Rep(rde) == 2) {\n    d1(GetModrmRegisterXmmPointerRead8(A), m, RexrReg(rde));\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"z4P\"    // res0 = GetXmmOrMemPointer(RexbRm)\n             \"a2i\"    // arg2 = RexrReg(rde)\n             \"s0a1=\"  // arg1 = machine\n             \"t\"      // arg0 = res0\n             \"m\",     // call function (d1)\n             RexrReg(rde), d1);\n    }\n  } else if (Rep(rde) == 3) {\n    union FloatPun x, y;\n    y.i = Read32(GetModrmRegisterXmmPointerRead4(A));\n    x.i = Read32(XmmRexrReg(m, rde));\n    x.f = fs(x.f, y.f);\n    Write32(XmmRexrReg(m, rde), x.i);\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"z4P\"    // res0 = GetXmmOrMemPointer(RexbRm)\n             \"a2i\"    // arg2 = RexrReg(rde)\n             \"s0a1=\"  // arg1 = machine\n             \"t\"      // arg0 = res0\n             \"m\",     // call function (d1)\n             RexrReg(rde), s1);\n    }\n  } else if (Osz(rde)) {\n    u8 *p;\n    union DoublePun x[2], y[2];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    y[0].i = Read64(p + 0 * 8);\n    y[1].i = Read64(p + 1 * 8);\n    p = XmmRexrReg(m, rde);\n    x[0].i = Read64(p + 0 * 8);\n    x[1].i = Read64(p + 1 * 8);\n    x[0].f = fd(x[0].f, y[0].f);\n    x[1].f = fd(x[1].f, y[1].f);\n    Write64(p + 0 * 8, x[0].i);\n    Write64(p + 1 * 8, x[1].i);\n  } else {\n    u8 *p;\n    union FloatPun x[4], y[4];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    y[0].i = Read32(p + 0 * 4);\n    y[1].i = Read32(p + 1 * 4);\n    y[2].i = Read32(p + 2 * 4);\n    y[3].i = Read32(p + 3 * 4);\n    p = XmmRexrReg(m, rde);\n    x[0].i = Read32(p + 0 * 4);\n    x[1].i = Read32(p + 1 * 4);\n    x[2].i = Read32(p + 2 * 4);\n    x[3].i = Read32(p + 3 * 4);\n    x[0].f = fs(x[0].f, y[0].f);\n    x[1].f = fs(x[1].f, y[1].f);\n    x[2].f = fs(x[2].f, y[2].f);\n    x[3].f = fs(x[3].f, y[3].f);\n    Write32(p + 0 * 4, x[0].i);\n    Write32(p + 1 * 4, x[1].i);\n    Write32(p + 2 * 4, x[2].i);\n    Write32(p + 3 * 4, x[3].i);\n  }\n  IGNORE_RACES_END();\n}\n\nstatic inline float Adds(float x, float y) {\n  return x + y;\n}\n\nstatic inline double Addd(double x, double y) {\n  return x + y;\n}\n\nvoid OpAddpsd(P) {\n  OpPsd(A, Adds, Addd, OpPsdAdds1, OpPsdAddd1);\n}\n\nstatic inline float Subs(float x, float y) {\n  return x - y;\n}\n\nstatic inline double Subd(double x, double y) {\n  return x - y;\n}\n\nvoid OpSubpsd(P) {\n  OpPsd(A, Subs, Subd, OpPsdSubs1, OpPsdSubd1);\n}\n\nstatic inline float Muls(float x, float y) {\n  return x * y;\n}\n\nstatic inline double Muld(double x, double y) {\n  return x * y;\n}\n\nvoid OpMulpsd(P) {\n  OpPsd(A, Muls, Muld, OpPsdMuls1, OpPsdMuld1);\n}\n\nstatic inline float Divs(float x, float y) {\n  return x / y;\n}\n\nstatic inline double Divd(double x, double y) {\n  return x / y;\n}\n\nvoid OpDivpsd(P) {\n  OpPsd(A, Divs, Divd, OpPsdDivs1, OpPsdDivd1);\n}\n\nstatic inline float Mins(float x, float y) {\n  return MIN(x, y);\n}\n\nstatic inline double Mind(double x, double y) {\n  return MIN(x, y);\n}\n\nvoid OpMinpsd(P) {\n  OpPsd(A, Mins, Mind, OpPsdMins1, OpPsdMind1);\n}\n\nstatic inline float Maxs(float x, float y) {\n  return MAX(x, y);\n}\n\nstatic inline double Maxd(double x, double y) {\n  return MAX(x, y);\n}\n\nvoid OpMaxpsd(P) {\n  OpPsd(A, Maxs, Maxd, OpPsdMaxs1, OpPsdMaxd1);\n}\n\nstatic int Cmps(int imm, float x, float y) {\n  switch (imm) {\n    case 0:\n      return x == y ? -1 : 0;\n    case 1:\n      return x < y ? -1 : 0;\n    case 2:\n      return x <= y ? -1 : 0;\n    case 3:\n      return isnan(x) || isnan(y) ? -1 : 0;\n    case 4:\n      return x != y ? -1 : 0;\n    case 5:\n      return x >= y ? -1 : 0;\n    case 6:\n      return x > y ? -1 : 0;\n    case 7:\n      return !(isnan(x) || isnan(y)) ? -1 : 0;\n    default:\n      return 0;\n  }\n}\n\nstatic i32 Cmpd(int imm, double x, double y) {\n  switch (imm) {\n    case 0:\n      return x == y ? -1 : 0;\n    case 1:\n      return x < y ? -1 : 0;\n    case 2:\n      return x <= y ? -1 : 0;\n    case 3:\n      return isnan(x) || isnan(y) ? -1 : 0;\n    case 4:\n      return x != y ? -1 : 0;\n    case 5:\n      return x >= y ? -1 : 0;\n    case 6:\n      return x > y ? -1 : 0;\n    case 7:\n      return !(isnan(x) || isnan(y)) ? -1 : 0;\n    default:\n      return 0;\n  }\n}\n\nvoid OpCmppsd(P) {\n  IGNORE_RACES_START();\n  int imm = uimm0;\n  if (Rep(rde) == 2) {\n    union DoublePun x, y;\n    y.i = Read64(GetModrmRegisterXmmPointerRead8(A));\n    x.i = Read64(XmmRexrReg(m, rde));\n    x.f = Cmpd(imm, x.f, y.f);\n    Write64(XmmRexrReg(m, rde), x.i);\n  } else if (Rep(rde) == 3) {\n    union FloatPun x, y;\n    y.i = Read32(GetModrmRegisterXmmPointerRead4(A));\n    x.i = Read32(XmmRexrReg(m, rde));\n    x.f = Cmps(imm, x.f, y.f);\n    Write32(XmmRexrReg(m, rde), x.i);\n  } else if (Osz(rde)) {\n    u8 *p;\n    union DoublePun x[2], y[2];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    y[0].i = Read64(p + 0 * 8);\n    y[1].i = Read64(p + 1 * 8);\n    p = XmmRexrReg(m, rde);\n    x[0].i = Read64(p + 0 * 8);\n    x[1].i = Read64(p + 1 * 8);\n    x[0].f = Cmpd(imm, x[0].f, y[0].f);\n    x[1].f = Cmpd(imm, x[1].f, y[1].f);\n    Write64(p + 0 * 8, x[0].i);\n    Write64(p + 1 * 8, x[1].i);\n  } else {\n    u8 *p;\n    union FloatPun x[4], y[4];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    y[0].i = Read32(p + 0 * 4);\n    y[1].i = Read32(p + 1 * 4);\n    y[2].i = Read32(p + 2 * 4);\n    y[3].i = Read32(p + 3 * 4);\n    p = XmmRexrReg(m, rde);\n    x[0].i = Read32(p + 0 * 4);\n    x[1].i = Read32(p + 1 * 4);\n    x[2].i = Read32(p + 2 * 4);\n    x[3].i = Read32(p + 3 * 4);\n    x[0].f = Cmps(imm, x[0].f, y[0].f);\n    x[1].f = Cmps(imm, x[1].f, y[1].f);\n    x[2].f = Cmps(imm, x[2].f, y[2].f);\n    x[3].f = Cmps(imm, x[3].f, y[3].f);\n    Write32(p + 0 * 4, x[0].i);\n    Write32(p + 1 * 4, x[1].i);\n    Write32(p + 2 * 4, x[2].i);\n    Write32(p + 3 * 4, x[3].i);\n  }\n  IGNORE_RACES_END();\n}\n\nvoid OpAndpsd(P) {\n  IGNORE_RACES_START();\n  u64 x[2], y[2];\n  memcpy(x, XmmRexrReg(m, rde), 16);\n  memcpy(y, GetModrmRegisterXmmPointerRead16(A), 16);\n  x[0] &= y[0];\n  x[1] &= y[1];\n  memcpy(XmmRexrReg(m, rde), x, 16);\n  IGNORE_RACES_END();\n}\n\nvoid OpAndnpsd(P) {\n  IGNORE_RACES_START();\n  u64 x[2], y[2];\n  memcpy(x, XmmRexrReg(m, rde), 16);\n  memcpy(y, GetModrmRegisterXmmPointerRead16(A), 16);\n  x[0] = ~x[0] & y[0];\n  x[1] = ~x[1] & y[1];\n  memcpy(XmmRexrReg(m, rde), x, 16);\n  IGNORE_RACES_END();\n}\n\nvoid OpOrpsd(P) {\n  IGNORE_RACES_START();\n  u64 x[2], y[2];\n  memcpy(x, XmmRexrReg(m, rde), 16);\n  memcpy(y, GetModrmRegisterXmmPointerRead16(A), 16);\n  x[0] |= y[0];\n  x[1] |= y[1];\n  memcpy(XmmRexrReg(m, rde), x, 16);\n  IGNORE_RACES_END();\n}\n\nvoid OpXorpsd(P) {\n  IGNORE_RACES_START();\n  u64 x[2], y[2];\n  memcpy(x, XmmRexrReg(m, rde), 16);\n  memcpy(y, GetModrmRegisterXmmPointerRead16(A), 16);\n  x[0] ^= y[0];\n  x[1] ^= y[1];\n  memcpy(XmmRexrReg(m, rde), x, 16);\n  IGNORE_RACES_END();\n}\n\nvoid OpHaddpsd(P) {\n  IGNORE_RACES_START();\n  u8 *p;\n  if (Rep(rde) == 2) {\n    union FloatPun x[4], y[4], z[4];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    y[0].i = Read32(p + 0 * 4);\n    y[1].i = Read32(p + 1 * 4);\n    y[2].i = Read32(p + 2 * 4);\n    y[3].i = Read32(p + 3 * 4);\n    p = XmmRexrReg(m, rde);\n    x[0].i = Read32(p + 0 * 4);\n    x[1].i = Read32(p + 1 * 4);\n    x[2].i = Read32(p + 2 * 4);\n    x[3].i = Read32(p + 3 * 4);\n    z[0].f = x[0].f + x[1].f;\n    z[1].f = x[2].f + x[3].f;\n    z[2].f = y[0].f + y[1].f;\n    z[3].f = y[2].f + y[3].f;\n    Write32(p + 0 * 4, z[0].i);\n    Write32(p + 1 * 4, z[1].i);\n    Write32(p + 2 * 4, z[2].i);\n    Write32(p + 3 * 4, z[3].i);\n  } else if (Osz(rde)) {\n    union DoublePun x[2], y[2], z[2];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    y[0].i = Read64(p + 0 * 8);\n    y[1].i = Read64(p + 1 * 8);\n    p = XmmRexrReg(m, rde);\n    x[0].i = Read64(p + 0 * 8);\n    x[1].i = Read64(p + 1 * 8);\n    z[0].f = x[0].f + x[1].f;\n    z[1].f = y[0].f + y[1].f;\n    Write64(p + 0 * 8, z[0].i);\n    Write64(p + 1 * 8, z[1].i);\n  } else {\n    OpUdImpl(m);\n  }\n  IGNORE_RACES_END();\n}\n\nvoid OpHsubpsd(P) {\n  IGNORE_RACES_START();\n  u8 *p;\n  if (Rep(rde) == 2) {\n    union FloatPun x[4], y[4], z[4];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    y[0].i = Read32(p + 0 * 4);\n    y[1].i = Read32(p + 1 * 4);\n    y[2].i = Read32(p + 2 * 4);\n    y[3].i = Read32(p + 3 * 4);\n    p = XmmRexrReg(m, rde);\n    x[0].i = Read32(p + 0 * 4);\n    x[1].i = Read32(p + 1 * 4);\n    x[2].i = Read32(p + 2 * 4);\n    x[3].i = Read32(p + 3 * 4);\n    z[0].f = x[0].f - x[1].f;\n    z[1].f = x[2].f - x[3].f;\n    z[2].f = y[0].f - y[1].f;\n    z[3].f = y[2].f - y[3].f;\n    Write32(p + 0 * 4, z[0].i);\n    Write32(p + 1 * 4, z[1].i);\n    Write32(p + 2 * 4, z[2].i);\n    Write32(p + 3 * 4, z[3].i);\n  } else if (Osz(rde)) {\n    union DoublePun x[2], y[2], z[2];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    y[0].i = Read64(p + 0 * 8);\n    y[1].i = Read64(p + 1 * 8);\n    p = XmmRexrReg(m, rde);\n    x[0].i = Read64(p + 0 * 8);\n    x[1].i = Read64(p + 1 * 8);\n    z[0].f = x[0].f - x[1].f;\n    z[1].f = y[0].f - y[1].f;\n    Write64(p + 0 * 8, z[0].i);\n    Write64(p + 1 * 8, z[1].i);\n  } else {\n    OpUdImpl(m);\n  }\n  IGNORE_RACES_END();\n}\n\nvoid OpAddsubpsd(P) {\n  IGNORE_RACES_START();\n  u8 *p;\n  if (Rep(rde) == 2) {\n    union FloatPun x[4], y[4], z[4];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    y[0].i = Read32(p + 0 * 4);\n    y[1].i = Read32(p + 1 * 4);\n    y[2].i = Read32(p + 2 * 4);\n    y[3].i = Read32(p + 3 * 4);\n    p = XmmRexrReg(m, rde);\n    x[0].i = Read32(p + 0 * 4);\n    x[1].i = Read32(p + 1 * 4);\n    x[2].i = Read32(p + 2 * 4);\n    x[3].i = Read32(p + 3 * 4);\n    z[0].f = x[0].f - y[0].f;\n    z[1].f = x[1].f + y[1].f;\n    z[2].f = x[2].f - y[2].f;\n    z[3].f = x[3].f + y[3].f;\n    Write32(p + 0 * 4, z[0].i);\n    Write32(p + 1 * 4, z[1].i);\n    Write32(p + 2 * 4, z[2].i);\n    Write32(p + 3 * 4, z[3].i);\n  } else if (Osz(rde)) {\n    union DoublePun x[2], y[2], z[2];\n    p = GetModrmRegisterXmmPointerRead16(A);\n    y[0].i = Read64(p + 0 * 8);\n    y[1].i = Read64(p + 1 * 8);\n    p = XmmRexrReg(m, rde);\n    x[0].i = Read64(p + 0 * 8);\n    x[1].i = Read64(p + 1 * 8);\n    z[0].f = x[0].f - y[0].f;\n    z[1].f = x[1].f + y[1].f;\n    Write64(p + 0 * 8, z[0].i);\n    Write64(p + 1 * 8, z[1].i);\n  } else {\n    OpUdImpl(m);\n  }\n  IGNORE_RACES_END();\n}\n"
  },
  {
    "path": "blink/ssemov.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n\n#include \"blink/biosrom.h\"\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/intrin.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/stats.h\"\n#include \"blink/tsan.h\"\n\nstatic u32 pmovmskb(const u8 p[16]) {\n#if X86_INTRINSICS\n  return __builtin_ia32_pmovmskb128(*(char_xmma_t *)p);\n#else\n  u32 i, m;\n  for (m = i = 0; i < 16; ++i) {\n    if (p[i] & 0x80) m |= 1 << i;\n  }\n  return m;\n#endif\n}\n\nstatic void MovdquVdqWdq(P) {\n  IGNORE_RACES_START();\n  memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead16(A), 16);\n  IGNORE_RACES_END();\n  if (IsMakingPath(m)) {\n    Jitter(A, \"z4B\"    // 128-bit GetRegOrMem\n              \"z4C\");  // 128-bit PutReg\n  }\n}\n\nstatic void MovdquWdqVdq(P) {\n  IGNORE_RACES_START();\n  memcpy(GetModrmRegisterXmmPointerWrite16(A), XmmRexrReg(m, rde), 16);\n  IGNORE_RACES_END();\n  if (IsMakingPath(m)) {\n    Jitter(A, \"z4A\"    // 128-bit GetReg\n              \"z4D\");  // 128-bit PutRegOrMem\n  }\n}\n\nstatic void MovupsVpsWps(P) {\n  MovdquVdqWdq(A);\n}\n\nstatic void MovupsWpsVps(P) {\n  MovdquWdqVdq(A);\n}\n\nstatic void MovupdVpsWps(P) {\n  MovdquVdqWdq(A);\n}\n\nstatic void MovupdWpsVps(P) {\n  MovdquWdqVdq(A);\n}\n\nvoid OpLddquVdqMdq(P) {\n  MovdquVdqWdq(A);\n}\n\nvoid OpMovntiMdqpGdqp(P) {\n  IGNORE_RACES_START();\n  if (Rexw(rde)) {\n    memcpy(ComputeReserveAddressWrite8(A), XmmRexrReg(m, rde), 8);\n  } else {\n    memcpy(ComputeReserveAddressWrite4(A), XmmRexrReg(m, rde), 4);\n  }\n  IGNORE_RACES_END();\n}\n\nstatic void MovdqaVdqWdq(P) {\n  IGNORE_RACES_START();\n  memcpy(XmmRexrReg(m, rde), GetXmmAddress(A), 16);\n  IGNORE_RACES_END();\n  if (IsMakingPath(m)) {\n    Jitter(A, \"z4B\"    // 128-bit GetRegOrMem\n              \"z4C\");  // 128-bit PutReg\n  }\n}\n\nstatic void MovdqaWdqVdq(P) {\n  u8 *dst;\n  IGNORE_RACES_START();\n  dst = GetXmmAddress(A);\n  if (!IsRomAddress(m, dst)) {\n    memcpy(dst, XmmRexrReg(m, rde), 16);\n  }\n  IGNORE_RACES_END();\n  if (IsMakingPath(m)) {\n    Jitter(A, \"z4A\"    // 128-bit GetReg\n              \"z4D\");  // 128-bit PutRegOrMem\n  }\n}\n\nstatic void MovntdqMdqVdq(P) {\n  MovdqaWdqVdq(A);\n}\n\nstatic void MovntpsMpsVps(P) {\n  MovdqaWdqVdq(A);\n}\n\nstatic void MovntpdMpdVpd(P) {\n  MovdqaWdqVdq(A);\n}\n\nvoid OpMovntdqaVdqMdq(P) {\n  MovdqaVdqWdq(A);\n}\n\nstatic void MovqPqQq(P) {\n  IGNORE_RACES_START();\n  memcpy(MmReg(m, rde), GetModrmRegisterMmPointerRead8(A), 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovqQqPq(P) {\n  IGNORE_RACES_START();\n  memcpy(GetModrmRegisterMmPointerWrite8(A), MmReg(m, rde), 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovqVdqEqp(P) {\n  IGNORE_RACES_START();\n  memcpy(XmmRexrReg(m, rde), GetModrmRegisterWordPointerRead8(A), 8);\n  IGNORE_RACES_END();\n  memset(XmmRexrReg(m, rde) + 8, 0, 8);\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"z3B\"   // res0 = GetRegOrMem[force64bit](RexbRm)\n           \"r1i\"   // res1 = zero\n           \"z4C\",  // PutReg[force128bit](RexrReg, res0, res1)\n           0);\n  }\n}\n\nstatic void MovdVdqEd(P) {\n  memset(XmmRexrReg(m, rde), 0, 16);\n  IGNORE_RACES_START();\n  memcpy(XmmRexrReg(m, rde), GetModrmRegisterWordPointerRead4(A), 4);\n  IGNORE_RACES_END();\n}\n\nstatic void MovqPqEqp(P) {\n  IGNORE_RACES_START();\n  memcpy(MmReg(m, rde), GetModrmRegisterWordPointerRead8(A), 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovdPqEd(P) {\n  IGNORE_RACES_START();\n  memcpy(MmReg(m, rde), GetModrmRegisterWordPointerRead4(A), 4);\n  IGNORE_RACES_END();\n  memset(MmReg(m, rde) + 4, 0, 4);\n}\n\nstatic void MovdEdVdq(P) {\n  if (IsModrmRegister(rde)) {\n    Put64(RegRexbRm(m, rde), Read32(XmmRexrReg(m, rde)));\n  } else {\n    IGNORE_RACES_START();\n    memcpy(ComputeReserveAddressWrite4(A), XmmRexrReg(m, rde), 4);\n    IGNORE_RACES_END();\n  }\n}\n\nstatic void MovqEqpVdq(P) {\n  IGNORE_RACES_START();\n  memcpy(GetModrmRegisterWordPointerWrite8(A), XmmRexrReg(m, rde), 8);\n  IGNORE_RACES_END();\n  if (IsMakingPath(m)) {\n    Jitter(A, \"z4A\"      // res0,res1 = GetReg[force128bit](RexrReg)\n              \"r0z3D\");  // PutRegOrMem[force64bit](RexbRm, res0)\n  }\n}\n\nstatic void MovdEdPq(P) {\n  if (IsModrmRegister(rde)) {\n    Put64(RegRexbRm(m, rde), Read32(MmReg(m, rde)));\n  } else {\n    IGNORE_RACES_START();\n    memcpy(ComputeReserveAddressWrite4(A), MmReg(m, rde), 4);\n    IGNORE_RACES_END();\n  }\n}\n\nstatic void MovqEqpPq(P) {\n  IGNORE_RACES_START();\n  memcpy(GetModrmRegisterWordPointerWrite8(A), MmReg(m, rde), 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovntqMqPq(P) {\n  IGNORE_RACES_START();\n  memcpy(ComputeReserveAddressWrite8(A), MmReg(m, rde), 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovqVqWq(P) {\n  IGNORE_RACES_START();\n  memcpy(XmmRexrReg(m, rde), GetModrmRegisterXmmPointerRead8(A), 8);\n  IGNORE_RACES_END();\n  memset(XmmRexrReg(m, rde) + 8, 0, 8);\n}\n\nstatic void MovssVpsWps(P) {\n  if (IsModrmRegister(rde)) {\n    memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde), 4);\n  } else {\n    IGNORE_RACES_START();\n    memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead4(A), 4);\n    IGNORE_RACES_END();\n    memset(XmmRexrReg(m, rde) + 4, 0, 12);\n  }\n}\n\nstatic void MovssWpsVps(P) {\n  IGNORE_RACES_START();\n  memcpy(GetModrmRegisterXmmPointerWrite4(A), XmmRexrReg(m, rde), 4);\n  IGNORE_RACES_END();\n}\n\nstatic void MovsdVpsWps(P) {\n  if (IsModrmRegister(rde)) {\n    memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde), 8);\n  } else {\n    IGNORE_RACES_START();\n    memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead8(A), 8);\n    IGNORE_RACES_END();\n    memset(XmmRexrReg(m, rde) + 8, 0, 8);\n    if (IsMakingPath(m)) {\n      Jitter(A,\n             \"z3B\"   // res0 = Get.....Mem[force64bit](RexbRm)\n             \"r1i\"   // res1 = 0\n             \"z4C\",  // 128-bit PutReg\n             (u64)0);\n    }\n  }\n}\n\nstatic void MovsdWpsVps(P) {\n  IGNORE_RACES_START();\n  memcpy(GetModrmRegisterXmmPointerWrite8(A), XmmRexrReg(m, rde), 8);\n  IGNORE_RACES_END();\n  if (IsMakingPath(m)) {\n    Jitter(A,\n           \"z4P\"    // res0 = GetXmmOrMemPointer(RexbRm)\n           \"a2i\"    // arg2 = RexrReg(rde)\n           \"s0a1=\"  // arg1 = machine\n           \"t\"      // arg0 = res0\n           \"m\",     // call function (d1)\n           RexrReg(rde), MovsdWpsVpsOp);\n  }\n}\n\nstatic void MovhlpsVqUq(P) {\n  memcpy(XmmRexrReg(m, rde), XmmRexbRm(m, rde) + 8, 8);\n}\n\nstatic void MovlpsVqMq(P) {\n  IGNORE_RACES_START();\n  memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead8(A), 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovlpdVqMq(P) {\n  IGNORE_RACES_START();\n  memcpy(XmmRexrReg(m, rde), ComputeReserveAddressRead8(A), 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovddupVqWq(P) {\n  u8 *src = GetModrmRegisterXmmPointerRead8(A);\n  IGNORE_RACES_START();\n  memcpy(XmmRexrReg(m, rde) + 0, src, 8);\n  memcpy(XmmRexrReg(m, rde) + 8, src, 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovsldupVqWq(P) {\n  u8 *dst, *src;\n  dst = XmmRexrReg(m, rde);\n  src = GetModrmRegisterXmmPointerRead16(A);\n  IGNORE_RACES_START();\n  memcpy(dst + 0 + 0, src + 0, 4);\n  memcpy(dst + 0 + 4, src + 0, 4);\n  memcpy(dst + 8 + 0, src + 8, 4);\n  memcpy(dst + 8 + 4, src + 8, 4);\n  IGNORE_RACES_END();\n}\n\nstatic void MovlpsMqVq(P) {\n  IGNORE_RACES_START();\n  memcpy(ComputeReserveAddressWrite8(A), XmmRexrReg(m, rde), 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovlpdMqVq(P) {\n  IGNORE_RACES_START();\n  memcpy(ComputeReserveAddressWrite8(A), XmmRexrReg(m, rde), 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovlhpsVqUq(P) {\n  memcpy(XmmRexrReg(m, rde) + 8, XmmRexbRm(m, rde), 8);\n}\n\nstatic void MovhpsVqMq(P) {\n  IGNORE_RACES_START();\n  memcpy(XmmRexrReg(m, rde) + 8, ComputeReserveAddressRead8(A), 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovhpdVqMq(P) {\n  IGNORE_RACES_START();\n  memcpy(XmmRexrReg(m, rde) + 8, ComputeReserveAddressRead8(A), 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovshdupVqWq(P) {\n  u8 *dst, *src;\n  dst = XmmRexrReg(m, rde);\n  src = GetModrmRegisterXmmPointerRead16(A);\n  IGNORE_RACES_START();\n  memcpy(dst + 0 + 0, src + 04, 4);\n  memcpy(dst + 0 + 4, src + 04, 4);\n  memcpy(dst + 8 + 0, src + 12, 4);\n  memcpy(dst + 8 + 4, src + 12, 4);\n  IGNORE_RACES_END();\n}\n\nstatic void MovhpsMqVq(P) {\n  IGNORE_RACES_START();\n  memcpy(ComputeReserveAddressWrite8(A), XmmRexrReg(m, rde) + 8, 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovhpdMqVq(P) {\n  IGNORE_RACES_START();\n  memcpy(ComputeReserveAddressWrite8(A), XmmRexrReg(m, rde) + 8, 8);\n  IGNORE_RACES_END();\n}\n\nstatic void MovqWqVq(P) {\n  if (IsModrmRegister(rde)) {\n    memcpy(XmmRexbRm(m, rde), XmmRexrReg(m, rde), 8);\n    memset(XmmRexbRm(m, rde) + 8, 0, 8);\n  } else {\n    IGNORE_RACES_START();\n    memcpy(ComputeReserveAddressWrite8(A), XmmRexrReg(m, rde), 8);\n    IGNORE_RACES_END();\n  }\n}\n\nstatic void Movq2dqVdqNq(P) {\n  memcpy(XmmRexrReg(m, rde), MmRm(m, rde), 8);\n  memset(XmmRexrReg(m, rde) + 8, 0, 8);\n}\n\nstatic void Movdq2qPqUq(P) {\n  memcpy(MmReg(m, rde), XmmRexbRm(m, rde), 8);\n}\n\nstatic void MovapsVpsWps(P) {\n  MovdqaVdqWdq(A);\n}\n\nstatic void MovapdVpdWpd(P) {\n  MovdqaVdqWdq(A);\n}\n\nstatic void MovapsWpsVps(P) {\n  MovdqaWdqVdq(A);\n}\n\nstatic void MovapdWpdVpd(P) {\n  MovdqaWdqVdq(A);\n}\n\nvoid OpMovWpsVps(P) {\n  switch (Rep(rde) | Osz(rde)) {\n    case 0:\n      MovupsWpsVps(A);\n      break;\n    case 1:\n      MovupdWpsVps(A);\n      break;\n    case 2:\n      MovsdWpsVps(A);  // hot\n      break;\n    case 3:\n      MovssWpsVps(A);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nvoid OpMov0f28(P) {\n  if (!Osz(rde)) {\n    MovapsVpsWps(A);\n  } else {\n    MovapdVpdWpd(A);\n  }\n}\n\nvoid OpMov0f6e(P) {\n  if (Osz(rde)) {\n    if (Rexw(rde)) {\n      MovqVdqEqp(A);\n    } else {\n      MovdVdqEd(A);\n    }\n  } else {\n    if (Rexw(rde)) {\n      MovqPqEqp(A);\n    } else {\n      MovdPqEd(A);\n    }\n  }\n}\n\nvoid OpMov0f6f(P) {\n  if (Osz(rde)) {\n    MovdqaVdqWdq(A);\n  } else if (Rep(rde) == 3) {\n    MovdquVdqWdq(A);\n  } else {\n    MovqPqQq(A);\n  }\n}\n\nvoid OpMov0fE7(P) {\n  if (!Osz(rde)) {\n    MovntqMqPq(A);\n  } else {\n    MovntdqMdqVdq(A);\n  }\n}\n\nvoid OpMov0f7e(P) {\n  if (Rep(rde) == 3) {\n    MovqVqWq(A);\n  } else if (Osz(rde)) {\n    if (Rexw(rde)) {\n      MovqEqpVdq(A);\n    } else {\n      MovdEdVdq(A);\n    }\n  } else {\n    if (Rexw(rde)) {\n      MovqEqpPq(A);\n    } else {\n      MovdEdPq(A);\n    }\n  }\n}\n\nvoid OpMov0f7f(P) {\n  if (Rep(rde) == 3) {\n    MovdquWdqVdq(A);\n  } else if (Osz(rde)) {\n    MovdqaWdqVdq(A);\n  } else {\n    MovqQqPq(A);\n  }\n}\n\nvoid OpMov0f10(P) {\n  switch (Rep(rde) | Osz(rde)) {\n    case 0:\n      MovupsVpsWps(A);\n      break;\n    case 1:\n      MovupdVpsWps(A);\n      break;\n    case 2:\n      MovsdVpsWps(A);\n      break;\n    case 3:\n      MovssVpsWps(A);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nvoid OpMov0f29(P) {\n  if (!Osz(rde)) {\n    MovapsWpsVps(A);\n  } else {\n    MovapdWpdVpd(A);\n  }\n}\n\nvoid OpMov0f2b(P) {\n  if (!Osz(rde)) {\n    MovntpsMpsVps(A);\n  } else {\n    MovntpdMpdVpd(A);\n  }\n}\n\nvoid OpMov0f12(P) {\n  switch (Rep(rde) | Osz(rde)) {\n    case 0:\n      if (IsModrmRegister(rde)) {\n        MovhlpsVqUq(A);\n      } else {\n        MovlpsVqMq(A);\n      }\n      break;\n    case 1:\n      MovlpdVqMq(A);\n      break;\n    case 2:\n      MovddupVqWq(A);\n      break;\n    case 3:\n      MovsldupVqWq(A);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nvoid OpMov0f13(P) {\n  if (Osz(rde)) {\n    MovlpdMqVq(A);\n  } else {\n    MovlpsMqVq(A);\n  }\n}\n\nvoid OpMov0f16(P) {\n  switch (Rep(rde) | Osz(rde)) {\n    case 0:\n      if (IsModrmRegister(rde)) {\n        MovlhpsVqUq(A);\n      } else {\n        MovhpsVqMq(A);\n      }\n      break;\n    case 1:\n      MovhpdVqMq(A);\n      break;\n    case 3:\n      MovshdupVqWq(A);\n      break;\n    default:\n      OpUdImpl(m);\n      break;\n  }\n}\n\nvoid OpMov0f17(P) {\n  if (Osz(rde)) {\n    MovhpdMqVq(A);\n  } else {\n    MovhpsMqVq(A);\n  }\n}\n\nvoid OpMov0fD6(P) {\n  if (Rep(rde) == 3) {\n    Movq2dqVdqNq(A);\n  } else if (Rep(rde) == 2) {\n    Movdq2qPqUq(A);\n  } else if (Osz(rde)) {\n    MovqWqVq(A);\n  } else {\n    OpUdImpl(m);\n  }\n}\n\nvoid OpPmovmskbGdqpNqUdq(P) {\n  Put64(RegRexrReg(m, rde),\n        pmovmskb(XmmRexbRm(m, rde)) & (Osz(rde) ? 0xffff : 0xff));\n}\n\nvoid OpMaskMovDiXmmRegXmmRm(P) {\n  void *p[2];\n  u64 v;\n  unsigned i, n;\n  u8 *mem, b[16];\n  v = AddressDi(A);\n  n = Osz(rde) ? 16 : 8;\n  mem = BeginStore(m, v, n, p, b);\n  for (i = 0; i < n; ++i) {\n    if (XmmRexbRm(m, rde)[i] & 0x80) {\n      mem[i] = XmmRexrReg(m, rde)[i];\n    }\n  }\n  EndStore(m, v, n, p, b);\n}\n"
  },
  {
    "path": "blink/stack.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n#include \"blink/tsan.h\"\n#include \"blink/x86.h\"\n\nstatic const u8 kStackOsz[2][3] = {{4, 4, 8}, {2, 2, 2}};\nstatic const u8 kCallOsz[2][3] = {{4, 4, 8}, {2, 2, 8}};\n\nstatic void WriteStackWord(u8 *p, u64 rde, u32 osz, u64 x) {\n  IGNORE_RACES_START();\n  if (osz == 8) {\n    Write64(p, x);\n  } else if (osz == 2) {\n    Write16(p, x);\n  } else {\n    Write32(p, x);\n  }\n  IGNORE_RACES_END();\n}\n\nstatic u64 ReadStackWord(u8 *p, u32 osz) {\n  u64 x;\n  IGNORE_RACES_START();\n  if (osz == 8) {\n    x = Read64(p);\n  } else if (osz == 2) {\n    x = Read16(p);\n  } else {\n    x = Read32(p);\n  }\n  IGNORE_RACES_END();\n  return x;\n}\n\nstatic void WriteMemWord(u8 *p, u64 rde, u32 osz, u64 x) {\n  if (osz == 8) {\n    Store64(p, x);\n  } else if (osz == 2) {\n    Store16(p, x);\n  } else {\n    Store32(p, x);\n  }\n}\n\nstatic u64 ReadMemWord(u8 *p, u32 osz) {\n  u64 x;\n  if (osz == 8) {\n    x = Load64(p);\n  } else if (osz == 2) {\n    x = Load16(p);\n  } else {\n    x = Load32(p);\n  }\n  return x;\n}\n\nstatic void PushN(P, u64 x, unsigned mode, unsigned osz) {\n  u8 *w;\n  u64 v;\n  u8 b[8];\n  void *p[2];\n  switch (mode) {\n    case XED_MODE_REAL:\n      v = (Get32(m->sp) - osz) & 0xffff;\n      Put16(m->sp, v);\n      v += m->ss.base;\n      break;\n    case XED_MODE_LEGACY:\n      v = (Get32(m->sp) - osz) & 0xffffffff;\n      Put64(m->sp, v);\n      v += m->ss.base;\n      break;\n    case XED_MODE_LONG:\n      v = (Get64(m->sp) - osz) & 0xffffffffffffffff;\n      Put64(m->sp, v);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n  w = AccessRam(m, v, osz, p, b, false);\n  WriteStackWord(w, rde, osz, x);\n  EndStore(m, v, osz, p, b);\n}\n\nvoid Push(P, u64 x) {\n  PushN(A, x, Mode(rde), kStackOsz[Osz(rde)][Mode(rde)]);\n}\n\nvoid OpPushZvq(P) {\n  int osz = kStackOsz[Osz(rde)][Mode(rde)];\n  PushN(A, ReadStackWord(RegRexbSrm(m, rde), osz), Mode(rde), osz);\n  if (IsMakingPath(m) && HasLinearMapping() && !Osz(rde)) {\n    Jitter(A,\n           \"a1i\"\n           \"m\",\n           RexbSrm(rde), FastPush);\n  }\n}\n\nstatic u64 PopN(P, u16 extra, unsigned osz) {\n  u64 v;\n  u8 b[8];\n  void *p[2];\n  switch (Mode(rde)) {\n    case XED_MODE_LONG:\n      v = Get64(m->sp);\n      Put64(m->sp, v + osz + extra);\n      break;\n    case XED_MODE_LEGACY:\n      v = Get32(m->sp);\n      Put64(m->sp, (v + osz + extra) & 0xffffffff);\n      v += m->ss.base;\n      break;\n    case XED_MODE_REAL:\n      v = Get16(m->sp);\n      Put16(m->sp, v + osz + extra);\n      v += m->ss.base;\n      break;\n    default:\n      __builtin_unreachable();\n  }\n  return ReadStackWord(AccessRam(m, v, osz, p, b, true), osz);\n}\n\nu64 Pop(P, u16 extra) {\n  return PopN(A, extra, kStackOsz[Osz(rde)][Mode(rde)]);\n}\n\nvoid OpPopZvq(P) {\n  u64 x;\n  int osz;\n  osz = kStackOsz[Osz(rde)][Mode(rde)];\n  x = PopN(A, 0, osz);\n  switch (osz) {\n    case 8:\n    case 4:\n      Put64(RegRexbSrm(m, rde), x);\n      break;\n    case 2:\n      Put16(RegRexbSrm(m, rde), x);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n  if (IsMakingPath(m) && HasLinearMapping() && !Osz(rde)) {\n    Jitter(A,\n           \"a1i\"\n           \"m\",\n           RexbSrm(rde), FastPop);\n  }\n}\n\nstatic void OpCall(P, u64 func) {\n  PushN(A, m->ip, Mode(rde), kCallOsz[Osz(rde)][Mode(rde)]);\n  m->ip = func;\n}\n\nvoid OpCallJvds(P) {\n  OpCall(A, m->ip + disp);\n  if (HasLinearMapping() && IsMakingPath(m)) {\n    Terminate(A, FastCall);\n  }\n}\n\nstatic u64 LoadAddressFromMemory(P) {\n  unsigned osz = kCallOsz[Osz(rde)][Mode(rde)];\n  return ReadMemWord(GetModrmRegisterWordPointerRead(A, osz), osz);\n}\n\nvoid OpCallEq(P) {\n  if (IsMakingPath(m) && HasLinearMapping() && !Osz(rde)) {\n    Jitter(A,\n           \"z3B\"    // res0 = GetRegOrMem[force64bit](RexbRm)\n           \"s0a1=\"  // arg1 = machine\n           \"t\"      // arg0 = res0\n           \"m\",     // call micro-op (FastCallAbs)\n           FastCallAbs);\n  }\n  OpCall(A, LoadAddressFromMemory(A));\n}\n\nvoid OpJmpEq(P) {\n  if (IsMakingPath(m) && HasLinearMapping() && !Osz(rde)) {\n    Jitter(A,\n           \"z3B\"    // res0 = GetRegOrMem[force64bit](RexbRm)\n           \"s0a1=\"  // arg1 = machine\n           \"t\"      // arg0 = res0\n           \"m\",     // call micro-op (FastJmpAbs)\n           FastJmpAbs);\n  }\n  m->ip = LoadAddressFromMemory(A);\n}\n\nvoid OpEnter(P) {\n  u16 allocsz = (u16)uimm0;\n  u8 nesting = (u8)(uimm0 >> 16);\n  unsigned osz = kStackOsz[Osz(rde)][Mode(rde)];\n  if (nesting != 0) OpUdImpl(m);\n  Push(A, Get64(m->bp));\n  switch (osz) {\n    case 8:\n      Put64(m->bp, Get64(m->sp));\n      Put64(m->sp, Get64(m->sp) - allocsz);\n      break;\n    case 4:\n      Put64(m->bp, Get32(m->sp));\n      Put64(m->sp, Get32(m->sp) - allocsz);\n      break;\n    case 2:\n      Put16(m->bp, Get16(m->sp));\n      Put16(m->sp, Get16(m->sp) - allocsz);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nvoid OpLeave(P) {\n  unsigned osz = kStackOsz[Osz(rde)][Mode(rde)];\n  switch (osz) {\n    case 8:\n      Put64(m->sp, Get64(m->bp));\n      Put64(m->bp, Pop(A, 0));\n      if (HasLinearMapping() && IsMakingPath(m)) {\n        Jitter(A, \"m\", FastLeave);\n      }\n      break;\n    case 4:\n      Put64(m->sp, Get32(m->bp));\n      Put64(m->bp, PopN(A, osz, 0));\n      break;\n    case 2:\n      Put16(m->sp, Get16(m->bp));\n      Put16(m->bp, PopN(A, osz, 0));\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nvoid OpRet(P) {\n  m->ip = Pop(A, 0);\n  if (IsMakingPath(m) && HasLinearMapping() && !Osz(rde)) {\n#ifdef __x86_64__\n    Jitter(A,\n           \"a1i\"  // arg1 = prediction\n           \"m\"    // call micro-op (PredictRet)\n           \"q\",   // arg0 = machine\n           m->ip, PredictRet);\n    AlignJit(m->path.jb, 8, 3);\n    u8 code[] = {\n        0x48, 0x85, 0300 | kJitRes0 << 3 | kJitRes0,  // test %rax,%rax\n        0x75, 0x05,                                   // jnz   +5\n    };\n#else\n    Jitter(A,\n           \"a1i\"    // arg1 = prediction\n           \"m\"      // call micro-op (PredictRet)\n           \"r0a2=\"  // arg2 = res0\n           \"q\",     // arg0 = machine\n           m->ip, PredictRet);\n    u32 code[] = {\n        0xb5000000 | (8 / 4) << 5 | kJitArg2,  // cbnz x2,#8\n    };\n#endif\n    AppendJit(m->path.jb, code, sizeof(code));\n    Connect(A, m->ip, true);\n    AppendJitJump(m->path.jb, (void *)m->system->ender);\n    FinishPath(m);\n  }\n}\n\nrelegated void OpRetIw(P) {\n  m->ip = Pop(A, uimm0);\n}\n\nvoid OpPushEvq(P) {\n  unsigned osz = kStackOsz[Osz(rde)][Mode(rde)];\n  Push(A, ReadMemWord(GetModrmRegisterWordPointerRead(A, osz), osz));\n}\n\nvoid OpPopEvq(P) {\n  unsigned osz = kStackOsz[Osz(rde)][Mode(rde)];\n  WriteMemWord(GetModrmRegisterWordPointerWrite(A, osz), rde, osz, Pop(A, 0));\n}\n"
  },
  {
    "path": "blink/startdir.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"blink/util.h\"\n\nstatic char *g_startdir;\n\nstatic void FreeStartDir(void) {\n  free(g_startdir);\n  g_startdir = 0;\n}\n\nchar *GetStartDir(void) {\n  if (!g_startdir) {\n    char cwd[PATH_MAX];\n    if (!getcwd(cwd, sizeof(cwd))) strcpy(cwd, \".\");\n    g_startdir = strdup(cwd);\n    atexit(FreeStartDir);\n  }\n  return g_startdir;\n}\n"
  },
  {
    "path": "blink/startswith.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/util.h\"\n\nbool StartsWith(const char *s, const char *p) {\n  for (;;) {\n    if (!*p) return true;\n    if (!*s) return false;\n    if (*s++ != *p++) return false;\n  }\n}\n"
  },
  {
    "path": "blink/statfs.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <sys/types.h>\n// ordering matters on openbsd\n#include <errno.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/param.h>\n#include <sys/statvfs.h>\n\n#include \"blink/endian.h\"\n#include \"blink/errno.h\"\n#include \"blink/linux.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/syscall.h\"\n#include \"blink/types.h\"\n\n#ifdef __linux\n#include <sys/vfs.h>\n#endif\n\n#if defined(HAVE_SYS_MOUNT_H) && !defined(_POSIX_C_SOURCE)\n#include <sys/mount.h>\n#endif\n\n#if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)) && \\\n    !defined(_POSIX_C_SOURCE)\n#include <sys/disklabel.h>\n#endif\n\nstruct FsId {\n  u32 val[2];\n};\n\nstatic unsigned long XlatStatvfsFlags(unsigned long flags) {\n  unsigned long res = 0;\n#ifdef MNT_RDONLY\n  if ((flags & MNT_RDONLY) == MNT_RDONLY) res |= ST_RDONLY_LINUX;\n#elif defined(ST_RDONLY)\n  if ((flags & ST_RDONLY) == ST_RDONLY) res |= ST_RDONLY_LINUX;\n#endif\n#ifdef MNT_NOSUID\n  if ((flags & MNT_NOSUID) == MNT_NOSUID) res |= ST_NOSUID_LINUX;\n#elif defined(ST_NOSUID)\n  if ((flags & ST_NOSUID) == ST_NOSUID) res |= ST_NOSUID_LINUX;\n#endif\n#ifdef MNT_NODEV\n  if ((flags & MNT_NODEV) == MNT_NODEV) res |= ST_NODEV_LINUX;\n#elif defined(ST_NODEV)\n  if ((flags & ST_NODEV) == ST_NODEV) res |= ST_NODEV_LINUX;\n#endif\n#ifdef MNT_NOEXEC\n  if ((flags & MNT_NOEXEC) == MNT_NOEXEC) res |= ST_NOEXEC_LINUX;\n#elif defined(ST_NOEXEC)\n  if ((flags & ST_NOEXEC) == ST_NOEXEC) res |= ST_NOEXEC_LINUX;\n#endif\n#ifdef MNT_SYNCHRONOUS\n  if ((flags & MNT_SYNCHRONOUS) == MNT_SYNCHRONOUS) res |= ST_SYNCHRONOUS_LINUX;\n#elif defined(ST_SYNCHRONOUS)\n  if ((flags & ST_SYNCHRONOUS) == ST_SYNCHRONOUS) res |= ST_SYNCHRONOUS_LINUX;\n#endif\n#ifdef MNT_NOATIME\n  if ((flags & MNT_NOATIME) == MNT_NOATIME) res |= ST_NOATIME_LINUX;\n#elif defined(ST_NOATIME)\n  if ((flags & ST_NOATIME) == ST_NOATIME) res |= ST_NOATIME_LINUX;\n#endif\n#ifdef MNT_RELATIME\n  if ((flags & MNT_RELATIME) == MNT_RELATIME) res |= ST_RELATIME_LINUX;\n#elif defined(ST_RELATIME)\n  if ((flags & ST_RELATIME) == ST_RELATIME) res |= ST_RELATIME_LINUX;\n#endif\n#ifdef MNT_APPEND\n  if ((flags & MNT_APPEND) == MNT_APPEND) res |= ST_APPEND_LINUX;\n#elif defined(ST_APPEND)\n  if ((flags & ST_APPEND) == ST_APPEND) res |= ST_APPEND_LINUX;\n#endif\n#ifdef MNT_IMMUTABLE\n  if ((flags & MNT_IMMUTABLE) == MNT_IMMUTABLE) res |= ST_IMMUTABLE_LINUX;\n#elif defined(ST_IMMUTABLE)\n  if ((flags & ST_IMMUTABLE) == ST_IMMUTABLE) res |= ST_IMMUTABLE_LINUX;\n#endif\n#ifdef MNT_MANDLOCK\n  if ((flags & MNT_MANDLOCK) == MNT_MANDLOCK) res |= ST_MANDLOCK_LINUX;\n#elif defined(ST_MANDLOCK)\n  if ((flags & ST_MANDLOCK) == ST_MANDLOCK) res |= ST_MANDLOCK_LINUX;\n#endif\n#ifdef MNT_NODIRATIME\n  if ((flags & MNT_NODIRATIME) == MNT_NODIRATIME) res |= ST_NODIRATIME_LINUX;\n#elif defined(ST_NODIRATIME)\n  if ((flags & ST_NODIRATIME) == ST_NODIRATIME) res |= ST_NODIRATIME_LINUX;\n#endif\n#ifdef MNT_WRITE\n  if ((flags & MNT_WRITE) == MNT_WRITE) res |= ST_WRITE_LINUX;\n#elif defined(ST_WRITE)\n  if ((flags & ST_WRITE) == ST_WRITE) res |= ST_WRITE_LINUX;\n#endif\n  return res;\n}\n\nstatic int ConvertBsdFsTypeNameToLinux(const char *fstypename) {\n  size_t i;\n  static const struct FsTypeName {\n    char name[8];\n    u32 lunix;\n  } kFsTypeName[] = {\n      {\"apfs\", 0x4253584e},                                    //\n      {\"zfs\", 0x2fc12fc1},                                     //\n      {\"ufs\", 0x00011954},                                     //\n      {\"iso9660\", 0x9660},                                     //\n      {\"ext\", 0x4244},                                         //\n      {\"ext2fs\", 0x4244},                                      //\n      {\"hfs\", 0x4244},                                         //\n      {\"msdos\", 0x4d44},                                       //\n      {\"ntfs\", 0x5346544e},                                    //\n      {\"efs\", 0x00414a53},                                     //\n      {\"jfs2\", 0x3153464a},                                    //\n      {\"udf\", 0x15013346},                                     //\n      {\"hpfs\", 0xf995e849},                                    //\n      {\"sysv\", 0x012ff7b5},                                    //\n      {\"devfs\", 0x1373},                                       //\n      {\"procfs\", 0x002f},                                      //\n      {{'l', 'i', 'n', 's', 'y', 's', 'f', 's'}, 0x62656572},  // linsysfs\n  };\n  for (i = 0; i < ARRAYLEN(kFsTypeName); ++i) {\n    if (Read64((const u8 *)fstypename) ==\n        Read64((const u8 *)kFsTypeName[i].name)) {\n      return kFsTypeName[i].lunix;\n    }\n  }\n  return 0;\n}\n\nstatic void XlatStatvfsToLinux(struct statfs_linux *sf, const void *arg) {\n#if defined(__linux) && !defined(_POSIX_C_SOURCE)\n  struct FsId fsid;\n  const struct statfs *vfs = (const struct statfs *)arg;\n  memset(sf, 0, sizeof(*sf));\n  memcpy(&fsid, &vfs->f_fsid, sizeof(fsid));\n  Write64(sf->type, vfs->f_type);\n  Write64(sf->bsize, vfs->f_bsize);\n  Write64(sf->frsize, vfs->f_frsize);\n  Write64(sf->blocks, vfs->f_blocks);\n  Write64(sf->bfree, vfs->f_bfree);\n  Write64(sf->bavail, vfs->f_bavail);\n  Write64(sf->files, vfs->f_files);\n  Write64(sf->ffree, vfs->f_ffree);\n  Write32(sf->fsid[0], fsid.val[0]);\n  Write32(sf->fsid[1], fsid.val[1]);\n  Write64(sf->flags, XlatStatvfsFlags(vfs->f_flags));\n  Write64(sf->namelen, vfs->f_namelen);\n#elif (defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && \\\n    !defined(_POSIX_C_SOURCE)\n  struct FsId fsid;\n  const struct statfs *vfs = (const struct statfs *)arg;\n  memset(sf, 0, sizeof(*sf));\n  memcpy(&fsid, &vfs->f_fsid, sizeof(fsid));\n  Write64(sf->type, ConvertBsdFsTypeNameToLinux(vfs->f_fstypename));\n  Write64(sf->bsize, vfs->f_iosize);\n  Write64(sf->frsize, vfs->f_bsize);\n  Write64(sf->blocks, vfs->f_blocks);\n  Write64(sf->bfree, vfs->f_bfree);\n  Write64(sf->bavail, vfs->f_bavail);\n  Write64(sf->files, vfs->f_files);\n  Write64(sf->ffree, vfs->f_ffree);\n  Write32(sf->fsid[0], fsid.val[0]);\n  Write32(sf->fsid[1], fsid.val[1]);\n  Write64(sf->flags, XlatStatvfsFlags(vfs->f_flags));\n#if defined(__APPLE__) || defined(__NetBSD__)\n  Write64(sf->namelen, NAME_MAX);\n#else\n  Write64(sf->namelen, vfs->f_namemax);\n#endif\n#else\n  const struct statvfs *vfs = (const struct statvfs *)arg;\n  memset(sf, 0, sizeof(*sf));\n  Write64(sf->bsize, vfs->f_bsize);\n  Write64(sf->frsize, vfs->f_frsize);\n  Write64(sf->blocks, vfs->f_blocks);\n  Write64(sf->bfree, vfs->f_bfree);\n  Write64(sf->bavail, vfs->f_bavail);\n  Write64(sf->files, vfs->f_files);\n  Write64(sf->ffree, vfs->f_ffree);\n  Write32(sf->fsid[0], vfs->f_fsid);\n  Write32(sf->fsid[1], (u64)vfs->f_fsid >> 32);\n  Write64(sf->flags, XlatStatvfsFlags(vfs->f_flag));\n  Write64(sf->namelen, vfs->f_namemax);\n#endif\n}\n\n#if (defined(__linux) || defined(__APPLE__) || defined(__FreeBSD__) || \\\n     defined(__OpenBSD__)) &&                                          \\\n    !defined(_POSIX_C_SOURCE)\nstatic int Statfs(uintptr_t arg, struct statfs *buf) {\n  return statfs((const char *)arg, buf);\n}\nstatic int Fstatfs(uintptr_t arg, struct statfs *buf) {\n  return fstatfs((int)arg, buf);\n}\nstatic int SysStatfsImpl(struct Machine *m, uintptr_t arg, i64 addr,\n                         int thunk(uintptr_t, struct statfs *)) {\n  int rc;\n  struct statfs vfs;\n  struct statfs_linux sf;\n  if (!IsValidMemory(m, addr, sizeof(sf), PROT_WRITE)) return efault();\n  RESTARTABLE(rc = thunk(arg, &vfs));\n  if (rc != -1) {\n    XlatStatvfsToLinux(&sf, &vfs);\n    CopyToUserWrite(m, addr, &sf, sizeof(sf));\n  }\n  return rc;\n}\n#else\nstatic int Statfs(uintptr_t arg, struct statvfs *buf) {\n  return statvfs((const char *)arg, buf);\n}\nstatic int Fstatfs(uintptr_t arg, struct statvfs *buf) {\n  return fstatvfs((int)arg, buf);\n}\nstatic int SysStatfsImpl(struct Machine *m, uintptr_t arg, i64 addr,\n                         int thunk(uintptr_t, struct statvfs *)) {\n  int rc;\n  struct statvfs vfs;\n  struct statfs_linux sf;\n  if (!IsValidMemory(m, addr, sizeof(sf), PROT_WRITE)) return efault();\n  RESTARTABLE(rc = thunk(arg, &vfs));\n  if (rc != -1) {\n    XlatStatvfsToLinux(&sf, &vfs);\n    CopyToUserWrite(m, addr, &sf, sizeof(sf));\n  }\n  return rc;\n}\n#endif\n\nint SysStatfs(struct Machine *m, i64 path, i64 addr) {\n  return SysStatfsImpl(m, (uintptr_t)LoadStr(m, path), addr, Statfs);\n}\n\nint SysFstatfs(struct Machine *m, i32 fildes, i64 addr) {\n  return SysStatfsImpl(m, (uintptr_t)(u32)fildes, addr, Fstatfs);\n}\n"
  },
  {
    "path": "blink/stats.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/stats.h\"\n\n#include \"blink/log.h\"\n\n#define DEFINE_AVERAGE(S) struct Average S;\n#define DEFINE_COUNTER(S) long S;\n#include \"blink/stats.inc\"\n#undef DEFINE_AVERAGE\n#undef DEFINE_COUNTER\n\n#define APPEND(...) o += snprintf(b + o, o > n ? 0 : n - o, __VA_ARGS__)\n\nvoid PrintStats(void) {\n#ifndef NDEBUG\n  char b[4096];\n  int n = sizeof(b);\n  int o = 0;\n  b[0] = 0;\n#define DEFINE_COUNTER(S) \\\n  if (S) APPEND(\"%-32s = %ld\\n\", #S, S);\n#define DEFINE_AVERAGE(S) \\\n  if (S.a) APPEND(\"%-32s = %.6g\\n\", #S, S.a);\n#include \"blink/stats.inc\"\n#undef S\n  WriteErrorString(b);\n#endif\n}\n"
  },
  {
    "path": "blink/stats.h",
    "content": "#ifndef BLINK_STATS_H_\n#define BLINK_STATS_H_\n#include <stdbool.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/tsan.h\"\n\n#ifndef NDEBUG\n// we don't care about the accuracy of statistics across threads. some\n// hardware architectures don't even seem to have atomic addition ops.\n#define STATISTIC(x)      \\\n  do {                    \\\n    IGNORE_RACES_START(); \\\n    x;                    \\\n    IGNORE_RACES_END();   \\\n  } while (0)\n#else\n#define STATISTIC(x) (void)0\n#endif\n\n#ifdef DEBUG\n#define COSTLY_STATISTIC(x) STATISTIC(x)\n#else\n#define COSTLY_STATISTIC(x) (void)0\n#endif\n\n#define AVERAGE(S, x) S.a += ((x)-S.a) / ++S.i\n\n#ifndef NDEBUG\n#ifdef __GNUC__\n#define GET_COUNTER(S)    \\\n  __extension__({         \\\n    IGNORE_RACES_START(); \\\n    long S_ = S;          \\\n    IGNORE_RACES_END();   \\\n    S_;                   \\\n  })\n#else\n#define GET_COUNTER(S) (S)\n#endif\n#else\n#define GET_COUNTER(S) 0L\n#endif\n\n#define DEFINE_COUNTER(S) extern long S;\n#define DEFINE_AVERAGE(S) extern struct Average S;\n#include \"blink/stats.inc\"\n#undef DEFINE_COUNTER\n#undef DEFINE_AVERAGE\n\nstruct Average {\n  double a;\n  long i;\n};\n\nextern bool FLAG_statistics;\n\nvoid PrintStats(void);\n\n#endif /* BLINK_STATS_H_ */\n"
  },
  {
    "path": "blink/stats.inc",
    "content": "DEFINE_COUNTER(instructions_cached)\nDEFINE_COUNTER(instructions_decoded)\nDEFINE_COUNTER(instructions_dispatched)\nDEFINE_COUNTER(instructions_jitted)\nDEFINE_COUNTER(interps)\nDEFINE_COUNTER(page_locks)\nDEFINE_COUNTER(page_overlaps)\nDEFINE_COUNTER(path_count)\nDEFINE_COUNTER(path_cycles)\nDEFINE_COUNTER(path_connected_total)\nDEFINE_COUNTER(path_connected_lazily)\nDEFINE_COUNTER(path_connected_directly)\nDEFINE_COUNTER(path_connected_interpreter)\nDEFINE_COUNTER(path_elements)\nDEFINE_COUNTER(path_elements_auto)\nDEFINE_COUNTER(path_longest)\nDEFINE_COUNTER(path_spliced)\nDEFINE_COUNTER(path_abandoned)\nDEFINE_COUNTER(path_longest_bytes)\nDEFINE_AVERAGE(path_average_bytes)\nDEFINE_AVERAGE(path_average_elements)\nDEFINE_COUNTER(path_patches)\nDEFINE_COUNTER(iov_created)\nDEFINE_COUNTER(iov_stretches)\nDEFINE_COUNTER(iov_fragments)\nDEFINE_COUNTER(iov_reallocs)\nDEFINE_COUNTER(smc_resets)\nDEFINE_COUNTER(syscalls)\nDEFINE_COUNTER(jumps_recorded)\nDEFINE_COUNTER(jumps_applied)\nDEFINE_COUNTER(path_ooms)\nDEFINE_COUNTER(alu_ops)\nDEFINE_COUNTER(freelisted)\nDEFINE_COUNTER(alu_unflagged)\nDEFINE_COUNTER(alu_simplified)\nDEFINE_COUNTER(fused_branches)\nDEFINE_COUNTER(tlb_hits)\nDEFINE_COUNTER(tlb_misses)\nDEFINE_COUNTER(tlb_resets)\nDEFINE_COUNTER(icache_resets)\nDEFINE_AVERAGE(jit_average_block)\nDEFINE_COUNTER(jit_blocks_retired)\nDEFINE_COUNTER(jit_blocks_wired)\nDEFINE_COUNTER(jit_blocks_killed)\nDEFINE_COUNTER(jit_max_paths_per_block)\nDEFINE_COUNTER(jit_max_edges_per_page)\nDEFINE_COUNTER(jit_cycles_avoided)\nDEFINE_COUNTER(jit_pages_hits_1)\nDEFINE_COUNTER(jit_pages_hits_2)\nDEFINE_COUNTER(jit_hooks_staged)\nDEFINE_COUNTER(jit_hooks_installed)\nDEFINE_COUNTER(jit_hooks_clobbered)\nDEFINE_COUNTER(jit_hooks_deleted)\nDEFINE_COUNTER(jit_hash_lookups)\nDEFINE_COUNTER(jit_hash_collisions)\nDEFINE_COUNTER(jit_hash_elements)\nDEFINE_COUNTER(jit_page_resets)\nDEFINE_AVERAGE(jit_page_resets_average_hooks)\nDEFINE_AVERAGE(jit_page_average_bits)\nDEFINE_COUNTER(jit_reallocs)\nDEFINE_COUNTER(jit_callocs)\nDEFINE_COUNTER(jit_frees)\nDEFINE_COUNTER(jit_ints_alloc_freelist)\nDEFINE_COUNTER(jit_ints_alloc_slab)\nDEFINE_COUNTER(jit_ints_alloc_system)\nDEFINE_COUNTER(jit_jump_alloc_freelist)\nDEFINE_COUNTER(jit_jump_alloc_system)\nDEFINE_COUNTER(jit_NewJitJump)\nDEFINE_COUNTER(jit_NewJitPage)\nDEFINE_COUNTER(jit_NewJitBlock)\nDEFINE_COUNTER(jit_NewJitStage)\nDEFINE_COUNTER(smc_checks)\nDEFINE_COUNTER(smc_flushes)\nDEFINE_COUNTER(smc_enqueued)\nDEFINE_COUNTER(smc_segfaults)\nDEFINE_AVERAGE(redraw_latency_us)\nDEFINE_AVERAGE(redraw_compressed_bytes)\nDEFINE_AVERAGE(redraw_uncompressed_bytes)\nDEFINE_COUNTER(x1)\nDEFINE_COUNTER(x2)\nDEFINE_COUNTER(x3)\nDEFINE_COUNTER(x4)\nDEFINE_COUNTER(x5)\nDEFINE_COUNTER(x6)\nDEFINE_COUNTER(x7)\nDEFINE_COUNTER(x8)\nDEFINE_COUNTER(x9)\nDEFINE_COUNTER(x10)\n"
  },
  {
    "path": "blink/strace.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/strace.h\"\n\n#include <arpa/inet.h>\n#include <errno.h>\n#include <inttypes.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/wait.h>\n#include <wchar.h>\n\n#include \"blink/assert.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/describeflags.h\"\n#include \"blink/endian.h\"\n#include \"blink/fds.h\"\n#include \"blink/flag.h\"\n#include \"blink/linux.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/thread.h\"\n#include \"blink/util.h\"\n\n#define APPEND(...) bi += snprintf(bp + bi, bi > bn ? 0 : bn - bi, __VA_ARGS__)\n\nstruct MagicNumber {\n  int x;\n  const char *s;\n};\n\nstatic const char *const kOpenAccmode[] = {\n    \"O_RDONLY\",  //\n    \"O_WRONLY\",  //\n    \"O_RDWR\",    //\n};\n\nstatic const struct DescribeFlagz kAccessModes[] = {\n    {R_OK_LINUX, \"R_OK\"},  //\n    {W_OK_LINUX, \"W_OK\"},  //\n    {X_OK_LINUX, \"X_OK\"},  //\n};\n\nstatic const struct DescribeFlagz kOpenFlags[] = {\n    {O_APPEND_LINUX, \"APPEND\"},        //\n    {O_CREAT_LINUX, \"CREAT\"},          //\n    {O_EXCL_LINUX, \"EXCL\"},            //\n    {O_TRUNC_LINUX, \"TRUNC\"},          //\n    {O_NDELAY_LINUX, \"NDELAY\"},        //\n    {O_DIRECT_LINUX, \"DIRECT\"},        //\n    {O_TMPFILE_LINUX, \"TMPFILE\"},      // comes before O_DIRECTORY\n    {O_DIRECTORY_LINUX, \"DIRECTORY\"},  //\n    {O_NOFOLLOW_LINUX, \"NOFOLLOW\"},    //\n    {O_CLOEXEC_LINUX, \"CLOEXEC\"},      //\n    {O_NOCTTY_LINUX, \"NOCTTY\"},        //\n    {O_ASYNC_LINUX, \"ASYNC\"},          //\n    {O_NOATIME_LINUX, \"NOATIME\"},      //\n    {O_PATH_LINUX, \"PATH\"},            //\n    {O_LARGEFILE_LINUX, \"LARGEFILE\"},  //\n    {O_SYNC_LINUX, \"SYNC\"},            // comes before O_DSYNC\n    {O_DSYNC_LINUX, \"DSYNC\"},          //\n};\n\nstatic const struct DescribeFlagz kProtFlags[] = {\n    {PROT_READ_LINUX, \"READ\"},            //\n    {PROT_WRITE_LINUX, \"WRITE\"},          //\n    {PROT_EXEC_LINUX, \"EXEC\"},            //\n    {PROT_SEM_LINUX, \"SEM\"},              //\n    {PROT_GROWSDOWN_LINUX, \"GROWSDOWN\"},  //\n    {PROT_GROWSUP_LINUX, \"GROWSUP\"},      //\n};\n\nstatic const struct DescribeFlagz kMapFlags[] = {\n    {MAP_SHARED_LINUX, \"SHARED\"},                    //\n    {MAP_PRIVATE_LINUX, \"PRIVATE\"},                  //\n    {MAP_FIXED_LINUX, \"FIXED\"},                      //\n    {MAP_FIXED_NOREPLACE_LINUX, \"FIXED_NOREPLACE\"},  //\n    {MAP_NONBLOCK_LINUX, \"NONBLOCK\"},                //\n    {MAP_ANONYMOUS_LINUX, \"ANONYMOUS\"},              //\n    {MAP_GROWSDOWN_LINUX, \"GROWSDOWN\"},              //\n    {MAP_STACK_LINUX, \"STACK\"},                      //\n    {MAP_NORESERVE_LINUX, \"NORESERVE\"},              //\n    {MAP_POPULATE_LINUX, \"POPULATE\"},                //\n    {MAP_HUGETLB_LINUX, \"HUGETLB\"},                  //\n    {MAP_SYNC_LINUX, \"SYNC\"},                        //\n    {MAP_UNINITIALIZED_LINUX, \"UNINITIALIZED\"},      //\n};\n\nstatic const struct DescribeFlagz kSaFlags[] = {\n    {SA_NOCLDSTOP_LINUX, \"NOCLDSTOP\"},            //\n    {SA_NOCLDWAIT_LINUX, \"NOCLDWAIT\"},            //\n    {SA_SIGINFO_LINUX, \"SIGINFO\"},                //\n    {SA_UNSUPPORTED_LINUX, \"UNSUPPORTED\"},        //\n    {SA_EXPOSE_TAGBITS_LINUX, \"EXPOSE_TAGBITS\"},  //\n    {SA_RESTORER_LINUX, \"RESTORER\"},              //\n    {SA_ONSTACK_LINUX, \"ONSTACK\"},                //\n    {SA_RESTART_LINUX, \"RESTART\"},                //\n    {SA_NODEFER_LINUX, \"NODEFER\"},                //\n    {SA_RESETHAND_LINUX, \"RESETHAND\"},            //\n};\n\nstatic const struct DescribeFlagz kAtFlags[] = {\n    {AT_SYMLINK_NOFOLLOW_LINUX, \"SYMLINK_NOFOLLOW\"},  //\n    {AT_REMOVEDIR_LINUX, \"REMOVEDIR\"},                //\n    {AT_EACCESS_LINUX, \"EACCESS\"},                    //\n    {AT_SYMLINK_FOLLOW_LINUX, \"SYMLINK_FOLLOW\"},      //\n    {AT_EMPTY_PATH_LINUX, \"EMPTY_PATH\"},              //\n};\n\n#ifndef DISABLE_THREADS\nstatic const struct DescribeFlagz kCloneFlags[] = {\n    {CLONE_VM_LINUX, \"VM\"},                          //\n    {CLONE_THREAD_LINUX, \"THREAD\"},                  //\n    {CLONE_FS_LINUX, \"FS\"},                          //\n    {CLONE_FILES_LINUX, \"FILES\"},                    //\n    {CLONE_SIGHAND_LINUX, \"SIGHAND\"},                //\n    {CLONE_VFORK_LINUX, \"VFORK\"},                    //\n    {CLONE_SYSVSEM_LINUX, \"SYSVSEM\"},                //\n    {CLONE_SETTLS_LINUX, \"SETTLS\"},                  //\n    {CLONE_PARENT_SETTID_LINUX, \"PARENT_SETTID\"},    //\n    {CLONE_CHILD_CLEARTID_LINUX, \"CHILD_CLEARTID\"},  //\n    {CLONE_DETACHED_LINUX, \"DETACHED\"},              //\n    {CLONE_CHILD_SETTID_LINUX, \"CHILD_SETTID\"},      //\n    {CLONE_NEWCGROUP_LINUX, \"NEWCGROUP\"},            //\n    {CLONE_NEWUTS_LINUX, \"NEWUTS\"},                  //\n    {CLONE_NEWIPC_LINUX, \"NEWIPC\"},                  //\n    {CLONE_NEWUSER_LINUX, \"NEWUSER\"},                //\n    {CLONE_NEWPID_LINUX, \"NEWPID\"},                  //\n    {CLONE_NEWNET_LINUX, \"NEWNET\"},                  //\n    {CLONE_IO_LINUX, \"IO\"},                          //\n};\n#endif\n\n#ifndef DISABLE_NONPOSIX\nstatic const struct DescribeFlagz kRenameFlags[] = {\n    {RENAME_NOREPLACE_LINUX, \"NOREPLACE\"},  //\n    {RENAME_EXCHANGE_LINUX, \"EXCHANGE\"},    //\n    {RENAME_WHITEOUT_LINUX, \"WHITEOUT\"},    //\n};\n#endif\n\n#ifdef HAVE_FORK\nstatic const struct DescribeFlagz kWaitFlags[] = {\n    {WNOHANG_LINUX, \"WNOHANG\"},          //\n    {WUNTRACED_LINUX, \"WUNTRACED\"},      //\n    {WEXITED_LINUX, \"WEXITED\"},          //\n    {WCONTINUED_LINUX, \"WCONTINUED\"},    //\n    {WNOWAIT_LINUX, \"WNOWAIT\"},          //\n    {__WNOTHREAD_LINUX, \"__WNOTHREAD\"},  //\n    {__WALL_LINUX, \"__WALL\"},            //\n    {__WCLONE_LINUX, \"__WCLONE\"},        //\n};\n#endif\n\n#ifndef DISABLE_SOCKETS\nstatic const struct DescribeFlagz kSockFlags[] = {\n    {SOCK_CLOEXEC_LINUX, \"CLOEXEC\"},    //\n    {SOCK_NONBLOCK_LINUX, \"NONBLOCK\"},  //\n};\n#endif\n\nconst struct MagicNumber kWhence[] = {\n    {SEEK_SET_LINUX, \"SEEK_SET\"},  //\n    {SEEK_CUR_LINUX, \"SEEK_CUR\"},  //\n    {SEEK_END_LINUX, \"SEEK_END\"},  //\n};\n\nconst struct MagicNumber kSigHow[] = {\n    {SIG_BLOCK_LINUX, \"SIG_BLOCK\"},      //\n    {SIG_UNBLOCK_LINUX, \"SIG_UNBLOCK\"},  //\n    {SIG_SETMASK_LINUX, \"SIG_SETMASK\"},  //\n};\n\nconst struct MagicNumber kSocketFamily[] = {\n    {AF_UNSPEC_LINUX, \"AF_UNSPEC\"},    //\n    {AF_UNIX_LINUX, \"AF_UNIX\"},        //\n    {AF_INET_LINUX, \"AF_INET\"},        //\n    {AF_INET6_LINUX, \"AF_INET6\"},      //\n    {AF_NETLINK_LINUX, \"AF_NETLINK\"},  //\n    {AF_PACKET_LINUX, \"AF_PACKET\"},    //\n    {AF_VSOCK_LINUX, \"AF_VSOCK\"},      //\n};\n\nconst struct MagicNumber kSocketType[] = {\n    {SOCK_STREAM_LINUX, \"SOCK_STREAM\"},  //\n    {SOCK_DGRAM_LINUX, \"SOCK_DGRAM\"},    //\n    {SOCK_RAW_LINUX, \"SOCK_RAW\"},        //\n};\n\nconst struct MagicNumber kClock[] = {\n    {CLOCK_REALTIME_LINUX, \"CLOCK_REALTIME\"},                      //\n    {CLOCK_MONOTONIC_LINUX, \"CLOCK_MONOTONIC\"},                    //\n    {CLOCK_PROCESS_CPUTIME_ID_LINUX, \"CLOCK_PROCESS_CPUTIME_ID\"},  //\n    {CLOCK_THREAD_CPUTIME_ID_LINUX, \"CLOCK_THREAD_CPUTIME_ID\"},    //\n    {CLOCK_MONOTONIC_RAW_LINUX, \"CLOCK_MONOTONIC_RAW\"},            //\n    {CLOCK_REALTIME_COARSE_LINUX, \"CLOCK_REALTIME_COARSE\"},        //\n    {CLOCK_MONOTONIC_COARSE_LINUX, \"CLOCK_MONOTONIC_COARSE\"},      //\n    {CLOCK_BOOTTIME_LINUX, \"CLOCK_BOOTTIME\"},                      //\n    {CLOCK_REALTIME_ALARM_LINUX, \"CLOCK_REALTIME_ALARM\"},          //\n    {CLOCK_BOOTTIME_ALARM_LINUX, \"CLOCK_BOOTTIME_ALARM\"},          //\n    {CLOCK_TAI_LINUX, \"CLOCK_TAI\"},                                //\n};\n\nconst struct MagicNumber kResource[] = {\n    {RLIMIT_CPU_LINUX, \"RLIMIT_CPU\"},                //\n    {RLIMIT_FSIZE_LINUX, \"RLIMIT_FSIZE\"},            //\n    {RLIMIT_DATA_LINUX, \"RLIMIT_DATA\"},              //\n    {RLIMIT_STACK_LINUX, \"RLIMIT_STACK\"},            //\n    {RLIMIT_CORE_LINUX, \"RLIMIT_CORE\"},              //\n    {RLIMIT_RSS_LINUX, \"RLIMIT_RSS\"},                //\n    {RLIMIT_NPROC_LINUX, \"RLIMIT_NPROC\"},            //\n    {RLIMIT_NOFILE_LINUX, \"RLIMIT_NOFILE\"},          //\n    {RLIMIT_MEMLOCK_LINUX, \"RLIMIT_MEMLOCK\"},        //\n    {RLIMIT_AS_LINUX, \"RLIMIT_AS\"},                  //\n    {RLIMIT_LOCKS_LINUX, \"RLIMIT_LOCKS\"},            //\n    {RLIMIT_SIGPENDING_LINUX, \"RLIMIT_SIGPENDING\"},  //\n    {RLIMIT_MSGQUEUE_LINUX, \"RLIMIT_MSGQUEUE\"},      //\n    {RLIMIT_NICE_LINUX, \"RLIMIT_NICE\"},              //\n    {RLIMIT_RTPRIO_LINUX, \"RLIMIT_RTPRIO\"},          //\n    {RLIMIT_RTTIME_LINUX, \"RLIMIT_RTTIME\"},          //\n};\n\nconst struct MagicNumber kFcntl[] = {\n    {F_DUPFD_LINUX, \"F_DUPFD\"},                  //\n    {F_DUPFD_CLOEXEC_LINUX, \"F_DUPFD_CLOEXEC\"},  //\n    {F_GETFL_LINUX, \"F_GETFL\"},                  //\n    {F_SETFL_LINUX, \"F_SETFL\"},                  //\n    {F_GETLK_LINUX, \"F_GETLK\"},                  //\n    {F_SETLK_LINUX, \"F_SETLK\"},                  //\n    {F_SETLKW_LINUX, \"F_SETLKW\"},                //\n    {F_SETOWN_LINUX, \"F_SETOWN\"},                //\n    {F_GETOWN_LINUX, \"F_GETOWN\"},                //\n    {F_SETSIG_LINUX, \"F_SETSIG\"},                //\n    {F_GETSIG_LINUX, \"F_GETSIG\"},                //\n    {F_SETOWN_EX_LINUX, \"F_SETOWN_EX\"},          //\n    {F_GETOWN_EX_LINUX, \"F_GETOWN_EX\"},          //\n    {F_GETOWNER_UIDS_LINUX, \"F_GETOWNER_UIDS\"},  //\n};\n\nconst struct MagicNumber kFlockType[] = {\n    {F_RDLCK_LINUX, \"F_RDLCK\"},  //\n    {F_WRLCK_LINUX, \"F_WRLCK\"},  //\n    {F_UNLCK_LINUX, \"F_UNLCK\"},  //\n};\n\nstatic const char *GetMagicNumber(const struct MagicNumber *p, int n, int x) {\n  int i;\n  _Thread_local static char ibuf[21];\n  for (i = 0; i < n; ++i) {\n    if (p[i].x == x) {\n      return p[i].s;\n    }\n  }\n  FormatInt64(ibuf, x);\n  return ibuf;\n}\n\nstatic const char *DescribeSockaddr(const struct sockaddr_storage_linux *ss) {\n  _Thread_local static char abuf[64], sabuf[80];\n  switch (Read16(ss->family)) {\n    case AF_UNIX_LINUX:\n      return !ss->storage[sizeof(struct sockaddr_un_linux)]\n                 ? ((const struct sockaddr_un_linux *)ss)->path\n                 : 0;\n    case AF_INET_LINUX:\n      snprintf(sabuf, sizeof(sabuf), \"{\\\"%s\\\", %d}\",\n               inet_ntop(Read16(ss->family),\n                         &((const struct sockaddr_in_linux *)ss)->addr, abuf,\n                         sizeof(abuf)),\n               htons(((const struct sockaddr_in6_linux *)ss)->port));\n      return sabuf;\n    case AF_INET6_LINUX:\n      snprintf(sabuf, sizeof(sabuf), \"{\\\"%s\\\", %d}\",\n               inet_ntop(Read16(ss->family),\n                         &((const struct sockaddr_in6_linux *)ss)->addr, abuf,\n                         sizeof(abuf)),\n               htons(((const struct sockaddr_in6_linux *)ss)->port));\n      return sabuf;\n    default:\n      snprintf(abuf, sizeof(abuf), \"{%s}\",\n               GetMagicNumber(kSocketFamily, ARRAYLEN(kSocketFamily),\n                              Read16(ss->family)));\n      return abuf;\n  }\n}\n\nstatic const char *DescribeBuf(struct Machine *m, i64 arg, u64 len, u64 ax,\n                               bool isentry, bool isout) {\n  _Thread_local static char bp[1 + kStraceBufMax * 3 + 1 + 3 + 2 + 21 + 1];\n  u64 have;\n  const u8 *data;\n  int j, bi, bn, preview;\n  bi = 0;\n  have = len;\n  bn = sizeof(bp);\n  preview = MIN(len, kStraceBufMax);\n  if (isout) {\n    if (!isentry) {\n      have = MIN(len, ax);\n      preview = MIN(preview, ax);\n    } else {\n      preview = -1;\n    }\n  }\n  if (preview > 0 && (data = (const u8 *)SchlepR(m, arg, preview))) {\n    APPEND(\"\\\"\");\n    for (j = 0; j < preview; ++j) {\n      APPEND(\"%lc\", (wint_t)kCp437[data[j]]);\n    }\n    APPEND(\"\\\"\");\n    if (j < have) {\n      APPEND(\"...\");\n    }\n  } else if (!preview) {\n    APPEND(\"\\\"\\\"\");\n  } else {\n    APPEND(\"%#\" PRIx64, arg);\n  }\n  APPEND(\", %\" PRId64, len);\n  return bp;\n}\n\nstatic void DescribeSigset(char *bp, int bn, u64 ss) {\n  int sig, got = 0, bi = 0;\n  if (popcount(ss) > 32) {\n    APPEND(\"~\");\n    ss = ~ss;\n  }\n  APPEND(\"{\");\n  for (sig = 1; sig <= 64; ++sig) {\n    if (ss & ((u64)1 << (sig - 1))) {\n      if (got) {\n        APPEND(\", \");\n      } else {\n        got = true;\n      }\n      APPEND(\"%s\", DescribeSignal(sig));\n    }\n  }\n  APPEND(\"}\");\n}\n\nvoid Strace(struct Machine *m, const char *func, bool isentry, const char *fmt,\n            ...) {\n  char *bp;\n  va_list va;\n  i64 ax, arg;\n  bool isoutmem;\n  int c, i, bi, bn;\n  char tmp[kStraceArgMax];\n  char buf[7][kStraceArgMax];\n  va_start(va, fmt);\n  for (i = 0; i < 7; ++i) {\n    buf[i][0] = 0;\n  }\n  i = 0;\n  if (isentry) {\n    strcpy(buf[0], \"...\");\n    ++i;\n  }\n  for (ax = 0; (c = fmt[i]); ++i) {\n    bi = 0;\n    bp = buf[i];\n    bn = sizeof(buf[i]);\n    if (i >= 2) APPEND(\", \");\n    arg = va_arg(va, i64);\n    if (IS_I32(c)) arg = (i32)arg;\n    if (i == 0) ax = arg;\n    if (i == 0 && arg == -1) {\n      APPEND(\"-%s\", DescribeHostErrno(errno));\n      continue;\n    }\n    if ((isoutmem = arg && !isentry &&                //\n                    (IS_MEM_O(c) || IS_MEM_IO(c)) &&  //\n                    !IS_ADDR(c))) {\n      APPEND(\"[\");\n    }\n    if (arg == -1) {\n      APPEND(\"-1\");\n    } else if (IS_MEM(c) && !arg) {\n      APPEND(\"NULL\");\n    } else if (c == I64_HEX[0] || (ax == -1 && (IS_MEM_O(c) || IS_MEM_IO(c)))) {\n    JustPrintHex:\n      APPEND(\"%#\" PRIx64, arg);\n    } else if (c == I64[0]) {\n      APPEND(\"%\" PRId64, arg);\n    } else if (c == I32[0]) {\n      APPEND(\"%\" PRId32, (i32)arg);\n    } else if (c == I32_OCTAL[0]) {\n      APPEND(\"%#\" PRIo32, (i32)arg);\n    } else if (c == I32_FD[0] || c == I32_DIRFD[0]) {\n      struct Fd *fd;\n      if (c == I32_DIRFD[0] && arg == AT_FDCWD_LINUX) {\n        APPEND(\"AT_FDCWD\");\n      } else {\n        APPEND(\"%d\", (int)arg);\n        LOCK(&m->system->fds.lock);\n        if ((fd = GetFd(&m->system->fds, arg))) {\n          if (fd->path) {\n            APPEND(\" \\\"%s\\\"\", fd->path);\n          }\n        }\n        UNLOCK(&m->system->fds.lock);\n      }\n    } else if (IS_BUF(c)) {\n      u64 len = va_arg(va, i64);\n      APPEND(\"%s\", DescribeBuf(m, arg, len, ax, isentry, c == O_BUF[0]));\n      ++i;\n    } else if (IS_IOVEC(c)) {\n      u64 rem;\n      const struct iovec_linux *iov;\n      int j, iovlen = va_arg(va, i64);\n      if ((iov = (const struct iovec_linux *)SchlepR(\n               m, arg, iovlen * sizeof(struct iovec_linux)))) {\n        rem = ax;\n        APPEND(\"{\");\n        for (j = 0; j < iovlen; ++j) {\n          if (j) APPEND(\", \");\n          APPEND(\"{%s}\", DescribeBuf(m, Read64(iov[j].base), Read64(iov[j].len),\n                                     rem, isentry, c == O_IOVEC[0]));\n          rem -= MIN(rem, Read64(iov[j].len));\n        }\n        APPEND(\"}\");\n      } else {\n        APPEND(\"%#\" PRIx64, arg);\n      }\n      ++i;\n      snprintf(buf[i], sizeof(buf[i]), \", %d\", iovlen);\n    } else if (c == I_STR[0]) {\n      const char *str;\n      if ((str = LoadStr(m, arg))) {\n        APPEND(\"\\\"%s\\\"\", str);\n      } else {\n        goto JustPrintHex;\n      }\n    } else if (c == I32_SIG[0]) {\n      APPEND(\"%s\", DescribeSignal(arg));\n    } else if (c == I32_ACCMODE[0]) {\n      if (!arg) {\n        APPEND(\"F_OK\");\n      } else {\n        DescribeFlagz(tmp, sizeof(tmp), kAccessModes, ARRAYLEN(kAccessModes),\n                      \"\", arg);\n        APPEND(\"%s\", tmp);\n      }\n#ifdef HAVE_FORK\n    } else if (c == I32_WAITFLAGS[0]) {\n      DescribeFlagz(tmp, sizeof(tmp), kWaitFlags, ARRAYLEN(kWaitFlags), \"\",\n                    arg);\n      APPEND(\"%s\", tmp);\n    } else if (c == O_WSTATUS[0]) {\n      const u8 *p;\n      if ((p = (const u8 *)SchlepR(m, arg, 4))) {\n        i32 s = Read32(p);\n        if (WIFEXITED(s)) {\n          APPEND(\"{WIFEXITED(s) && WEXITSTATUS(s) == %d}\", WEXITSTATUS(s));\n        } else if (WIFSTOPPED(s)) {\n          APPEND(\"{WIFSTOPPED(s) && WSTOPSIG(s) == %s}\",\n                 DescribeSignal(WSTOPSIG(s)));\n        } else if (WIFSIGNALED(s)) {\n          APPEND(\"{WIFSIGNALED(s) && WTERMSIG(s) == %s}\",\n                 DescribeSignal(WTERMSIG(s)));\n        } else {\n          APPEND(\"{%#\" PRIx32 \"}\", s);\n        }\n      }\n#endif\n    } else if (c == I32_PROT[0]) {\n      if (arg) {\n        DescribeFlagz(tmp, sizeof(tmp), kProtFlags, ARRAYLEN(kProtFlags),\n                      \"PROT_\", arg);\n        APPEND(\"%s\", tmp);\n      } else {\n        APPEND(\"PROT_NONE\");\n      }\n    } else if (c == I32_MAPFLAGS[0]) {\n      DescribeFlagz(tmp, sizeof(tmp), kMapFlags, ARRAYLEN(kMapFlags), \"MAP_\",\n                    arg);\n      APPEND(\"%s\", tmp);\n    } else if (c == I32_OFLAGS[0]) {\n      i32 arg2 = arg;\n      if ((arg2 & O_ACCMODE_LINUX) < ARRAYLEN(kOpenAccmode)) {\n        APPEND(\"%s\", kOpenAccmode[arg2 & O_ACCMODE_LINUX]);\n        arg2 &= ~O_ACCMODE_LINUX;\n      }\n      if (arg2) {\n        DescribeFlagz(tmp, sizeof(tmp), kOpenFlags, ARRAYLEN(kOpenFlags), \"O_\",\n                      arg2);\n        APPEND(\"|%s\", tmp);\n      }\n      if (!(arg & O_CREAT_LINUX) && !(arg & __O_TMPFILE_LINUX)) {\n        ++i;  // ignore mode\n      }\n    } else if (c == I32_ATFLAGS[0]) {\n      DescribeFlagz(tmp, sizeof(tmp), kAtFlags, ARRAYLEN(kAtFlags), \"AT_\", arg);\n      APPEND(\"%s\", tmp);\n#ifndef DISABLE_THREADS\n    } else if (c == I32_CLONEFLAGS[0]) {\n      DescribeFlagz(tmp, sizeof(tmp), kCloneFlags, ARRAYLEN(kCloneFlags),\n                    \"CLONE_\", arg);\n      APPEND(\"%s\", tmp);\n#endif\n    } else if (IS_SIGSET(c)) {\n      const struct sigset_linux *ss;\n      if ((ss = (const struct sigset_linux *)SchlepR(\n               m, arg, sizeof(struct sigset_linux)))) {\n        DescribeSigset(tmp, sizeof(tmp), Read64(ss->sigmask));\n        APPEND(\"%s\", tmp);\n      } else {\n        goto JustPrintHex;\n      }\n#if defined(HAVE_FORK) || defined(HAVE_THREADS)\n    } else if (c == O_PFDS[0]) {\n      const u8 *pfds;\n      if ((pfds = (const u8 *)SchlepR(m, arg, 8))) {\n        APPEND(\"{%\" PRId32 \", %\" PRId32 \"}\", Read32(pfds), Read32(pfds + 4));\n      } else {\n        goto JustPrintHex;\n      }\n#endif\n    } else if (c == IO_FDSET[0]) {\n      const u8 *fdset;\n      if ((fdset = (const u8 *)SchlepR(m, arg, FD_SETSIZE_LINUX / 8))) {\n        int fd;\n        bool gotsome = false;\n        APPEND(\"{\");\n        for (fd = 0; fd < FD_SETSIZE_LINUX; ++fd) {\n          if (fdset[fd >> 3] & (1 << (fd & 7))) {\n            if (!gotsome) {\n              gotsome = true;\n            } else {\n              APPEND(\",\");\n            }\n            APPEND(\"%d\", fd);\n          }\n        }\n        APPEND(\"}\");\n      } else {\n        goto JustPrintHex;\n      }\n    } else if (IS_TIME(c) || c == IO_TIMEV[0]) {\n      const struct timespec_linux *ts;\n      if ((ts = (const struct timespec_linux *)SchlepR(\n               m, arg, sizeof(struct timespec_linux)))) {\n        APPEND(\"{%\" PRId64 \", %\" PRId64 \"}\", Read64(ts->sec), Read64(ts->nsec));\n      } else {\n        goto JustPrintHex;\n      }\n    } else if (c == O_TIME2[0]) {\n      const struct timespec_linux *ts;\n      if ((ts = (const struct timespec_linux *)SchlepR(\n               m, arg, sizeof(struct timespec_linux) * 2))) {\n        APPEND(\"{.atim = {%\" PRId64 \", %\" PRId64 \"},\"\n               \" .mtim = {%\" PRId64 \", %\" PRId64 \"}}\",\n               Read64(ts[0].sec), Read64(ts[0].nsec), Read64(ts[1].sec),\n               Read64(ts[1].nsec));\n      } else {\n        goto JustPrintHex;\n      }\n    } else if (c == O_STAT[0]) {\n      const struct stat_linux *st;\n      if ((st = (const struct stat_linux *)SchlepR(\n               m, arg, sizeof(struct stat_linux)))) {\n        APPEND(\"{.st_%s=%\" PRId64, \"size\", Read64(st->size));\n        if (Read64(st->blocks)) {\n          APPEND(\", .st_blocks=%\" PRIu64 \"/512\", Read64(st->blocks) * 512);\n        }\n        if (Read32(st->mode)) {\n          APPEND(\", .st_mode=%#\" PRIo32, Read32(st->mode));\n        }\n        if (Read64(st->nlink) != 1) {\n          APPEND(\", .st_nlink=%\" PRIu64, Read64(st->nlink));\n        }\n        if (Read32(st->uid)) {\n          APPEND(\", .st_uid=%\" PRIu32, Read32(st->uid));\n        }\n        if (Read32(st->gid)) {\n          APPEND(\", .st_gid=%\" PRIu32, Read32(st->gid));\n        }\n        if (Read64(st->dev)) {\n          APPEND(\", .st_dev=%\" PRIu64, Read64(st->dev));\n        }\n        if (Read64(st->ino)) {\n          APPEND(\", .st_ino=%\" PRIu64, Read64(st->ino));\n        }\n        if (Read64(st->rdev)) {\n          APPEND(\", .st_rdev=%\" PRIu64, Read64(st->rdev));\n        }\n        if (Read64(st->blksize) != 4096) {\n          APPEND(\", .st_blksize=%\" PRIu64, Read64(st->blksize));\n        }\n        APPEND(\"}\");\n      } else {\n        goto JustPrintHex;\n      }\n    } else if (IS_HAND(c)) {\n      const struct sigaction_linux *sa;\n      if ((sa = (const struct sigaction_linux *)SchlepR(\n               m, arg, sizeof(struct sigaction_linux)))) {\n        APPEND(\"{.sa_handler=\");\n        switch (Read64(sa->handler)) {\n          case SIG_DFL_LINUX:\n            APPEND(\"SIG_DFL\");\n            break;\n          case SIG_IGN_LINUX:\n            APPEND(\"SIG_DFL\");\n            break;\n          default:\n            APPEND(\"%#\" PRIx64, Read64(sa->handler));\n            break;\n        }\n        if (Read64(sa->flags)) {\n          DescribeFlagz(tmp, sizeof(tmp), kSaFlags, ARRAYLEN(kSaFlags), \"SA_\",\n                        Read64(sa->flags));\n          APPEND(\", .sa_flags=%s\", tmp);\n        }\n        if (Read64(sa->mask)) {\n          DescribeSigset(tmp, sizeof(tmp), Read64(sa->mask));\n          APPEND(\", .sa_mask=%s\", tmp);\n        }\n        if (Read64(sa->restorer)) {\n          APPEND(\", .sa_restorer=%#\" PRIx64, Read64(sa->restorer));\n        }\n        APPEND(\"}\");\n      } else {\n        goto JustPrintHex;\n      }\n    } else if (c == I32_SIGHOW[0]) {\n      APPEND(\"%s\", GetMagicNumber(kSigHow, ARRAYLEN(kSigHow), arg));\n    } else if (c == I32_FAMILY[0]) {\n      APPEND(\"%s\", GetMagicNumber(kSocketFamily, ARRAYLEN(kSocketFamily), arg));\n    } else if (c == I32_SOCKTYPE[0]) {\n      if (arg & SOCK_NONBLOCK_LINUX) {\n        APPEND(\"SOCK_NONBLOCK|\");\n        arg &= ~SOCK_NONBLOCK_LINUX;\n      }\n      if (arg & SOCK_CLOEXEC_LINUX) {\n        APPEND(\"SOCK_CLOEXEC|\");\n        arg &= ~SOCK_CLOEXEC_LINUX;\n      }\n      APPEND(\"%s\", GetMagicNumber(kSocketType, ARRAYLEN(kSocketType), arg));\n    } else if (c == I32_RESOURCE[0]) {\n      APPEND(\"%s\", GetMagicNumber(kResource, ARRAYLEN(kResource), arg));\n    } else if (c == I_RLIMIT[0] || c == O_RLIMIT[0]) {\n      const struct rlimit_linux *ts;\n      if ((ts = (const struct rlimit_linux *)SchlepR(\n               m, arg, sizeof(struct rlimit_linux)))) {\n        APPEND(\"{%\" PRId64 \", %\" PRId64 \"}\", Read64(ts->cur), Read64(ts->max));\n      } else {\n        goto JustPrintHex;\n      }\n    } else if (c == I32_CLOCK[0]) {\n      APPEND(\"%s\", GetMagicNumber(kClock, ARRAYLEN(kClock), arg));\n#ifndef DISABLE_SOCKETS\n    } else if (c == I32_SOCKFLAGS[0]) {\n      DescribeFlagz(tmp, sizeof(tmp), kSockFlags, ARRAYLEN(kSockFlags), \"SOCK_\",\n                    arg);\n      APPEND(\"%s\", tmp);\n    } else if (IS_ADDR(c)) {\n      const u8 *p = 0;\n      i64 len = va_arg(va, i64);\n      struct sockaddr_storage_linux ss;\n      memset(&ss, 0, sizeof(ss));\n      if (c == I_ADDR[0]) len = (u32)len;\n      if (c != I_ADDR[0] && !(p = (const u8 *)SchlepR(m, len, 4))) {\n        APPEND(\"%#\" PRIx64 \", %\" PRIx64, arg, len);\n      } else {\n        if (c == I_ADDR[0]) {\n          len = (u32)len;\n        } else {\n          len = Read32(p);\n        }\n        if (c != I_ADDR[0]) APPEND(\"[\");\n        if (arg && CopyFromUserRead(m, &ss, arg, MIN(len, sizeof(ss))) != -1) {\n          APPEND(\"%s\", DescribeSockaddr(&ss));\n        } else {\n          APPEND(\"%#\" PRIx64, arg);\n        }\n        if (c != I_ADDR[0]) APPEND(\"]\");\n        if (c == I_ADDR[0]) {\n          APPEND(\", %\" PRId64, len);\n        } else {\n          APPEND(\", [%\" PRId64 \"]\", len);\n        }\n      }\n      ++i;\n#endif\n#ifndef DISABLE_NONPOSIX\n    } else if (c == I32_RENFLAGS[0]) {\n      DescribeFlagz(tmp, sizeof(tmp), kRenameFlags, ARRAYLEN(kRenameFlags),\n                    \"RENAME_\", arg);\n      APPEND(\"%s\", tmp);\n#endif\n    } else if (c == WAT_FCNTL[0]) {\n      APPEND(\"%s\", GetMagicNumber(kFcntl, ARRAYLEN(kFcntl), arg));\n      if (arg == F_SETLK_LINUX ||   //\n          arg == F_SETLKW_LINUX ||  //\n          arg == F_GETLK_LINUX) {\n        i64 addr = va_arg(va, i64);\n        const struct flock_linux *l;\n        if ((l = (const struct flock_linux *)SchlepR(\n                 m, addr, sizeof(struct flock_linux)))) {\n          APPEND(\", \");\n          if (arg == F_GETLK_LINUX) {\n            APPEND(\"[\");\n          }\n          APPEND(\"{%s\", GetMagicNumber(kFlockType, ARRAYLEN(kFlockType),\n                                       Read16(l->type)));\n          APPEND(\", %s\",\n                 GetMagicNumber(kWhence, ARRAYLEN(kWhence), Read16(l->whence)));\n          if (Read64(l->start)) {\n            APPEND(\", .l_start=%#\" PRIx64, Read64(l->start));\n          }\n          if (Read64(l->len)) {\n            APPEND(\", .l_len=%\" PRIu64, Read64(l->len));\n          }\n          if (Read64(l->pid) && arg == F_GETLK_LINUX) {\n            APPEND(\", .l_pid=%\" PRIu32, Read32(l->pid));\n          }\n          APPEND(\"}\");\n          if (arg == F_GETLK_LINUX) {\n            APPEND(\"]\");\n          }\n        } else {\n          APPEND(\", %#\" PRIx64, addr);\n        }\n      } else if (arg == F_SETFD_LINUX) {\n        i32 flags = va_arg(va, i64);\n        if (flags == FD_CLOEXEC_LINUX) {\n          APPEND(\", FD_CLOEXEC\");\n        } else {\n          APPEND(\", %#\" PRIx32, flags);\n        }\n      } else if (arg == F_SETFL_LINUX) {\n        i32 flags = va_arg(va, i64);\n        DescribeFlagz(tmp, sizeof(tmp), kOpenFlags, ARRAYLEN(kOpenFlags), \"O_\",\n                      flags);\n        APPEND(\"%s\", tmp);\n      } else if (arg == F_SETOWN_LINUX) {\n        i32 fd = va_arg(va, i64);\n        APPEND(\", %#\" PRIx32, fd);\n      }\n    } else {\n      LOGF(\"missing strace signature specifier %#o\", c);\n      goto JustPrintHex;\n    }\n    if (bi + 2 > bn) {\n      bi = bn - 5;\n      bp[bi++] = '.';\n      bp[bi++] = '.';\n      bp[bi++] = '.';\n      bp[bi] = 0;\n    }\n    if (isoutmem) {\n      bp[bi++] = ']';\n      bp[bi] = 0;\n    }\n  }\n  va_end(va);\n  SYS_LOGF(\"%s(%s%s%s%s%s%s) -> %s\", func, buf[1], buf[2], buf[3], buf[4],\n           buf[5], buf[6], buf[0]);\n}\n"
  },
  {
    "path": "blink/strace.h",
    "content": "#ifndef BLINK_STRACE_H_\n#define BLINK_STRACE_H_\n#include \"blink/machine.h\"\n\n#if !defined(DISABLE_STRACE) && !defined(TINY)\n#define STRACE 1\n#else\n#define STRACE 0\n#endif\n\n#define IS_INT(c)    (0000 == (0200 & (c)))\n#define IS_I32(c)    (0000 == (0300 & (c)))\n#define IS_I64(c)    (0100 == (0300 & (c)))\n#define IS_MEM(c)    (0200 == (0200 & (c)))\n#define IS_MEM_I(c)  (0200 == (0340 & (c)))\n#define IS_MEM_O(c)  (0300 == (0340 & (c)))\n#define IS_MEM_IO(c) (0360 == (0340 & (c)))\n#define IS_BUF(c)    (0200 == (0277 & (c)))\n#define IS_TIME(c)   (0202 == (0237 & (c)))\n#define IS_HAND(c)   (0203 == (0277 & (c)))\n#define IS_ADDR(c)   (0210 == (0277 & (c)))\n#define IS_IOVEC(c)  (0212 == (0277 & (c)))\n#define IS_SIGSET(c) (0204 == (0277 & (c)))\n\n#define ST_HAS(s, f) \\\n  (f(s[1]) || f(s[2]) || f(s[3]) || f(s[4]) || f(s[5]) || f(s[6]))\n\n// system call classification, numbered by minimum number of `-s` flags\n// that need to be supplied on the command line to log a syscall entry.\n#define TWOWAY \"\\001\"  // has read+write parameter\n#define BLOCKY \"\\002\"  // cancellation points likely to block\n#define CANCPT \"\\003\"  // cancellation points unlikely to block\n#define NORMAL \"\\004\"  // everything else\n\n#define UN\n#define PAD            \"\\000\"\n#define I32            \"\\001\"\n#define I32_FD         \"\\002\"\n#define I32_DIRFD      \"\\003\"\n#define I32_OCTAL      \"\\004\"\n#define I32_OFLAGS     \"\\005\"\n#define I32_WHENCE     \"\\006\"\n#define I32_ATFLAGS    \"\\007\"\n#define I32_PROT       \"\\010\"\n#define I32_MAPFLAGS   \"\\011\"\n#define I32_MSFLAGS    \"\\012\"\n#define I32_SIG        \"\\013\"\n#define I32_RENFLAGS   \"\\014\"\n#define I32_CLONEFLAGS \"\\015\"\n#define I32_CLOCK      \"\\016\"\n#define I32_WAITFLAGS  \"\\017\"\n#define I32_FAMILY     \"\\020\"\n#define I32_SOCKTYPE   \"\\021\"\n#define I32_SOCKFLAGS  \"\\022\"\n#define I32_SIGHOW     \"\\023\"\n#define I32_ACCMODE    \"\\024\"\n#define I32_RESOURCE   \"\\025\"\n#define I64            \"\\100\"\n#define I64_HEX        \"\\101\"\n#define I_BUF          \"\\200\"\n#define I_STR          \"\\201\"\n#define I_TIME         \"\\202\"\n#define I_HAND         \"\\203\"\n#define I_SIGSET       \"\\204\"\n#define I_ADDR         \"\\210\"\n#define I_IOVEC        \"\\212\"\n#define I_RLIMIT       \"\\213\"\n#define O_BUF          \"\\300\"\n#define O_STAT         \"\\301\"\n#define O_TIME         \"\\302\"\n#define O_HAND         \"\\303\"\n#define O_SIGSET       \"\\304\"\n#define O_PFDS         \"\\306\"\n#define O_WSTATUS      \"\\307\"\n#define O_ADDR         \"\\310\"\n#define O_TIME2        \"\\311\"\n#define O_IOVEC        \"\\312\"\n#define O_RLIMIT       \"\\313\"\n#define IO_POLL        \"\\340\"\n#define IO_TIME        \"\\342\"\n#define IO_TIMEV       \"\\343\"\n#define IO_FDSET       \"\\344\"\n#define WAT_IOCTL      \"\\375\"\n#define WAT_FCNTL      \"\\376\"\n#define WAT_PSELECT    \"\\377\"\n\n#define RC0        I32\n#define PID        I32\n#define UID        I32\n#define GID        I32\n#define ADDRLEN    I32\n#define FD         I32_FD\n#define DIRFD      I32_DIRFD\n#define SIG        I32_SIG\n#define MODE       I32_OCTAL\n#define PROT       I32_PROT\n#define CLOCK      I32_CLOCK\n#define WHENCE     I32_WHENCE\n#define OFLAGS     I32_OFLAGS\n#define FAMILY     I32_FAMILY\n#define MSFLAGS    I32_MSFLAGS\n#define ATFLAGS    I32_ATFLAGS\n#define SOCKTYPE   I32_SOCKTYPE\n#define MAPFLAGS   I32_MAPFLAGS\n#define RENFLAGS   I32_RENFLAGS\n#define WAITFLAGS  I32_WAITFLAGS\n#define SOCKFLAGS  I32_SOCKFLAGS\n#define CLONEFLAGS I32_CLONEFLAGS\n#define RESOURCE   I32_RESOURCE\n#define ACCMODE    I32_ACCMODE\n#define SIGHOW     I32_SIGHOW\n#define SIZE       I64_HEX\n#define SSIZE_     I64\n#define OFF        I64_HEX\n#define HEX        I64_HEX\n#define PTR        I64_HEX\n#define STR        I_STR\n#define PATH       I_STR\n#define BUFSZ      I64\n#define O_RUSAGE   I64_HEX\n\n// clang-format off\n//      SYSCALL             KIND    RET    ARG1       ARG2       ARG3      ARG4      ARG5     ARG6\n#define STRACE_0            NORMAL  HEX    UN         UN         UN        UN        UN       UN\n#define STRACE_1            NORMAL  HEX    HEX        UN         UN        UN        UN       UN\n#define STRACE_2            NORMAL  HEX    HEX        HEX        UN        UN        UN       UN\n#define STRACE_3            NORMAL  HEX    HEX        HEX        HEX       UN        UN       UN\n#define STRACE_4            NORMAL  HEX    HEX        HEX        HEX       HEX       UN       UN\n#define STRACE_5            NORMAL  HEX    HEX        HEX        HEX       HEX       HEX      UN\n#define STRACE_6            NORMAL  HEX    HEX        HEX        HEX       HEX       HEX      HEX\n#define STRACE_READ         BLOCKY  SSIZE_ FD         O_BUF      BUFSZ     UN        UN       UN\n#define STRACE_READV        BLOCKY  SSIZE_ FD         O_IOVEC    BUFSZ     UN        UN       UN\n#define STRACE_PREAD        BLOCKY  SSIZE_ FD         O_BUF      BUFSZ     OFF       UN       UN\n#define STRACE_PREADV       BLOCKY  SSIZE_ FD         O_IOVEC    BUFSZ     OFF       UN       UN\n#define STRACE_PREADV2      BLOCKY  SSIZE_ FD         O_IOVEC    BUFSZ     OFF       I32      UN\n#define STRACE_WRITE        CANCPT  SSIZE_ FD         I_BUF      BUFSZ     UN        UN       UN\n#define STRACE_WRITEV       CANCPT  SSIZE_ FD         I_IOVEC    BUFSZ     UN        UN       UN\n#define STRACE_PWRITE       CANCPT  SSIZE_ FD         I_BUF      BUFSZ     OFF       UN       UN\n#define STRACE_PWRITEV      CANCPT  SSIZE_ FD         I_IOVEC    BUFSZ     OFF       UN       UN\n#define STRACE_PWRITEV2     CANCPT  SSIZE_ FD         I_IOVEC    BUFSZ     OFF       I32      UN\n#define STRACE_OPEN         CANCPT  I32    PATH       OFLAGS     MODE      UN        UN       UN\n#define STRACE_OPENAT       CANCPT  I32    DIRFD      STR        OFLAGS    MODE      UN       UN\n#define STRACE_CREAT        CANCPT  I32    PATH       MODE       UN        UN        UN       UN\n#define STRACE_CLOSE        CANCPT  RC0    FD         UN         UN        UN        UN       UN\n#define STRACE_STAT         NORMAL  RC0    PATH       O_STAT     UN        UN        UN       UN\n#define STRACE_FSTAT        NORMAL  RC0    FD         O_STAT     UN        UN        UN       UN\n#define STRACE_LSTAT        NORMAL  RC0    PATH       O_STAT     UN        UN        UN       UN\n#define STRACE_FSTATAT      NORMAL  RC0    DIRFD      PATH       O_STAT    ATFLAGS   UN       UN\n#define STRACE_UTIMENSAT    NORMAL  RC0    DIRFD      PATH       O_TIME2   ATFLAGS   UN       UN\n#define STRACE_POLL         TWOWAY  I32    IO_POLL    I32        UN        UN        UN       UN\n#define STRACE_PPOLL        TWOWAY  RC0    IO_POLL    IO_TIME    I_SIGSET  SSIZE_    UN       UN\n#define STRACE_LSEEK        NORMAL  OFF    FD         OFF        WHENCE    UN        UN       UN\n#define STRACE_MMAP         NORMAL  PTR    PTR        SIZE       PROT      MAPFLAGS  FD       OFF\n#define STRACE_PAUSE        BLOCKY  RC0    UN         UN         UN        UN        UN       UN\n#define STRACE_SYNC         BLOCKY  RC0    UN         UN         UN        UN        UN       UN\n#define STRACE_FSYNC        BLOCKY  RC0    FD         UN         UN        UN        UN       UN\n#define STRACE_FDATASYNC    BLOCKY  RC0    FD         UN         UN        UN        UN       UN\n#define STRACE_DUP          NORMAL  I32    FD         UN         UN        UN        UN       UN\n#define STRACE_DUP2         NORMAL  I32    FD         I32        UN        UN        UN       UN\n#define STRACE_DUP3         NORMAL  I32    FD         I32        OFLAGS    PAD       UN       UN\n#define STRACE_MSYNC        NORMAL  RC0    PTR        SIZE       MSFLAGS   UN        UN       UN\n#define STRACE_ALARM        NORMAL  I32    I32        UN         UN        UN        UN       UN\n#define STRACE_GETCWD       NORMAL  SSIZE_ O_BUF      BUFSZ      UN        UN        UN       UN\n#define STRACE_TRUNCATE     CANCPT  RC0    STR        OFF        UN        UN        UN       UN\n#define STRACE_FTRUNCATE    CANCPT  RC0    FD         OFF        UN        UN        UN       UN\n#define STRACE_GETRANDOM    CANCPT  SSIZE_ O_BUF      BUFSZ      I32       UN        UN       UN\n#define STRACE_MPROTECT     NORMAL  RC0    PTR        SIZE       PROT      UN        UN       UN\n#define STRACE_MUNMAP       NORMAL  RC0    PTR        SIZE       UN        UN        UN       UN\n#define STRACE_SIGACTION    NORMAL  RC0    SIG        I_HAND     O_HAND    SSIZE_    UN       UN\n#define STRACE_SIGPROCMASK  NORMAL  RC0    SIGHOW     I_SIGSET   O_SIGSET  SSIZE_    UN       UN\n#define STRACE_CLOCK_SLEEP  BLOCKY  RC0    CLOCK      I32        I_TIME    O_TIME    UN       UN\n#define STRACE_SIGSUSPEND   BLOCKY  RC0    I_SIGSET   SSIZE_     UN        UN        UN       UN\n#define STRACE_NANOSLEEP    BLOCKY  RC0    I_TIME     O_TIME     UN        UN        UN       UN\n#define STRACE_IOCTL        CANCPT  I32    FD         WAT_IOCTL  UN        UN        UN       UN\n#define STRACE_PIPE         NORMAL  SSIZE_ O_PFDS     UN         UN        UN        UN       UN\n#define STRACE_PIPE2        NORMAL  SSIZE_ O_PFDS     OFLAGS     PAD       UN        UN       UN\n#define STRACE_SOCKETPAIR   NORMAL  RC0    FAMILY     SOCKTYPE   I32       O_PFDS    UN       UN\n#define STRACE_SELECT       TWOWAY  SSIZE_ I32        IO_FDSET   IO_FDSET  IO_FDSET  IO_TIMEV UN\n#define STRACE_PSELECT      TWOWAY  SSIZE_ I32        IO_FDSET   IO_FDSET  IO_FDSET  IO_TIME  WAT_PSELECT\n#define STRACE_SCHED_YIELD  NORMAL  RC0    UN         UN         UN        UN        UN       UN\n#define STRACE_FCNTL        CANCPT  I64    FD         WAT_FCNTL  UN        UN        UN       UN\n#define STRACE_FORK         NORMAL  PID    UN         UN         UN        UN        UN       UN\n#define STRACE_VFORK        NORMAL  PID    UN         UN         UN        UN        UN       UN\n#define STRACE_WAIT4        BLOCKY  PID    PID        O_WSTATUS  WAITFLAGS O_RUSAGE  UN       UN\n#define STRACE_KILL         NORMAL  RC0    PID        SIG        UN        UN        UN       UN\n#define STRACE_TKILL        NORMAL  RC0    PID        SIG        UN        UN        UN       UN\n#define STRACE_ACCESS       NORMAL  RC0    PATH       ACCMODE    UN        UN        UN       UN\n#define STRACE_FACCESSAT    NORMAL  RC0    DIRFD      PATH       ACCMODE   UN        UN       UN\n#define STRACE_FACCESSAT2   NORMAL  RC0    DIRFD      PATH       ACCMODE   ATFLAGS   UN       UN\n#define STRACE_READLINK     NORMAL  SSIZE_ PATH       O_BUF      BUFSZ     UN        UN       UN\n#define STRACE_READLINKAT   NORMAL  SSIZE_ DIRFD      STR        O_BUF     BUFSZ     UN       UN\n#define STRACE_SYMLINK      NORMAL  RC0    PATH       PATH       UN        UN        UN       UN\n#define STRACE_SYMLINKAT    NORMAL  RC0    PATH       DIRFD      PATH      UN        UN       UN\n#define STRACE_UNLINK       NORMAL  RC0    PATH       UN         UN        UN        UN       UN\n#define STRACE_UNLINKAT     NORMAL  RC0    DIRFD      PATH       ATFLAGS   UN        UN       UN\n#define STRACE_LINK         NORMAL  RC0    PATH       PATH       UN        UN        UN       UN\n#define STRACE_LINKAT       NORMAL  RC0    DIRFD      PATH       DIRFD     PATH      ATFLAGS  UN\n#define STRACE_RENAME       NORMAL  RC0    PATH       PATH       UN        UN        UN       UN\n#define STRACE_RENAMEAT     NORMAL  RC0    DIRFD      PATH       DIRFD     PATH      UN       UN\n#define STRACE_RENAMEAT2    NORMAL  RC0    DIRFD      PATH       DIRFD     PATH      ATFLAGS  UN\n#define STRACE_MKDIR        NORMAL  RC0    PATH       MODE       UN        UN        RENFLAGS UN\n#define STRACE_MKDIRAT      NORMAL  RC0    DIRFD      PATH       MODE      UN        UN       UN\n#define STRACE_RMDIR        NORMAL  RC0    PATH       UN         UN        UN        UN       UN\n#define STRACE_CHMOD        NORMAL  RC0    PATH       MODE       UN        UN        UN       UN\n#define STRACE_FCHMOD       NORMAL  RC0    FD         MODE       UN        UN        UN       UN\n#define STRACE_FCHMODAT     NORMAL  RC0    DIRFD      PATH       MODE      ATFLAGS   UN       UN\n#define STRACE_CHOWN        NORMAL  RC0    PATH       UID        GID       UN        UN       UN\n#define STRACE_LCHOWN       NORMAL  RC0    PATH       UID        GID       UN        UN       UN\n#define STRACE_FCHOWN       NORMAL  RC0    FD         UID        GID       UN        UN       UN\n#define STRACE_CHOWNAT      NORMAL  RC0    DIRFD      PATH       UID       GID       ATFLAGS  UN\n#define STRACE_GETTID       NORMAL  PID    UN         UN         UN        UN        UN       UN\n#define STRACE_GETPID       NORMAL  PID    UN         UN         UN        UN        UN       UN\n#define STRACE_GETPPID      NORMAL  PID    UN         UN         UN        UN        UN       UN\n#define STRACE_GETPGID      NORMAL  PID    PID        UN         UN        UN        UN       UN\n#define STRACE_GETUID       NORMAL  UID    UN         UN         UN        UN        UN       UN\n#define STRACE_GETGID       NORMAL  GID    UN         UN         UN        UN        UN       UN\n#define STRACE_GETEUID      NORMAL  UID    UN         UN         UN        UN        UN       UN\n#define STRACE_GETEGID      NORMAL  GID    UN         UN         UN        UN        UN       UN\n#define STRACE_SETSID       NORMAL  PID    UN         UN         UN        UN        UN       UN\n#define STRACE_GETPGRP      NORMAL  PID    UN         UN         UN        UN        UN       UN\n#define STRACE_SETUID       NORMAL  RC0    UID        UN         UN        UN        UN       UN\n#define STRACE_SETGID       NORMAL  RC0    GID        UN         UN        UN        UN       UN\n#define STRACE_SETREUID     NORMAL  RC0    UID        UID        UN        UN        UN       UN\n#define STRACE_SETREGID     NORMAL  RC0    GID        GID        UN        UN        UN       UN\n#define STRACE_SETRESUID    NORMAL  RC0    UID        UID        UID       UN        UN       UN\n#define STRACE_SETRESGID    NORMAL  RC0    GID        GID        GID       UN        UN       UN\n#define STRACE_UMASK        NORMAL  MODE   MODE       UN         UN        UN        UN       UN\n#define STRACE_CHDIR        NORMAL  RC0    PATH       UN         UN        UN        UN       UN\n#define STRACE_CHROOT       NORMAL  RC0    PATH       UN         UN        UN        UN       UN\n#define STRACE_FCHDIR       NORMAL  RC0    FD         UN         UN        UN        UN       UN\n#define STRACE_CLONE        NORMAL  PID    CLONEFLAGS PTR        PTR       PTR       PTR      PTR\n#define STRACE_FUTEX        CANCPT  HEX    HEX        HEX        HEX       HEX       HEX      HEX\n#define STRACE_SOCKET       NORMAL  I32    FAMILY     SOCKTYPE   I32       UN        UN       UN\n#define STRACE_CONNECT      NORMAL  I32    FD         I_ADDR     ADDRLEN   UN        UN       UN\n#define STRACE_LISTEN       NORMAL  RC0    FD         UN         UN        UN        UN       UN\n#define STRACE_ACCEPT       BLOCKY  FD     FD         O_ADDR     I64       UN        UN       UN\n#define STRACE_ACCEPT4      BLOCKY  FD     FD         O_ADDR     I64       SOCKFLAGS UN       UN\n#define STRACE_BIND         NORMAL  RC0    FD         I_ADDR     ADDRLEN   UN        UN       UN\n#define STRACE_GETSOCKNAME  NORMAL  RC0    FD         O_ADDR     I64       UN        UN       UN\n#define STRACE_GETPEERNAME  NORMAL  RC0    FD         O_ADDR     I64       UN        UN       UN\n#define STRACE_SENDTO       NORMAL  SSIZE_ FD         I_BUF      SIZE      I32       I_ADDR   ADDRLEN\n#define STRACE_RECVFROM     BLOCKY  SSIZE_ FD         O_BUF      SIZE      I32       O_ADDR   I64\n#define STRACE_GETRLIMIT    NORMAL  RC0    RESOURCE   O_RLIMIT   UN        UN        UN       UN\n#define STRACE_SETRLIMIT    NORMAL  RC0    RESOURCE   I_RLIMIT   UN        UN        UN       UN\n#define STRACE_PRLIMIT      NORMAL  RC0    PID        RESOURCE   I_RLIMIT  O_RLIMIT  UN       UN\n#define STRACE_MOUNT        NORMAL  STR    STR        STR        MSFLAGS   PTR       UN       UN\n// clang-format on\n\nvoid EnterStrace(struct Machine *, const char *, const char *, ...);\nvoid LeaveStrace(struct Machine *, const char *, const char *, ...);\n\n#endif /* BLINK_STRACE_H_ */\n"
  },
  {
    "path": "blink/strchrnul.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/util.h\"\n\nchar *strchrnul_(const char *s, int c) {\n  for (;; ++s) {\n    if ((*s & 255) == (c & 255)) return (char *)s;\n    if (!*s) return (char *)s;\n  }\n}\n"
  },
  {
    "path": "blink/string.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/string.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/alu.h\"\n#include \"blink/atomic.h\"\n#include \"blink/biosrom.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n#include \"blink/tsan.h\"\n#include \"blink/util.h\"\n#include \"blink/x86.h\"\n\nstatic u64 ReadInt(u8 p[8], unsigned long w) {\n  switch (w) {\n    case 0:\n      return Read8(p);\n    case 1:\n      return Read16(p);\n    case 2:\n      return Read32(p);\n    case 3:\n      return Read64(p);\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic void WriteInt(u8 p[8], u64 x, unsigned long w) {\n  switch (w) {\n    case 0:\n      Write8(p, x);\n      break;\n    case 1:\n      Write16(p, x);\n      break;\n    case 2:\n      Write32(p, x);\n      break;\n    case 3:\n      Write64(p, x);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic void AddDi(P, u64 x) {\n  switch (Eamode(rde)) {\n    case XED_MODE_LONG:\n      Put64(m->di, Get64(m->di) + x);\n      break;\n    case XED_MODE_LEGACY:\n      Put64(m->di, (Get32(m->di) + x) & 0xffffffff);\n      break;\n    case XED_MODE_REAL:\n      Put16(m->di, Get16(m->di) + x);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic void AddSi(P, u64 x) {\n  switch (Eamode(rde)) {\n    case XED_MODE_LONG:\n      Put64(m->si, Get64(m->si) + x);\n      break;\n    case XED_MODE_LEGACY:\n      Put64(m->si, (Get32(m->si) + x) & 0xffffffff);\n      break;\n    case XED_MODE_REAL:\n      Put16(m->si, Get16(m->si) + x);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic u64 ReadCx(P) {\n  switch (Eamode(rde)) {\n    case XED_MODE_LONG:\n      return Get64(m->cx);\n    case XED_MODE_LEGACY:\n      return Get32(m->cx);\n    case XED_MODE_REAL:\n      return Get16(m->cx);\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic u64 SubtractCx(P, u64 x) {\n  u64 cx = Get64(m->cx) - x;\n  if (Eamode(rde) != XED_MODE_REAL) {\n    if (Eamode(rde) == XED_MODE_LEGACY) {\n      cx &= 0xffffffff;\n    }\n    Put64(m->cx, cx);\n  } else {\n    cx &= 0xffff;\n    Put16(m->cx, cx);\n  }\n  return cx;\n}\n\nstatic void StringOp(P, int op) {\n  bool stop;\n  unsigned n;\n  i64 sgn, v;\n  void *p[2];\n  u8 s[3][8];\n  stop = false;\n  n = 1 << RegLog2(rde);\n  sgn = GetFlag(m->flags, FLAGS_DF) ? -1 : 1;\n  IGNORE_RACES_START();\n  atomic_thread_fence(memory_order_acquire);\n  do {\n    if (Rep(rde) && !ReadCx(A)) break;\n    switch (op) {\n      case STRING_CMPS:\n        kAlu[ALU_SUB][RegLog2(rde)](\n            m, ReadInt(Load(m, AddressSi(A), n, s[2]), RegLog2(rde)),\n            ReadInt(Load(m, AddressDi(A), n, s[1]), RegLog2(rde)));\n        AddDi(A, sgn * n);\n        AddSi(A, sgn * n);\n        stop = (Rep(rde) == 2 && GetFlag(m->flags, FLAGS_ZF)) ||\n               (Rep(rde) == 3 && !GetFlag(m->flags, FLAGS_ZF));\n        break;\n      case STRING_MOVS:\n        memmove(BeginStore(m, (v = AddressDi(A)), n, p, s[0]),\n                Load(m, AddressSi(A), n, s[1]), n);\n        AddDi(A, sgn * n);\n        AddSi(A, sgn * n);\n        EndStore(m, v, n, p, s[0]);\n        break;\n      case STRING_STOS:\n        memmove(BeginStore(m, (v = AddressDi(A)), n, p, s[0]), m->ax, n);\n        AddDi(A, sgn * n);\n        EndStore(m, v, n, p, s[0]);\n        break;\n      case STRING_LODS:\n        memmove(m->ax, Load(m, AddressSi(A), n, s[1]), n);\n        AddSi(A, sgn * n);\n        break;\n      case STRING_SCAS:\n        kAlu[ALU_SUB][RegLog2(rde)](\n            m, ReadInt(Load(m, AddressDi(A), n, s[1]), RegLog2(rde)),\n            ReadInt(m->ax, RegLog2(rde)));\n        AddDi(A, sgn * n);\n        stop = (Rep(rde) == 2 && GetFlag(m->flags, FLAGS_ZF)) ||\n               (Rep(rde) == 3 && !GetFlag(m->flags, FLAGS_ZF));\n        break;\n#ifndef DISABLE_METAL\n      case STRING_OUTS:\n        OpOut(m, Get16(m->dx),\n              ReadInt(Load(m, AddressSi(A), n, s[1]), RegLog2(rde)));\n        AddSi(A, sgn * n);\n        break;\n      case STRING_INS:\n        WriteInt((u8 *)BeginStore(m, (v = AddressDi(A)), n, p, s[0]),\n                 OpIn(m, Get16(m->dx)), RegLog2(rde));\n        AddDi(A, sgn * n);\n        EndStore(m, v, n, p, s[0]);\n        break;\n#endif /* DISABLE_METAL */\n      default:\n        Abort();\n    }\n    if (Rep(rde)) {\n      SubtractCx(A, 1);\n    } else {\n      break;\n    }\n  } while (!stop);\n  atomic_thread_fence(memory_order_release);\n  IGNORE_RACES_END();\n}\n\nstatic void RepMovsbEnhanced(P) {\n  u8 *direal, *sireal;\n  u64 diactual, siactual, cx;\n  u16 dilow, silow;\n  long diremain, siremain, i, n;\n  if ((cx = ReadCx(A))) {\n    diactual = AddressDi(A);\n    siactual = AddressSi(A);\n    if (diactual != siactual) {\n      if (!GetFlag(m->flags, FLAGS_DF)) {\n        SetWriteAddr(m, diactual, cx);\n        SetReadAddr(m, siactual, cx);\n      } else {\n        SetWriteAddr(m, diactual - cx + 1, cx);\n        SetReadAddr(m, siactual - cx + 1, cx);\n      }\n      IGNORE_RACES_START();\n      atomic_thread_fence(memory_order_acquire);\n      do {\n        direal = ResolveAddress(m, diactual);\n        sireal = ResolveAddress(m, siactual);\n        dilow = Get16(m->di);\n        silow = Get16(m->si);\n        if (!GetFlag(m->flags, FLAGS_DF)) {\n          diremain = 4096 - (diactual & 4095);\n          diremain = MIN(diremain, 65536 - dilow);\n          siremain = 4096 - (siactual & 4095);\n          siremain = MIN(siremain, 65536 - silow);\n          n = MIN(cx, MIN(diremain, siremain));\n          if (!IsRomAddress(m, direal)) {\n            for (i = 0; i < n; ++i) {\n              direal[i] = sireal[i];\n            }\n          }\n          AddDi(A, n);\n          AddSi(A, n);\n        } else {\n          diremain = (diactual & 4095) + 1;\n          diremain = MIN(diremain, (long)dilow + 1);\n          siremain = (siactual & 4095) + 1;\n          siremain = MIN(siremain, (long)silow + 1);\n          n = MIN(cx, MIN(diremain, siremain));\n          if (!IsRomAddress(m, direal)) {\n            for (i = 0; i < n; ++i) {\n              direal[-i] = sireal[-i];\n            }\n          }\n          AddDi(A, -n);\n          AddSi(A, -n);\n        }\n        cx = SubtractCx(A, n);\n        if (cx) {\n          diactual = AddressDi(A);\n          siactual = AddressSi(A);\n        }\n      } while (cx);\n      atomic_thread_fence(memory_order_release);\n      IGNORE_RACES_END();\n    }\n  }\n}\n\nstatic void RepStosbEnhanced(P) {\n  u8 *direal;\n  u64 diactual, cx;\n  u16 dilow;\n  unsigned diremain, n;\n  if ((cx = ReadCx(A))) {\n    diactual = AddressDi(A);\n    SetWriteAddr(m, diactual, cx);\n    IGNORE_RACES_START();\n    do {\n      direal = ResolveAddress(m, diactual);\n      dilow = Get16(m->di);\n      diremain = 4096 - (diactual & 4095);\n      diremain = MIN(diremain, 65536 - dilow);\n      n = MIN(cx, diremain);\n      if (!IsRomAddress(m, direal)) memset(direal, m->al, n);\n      AddDi(A, n);\n      cx = SubtractCx(A, n);\n      if (cx) diactual = AddressDi(A);\n    } while (cx);\n    atomic_thread_fence(memory_order_release);\n    IGNORE_RACES_END();\n  }\n}\n\nvoid OpMovs(P) {\n  StringOp(A, STRING_MOVS);\n}\n\nvoid OpCmps(P) {\n  StringOp(A, STRING_CMPS);\n}\n\nvoid OpStos(P) {\n  StringOp(A, STRING_STOS);\n}\n\nvoid OpLods(P) {\n  StringOp(A, STRING_LODS);\n}\n\nvoid OpScas(P) {\n  StringOp(A, STRING_SCAS);\n}\n\nvoid OpIns(P) {\n  StringOp(A, STRING_INS);\n}\n\nvoid OpOuts(P) {\n  StringOp(A, STRING_OUTS);\n}\n\nvoid OpMovsb(P) {\n  if (Rep(rde)) {\n    RepMovsbEnhanced(A);\n  } else {\n    OpMovs(A);\n  }\n}\n\nvoid OpStosb(P) {\n  if (Rep(rde) && !GetFlag(m->flags, FLAGS_DF)) {\n    RepStosbEnhanced(A);\n  } else {\n    OpStos(A);\n  }\n}\n"
  },
  {
    "path": "blink/string.h",
    "content": "#ifndef BLINK_STRING_H_\n#define BLINK_STRING_H_\n#include \"blink/machine.h\"\n\n#define STRING_CMPS 0\n#define STRING_MOVS 1\n#define STRING_STOS 2\n#define STRING_LODS 3\n#define STRING_SCAS 4\n#define STRING_OUTS 5\n#define STRING_INS  6\n\nvoid OpCmps(P);\nvoid OpIns(P);\nvoid OpLods(P);\nvoid OpMovs(P);\nvoid OpMovsb(P);\nvoid OpOuts(P);\nvoid OpScas(P);\nvoid OpStos(P);\nvoid OpStosb(P);\n\n#endif /* BLINK_STRING_H_ */\n"
  },
  {
    "path": "blink/strwidth.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/strwidth.h\"\n\n#include <wchar.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/macros.h\"\n#include \"blink/thompike.h\"\n#include \"blink/util.h\"\n\n/**\n * Returns monospace display width of UTF-8 string.\n *\n * - Control codes are discounted\n * - ANSI escape sequences are discounted\n * - East asian glyphs, emoji, etc. count as two\n *\n * @param s is NUL-terminated string\n * @param o is string offset for computing tab widths\n * @return monospace display width\n */\nint strwidth(const char *s, size_t o) {\n  return strnwidth(s, -1, 0);\n}\n\n/**\n * Returns monospace display width of UTF-8 string.\n *\n * - Control codes are discounted\n * - ANSI escape sequences are discounted\n * - East asian glyphs, emoji, etc. count as two\n *\n * @param s is NUL-terminated string\n * @param n is max bytes to consider\n * @param o is offset for doing tabs\n * @return monospace display width\n */\nint strnwidth(const char *s, size_t n, size_t o) {\n  size_t i;\n  wint_t c, w;\n  unsigned l, r, k;\n  enum { kAscii, kUtf8, kEsc, kCsi } t;\n  for (t = kAscii, w = r = l = i = 0; i < n;) {\n    if ((c = s[i++] & 0xff)) {\n      switch (t) {\n        case kAscii:\n          if (0x20 <= c && c <= 0x7E) {\n            ++l;\n          } else if (c == '\\t') {\n            if ((k = (o + i - 1) & 7)) {\n              l += 8 - k;\n            } else {\n              l += 8;\n            }\n          } else if (c == 033) {\n            t = kEsc;\n          } else if (c >= 0300) {\n            t = kUtf8;\n            w = ThomPikeByte(c);\n            r = ThomPikeLen(c) - 1;\n          }\n          break;\n        case kUtf8:\n          if (ThomPikeCont(c)) {\n            w = ThomPikeMerge(w, c);\n            if (--r) break;\n          }\n          k = wcwidth(w);\n          l += MAX(0, k);\n          t = kAscii;\n          break;\n        case kEsc:\n          if (c == '[') {\n            t = kCsi;\n          } else if (!(040 <= c && c < 060)) {\n            t = kAscii;\n          }\n          break;\n        case kCsi:\n          if (!(060 <= c && c < 0100)) {\n            t = kAscii;\n          }\n          break;\n        default:\n          __builtin_unreachable();\n      }\n    } else {\n      break;\n    }\n  }\n  return l;\n}\n"
  },
  {
    "path": "blink/strwidth.h",
    "content": "#ifndef BLINK_STRWIDTH_H_\n#define BLINK_STRWIDTH_H_\n#include <stddef.h>\n\nint strwidth(const char *, size_t);\nint strnwidth(const char *, size_t, size_t);\n\n#endif /* BLINK_STRWIDTH_H_ */\n"
  },
  {
    "path": "blink/swap.h",
    "content": "#ifndef BLINK_SWAP_H_\n#define BLINK_SWAP_H_\n#include <stdint.h>\n\n#include \"blink/builtin.h\"\n\n#if __has_builtin(__builtin_bswap64) || defined(__GNUC__)\n#define SWAP16(x) __builtin_bswap16(x)\n#define SWAP32(x) __builtin_bswap32(x)\n#define SWAP64(x) __builtin_bswap64(x)\n#else\n#define SWAP16(x)                                  \\\n  (((UINT64_C(0x00000000000000ff) & (x)) << 010) | \\\n   ((UINT64_C(0x000000000000ff00) & (x)) >> 010))\n#define SWAP32(x)                                  \\\n  (((UINT64_C(0x00000000000000ff) & (x)) << 030) | \\\n   ((UINT64_C(0x000000000000ff00) & (x)) << 010) | \\\n   ((UINT64_C(0x0000000000ff0000) & (x)) >> 010) | \\\n   ((UINT64_C(0x00000000ff000000) & (x)) >> 030))\n#define SWAP64(x)                                  \\\n  (((UINT64_C(0x00000000000000ff) & (x)) << 070) | \\\n   ((UINT64_C(0x000000000000ff00) & (x)) << 050) | \\\n   ((UINT64_C(0x0000000000ff0000) & (x)) << 030) | \\\n   ((UINT64_C(0x00000000ff000000) & (x)) << 010) | \\\n   ((UINT64_C(0x000000ff00000000) & (x)) >> 010) | \\\n   ((UINT64_C(0x0000ff0000000000) & (x)) >> 030) | \\\n   ((UINT64_C(0x00ff000000000000) & (x)) >> 050) | \\\n   ((UINT64_C(0xff00000000000000) & (x)) >> 070))\n#endif\n\n#endif /* BLINK_SWAP_H_ */\n"
  },
  {
    "path": "blink/syscall.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/syscall.h\"\n\n#include <dirent.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <grp.h>\n#include <inttypes.h>\n#include <limits.h>\n#include <net/if.h>\n#include <netdb.h>\n#include <netinet/in.h>\n#include <netinet/ip.h>\n#include <poll.h>\n#include <signal.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/file.h>\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#include <sys/param.h>\n#include <sys/resource.h>\n#include <sys/select.h>\n#include <sys/socket.h>\n#include <sys/statvfs.h>\n#include <sys/time.h>\n#include <sys/times.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <time.h>\n#include <unistd.h>\n\n#include \"blink/ancillary.h\"\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/bus.h\"\n#include \"blink/case.h\"\n#include \"blink/checked.h\"\n#include \"blink/debug.h\"\n#include \"blink/endian.h\"\n#include \"blink/errno.h\"\n#include \"blink/flag.h\"\n#include \"blink/iovs.h\"\n#include \"blink/limits.h\"\n#include \"blink/linux.h\"\n#include \"blink/loader.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/ndelay.h\"\n#include \"blink/overlays.h\"\n#include \"blink/pml4t.h\"\n#include \"blink/preadv.h\"\n#include \"blink/random.h\"\n#include \"blink/signal.h\"\n#include \"blink/stats.h\"\n#include \"blink/strace.h\"\n#include \"blink/swap.h\"\n#include \"blink/thread.h\"\n#include \"blink/timespec.h\"\n#include \"blink/util.h\"\n#include \"blink/vfs.h\"\n#include \"blink/xlat.h\"\n\n#ifdef __linux\n#include <sys/prctl.h>\n#endif\n\n#ifdef __EMSCRIPTEN__\n#include <emscripten.h>\n#endif\n\n#ifdef __HAIKU__\n#include <OS.h>\n#include <sys/sockio.h>\n#endif\n\n#ifdef HAVE_SCHED_H\n#include <sched.h>\n#endif\n\n#ifdef HAVE_EPOLL_PWAIT1\n#include <sys/epoll.h>\n#endif\n\n#ifdef HAVE_SYS_MOUNT_H\n#include <sys/mount.h>\n#endif\n\n#ifdef SO_LINGER_SEC\n#define SO_LINGER_ SO_LINGER_SEC\n#else\n#define SO_LINGER_ SO_LINGER\n#endif\n\n#define SYSARGS0\n#define SYSARGS1 , di\n#define SYSARGS2 , di, si\n#define SYSARGS3 , di, si, dx\n#define SYSARGS4 , di, si, dx, r0\n#define SYSARGS5 , di, si, dx, r0, r8\n#define SYSARGS6 , di, si, dx, r0, r8, r9\n\n#define SYSCALL(arity, ordinal, name, func, signature)            \\\n  case ordinal:                                                   \\\n    if (STRACE && FLAG_strace >= (signature)[0]) {                \\\n      Strace(m, name, true, &(signature)[1] SYSARGS##arity);      \\\n    }                                                             \\\n    ax = func(m SYSARGS##arity);                                  \\\n    if (STRACE && FLAG_strace) {                                  \\\n      Strace(m, name, false, &(signature)[1], ax SYSARGS##arity); \\\n    }                                                             \\\n    break\n\nchar *g_blink_path;\nbool FLAG_statistics;\n\n// delegate to work around function pointer errors, b/c\n// old musl toolchains using `int ioctl(int, int, ...)`\nstatic int SystemIoctl(int fd, unsigned long request, ...) {\n  va_list va;\n  uintptr_t arg;\n  va_start(va, request);\n  arg = va_arg(va, uintptr_t);\n  va_end(va);\n  return VfsIoctl(fd, request, (void *)arg);\n}\n\n#ifdef __EMSCRIPTEN__\n// If this runs on the main thread, the browser is blocked until we return\n// back to the main loop. Yield regularly when the process waits for some\n// user input.\n\nint em_poll(struct pollfd *fds, nfds_t nfds, int timeout) {\n  int ret = VfsPoll(fds, nfds, timeout);\n  if (ret == 0) emscripten_sleep(50);\n  return ret;\n}\n\nssize_t em_readv(int fd, const struct iovec *iov, int iovcnt) {\n  // Handle blocking reads by waiting for POLLIN\n  if ((VfsFcntl(fd, F_GETFL, 0) & O_NONBLOCK) == 0) {\n    struct pollfd pfd;\n    pfd.fd = fd;\n    pfd.events = POLLIN;\n    while (em_poll(&pfd, 1, 50) == 0) {\n    }\n  }\n  size_t ret = VfsReadv(fd, iov, iovcnt);\n  if (ret == -1 && errno == EAGAIN) emscripten_sleep(50);\n  return ret;\n}\n#endif\n\nstatic int my_tcgetwinsize(int fd, struct winsize *ws) {\n  return VfsIoctl(fd, TIOCGWINSZ, (void *)ws);\n}\n\nstatic int my_tcsetwinsize(int fd, const struct winsize *ws) {\n  return VfsIoctl(fd, TIOCSWINSZ, (void *)ws);\n}\n\nconst struct FdCb kFdCbHost = {\n    .close = VfsClose,\n#ifdef __EMSCRIPTEN__\n    .readv = em_readv,\n#else\n    .readv = VfsReadv,\n#endif\n    .writev = VfsWritev,\n#ifdef __EMSCRIPTEN__\n    .poll = em_poll,\n#else\n    .poll = VfsPoll,\n#endif\n    .tcgetattr = VfsTcgetattr,\n    .tcsetattr = VfsTcsetattr,\n    .tcgetwinsize = my_tcgetwinsize,\n    .tcsetwinsize = my_tcsetwinsize,\n};\n\nstruct Fd *GetAndLockFd(struct Machine *m, int fildes) {\n  struct Fd *fd;\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) LockFd(fd);\n  UNLOCK(&m->system->fds.lock);\n  return fd;\n}\n\nint GetDirFildes(int fildes) {\n  if (fildes == AT_FDCWD_LINUX) return AT_FDCWD;\n  return fildes;\n}\n\nconst char *GetDirFildesPath(struct System *s, int fildes) {\n  struct Fd *fd;\n  if (fildes == AT_FDCWD_LINUX) return \".\";\n  if ((fd = GetFd(&s->fds, fildes))) return fd->path;\n  return 0;\n}\n\nvoid SignalActor(struct Machine *m) {\n  for (;;) {\n    STATISTIC(++interps);\n    JitlessDispatch(DISPATCH_NOTHING);\n    if (atomic_load_explicit(&m->attention, memory_order_acquire)) {\n      if (m->restored) break;\n      CheckForSignals(m);\n    }\n  }\n}\n\nbool DeliverSignalRecursively(struct Machine *m, int sig) {\n  bool issigsuspend;\n  sigset_t unblock, oldmask;\n  SYS_LOGF(\"recursing %s\", DescribeSignal(sig));\n  if (m->sigdepth >= kMaxSigDepth) {\n    LOGF(\"exceeded max signal depth\");\n    return false;\n  }\n  // we're officially calling a signal handler\n  // run the signal handler code inside the i/o routine\n  // it's very important that no locks are currently held\n  // garbage may exist on the freelist for calls like sendmsg\n  ++m->sigdepth;\n  if ((issigsuspend = m->issigsuspend)) {\n    m->issigsuspend = false;\n    unassert(!sigemptyset(&unblock));\n    unassert(!pthread_sigmask(SIG_BLOCK, &unblock, &oldmask));\n  }\n  m->restored = false;\n  m->insyscall = false;\n  SignalActor(m);\n  m->insyscall = true;\n  m->restored = false;\n  if (issigsuspend) {\n    unassert(!pthread_sigmask(SIG_SETMASK, &oldmask, 0));\n    m->issigsuspend = true;\n  }\n  --m->sigdepth;\n  return true;\n}\n\nbool CheckInterrupt(struct Machine *m, bool restartable) {\n  bool res, restart;\n  int sig, delivered;\n  // an actual i/o call just received EINTR from the kernel\nHandleSomeMoreInterrupts:\n  // determine if there's any signals pending for our guest\n  Put64(m->ax, -EINTR_LINUX);\n  if ((sig = ConsumeSignal(m, &delivered, &restart))) {\n    TerminateSignal(m, sig, 0);\n  }\n  if (delivered) {\n    if (DeliverSignalRecursively(m, delivered)) {\n      if (restart && restartable) {\n        // try to consume some more signals while we're here\n        goto HandleSomeMoreInterrupts;\n      } else {\n        // let the i/o routine return eintr\n        errno = EINTR;\n        res = true;\n      }\n    } else {\n      errno = EINTR;\n      res = true;\n    }\n  } else {\n    // no signal is being delivered\n    res = false;\n  }\n  m->interrupted = res;\n  return res;\n}\n\nstatic struct Futex *FindFutex(struct Machine *m, i64 addr) {\n  struct Dll *e;\n  for (e = dll_first(g_bus->futexes.active); e;\n       e = dll_next(g_bus->futexes.active, e)) {\n    if (FUTEX_CONTAINER(e)->addr == addr) {\n      return FUTEX_CONTAINER(e);\n    }\n  }\n  return 0;\n}\n\nstatic int SysFutexWake(struct Machine *m, i64 uaddr, u32 count) {\n  int rc;\n  struct Futex *f;\n  if (!count) return 0;\n  LOCK(&g_bus->futexes.lock);\n  if ((f = FindFutex(m, uaddr))) {\n    LOCK(&f->lock);\n  }\n  UNLOCK(&g_bus->futexes.lock);\n  if (f && f->waiters) {\n    THR_LOGF(\"pid=%d tid=%d is waking %d waiters at address %#\" PRIx64,\n             m->system->pid, m->tid, f->waiters, uaddr);\n    if (count == 1) {\n      unassert(!pthread_cond_signal(&f->cond));\n      rc = 1;\n    } else {\n      unassert(!pthread_cond_broadcast(&f->cond));\n      rc = f->waiters;\n    }\n    UNLOCK(&f->lock);\n  } else {\n    if (f) UNLOCK(&f->lock);\n    THR_LOGF(\"pid=%d tid=%d is waking no one at address %#\" PRIx64,\n             m->system->pid, m->tid, uaddr);\n    rc = 0;\n  }\n  return rc;\n}\n\nstatic void ClearChildTid(struct Machine *m) {\n#if defined(HAVE_FORK) || defined(HAVE_THREADS)\n  _Atomic(int) *ctid;\n  if (m->ctid) {\n    THR_LOGF(\"ClearChildTid(%#\" PRIx64 \")\", m->ctid);\n    if ((ctid = (_Atomic(int) *)LookupAddress(m, m->ctid))) {\n      atomic_store_explicit(ctid, 0, memory_order_seq_cst);\n    } else {\n      THR_LOGF(\"invalid clear child tid address %#\" PRIx64, m->ctid);\n    }\n  }\n  SysFutexWake(m, m->ctid, INT_MAX);\n#endif\n}\n\n_Noreturn void SysExitGroup(struct Machine *m, int rc) {\n  THR_LOGF(\"pid=%d tid=%d SysExitGroup\", m->system->pid, m->tid);\n  ClearChildTid(m);\n  if (m->system->isfork) {\n#ifndef NDEBUG\n    if (FLAG_statistics) {\n      PrintStats();\n    }\n#endif\n    THR_LOGF(\"calling _Exit(%d)\", rc);\n    _Exit(rc);\n  } else {\n    THR_LOGF(\"calling exit(%d)\", rc);\n    KillOtherThreads(m->system);\n#ifdef HAVE_JIT\n    DisableJit(&m->system->jit);  // unmapping exec pages is slow\n#endif\n    if (m->system->trapexit && !m->system->exited) {\n      m->system->exited = true;\n      m->system->exitcode = rc;\n      HaltMachine(m, kMachineExitTrap);\n    }\n    FreeMachine(m);\n#ifdef HAVE_JIT\n    ShutdownJit();\n#endif\n#ifndef NDEBUG\n    if (FLAG_statistics) {\n      PrintStats();\n    }\n#endif\n    exit(rc);\n  }\n}\n\n_Noreturn void SysExit(struct Machine *m, int rc) {\n#ifdef HAVE_THREADS\n  THR_LOGF(\"pid=%d tid=%d SysExit\", m->system->pid, m->tid);\n  if (IsOrphan(m)) {\n    SysExitGroup(m, rc);\n  } else {\n    ClearChildTid(m);\n    FreeMachine(m);\n    pthread_exit(EXIT_SUCCESS);\n  }\n#else\n  SysExitGroup(m, rc);\n#endif\n}\n\nstatic int Fork(struct Machine *m, u64 flags, u64 stack, u64 ctid) {\n  int pid, newpid = 0;\n  _Atomic(int) *ctid_ptr;\n  unassert(!m->path.jb);\n  // NOTES ON THE LOCKING TOPOLOGY\n  // exec_lock must come before sig_lock (see dup3)\n  // exec_lock must come before fds.lock (see dup3)\n  // exec_lock must come before fds.lock (see execve)\n  // mmap_lock must come before fds.lock (see GetOflags)\n  // mmap_lock must come before pagelocks_lock (see FreePage)\n  if (m->threaded) {\n    LOCK(&m->system->exec_lock);\n    LOCK(&m->system->sig_lock);\n    LOCK(&m->system->mmap_lock);\n    LOCK(&m->system->pagelocks_lock);\n    LOCK(&m->system->fds.lock);\n    LOCK(&m->system->machines_lock);\n#ifndef HAVE_PTHREAD_PROCESS_SHARED\n    LOCK(&g_bus->futexes.lock);\n#endif\n#ifdef HAVE_JIT\n    LOCK(&m->system->jit.lock);\n#endif\n  }\n  pid = fork();\n#ifdef __HAIKU__\n  // haiku wipes tls after fork() in child\n  // https://dev.haiku-os.org/ticket/17896\n  if (!pid) g_machine = m;\n#endif\n  if (m->threaded) {\n#ifdef HAVE_JIT\n    UNLOCK(&m->system->jit.lock);\n#endif\n#ifndef HAVE_PTHREAD_PROCESS_SHARED\n    UNLOCK(&g_bus->futexes.lock);\n#endif\n    UNLOCK(&m->system->machines_lock);\n    UNLOCK(&m->system->fds.lock);\n    UNLOCK(&m->system->pagelocks_lock);\n    UNLOCK(&m->system->mmap_lock);\n    UNLOCK(&m->system->sig_lock);\n    UNLOCK(&m->system->exec_lock);\n  }\n  if (!pid) {\n    newpid = getpid();\n    if (stack) {\n      Put64(m->sp, stack);\n    }\n#ifndef HAVE_PTHREAD_PROCESS_SHARED\n    InitBus();\n#endif\n    THR_LOGF(\"pid=%d tid=%d SysFork -> pid=%d tid=%d\",  //\n             m->system->pid, m->tid, newpid, newpid);\n    m->tid = m->system->pid = newpid;\n    m->system->isfork = true;\n    RemoveOtherThreads(m->system);\n#ifdef __CYGWIN__\n    // Cygwin doesn't seem to properly set the PROT_EXEC\n    // protection for JIT blocks after forking.\n    FixJitProtection(&m->system->jit);\n#endif\n    if ((flags & (CLONE_CHILD_SETTID_LINUX | CLONE_CHILD_CLEARTID_LINUX)) &&\n        !(ctid & (sizeof(i32) - 1)) &&\n        (ctid_ptr = (_Atomic(i32) *)LookupAddress(m, ctid))) {\n      if (flags & CLONE_CHILD_SETTID_LINUX) {\n        atomic_store_explicit(ctid_ptr, Little32(newpid), memory_order_release);\n      }\n      if (flags & CLONE_CHILD_CLEARTID_LINUX) {\n        m->ctid = ctid;\n      }\n    }\n  }\n  return pid;\n}\n\nstatic int SysFork(struct Machine *m) {\n  return Fork(m, 0, 0, 0);\n}\n\nstatic int SysVfork(struct Machine *m) {\n  // TODO: Parent should be stopped while child is running.\n  return SysFork(m);\n}\n\nstatic void *OnSpawn(void *arg) {\n  int rc;\n  struct Machine *m = (struct Machine *)arg;\n  THR_LOGF(\"pid=%d tid=%d OnSpawn\", m->system->pid, m->tid);\n  m->thread = pthread_self();\n  if (!(rc = sigsetjmp(m->onhalt, 1))) {\n    m->canhalt = true;\n    unassert(!pthread_sigmask(SIG_SETMASK, &m->spawn_sigmask, 0));\n  } else if (rc == kMachineFatalSystemSignal) {\n    HandleFatalSystemSignal(m, &g_siginfo);\n  }\n  Blink(m);\n}\n\n#ifdef HAVE_THREADS\nstatic int SysSpawn(struct Machine *m, u64 flags, u64 stack, u64 ptid, u64 ctid,\n                    u64 tls, u64 func) {\n  int tid;\n  int err;\n  int ignored;\n  pthread_t thread;\n  unsigned supported;\n  unsigned mandatory;\n  sigset_t ss, oldss;\n  pthread_attr_t attr;\n  _Atomic(int) *ptid_ptr;\n  _Atomic(int) *ctid_ptr;\n  struct Machine *m2 = 0;\n  THR_LOGF(\"pid=%d tid=%d SysSpawn\", m->system->pid, m->tid);\n  if ((flags & 255) != 0 && (flags & 255) != SIGCHLD_LINUX) {\n    LOGF(\"unsupported clone() signal: %\" PRId64, flags & 255);\n    return einval();\n  }\n  flags &= ~255;\n  supported = CLONE_THREAD_LINUX | CLONE_VM_LINUX | CLONE_FS_LINUX |\n              CLONE_FILES_LINUX | CLONE_SIGHAND_LINUX | CLONE_SETTLS_LINUX |\n              CLONE_PARENT_SETTID_LINUX | CLONE_CHILD_CLEARTID_LINUX |\n              CLONE_CHILD_SETTID_LINUX | CLONE_SYSVSEM_LINUX;\n  mandatory = CLONE_THREAD_LINUX | CLONE_VM_LINUX | CLONE_FS_LINUX |\n              CLONE_FILES_LINUX | CLONE_SIGHAND_LINUX;\n  ignored = CLONE_DETACHED_LINUX | CLONE_IO_LINUX;\n  flags &= ~ignored;\n  if (flags & ~supported) {\n    LOGF(\"unsupported clone() flags: %#\" PRIx64, flags & ~supported);\n    return einval();\n  }\n  if ((flags & mandatory) != mandatory) {\n    LOGF(\"missing mandatory clone() thread flags: %#\" PRIx64\n         \" out of %#\" PRIx64,\n         (flags & mandatory) ^ mandatory, flags);\n    return einval();\n  }\n  if (((flags & CLONE_PARENT_SETTID_LINUX) &&\n       ((ptid & (sizeof(int) - 1)) ||\n        !IsValidMemory(m, ptid, 4, PROT_READ | PROT_WRITE) ||\n        !(ptid_ptr = (_Atomic(int) *)LookupAddress(m, ptid)))) ||\n      ((flags & CLONE_CHILD_SETTID_LINUX) &&\n       ((ctid & (sizeof(int) - 1)) ||\n        !IsValidMemory(m, ctid, 4, PROT_READ | PROT_WRITE) ||\n        !(ctid_ptr = (_Atomic(int) *)LookupAddress(m, ctid))))) {\n    LOGF(\"bad clone() ptid / ctid pointers: %#\" PRIx64, flags);\n    return efault();\n  }\n  m->threaded = true;\n  m->system->jit.threaded = true;\n  if (!(m2 = NewMachine(m->system, m))) {\n    return eagain();\n  }\n  sigfillset(&ss);\n  unassert(!pthread_sigmask(SIG_SETMASK, &ss, &oldss));\n  tid = m2->tid;\n  if (flags & CLONE_SETTLS_LINUX) {\n    m2->fs.base = tls;\n  }\n  if (flags & CLONE_CHILD_CLEARTID_LINUX) {\n    m2->ctid = ctid;\n  }\n  if (flags & CLONE_CHILD_SETTID_LINUX) {\n    atomic_store_explicit(ctid_ptr, Little32(tid), memory_order_release);\n  }\n  Put64(m2->ax, 0);\n  Put64(m2->sp, stack);\n  m2->spawn_sigmask = oldss;\n  unassert(!pthread_attr_init(&attr));\n  unassert(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));\n  err = pthread_create(&thread, &attr, OnSpawn, m2);\n  unassert(!pthread_attr_destroy(&attr));\n  if (err) {\n    FreeMachine(m2);\n    unassert(!pthread_sigmask(SIG_SETMASK, &oldss, 0));\n    return eagain();\n  }\n  if (flags & CLONE_PARENT_SETTID_LINUX) {\n    atomic_store_explicit(ptid_ptr, Little32(tid), memory_order_release);\n  }\n  unassert(!pthread_sigmask(SIG_SETMASK, &oldss, 0));\n  return tid;\n}\n#endif\n\nstatic bool IsForkOrVfork(u64 flags) {\n  u64 supported = CLONE_CHILD_SETTID_LINUX | CLONE_CHILD_CLEARTID_LINUX;\n  return (flags & ~supported) == SIGCHLD_LINUX ||\n         (flags & ~supported) ==\n             (CLONE_VM_LINUX | CLONE_VFORK_LINUX | SIGCHLD_LINUX);\n}\n\nstatic int SysClone(struct Machine *m, u64 flags, u64 stack, u64 ptid, u64 ctid,\n                    u64 tls, u64 func) {\n  if (IsForkOrVfork(flags)) {\n#ifdef HAVE_FORK\n    return Fork(m, flags, stack, ctid);\n#else\n    LOGF(\"forking support disabled\");\n    return enosys();\n#endif\n  }\n#ifdef HAVE_THREADS\n  return SysSpawn(m, flags, stack, ptid, ctid, tls, func);\n#else\n  LOGF(\"threading support disabled\");\n  return enosys();\n#endif\n}\n\nstatic struct Futex *NewFutex(i64 addr) {\n  struct Dll *e;\n  struct Futex *f;\n  if (!(e = dll_first(g_bus->futexes.free))) {\n    LOG_ONCE(LOGF(\"ran out of futexes\"));\n    enomem();\n    return 0;\n  }\n  dll_remove(&g_bus->futexes.free, e);\n  f = FUTEX_CONTAINER(e);\n  f->waiters = 1;\n  f->addr = addr;\n  return f;\n}\n\nstatic void FreeFutex(struct Futex *f) {\n  dll_make_first(&g_bus->futexes.free, &f->elem);\n}\n\nstatic int LoadTimespec(struct Machine *m, i64 addr, struct timespec *ts,\n                        u64 mask, u64 need) {\n  const struct timespec_linux *gt;\n  if ((gt = (const struct timespec_linux *)Schlep(m, addr, sizeof(*gt), mask,\n                                                  need))) {\n    ts->tv_sec = Read64(gt->sec);\n    ts->tv_nsec = Read64(gt->nsec);\n    if (0 <= ts->tv_sec && (0 <= ts->tv_nsec && ts->tv_nsec < 1000000000)) {\n      return 0;\n    } else {\n      return einval();\n    }\n  } else {\n    return -1;\n  }\n}\n\nstatic int LoadTimespecR(struct Machine *m, i64 addr, struct timespec *ts) {\n  return LoadTimespec(m, addr, ts, PAGE_U, PAGE_U);\n}\n\nstatic int LoadTimespecRW(struct Machine *m, i64 addr, struct timespec *ts) {\n  return LoadTimespec(m, addr, ts, PAGE_U | PAGE_RW, PAGE_U | PAGE_RW);\n}\n\nstatic int SysFutexWait(struct Machine *m,  //\n                        i64 uaddr,          //\n                        i32 op,             //\n                        u32 expect,         //\n                        i64 timeout_addr) {\n  int rc;\n  u8 *mem;\n  struct Futex *f;\n  const struct timespec_linux *gtimeout;\n  struct timespec now, tick, timeout, deadline;\n  now = tick = GetTime();\n  if (timeout_addr) {\n    if (!(gtimeout = (const struct timespec_linux *)SchlepR(\n              m, timeout_addr, sizeof(*gtimeout)))) {\n      return -1;\n    }\n    timeout.tv_sec = Read64(gtimeout->sec);\n    timeout.tv_nsec = Read64(gtimeout->nsec);\n    if (!(0 <= timeout.tv_nsec && timeout.tv_nsec < 1000000000)) {\n      return einval();\n    }\n    deadline = AddTime(now, timeout);\n  } else {\n    deadline = GetMaxTime();\n  }\n  if (!(mem = LookupAddress(m, uaddr))) return -1;\n  LOCK(&g_bus->futexes.lock);\n  if (Load32(mem) != expect) {\n    UNLOCK(&g_bus->futexes.lock);\n    return eagain();\n  }\n  if ((f = FindFutex(m, uaddr))) {\n    LOCK(&f->lock);\n    ++f->waiters;\n    UNLOCK(&f->lock);\n  }\n  if (!f) {\n    if ((f = NewFutex(uaddr))) {\n      dll_make_first(&g_bus->futexes.active, &f->elem);\n    } else {\n      UNLOCK(&g_bus->futexes.lock);\n      return -1;\n    }\n  }\n  UNLOCK(&g_bus->futexes.lock);\n  THR_LOGF(\"pid=%d tid=%d is waiting at address %#\" PRIx64, m->system->pid,\n           m->tid, uaddr);\n  do {\n    if (m->killed) {\n      rc = EAGAIN;\n      break;\n    }\n    if (CheckInterrupt(m, true)) {\n      rc = EINTR;\n      break;\n    }\n    if (!(mem = LookupAddress(m, uaddr))) {\n      rc = errno;\n      break;\n    }\n    LOCK(&f->lock);\n    if (Load32(mem) != expect) {\n      rc = 0;\n    } else {\n      tick = AddTime(tick, FromMilliseconds(kPollingMs));\n      if (CompareTime(tick, deadline) > 0) tick = deadline;\n      rc = pthread_cond_timedwait(&f->cond, &f->lock, &tick);\n      if (rc == ETIMEDOUT) {\n        THR_LOGF(\"futex wait timed out\");\n      } else {\n        THR_LOGF(\"futex wait returned %s\", DescribeHostErrno(rc));\n      }\n    }\n    UNLOCK(&f->lock);\n  } while (rc == ETIMEDOUT && CompareTime(tick, deadline) < 0);\n  LOCK(&g_bus->futexes.lock);\n  LOCK(&f->lock);\n  if (!--f->waiters) {\n    dll_remove(&g_bus->futexes.active, &f->elem);\n    UNLOCK(&f->lock);\n    FreeFutex(f);\n    UNLOCK(&g_bus->futexes.lock);\n  } else {\n    UNLOCK(&f->lock);\n    UNLOCK(&g_bus->futexes.lock);\n  }\n  if (rc) {\n    errno = rc;\n    rc = -1;\n  }\n  return rc;\n}\n\nstatic int SysFutex(struct Machine *m,  //\n                    i64 uaddr,          //\n                    i32 op,             //\n                    u32 val,            //\n                    i64 timeout_addr,   //\n                    i64 uaddr2,         //\n                    u32 val3) {\n  if (uaddr & 3) return efault();\n  op &= ~FUTEX_PRIVATE_FLAG_LINUX;\n  switch (op) {\n    case FUTEX_WAIT_LINUX:\n      return SysFutexWait(m, uaddr, op, val, timeout_addr);\n    case FUTEX_WAKE_LINUX:\n      return SysFutexWake(m, uaddr, val);\n    case FUTEX_WAIT_BITSET_LINUX:\n    case FUTEX_WAIT_BITSET_LINUX | FUTEX_CLOCK_REALTIME_LINUX:\n      // will be supported soon\n      // avoid logging when cosmo feature checks this\n      if (!m->system->iscosmo) goto DefaultCase;\n      return einval();\n    default:\n    DefaultCase:\n      LOGF(\"unsupported %s op %#x\", \"futex\", op);\n      return einval();\n  }\n}\n\nstatic void UnlockRobustFutex(struct Machine *m, u64 futex_addr,\n                              bool ispending) {\n  int owner;\n  u32 value, replace;\n  _Atomic(u32) *futex;\n  if (futex_addr & 3) {\n    LOGF(\"robust futex isn't aligned\");\n    return;\n  }\n  if (!(futex = (_Atomic(u32) *)SchlepR(m, futex_addr, 4))) {\n    LOGF(\"encountered efault in robust futex list\");\n    return;\n  }\n  for (value = atomic_load_explicit(futex, memory_order_acquire);;) {\n    owner = value & FUTEX_TID_MASK_LINUX;\n    if (ispending && !owner) {\n      THR_LOGF(\"unlocking pending ownerless futex\");\n      SysFutexWake(m, futex_addr, 1);\n      return;\n    }\n    if (owner && owner != m->tid) {\n      THR_LOGF(\"robust futex 0x%08\" PRIx32\n               \" was owned by %d but we're tid=%d pid=%d\",\n               value, owner, m->tid, m->system->pid);\n      return;\n    }\n    replace = FUTEX_OWNER_DIED_LINUX | (value & FUTEX_WAITERS_LINUX);\n    if (atomic_compare_exchange_weak_explicit(futex, &value, replace,\n                                              memory_order_release,\n                                              memory_order_acquire)) {\n      THR_LOGF(\"successfully unlocked robust futex\");\n      if (value & FUTEX_WAITERS_LINUX) {\n        THR_LOGF(\"waking robust futex waiters\");\n        SysFutexWake(m, futex_addr, 1);\n      }\n      return;\n    } else {\n      THR_LOGF(\"robust futex cas failed\");\n    }\n  }\n}\n\nvoid UnlockRobustFutexes(struct Machine *m) {\n  if (1) return;  // TODO: Figure out how these work.\n  int limit = 1000;\n  bool once = false;\n  u64 list, item, pending;\n  struct robust_list_linux *data;\n  if (!(item = list = m->robust_list)) return;\n  m->robust_list = 0;\n  pending = 0;\n  do {\n    if (!(data = (struct robust_list_linux *)SchlepR(m, item, sizeof(*data)))) {\n      LOGF(\"encountered efault in robust futex list\");\n      break;\n    }\n    THR_LOGF(\"unlocking robust futex %#\" PRIx64 \" {.next=%#\" PRIx64\n             \" .offset=%\" PRId64 \" .pending=%#\" PRIx64 \"}\",\n             item, Read64(data->next), Read64(data->offset),\n             Read64(data->pending));\n    if (!once) {\n      pending = Read64(data->pending);\n      once = true;\n    }\n    if (!--limit) {\n      LOGF(\"encountered cycle or limit in robust futex list\");\n      break;\n    }\n    if (item != pending) {\n      UnlockRobustFutex(m, item + Read64(data->offset), false);\n    }\n    item = Read64(data->next);\n  } while (item != list);\n  if (!pending) return;\n  if (!(data =\n            (struct robust_list_linux *)SchlepR(m, pending, sizeof(*data)))) {\n    LOGF(\"encountered efault in robust futex list\");\n    return;\n  }\n  THR_LOGF(\"unlocking pending robust futex %#\" PRIx64 \" {.next=%#\" PRIx64\n           \" .offset=%\" PRId64 \" .pending=%#\" PRIx64 \"}\",\n           item, Read64(data->next), Read64(data->offset),\n           Read64(data->pending));\n  UnlockRobustFutex(m, pending + Read64(data->offset), true);\n}\n\nstatic i32 ReturnRobustList(struct Machine *m, i64 head_ptr_addr,\n                            i64 len_ptr_addr) {\n  u8 buf[8];\n  Write64(buf, m->robust_list);\n  CopyToUserWrite(m, head_ptr_addr, buf, sizeof(buf));\n  Write64(buf, sizeof(struct robust_list_linux));\n  CopyToUserWrite(m, len_ptr_addr, buf, sizeof(buf));\n  return 0;\n}\n\nstatic i32 SysGetRobustList(struct Machine *m, int pid, i64 head_ptr_addr,\n                            i64 len_ptr_addr) {\n  int rc;\n  struct Dll *e;\n  struct Machine *m2;\n  if (!pid || pid == m->tid) {\n    rc = ReturnRobustList(m, head_ptr_addr, len_ptr_addr);\n  } else {\n    rc = -1;\n    errno = ESRCH;\n    LOCK(&m->system->machines_lock);\n    for (e = dll_first(m->system->machines); e;\n         e = dll_next(m->system->machines, e)) {\n      m2 = MACHINE_CONTAINER(e);\n      if (m2->tid == pid) {\n        rc = ReturnRobustList(m2, head_ptr_addr, len_ptr_addr);\n        break;\n      }\n    }\n    UNLOCK(&m->system->machines_lock);\n  }\n  return rc;\n}\n\nstatic i32 SysSetRobustList(struct Machine *m, i64 head_addr, u64 len) {\n  if (len != sizeof(struct robust_list_linux)) return einval();\n  if (!IsValidMemory(m, head_addr, len, PROT_READ | PROT_WRITE)) return -1;\n  m->robust_list = head_addr;\n  return 0;\n}\n\nstatic int ValidateAffinityPid(struct Machine *m, int pid) {\n  if (pid < 0) return esrch();\n  if (pid && pid != m->tid && pid != m->system->pid) return eperm();\n  return 0;\n}\n\nstatic int SysSchedSetaffinity(struct Machine *m,  //\n                               i32 pid,            //\n                               u64 cpusetsize,     //\n                               i64 maskaddr) {\n  if (ValidateAffinityPid(m, pid) == -1) return -1;\n#ifdef HAVE_SCHED_GETAFFINITY\n  u8 *mask;\n  size_t i, n;\n  cpu_set_t sysmask;\n  GetCpuCount();  // call for effect\n  n = MIN(cpusetsize, CPU_SETSIZE / 8) * 8;\n  if (!(mask = (u8 *)AddToFreeList(m, malloc(n / 8)))) return -1;\n  if (CopyFromUserRead(m, mask, maskaddr, n / 8) == -1) return -1;\n  CPU_ZERO(&sysmask);\n  for (i = 0; i < n; ++i) {\n    if (mask[i / 8] & (1 << (i % 8))) {\n      CPU_SET(i, &sysmask);\n    }\n  }\n  return sched_setaffinity(pid, sizeof(sysmask), &sysmask);\n#else\n  return 0;  // do nothing\n#endif\n}\n\nstatic int SysSchedGetaffinity(struct Machine *m,  //\n                               i32 pid,            //\n                               u64 cpusetsize,     //\n                               i64 maskaddr) {\n  if (ValidateAffinityPid(m, pid) == -1) return -1;\n#ifdef HAVE_SCHED_GETAFFINITY\n  int rc;\n  u8 *mask;\n  size_t i, n;\n  cpu_set_t sysmask;\n  n = MIN(cpusetsize, CPU_SETSIZE / 8) * 8;\n  if (!(mask = (u8 *)AddToFreeList(m, malloc(n / 8)))) return -1;\n  rc = sched_getaffinity(pid, sizeof(sysmask), &sysmask);\n  unassert(rc == 0 || rc == -1);\n  if (!rc) {\n    rc = n / 8;\n    memset(mask, 0, n / 8);\n    for (i = 0; i < n; ++i) {\n      if (CPU_ISSET(i, &sysmask)) {\n        mask[i / 8] |= 1 << (i % 8);\n      }\n    }\n    if (CopyToUserWrite(m, maskaddr, mask, n / 8) == -1) rc = -1;\n  }\n  return rc;\n#else\n  u8 *mask;\n  unsigned i, rc, count;\n  count = GetCpuCount();\n  rc = ROUNDUP(count, 64) / 8;\n  if (cpusetsize < rc) return einval();\n  if (!(mask = (u8 *)AddToFreeList(m, calloc(1, rc)))) return -1;\n  count = MIN(count, rc * 8);\n  for (i = 0; i < count; ++i) {\n    mask[i / 8] |= 1 << (i % 8);\n  }\n  if (CopyToUserWrite(m, maskaddr, mask, rc) == -1) rc = -1;\n  return rc;\n#endif\n}\n\nstatic int SysPrctlGetTsc(struct Machine *m, i64 arg2) {\n  u8 word[4];\n  Write32(word, m->traprdtsc ? PR_TSC_SIGSEGV_LINUX : PR_TSC_ENABLE_LINUX);\n  return CopyToUserWrite(m, arg2, word, sizeof(word));\n}\n\nstatic int SysPrctlSetTsc(struct Machine *m, i64 arg2) {\n  switch (arg2) {\n    case PR_TSC_ENABLE_LINUX:\n      m->traprdtsc = false;\n      return 0;\n    case PR_TSC_SIGSEGV_LINUX:\n      m->traprdtsc = true;\n      return 0;\n    default:\n      return einval();\n  }\n}\n\nstatic int SysPrctl(struct Machine *m, int op, i64 arg2, i64 arg3, i64 arg4,\n                    i64 arg5) {\n  switch (op) {\n    case PR_GET_TSC_LINUX:\n      return SysPrctlGetTsc(m, arg2);\n    case PR_SET_TSC_LINUX:\n      return SysPrctlSetTsc(m, arg2);\n#ifdef PR_CAPBSET_DROP\n    case PR_CAPBSET_DROP_LINUX:\n      return prctl(PR_CAPBSET_DROP, arg2, arg3, arg4, arg5);\n#else\n    case PR_CAPBSET_DROP_LINUX:\n      return einval();\n#endif\n#ifdef PR_SET_NO_NEW_PRIVS\n    case PR_SET_NO_NEW_PRIVS_LINUX:\n      return prctl(PR_SET_NO_NEW_PRIVS, arg2, arg3, arg4, arg5);\n#else\n    case PR_SET_NO_NEW_PRIVS_LINUX:\n      return einval();\n#endif\n    case PR_GET_SECCOMP_LINUX:\n    case PR_SET_SECCOMP_LINUX:\n      // avoid noisy feature check warnings in cosmopolitan\n      if (!m->system->iscosmo) goto DefaultCase;\n      return einval();\n    default:\n    DefaultCase:\n      LOGF(\"unsupported %s op %#x\", \"prctl\", op);\n      return einval();\n  }\n}\n\nstatic int SysArchPrctl(struct Machine *m, int op, i64 addr) {\n#ifndef DISABLE_NONPOSIX\n  u8 buf[8];\n#endif\n  switch (op) {\n    case ARCH_SET_FS_LINUX:\n      m->fs.base = addr;\n      return 0;\n#ifndef DISABLE_NONPOSIX\n    case ARCH_SET_GS_LINUX:\n      m->gs.base = addr;\n      return 0;\n    case ARCH_GET_FS_LINUX:\n      Write64(buf, m->fs.base);\n      return CopyToUserWrite(m, addr, buf, 8);\n    case ARCH_GET_GS_LINUX:\n      Write64(buf, m->gs.base);\n      return CopyToUserWrite(m, addr, buf, 8);\n    case ARCH_GET_CPUID_LINUX:\n      return !m->trapcpuid;\n    case ARCH_SET_CPUID_LINUX:\n      m->trapcpuid = !addr;\n      return 0;\n#endif\n    default:\n      LOGF(\"unsupported %s op %#x\", \"arch_prctl\", op);\n      return einval();\n  }\n}\n\nstatic u64 Prot2Page(int prot) {\n  u64 key = 0;\n  if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) return einval();\n  if (prot & PROT_READ) key |= PAGE_U;\n  if (prot & PROT_WRITE) key |= PAGE_RW | PAGE_U;\n  if (~prot & PROT_EXEC) key |= PAGE_XD;\n  return key;\n}\n\nstatic int SysMprotect(struct Machine *m, i64 addr, u64 size, int prot) {\n  _Static_assert(PROT_READ == 1, \"\");\n  _Static_assert(PROT_WRITE == 2, \"\");\n  _Static_assert(PROT_EXEC == 4, \"\");\n  int rc;\n  int unsupported;\n  if (size > NUMERIC_MAX(size_t)) return eoverflow();\n  if (!IsValidAddrSize(addr, size)) return einval();\n  if ((unsupported = prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))) {\n    LOGF(\"unsupported mprotect() protection: %#x\", unsupported);\n    return einval();\n  }\n  BEGIN_NO_PAGE_FAULTS;\n  LOCK(&m->system->mmap_lock);\n  rc = ProtectVirtual(m->system, addr, size, prot, false);\n  unassert(CheckMemoryInvariants(m->system));\n  UNLOCK(&m->system->mmap_lock);\n  END_NO_PAGE_FAULTS;\n  return rc;\n}\n\nstatic int SysMadvise(struct Machine *m, i64 addr, u64 len, int advice) {\n  return 0;\n}\n\nstatic i64 SysBrk(struct Machine *m, i64 addr) {\n  i64 rc, size;\n  long pagesize;\n  BEGIN_NO_PAGE_FAULTS;\n  LOCK(&m->system->mmap_lock);\n  MEM_LOGF(\"brk(%#\" PRIx64 \") currently %#\" PRIx64, addr, m->system->brk);\n  pagesize = FLAG_pagesize;\n  addr = ROUNDUP(addr, pagesize);\n  if (addr >= kNullSize) {\n    if (addr > m->system->brk) {\n      size = addr - m->system->brk;\n      CleanseMemory(m->system, size);\n      if (m->system->rss < GetMaxRss(m->system)) {\n        if (size / 4096 + m->system->vss < GetMaxVss(m->system)) {\n          if (ReserveVirtual(m->system, m->system->brk, addr - m->system->brk,\n                             PAGE_FILE | PAGE_RW | PAGE_U | PAGE_XD, -1, 0, 0,\n                             0) != -1) {\n            if (!m->system->brkchanged) {\n              unassert(AddFileMap(m->system, m->system->brk,\n                                  addr - m->system->brk, \"[heap]\", -1));\n              m->system->brkchanged = true;\n            }\n            MEM_LOGF(\"increased break %\" PRIx64 \" -> %\" PRIx64, m->system->brk,\n                     addr);\n            m->system->brk = addr;\n          }\n        } else {\n          LOGF(\"not enough virtual memory (%lx / %#lx pages) to map size \"\n               \"%#\" PRIx64,\n               m->system->vss, GetMaxVss(m->system), size);\n        }\n      } else {\n        LOGF(\"ran out of resident memory (%#lx / %#lx pages)\", m->system->rss,\n             GetMaxRss(m->system));\n      }\n    } else if (addr < m->system->brk) {\n      if (FreeVirtual(m->system, addr, m->system->brk - addr) != -1) {\n        m->system->brk = addr;\n      }\n    }\n  }\n  rc = m->system->brk;\n  unassert(CheckMemoryInvariants(m->system));\n  UNLOCK(&m->system->mmap_lock);\n  END_NO_PAGE_FAULTS;\n  return rc;\n}\n\nstatic int SysMunmap(struct Machine *m, i64 virt, u64 size) {\n  int rc;\n  BEGIN_NO_PAGE_FAULTS;\n  LOCK(&m->system->mmap_lock);\n  rc = FreeVirtual(m->system, virt, size);\n  unassert(CheckMemoryInvariants(m->system));\n  UNLOCK(&m->system->mmap_lock);\n  END_NO_PAGE_FAULTS;\n  return rc;\n}\n\nint GetOflags(struct Machine *m, int fildes) {\n  int oflags;\n  struct Fd *fd;\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    oflags = fd->oflags;\n  } else {\n    oflags = -1;\n  }\n  UNLOCK(&m->system->fds.lock);\n  return oflags;\n}\n\nstatic i64 SysMmapImpl(struct Machine *m, i64 virt, i64 size, int prot,\n                       int flags, int fildes, i64 offset) {\n  u64 key;\n  int oflags;\n  bool fixedmap;\n  i64 newautomap;\n  if (!IsValidAddrSize(virt, size)) return einval();\n  if (flags & MAP_GROWSDOWN_LINUX) return enotsup();\n  if ((key = Prot2Page(prot)) == (u64)-1) return einval();\n  CleanseMemory(m->system, size);\n  if (m->system->rss >= GetMaxRss(m->system)) {\n    LOGF(\"ran out of resident memory (%lx / %lx pages)\", m->system->rss,\n         GetMaxRss(m->system));\n    return enomem();\n  }\n  if (size / 4096 + m->system->vss > GetMaxVss(m->system)) {\n    LOGF(\"not enough virtual memory (%lx / %lx pages) to map size %\" PRIx64,\n         m->system->vss, GetMaxVss(m->system), size);\n    return enomem();\n  }\n  if (flags & MAP_ANONYMOUS_LINUX) {\n    fildes = -1;\n    if ((flags & MAP_TYPE_LINUX) == MAP_FILE_LINUX) {\n      return einval();\n    }\n  } else if (offset < 0) {\n    return einval();\n  } else if (offset > NUMERIC_MAX(off_t)) {\n    return eoverflow();\n  }\n  if (fildes != -1) {\n    if ((oflags = GetOflags(m, fildes)) == -1) return -1;\n    if ((oflags & O_ACCMODE) == O_WRONLY ||  //\n        ((prot & PROT_WRITE) &&              //\n         (oflags & O_APPEND)) ||             //\n        ((prot & PROT_WRITE) &&              //\n         (flags & MAP_SHARED_LINUX) &&       //\n         (oflags & O_ACCMODE) != O_RDWR)) {  //\n      errno = EACCES;\n      return -1;\n    }\n  }\n  newautomap = -1;\n  fixedmap = false;\n  if (flags & MAP_FIXED_LINUX) {\n    fixedmap = true;\n    goto CreateTheMap;\n  }\n  if (flags & MAP_FIXED_NOREPLACE_LINUX) {\n    if (IsFullyUnmapped(m->system, virt, size)) {\n      goto CreateTheMap;\n    } else {\n      MEM_LOGF(\"memory already exists on the interval\"\n               \" [%\" PRIx64 \",%\" PRIx64 \")\\n\"\n               \"%s\",\n               virt, virt + size, FormatPml4t(g_machine));\n      errno = EEXIST;\n      virt = -1;\n      goto Finished;\n    }\n  }\n  if (HasLinearMapping() && FLAG_vabits <= 47 && !kSkew && !virt) {\n    goto CreateTheMap;\n  }\n  if ((!virt || !IsFullyUnmapped(m->system, virt, size))) {\n    if ((virt = FindVirtual(m->system, m->system->automap, size)) == -1) {\n      goto Finished;\n    }\n    newautomap = ROUNDUP(virt + size, FLAG_pagesize);\n    if (newautomap >= FLAG_automapend) {\n      newautomap = FLAG_automapstart;\n    }\n  }\nCreateTheMap:\n  virt = ReserveVirtual(m->system, virt, size, key, fildes, offset,\n                        !!(flags & MAP_SHARED_LINUX), fixedmap);\n  if (virt != -1 && newautomap != -1) {\n    m->system->automap = newautomap;\n  }\nFinished:\n  return virt;\n}\n\nstatic i64 SysMmap(struct Machine *m, i64 virt, u64 size, int prot, int flags,\n                   int fildes, i64 offset) {\n  i64 res;\n  BEGIN_NO_PAGE_FAULTS;\n  LOCK(&m->system->mmap_lock);\n  res = SysMmapImpl(m, virt, size, prot, flags, fildes, offset);\n  unassert(CheckMemoryInvariants(m->system));\n  UNLOCK(&m->system->mmap_lock);\n  END_NO_PAGE_FAULTS;\n  return res;\n}\n\nstatic i64 SysMremap(struct Machine *m, i64 old_address, u64 old_size,\n                     u64 new_size, int flags, i64 new_address) {\n  // would be nice to have\n  // avoid being noisy in the logs\n  // hope program has fallback for failure\n  LOG_ONCE(MEM_LOGF(\"mremap() not supported yet\"));\n  return enomem();\n}\n\nstatic int XlatMsyncFlags(int flags) {\n  int sysflags;\n  if (flags & ~(MS_ASYNC_LINUX | MS_SYNC_LINUX | MS_INVALIDATE_LINUX)) {\n    LOGF(\"unsupported msync() flags %#x\", flags);\n    return einval();\n  }\n  // According to POSIX, either MS_SYNC or MS_ASYNC must be specified\n  // in flags, and indeed failure to include one of these flags will\n  // cause msync() to fail on some systems. However, Linux permits a\n  // call to msync() that specifies neither of these flags, with\n  // semantics that are (currently) equivalent to specifying MS_ASYNC.\n  // ──Quoth msync(2) of Linux Programmer's Manual\n  if (flags & MS_ASYNC_LINUX) {\n    sysflags = MS_ASYNC;\n  } else if (flags & MS_SYNC_LINUX) {\n    sysflags = MS_SYNC;\n  } else {\n    sysflags = MS_ASYNC;\n  }\n  if (flags & MS_INVALIDATE_LINUX) {\n    sysflags |= MS_INVALIDATE;\n  }\n#ifdef __FreeBSD__\n  // FreeBSD's manual says \"The flags argument was both MS_ASYNC and\n  // MS_INVALIDATE. Only one of these flags is allowed.\" which makes\n  // following the POSIX recommendation somewhat difficult.\n  if (sysflags == (MS_ASYNC | MS_INVALIDATE)) {\n    sysflags = MS_INVALIDATE;\n  }\n#endif\n  return sysflags;\n}\n\nstatic int SysMsync(struct Machine *m, i64 virt, u64 size, int flags) {\n  if (size > NUMERIC_MAX(size_t)) return eoverflow();\n  if ((flags = XlatMsyncFlags(flags)) == -1) return -1;\n  return SyncVirtual(m->system, virt, size, flags);\n}\n\nstatic int SysDup1(struct Machine *m, i32 fildes) {\n  int lim;\n  int oflags;\n  int newfildes;\n  struct Fd *fd;\n  if (fildes < 0) return ebadf();\n  if (!(lim = GetFileDescriptorLimit(m->system))) return emfile();\n  if ((newfildes = VfsDup(fildes)) != -1) {\n    if (newfildes >= lim) {\n      VfsClose(newfildes);\n      return emfile();\n    }\n    LOCK(&m->system->fds.lock);\n    unassert(fd = GetFd(&m->system->fds, fildes));\n    oflags = fd->oflags & ~O_CLOEXEC;\n    unassert(ForkFd(&m->system->fds, fd, newfildes, oflags));\n    UNLOCK(&m->system->fds.lock);\n  }\n  return newfildes;\n}\n\nstatic int Dup2(struct Machine *m, int fildes, int newfildes) {\n  int rc;\n  // POSIX.1-2007 lists dup2() as raising EINTR which seems impossible\n  // so it'd be wonderful to learn what kernel(s) actually return this\n  // noting Linux reproduces that in both its dup(2) and dup(3) manual\n  RESTARTABLE(rc = VfsDup2(fildes, newfildes));\n  return rc;\n}\n\n#ifdef HAVE_DUP3\nstatic int Dup3(struct Machine *m, int fildes, int newfildes, int flags) {\n  int rc;\n  // The Linux Programmer's Manual also lists this as interruptible.\n  RESTARTABLE(rc = VfsDup3(fildes, newfildes, flags));\n  return rc;\n}\n#endif\n\nstatic int SysDup2(struct Machine *m, i32 fildes, i32 newfildes) {\n  int rc, oflags;\n  struct Fd *fd;\n  if (newfildes < 0) {\n    LOGF(\"dup2() ebadf\");\n    return ebadf();\n  }\n  if (fildes == newfildes) {\n    // no-op system call, but still must validate\n    LOCK(&m->system->fds.lock);\n    if (GetFd(&m->system->fds, fildes)) {\n      rc = fildes;\n    } else {\n      rc = -1;\n    }\n    UNLOCK(&m->system->fds.lock);\n  } else if (newfildes >= GetFileDescriptorLimit(m->system)) {\n    return ebadf();\n  } else if ((rc = Dup2(m, fildes, newfildes)) != -1) {\n    LOCK(&m->system->fds.lock);\n    if ((fd = GetFd(&m->system->fds, newfildes))) {\n      dll_remove(&m->system->fds.list, &fd->elem);\n      FreeFd(fd);\n    }\n    unassert(fd = GetFd(&m->system->fds, fildes));\n    oflags = fd->oflags & ~O_CLOEXEC;\n    unassert(ForkFd(&m->system->fds, fd, newfildes, oflags));\n    UNLOCK(&m->system->fds.lock);\n  }\n  return rc;\n}\n\nstatic int SysDup3(struct Machine *m, i32 fildes, i32 newfildes, i32 flags) {\n  int rc;\n  int oflags;\n  struct Fd *fd;\n  if (newfildes < 0) return ebadf();\n  if (fildes == newfildes) return einval();\n  if (flags & ~O_CLOEXEC_LINUX) return einval();\n  if (newfildes >= GetFileDescriptorLimit(m->system)) return ebadf();\n#ifdef HAVE_DUP3\n  if ((rc = Dup3(m, fildes, newfildes, XlatOpenFlags(flags))) != -1) {\n#else\n  if ((rc = Dup2(m, fildes, newfildes)) != -1) {\n    if (flags & O_CLOEXEC_LINUX) {\n      unassert(!VfsFcntl(newfildes, F_SETFD, FD_CLOEXEC));\n    }\n#endif\n    LOCK(&m->system->fds.lock);\n    if ((fd = GetFd(&m->system->fds, newfildes))) {\n      dll_remove(&m->system->fds.list, &fd->elem);\n      FreeFd(fd);\n    }\n    unassert(fd = GetFd(&m->system->fds, fildes));\n    oflags = fd->oflags & ~O_CLOEXEC;\n    if (flags & O_CLOEXEC_LINUX) {\n      oflags |= O_CLOEXEC;\n    }\n    unassert(ForkFd(&m->system->fds, fd, newfildes, oflags));\n    UNLOCK(&m->system->fds.lock);\n  }\n  return rc;\n}\n\nstatic int SysDupf(struct Machine *m, i32 fildes, i32 minfildes, int cmd) {\n  struct Fd *fd;\n  int lim, oflags, newfildes;\n  if (minfildes >= (lim = GetFileDescriptorLimit(m->system))) return emfile();\n  if ((newfildes = VfsFcntl(fildes, cmd, minfildes)) != -1) {\n    if (newfildes >= lim) {\n      VfsClose(newfildes);\n      return emfile();\n    }\n    LOCK(&m->system->fds.lock);\n    unassert(fd = GetFd(&m->system->fds, fildes));\n    oflags = fd->oflags & ~O_CLOEXEC;\n    if (cmd == F_DUPFD_CLOEXEC) {\n      oflags |= O_CLOEXEC;\n    }\n    unassert(ForkFd(&m->system->fds, fd, newfildes, oflags));\n    UNLOCK(&m->system->fds.lock);\n  }\n  return newfildes;\n}\n\nstatic void FixupSock(int fd, int flags) {\n  if (flags & SOCK_CLOEXEC_LINUX) {\n    unassert(!VfsFcntl(fd, F_SETFD, FD_CLOEXEC));\n  }\n  if (flags & SOCK_NONBLOCK_LINUX) {\n    unassert(!VfsFcntl(fd, F_SETFL, O_NDELAY));\n  }\n}\n\n#ifndef BUILD_TIMESTAMP\n#define BUILD_TIMESTAMP __TIMESTAMP__\n#endif\n#ifndef BLINK_VERSION\n#define BLINK_VERSION \"BLINK_VERSION_UNKNOWN\"\n#warning \"-DBLINK_VERSION=... should be passed to blink/syscall.c\"\n#endif\n#ifndef LINUX_VERSION\n#define LINUX_VERSION \"LINUX_VERSION_UNKNOWN\"\n#warning \"-DLINUX_VERSION=... should be passed to blink/syscall.c\"\n#endif\n#ifndef BLINK_COMMITS\n#define BLINK_COMMITS \"BLINK_COMMITS_UNKNOWN\"\n#warning \"-DBLINK_COMMITS=... should be passed to blink/syscall.c\"\n#endif\n#ifndef BLINK_UNAME_V\n#define BLINK_UNAME_V \"BLINK_UNAME_V_UNKNOWN\"\n#warning \"-DBLINK_UNAME_V=... should be passed to blink/syscall.c\"\n#endif\n\nstatic int SysUname(struct Machine *m, i64 utsaddr) {\n  // glibc binaries won't run unless we report blink as a\n  // modern linux kernel on top of genuine intel hardware\n  struct utsname_linux uts;\n  union {\n    char host[sizeof(uts.nodename)];\n    char domain[sizeof(uts.domainname)];\n  } u;\n  memset(&uts, 0, sizeof(uts));\n  strcpy(uts.machine, \"x86_64\");\n  strcpy(uts.sysname, \"Linux\");\n  strcpy(uts.release, LINUX_VERSION \"-blink-\" BLINK_VERSION);\n  strcpy(uts.version, \"#\" BLINK_COMMITS \" \" BLINK_UNAME_V \" \" BUILD_TIMESTAMP);\n  memset(u.host, 0, sizeof(u.host));\n  gethostname(u.host, sizeof(u.host) - 1);\n  strcpy(uts.nodename, u.host);\n#ifdef HAVE_GETDOMAINNAME\n  memset(u.domain, 0, sizeof(u.domain));\n  if (getdomainname(u.domain, sizeof(u.domain) - 1) != 0 || !*u.domain)\n#endif\n  {\n    strcpy(u.domain, \"(none)\");\n  }\n  strcpy(uts.domainname, u.domain);\n  return CopyToUser(m, utsaddr, &uts, sizeof(uts));\n}\n\nstatic int SysSocket(struct Machine *m, i32 family, i32 type, i32 protocol) {\n  struct Fd *fd;\n  int lim, flags, fildes;\n  flags = type & (SOCK_NONBLOCK_LINUX | SOCK_CLOEXEC_LINUX);\n  type &= ~(SOCK_NONBLOCK_LINUX | SOCK_CLOEXEC_LINUX);\n  if ((type = XlatSocketType(type)) == -1) return -1;\n  if ((family = XlatSocketFamily(family)) == -1) return -1;\n  if ((protocol = XlatSocketProtocol(protocol)) == -1) return -1;\n  if (!(lim = GetFileDescriptorLimit(m->system))) return emfile();\n  if (flags) LOCK(&m->system->exec_lock);\n  if ((fildes = VfsSocket(family, type, protocol)) != -1) {\n    if (fildes >= lim) {\n      VfsClose(fildes);\n      fildes = emfile();\n    } else {\n      FixupSock(fildes, flags);\n      LOCK(&m->system->fds.lock);\n      fd = AddFd(&m->system->fds, fildes,\n                 O_RDWR | (flags & SOCK_CLOEXEC_LINUX ? O_CLOEXEC : 0) |\n                     (flags & SOCK_NONBLOCK_LINUX ? O_NDELAY : 0));\n      fd->socktype = type;\n      UNLOCK(&m->system->fds.lock);\n    }\n  }\n  if (flags) UNLOCK(&m->system->exec_lock);\n  return fildes;\n}\n\nstatic int SysSocketpair(struct Machine *m, i32 family, i32 type, i32 protocol,\n                         i64 pipefds_addr) {\n  struct Fd *fd;\n  u8 fds_linux[2][4];\n  int rc, lim, flags, sysflags, fds[2];\n  flags = type & (SOCK_NONBLOCK_LINUX | SOCK_CLOEXEC_LINUX);\n  type &= ~(SOCK_NONBLOCK_LINUX | SOCK_CLOEXEC_LINUX);\n  if ((type = XlatSocketType(type)) == -1) return -1;\n  if ((family = XlatSocketFamily(family)) == -1) return -1;\n  if ((protocol = XlatSocketProtocol(protocol)) == -1) return -1;\n  if (!IsValidMemory(m, pipefds_addr, sizeof(fds_linux), PROT_WRITE)) return -1;\n  if (!(lim = GetFileDescriptorLimit(m->system))) return emfile();\n  if (flags) LOCK(&m->system->exec_lock);\n  if ((rc = VfsSocketpair(family, type, protocol, fds)) != -1) {\n    if (fds[0] >= lim || fds[1] >= lim) {\n      VfsClose(fds[0]);\n      VfsClose(fds[1]);\n      rc = emfile();\n    } else {\n      FixupSock(fds[0], flags);\n      FixupSock(fds[1], flags);\n      LOCK(&m->system->fds.lock);\n      sysflags = O_RDWR;\n      if (flags & SOCK_CLOEXEC_LINUX) sysflags |= O_CLOEXEC;\n      if (flags & SOCK_NONBLOCK_LINUX) sysflags |= O_NDELAY;\n      unassert(fd = AddFd(&m->system->fds, fds[0], sysflags));\n      fd->socktype = type;\n      unassert(fd = AddFd(&m->system->fds, fds[1], sysflags));\n      fd->socktype = type;\n      UNLOCK(&m->system->fds.lock);\n      Write32(fds_linux[0], fds[0]);\n      Write32(fds_linux[1], fds[1]);\n      unassert(!CopyToUserWrite(m, pipefds_addr, fds_linux, sizeof(fds_linux)));\n    }\n  }\n  if (flags) UNLOCK(&m->system->exec_lock);\n  return rc;\n}\n\nstatic u32 LoadAddrSize(struct Machine *m, i64 asa) {\n  const u8 *p;\n  if (asa && (p = (const u8 *)SchlepR(m, asa, 4))) {\n    return Read32(p);\n  } else {\n    return 0;\n  }\n}\n\nstatic int StoreAddrSize(struct Machine *m, i64 asa, socklen_t len) {\n  u8 buf[4];\n  if (!asa) return 0;\n  Write32(buf, len);\n  return CopyToUserWrite(m, asa, buf, sizeof(buf));\n}\n\nstatic int LoadSockaddr(struct Machine *m, i64 sockaddr_addr, u32 sockaddr_size,\n                        struct sockaddr_storage *out_sockaddr) {\n  const struct sockaddr_linux *sockaddr_linux;\n  if ((sockaddr_linux = (const struct sockaddr_linux *)SchlepR(\n           m, sockaddr_addr, sockaddr_size))) {\n    return XlatSockaddrToHost(out_sockaddr, sockaddr_linux, sockaddr_size);\n  } else {\n    return -1;\n  }\n}\n\nstatic int CheckSockaddr(struct Machine *m, i64 sockaddr_addr,\n                         i64 sockaddr_size_addr) {\n  const u8 *size;\n  if (!sockaddr_size_addr) return 0;\n  if (!(size = (const u8 *)SchlepRW(m, sockaddr_size_addr, 4))) return -1;\n  if ((i32)Read32(size) < 0) return einval();\n  return 0;\n}\n\nstatic int StoreSockaddr(struct Machine *m, i64 sockaddr_addr,\n                         i64 sockaddr_size_addr, const struct sockaddr *sa,\n                         socklen_t salen) {\n  int got;\n  u32 avail;\n  struct sockaddr_storage_linux ss;\n  if (!sockaddr_addr) return 0;\n  if (!sockaddr_size_addr) return 0;\n  avail = LoadAddrSize(m, sockaddr_size_addr);\n  if ((got = XlatSockaddrToLinux(&ss, sa, salen)) == -1) return -1;\n  if (StoreAddrSize(m, sockaddr_size_addr, got) == -1) return -1;\n  return CopyToUserWrite(m, sockaddr_addr, &ss, MIN(got, avail));\n}\n\nstatic int SysSocketName(struct Machine *m, i32 fildes, i64 sockaddr_addr,\n                         i64 sockaddr_size_addr,\n                         int SocketName(int, struct sockaddr *, socklen_t *)) {\n  int rc;\n  socklen_t addrlen;\n  struct sockaddr_storage addr;\n  addrlen = sizeof(addr);\n  rc = SocketName(fildes, (struct sockaddr *)&addr, &addrlen);\n  if (rc != -1) {\n    if (StoreSockaddr(m, sockaddr_addr, sockaddr_size_addr,\n                      (struct sockaddr *)&addr, addrlen) == -1) {\n      rc = -1;\n    }\n  }\n  return rc;\n}\n\nstatic int SysGetsockname(struct Machine *m, int fd, i64 aa, i64 asa) {\n  return SysSocketName(m, fd, aa, asa, VfsGetsockname);\n}\n\nstatic int SysGetpeername(struct Machine *m, int fd, i64 aa, i64 asa) {\n  return SysSocketName(m, fd, aa, asa, VfsGetpeername);\n}\n\nstatic int GetNoRestart(struct Machine *m, int fildes, bool *norestart) {\n  struct Fd *fd;\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    *norestart = fd->norestart;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!fd) return ebadf();\n  return 0;\n}\n\nstatic int SysAccept4(struct Machine *m, i32 fildes, i64 sockaddr_addr,\n                      i64 sockaddr_size_addr, i32 flags) {\n  struct Fd *fd;\n  socklen_t addrlen;\n  bool restartable = false;\n  int lim, newfd, socktype;\n  struct sockaddr_storage addr;\n  if (flags & ~(SOCK_CLOEXEC_LINUX | SOCK_NONBLOCK_LINUX)) return einval();\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    socktype = fd->socktype;\n    restartable = !fd->norestart;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!fd) {\n    return -1;\n  }\n  if (!socktype) {\n    errno = ENOTSOCK;\n    return -1;\n  }\n  if (socktype != SOCK_STREAM) {\n    // POSIX.1 and Linux require EOPNOTSUPP when called on a file\n    // descriptor that doesn't support accepting, i.e. SOCK_STREAM,\n    // but FreeBSD incorrectly returns EINVAL.\n    return eopnotsupp();\n  }\n  if (!(lim = GetFileDescriptorLimit(m->system))) return emfile();\n  addrlen = sizeof(addr);\n  INTERRUPTIBLE(restartable,\n                newfd = VfsAccept(fildes, (struct sockaddr *)&addr, &addrlen));\n  if (newfd != -1) {\n    if (newfd >= lim) {\n      VfsClose(newfd);\n      newfd = emfile();\n    } else {\n      FixupSock(newfd, flags);\n      LOCK(&m->system->fds.lock);\n      if (!(fd = GetFd(&m->system->fds, fildes)) ||\n          !ForkFd(&m->system->fds, fd, newfd,\n                  O_RDWR | (flags & SOCK_CLOEXEC_LINUX ? O_CLOEXEC : 0) |\n                      (flags & SOCK_NONBLOCK_LINUX ? O_NDELAY : 0))) {\n        VfsClose(newfd);\n        newfd = -1;\n      }\n      UNLOCK(&m->system->fds.lock);\n      if (newfd != -1) {\n        StoreSockaddr(m, sockaddr_addr, sockaddr_size_addr,\n                      (struct sockaddr *)&addr, addrlen);\n      }\n    }\n  }\n  return newfd;\n}\n\nstatic int XlatSendFlags(int flags, int socktype) {\n  int supported, hostflags;\n  supported = MSG_OOB_LINUX |        //\n              MSG_DONTROUTE_LINUX |  //\n              MSG_NOSIGNAL_LINUX |   //\n#ifdef MSG_EOR\n              MSG_EOR_LINUX |\n#endif\n              MSG_DONTWAIT_LINUX;\n  if (flags & ~supported) {\n    LOGF(\"unsupported %s flags %#x\", \"send\", flags & ~supported);\n    return einval();\n  }\n  hostflags = 0;\n  if (flags & MSG_OOB_LINUX) {\n    if (socktype != SOCK_STREAM) {\n      return eopnotsupp();\n    }\n    hostflags |= MSG_OOB;\n  }\n  if (flags & MSG_DONTROUTE_LINUX) hostflags |= MSG_DONTROUTE;\n  if (flags & MSG_DONTWAIT_LINUX) hostflags |= MSG_DONTWAIT;\n#ifdef MSG_EOR\n  if (flags & MSG_EOR_LINUX) hostflags |= MSG_EOR;\n#endif\n  return hostflags;\n}\n\nstatic int XlatRecvFlags(int flags) {\n  int supported, hostflags;\n  supported = MSG_OOB_LINUX |    //\n              MSG_PEEK_LINUX |   //\n              MSG_TRUNC_LINUX |  //\n#ifndef DISABLE_NONPOSIX\n              MSG_DONTWAIT_LINUX |      //\n              MSG_CMSG_CLOEXEC_LINUX |  //\n#endif\n              MSG_WAITALL_LINUX;\n  if (flags & ~supported) {\n    LOGF(\"unsupported %s flags %#x\", \"recv\", flags & ~supported);\n    return einval();\n  }\n  hostflags = 0;\n  if (flags & MSG_OOB_LINUX) hostflags |= MSG_OOB;\n  if (flags & MSG_PEEK_LINUX) hostflags |= MSG_PEEK;\n  if (flags & MSG_TRUNC_LINUX) hostflags |= MSG_TRUNC;\n  if (flags & MSG_WAITALL_LINUX) hostflags |= MSG_WAITALL;\n  if (flags & MSG_DONTWAIT_LINUX) hostflags |= MSG_DONTWAIT;\n#ifdef MSG_CMSG_CLOEXEC\n  if (flags & MSG_CMSG_CLOEXEC_LINUX) hostflags |= MSG_CMSG_CLOEXEC;\n#endif\n  return hostflags;\n}\n\nstatic int UnXlatMsgFlags(int flags) {\n  int guestflags = 0;\n  if (flags & MSG_OOB) {\n    guestflags |= MSG_OOB_LINUX;\n    flags &= ~MSG_OOB;\n  }\n  if (flags & MSG_PEEK) {\n    guestflags |= MSG_PEEK_LINUX;\n    flags &= ~MSG_PEEK;\n  }\n  if (flags & MSG_TRUNC) {\n    guestflags |= MSG_TRUNC_LINUX;\n    flags &= ~MSG_TRUNC;\n  }\n  if (flags & MSG_CTRUNC) {\n    guestflags |= MSG_CTRUNC_LINUX;\n    flags &= ~MSG_CTRUNC;\n  }\n  if (flags & MSG_WAITALL) {\n    guestflags |= MSG_WAITALL_LINUX;\n    flags &= ~MSG_WAITALL;\n  }\n  if (flags & MSG_DONTROUTE) {\n    guestflags |= MSG_DONTROUTE_LINUX;\n    flags &= ~MSG_DONTROUTE;\n  }\n#ifdef MSG_EOR\n  if (flags & MSG_EOR) {\n    guestflags |= MSG_EOR_LINUX;\n    flags &= ~MSG_EOR;\n  }\n#endif\n#ifdef MSG_CMSG_CLOEXEC\n#ifndef DISABLE_NONPOSIX\n  if (flags & MSG_CMSG_CLOEXEC) {\n    guestflags |= MSG_CMSG_CLOEXEC_LINUX;\n    flags &= ~MSG_CMSG_CLOEXEC;\n  }\n#endif\n#endif\n  if (flags) {\n    LOGF(\"unsupported %s flags %#x\", \"msg\", flags);\n  }\n  return guestflags;\n}\n\n// we need to handle any shutdown via pipeline explicitly\n// because blink always puts SIGPIPE in the SIG_IGN state\nstatic i64 HandleSigpipe(struct Machine *m, i64 rc, int flags) {\n#ifndef __linux\n  // TODO(jart): Should we just intercept shutdown() state instead?\n  if (rc == -1 && errno == ENOTCONN) {\n    errno = EPIPE;\n  }\n#endif\n  if (rc == -1 && errno == EPIPE &&\n      !((flags & MSG_NOSIGNAL_LINUX) ||\n        (m->sigmask & ((u64)1 << (SIGPIPE_LINUX - 1))))) {\n    LOCK(&m->system->sig_lock);\n    switch (Read64(m->system->hands[SIGPIPE_LINUX - 1].handler)) {\n      case SIG_IGN_LINUX:\n        break;\n      case SIG_DFL_LINUX:\n        TerminateSignal(m, SIGPIPE_LINUX, 0);\n        errno = EPIPE;\n        break;\n      default:\n        m->interrupted = true;\n        Put64(m->ax, -EPIPE_LINUX);\n        DeliverSignal(m, SIGPIPE_LINUX, SI_KERNEL_LINUX);\n        break;\n    }\n    UNLOCK(&m->system->sig_lock);\n  }\n  return rc;\n}\n\nstatic bool IsSockAddrEmpty(const struct sockaddr *sa) {\n  return (sa->sa_family == AF_INET &&\n          !((const struct sockaddr_in *)sa)->sin_addr.s_addr) ||\n         (sa->sa_family == AF_INET6 &&\n          !Read64(((u8 *)&((struct sockaddr_in6 *)sa)->sin6_addr) + 0) &&\n          !Read64(((u8 *)&((struct sockaddr_in6 *)sa)->sin6_addr) + 8));\n}\n\n// Operating systems like Linux let you sendmsg(buf, dest=0.0.0.0) where\n// the empty destination address implies the source address. Other OSes,\n// e.g. OpenBSD, do not implement this behavior. See also this Stack\n// Exchange question: https://unix.stackexchange.com/a/419881/451352\nstatic void EnsureSockAddrHasDestination(struct Machine *m, int fildes,\n                                         struct sockaddr_storage *ss) {\n#ifndef HAVE_SENDTO_ZERO\n  struct Fd *fd;\n  if (!IsSockAddrEmpty((const struct sockaddr *)ss)) return;\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    if (ss->ss_family == fd->saddr.sa.sa_family) {\n      if (ss->ss_family == AF_INET) {\n        memcpy(&((struct sockaddr_in *)ss)->sin_addr, &fd->saddr.sin.sin_addr,\n               sizeof(fd->saddr.sin.sin_addr));\n      } else if (ss->ss_family == AF_INET6) {\n        memcpy(&((struct sockaddr_in6 *)ss)->sin6_addr,\n               &fd->saddr.sin6.sin6_addr, sizeof(fd->saddr.sin6.sin6_addr));\n      } else {\n        unassert(!\"inconsistent code\");\n        __builtin_unreachable();\n      }\n    } else if (ss->ss_family == AF_INET) {\n      // if we do socket() followed by connect(0.0.0.0) assume 127.0.0.1\n      ((struct sockaddr_in *)ss)->sin_addr.s_addr = htonl(INADDR_LOOPBACK);\n    }\n  }\n  UNLOCK(&m->system->fds.lock);\n#endif\n}\n\nstatic i64 SysSendto(struct Machine *m,  //\n                     i32 fildes,         //\n                     i64 bufaddr,        //\n                     u64 buflen,         //\n                     i32 flags,          //\n                     i64 sockaddr_addr,  //\n                     i32 sockaddr_size) {\n  ssize_t rc;\n  int socktype;\n  struct Fd *fd;\n  struct Iovs iv;\n  bool norestart;\n  struct msghdr msg;\n  int len, hostflags;\n  struct sockaddr_storage ss;\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    socktype = fd->socktype;\n    norestart = fd->norestart;\n  } else {\n    socktype = 0;\n    norestart = false;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!fd) return ebadf();\n  if (sockaddr_size < 0) return einval();\n  if ((hostflags = XlatSendFlags(flags, socktype)) == -1) return -1;\n  memset(&msg, 0, sizeof(msg));\n  // \"If sendto() is used on a connection-mode socket, the arguments\n  // dest_addr and addrlen are ignored.\" ──Quoth the Linux Programmer's\n  // Manual § send(2). However FreeBSD behaves differently.\n  if (socktype != SOCK_STREAM && sockaddr_size) {\n    if ((len = LoadSockaddr(m, sockaddr_addr, sockaddr_size, &ss)) != -1) {\n      msg.msg_namelen = len;\n      EnsureSockAddrHasDestination(m, fildes, &ss);\n    } else {\n      return -1;\n    }\n    msg.msg_name = &ss;\n  }\n  InitIovs(&iv);\n  if ((rc = AppendIovsReal(m, &iv, bufaddr, buflen, PROT_READ)) != -1) {\n    msg.msg_iov = iv.p;\n    msg.msg_iovlen = iv.i;\n    INTERRUPTIBLE(!norestart, rc = VfsSendmsg(fildes, &msg, hostflags));\n  }\n  FreeIovs(&iv);\n  return HandleSigpipe(m, rc, flags);\n}\n\nstatic i64 SysRecvfrom(struct Machine *m,  //\n                       i32 fildes,         //\n                       i64 bufaddr,        //\n                       u64 buflen,         //\n                       i32 flags,          //\n                       i64 sockaddr_addr,  //\n                       i64 sockaddr_size_addr) {\n  ssize_t rc;\n  int hostflags;\n  struct Iovs iv;\n  struct msghdr msg;\n  bool norestart = false;\n  struct sockaddr_storage addr;\n  if ((hostflags = XlatRecvFlags(flags)) == -1) return -1;\n  if (GetNoRestart(m, fildes, &norestart) == -1) return -1;\n  if (CheckSockaddr(m, sockaddr_addr, sockaddr_size_addr) == -1) return -1;\n  memset(&msg, 0, sizeof(msg));\n  if (sockaddr_addr && sockaddr_size_addr) {\n    msg.msg_name = &addr;\n    msg.msg_namelen = sizeof(addr);\n  }\n  InitIovs(&iv);\n  if ((rc = AppendIovsReal(m, &iv, bufaddr, buflen, PROT_WRITE)) != -1) {\n    msg.msg_iov = iv.p;\n    msg.msg_iovlen = iv.i;\n    INTERRUPTIBLE(!norestart, rc = VfsRecvmsg(fildes, &msg, hostflags));\n    if (rc != -1) {\n      StoreSockaddr(m, sockaddr_addr, sockaddr_size_addr,\n                    (struct sockaddr *)msg.msg_name, msg.msg_namelen);\n    }\n  }\n  FreeIovs(&iv);\n  return rc;\n}\n\nstatic i64 SysSendmsg(struct Machine *m, i32 fildes, i64 msgaddr, i32 flags) {\n  i32 len;\n  u64 iovlen;\n  ssize_t rc;\n  i64 iovaddr;\n  int socktype;\n  struct Fd *fd;\n  struct Iovs iv;\n  bool norestart;\n  struct msghdr msg;\n  struct sockaddr_storage ss;\n  const struct msghdr_linux *gm;\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    socktype = fd->socktype;\n    norestart = fd->norestart;\n  } else {\n    socktype = 0;\n    norestart = false;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!fd) return ebadf();\n  if ((flags = XlatSendFlags(flags, socktype)) == -1) return -1;\n  if (!(gm = (const struct msghdr_linux *)SchlepR(m, msgaddr, sizeof(*gm)))) {\n    return -1;\n  }\n  memset(&msg, 0, sizeof(msg));\n  if (socktype != SOCK_STREAM && (len = Read32(gm->namelen)) > 0) {\n    if ((len = LoadSockaddr(m, Read64(gm->name), len, &ss)) == -1) {\n      return -1;\n    }\n    EnsureSockAddrHasDestination(m, fildes, &ss);\n    msg.msg_name = &ss;\n    msg.msg_namelen = len;\n  }\n#ifndef DISABLE_ANCILLARY\n  if (SendAncillary(m, &msg, gm) == -1) {\n    return -1;\n  }\n#else\n  if (Read64(gm->controllen)) {\n    LOGF(\"ancillary support disabled\");\n    return einval();\n  }\n#endif\n  iovaddr = Read64(gm->iov);\n  iovlen = Read64(gm->iovlen);\n  if (!iovlen || iovlen > IOV_MAX_LINUX) {\n    errno = EMSGSIZE;\n    return -1;\n  }\n  InitIovs(&iv);\n  if ((rc = AppendIovsGuest(m, &iv, iovaddr, iovlen, PROT_READ)) != -1) {\n    msg.msg_iov = iv.p;\n    msg.msg_iovlen = iv.i;\n    INTERRUPTIBLE(!norestart, rc = VfsSendmsg(fildes, &msg, flags));\n  }\n  FreeIovs(&iv);\n  return HandleSigpipe(m, rc, flags);\n}\n\nstatic i64 SysRecvmsg(struct Machine *m, i32 fildes, i64 msgaddr, i32 flags) {\n  ssize_t rc;\n  u64 iovlen;\n  i64 iovaddr;\n  struct Iovs iv;\n  struct msghdr msg;\n  bool norestart = false;\n  struct msghdr_linux gm;\n  struct sockaddr_storage addr;\n  if ((flags = XlatRecvFlags(flags)) == -1) return -1;\n  if (GetNoRestart(m, fildes, &norestart) == -1) return -1;\n  if (CopyFromUserRead(m, &gm, msgaddr, sizeof(gm)) == -1) return -1;\n  memset(&msg, 0, sizeof(msg));\n  iovaddr = Read64(gm.iov);\n  iovlen = Read64(gm.iovlen);\n  if (!iovlen || iovlen > IOV_MAX_LINUX) {\n    errno = EMSGSIZE;\n    return -1;\n  }\n  if (Read64(gm.controllen)) {\n#ifndef DISABLE_ANCILLARY\n    msg.msg_control = AddToFreeList(m, calloc(1, kMaxAncillary));\n    msg.msg_controllen = kMaxAncillary;\n#else\n    LOGF(\"ancillary support disabled\");\n    return einval();\n#endif\n  }\n  InitIovs(&iv);\n  if ((rc = AppendIovsGuest(m, &iv, iovaddr, iovlen, PROT_WRITE)) != -1) {\n    msg.msg_iov = iv.p;\n    msg.msg_iovlen = iv.i;\n    if (Read64(gm.name)) {\n      memset(&addr, 0, sizeof(addr));\n      msg.msg_name = &addr;\n      msg.msg_namelen = sizeof(addr);\n    }\n    INTERRUPTIBLE(!norestart, rc = VfsRecvmsg(fildes, &msg, flags));\n    if (rc != -1) {\n      Write32(gm.flags, UnXlatMsgFlags(msg.msg_flags));\n      unassert(CopyToUserWrite(m, msgaddr, &gm, sizeof(gm)) != -1);\n#ifndef DISABLE_ANCILLARY\n      if (ReceiveAncillary(m, &gm, &msg, flags) == -1) {\n        return -1;\n      }\n#endif\n      if (Read64(gm.name)) {\n        StoreSockaddr(m, Read64(gm.name),\n                      msgaddr + offsetof(struct msghdr_linux, namelen),\n                      (struct sockaddr *)&addr, msg.msg_namelen);\n      }\n    }\n  }\n  FreeIovs(&iv);\n  return rc;\n}\n\nstatic i64 SysSendmmsg(struct Machine *m, i32 fildes, i64 msgsaddr, u32 msgcnt,\n                       i32 flags) {\n  u32 i;\n  i64 rc;\n  u8 word[4];\n  const struct mmsghdr_linux *msgs;\n  if (!(msgs = (const struct mmsghdr_linux *)SchlepRW(\n            m, msgsaddr, msgcnt * sizeof(*msgs)))) {\n    return -1;\n  }\n  for (i = 0; i < msgcnt; ++i) {\n    if ((rc = SysSendmsg(m, fildes, msgsaddr + i * sizeof(*msgs), flags)) !=\n        -1) {\n      Write32(word, rc);\n      unassert(CopyToUserWrite(m,\n                               msgsaddr + i * sizeof(*msgs) +\n                                   offsetof(struct mmsghdr_linux, len),\n                               word, 4) != -1);\n    } else {\n      if (!i) return -1;\n      if (errno == EINTR || errno == EWOULDBLOCK) break;\n      LOGF(\"%s raised %s after doing work\", \"sendmmsg\",\n           DescribeHostErrno(errno));\n      break;\n    }\n  }\n  return i;\n}\n\nstatic i64 SysRecvmmsg(struct Machine *m, i32 fildes, i64 msgsaddr, u32 msgcnt,\n                       i32 flags, i64 timeoutaddr) {\n  u32 i;\n  i64 rc;\n  u8 word[4];\n  i32 flags2;\n  struct timespec_linux gt;\n  const struct mmsghdr_linux *msgs;\n  struct timespec ts, now, remain, deadline = {0};\n  if (!(msgs = (const struct mmsghdr_linux *)SchlepRW(\n            m, msgsaddr, msgcnt * sizeof(*msgs)))) {\n    return -1;\n  }\n  if (timeoutaddr) {\n    if (LoadTimespecR(m, timeoutaddr, &ts) == -1) return -1;\n    deadline = AddTime(GetTime(), ts);\n  }\n  for (i = 0; i < msgcnt; ++i) {\n    flags2 = flags & ~MSG_WAITFORONE_LINUX;\n    if ((flags & MSG_WAITFORONE_LINUX) && i) {\n      flags2 |= MSG_DONTWAIT_LINUX;\n    }\n    if ((rc = SysRecvmsg(m, fildes, msgsaddr + i * sizeof(*msgs), flags2)) !=\n        -1) {\n      Write32(word, rc);\n      unassert(CopyToUserWrite(m,\n                               msgsaddr + i * sizeof(*msgs) +\n                                   offsetof(struct mmsghdr_linux, len),\n                               word, 4) != -1);\n    } else {\n      if (!i) return -1;\n      if (errno == EAGAIN || errno == EWOULDBLOCK) break;\n      // If an error occurs after at least one message has been\n      // received, the call succeeds, and returns the number of messages\n      // received. The error code is expected to be returned on a\n      // subsequent call to recvmmsg(). In the current implementation,\n      // however, the error code can be overwritten in the meantime by\n      // an unrelated network event on a socket, for example an incoming\n      // ICMP packet. ──Quoth the Linux Programmer's Manual § recvmmsg()\n      LOGF(\"%s raised %s after doing work\", \"recvmmsg\",\n           DescribeHostErrno(errno));\n      break;\n    }\n    // The timeout argument does not work as intended. The timeout is\n    // checked only after the receipt of each datagram, so that if up to\n    // vlen-1 datagrams are received before the timeout expires, but\n    // then no further datagrams are received, the call will block\n    // forever. ──Quoth the Linux Programmer's Manual § recvmmsg()\n    if (timeoutaddr && CompareTime(GetTime(), deadline) >= 0) {\n      break;\n    }\n  }\n  if (timeoutaddr) {\n    now = GetTime();\n    if (CompareTime(now, deadline) >= 0) {\n      remain = GetZeroTime();\n    } else {\n      remain = SubtractTime(deadline, now);\n    }\n    Write64(gt.sec, remain.tv_sec);\n    Write64(gt.nsec, remain.tv_nsec);\n    CopyToUserWrite(m, timeoutaddr, &gt, sizeof(gt));\n  }\n  return i;\n}\n\nstatic int SysConnectBind(struct Machine *m, i32 fildes, i64 sockaddr_addr,\n                          u32 sockaddr_size,\n                          int impl(int, const struct sockaddr *, socklen_t)) {\n  int rc, len;\n  struct Fd *fd;\n  socklen_t addrlen;\n  bool norestart = false;\n  struct sockaddr_storage addr;\n  if (GetNoRestart(m, fildes, &norestart) == -1) return -1;\n  if ((len = LoadSockaddr(m, sockaddr_addr, sockaddr_size, &addr)) != -1) {\n    addrlen = len;\n    if (impl == VfsConnect) {\n      EnsureSockAddrHasDestination(m, fildes, &addr);\n    }\n  } else {\n    return -1;\n  }\n  INTERRUPTIBLE(!norestart,\n                (rc = impl(fildes, (const struct sockaddr *)&addr, addrlen)));\n  if (rc != -1 && impl == VfsBind) {\n    LOCK(&m->system->fds.lock);\n    if ((fd = GetFd(&m->system->fds, fildes))) {\n      memcpy(&fd->saddr, &addr, sizeof(fd->saddr));\n    }\n    UNLOCK(&m->system->fds.lock);\n  }\n  return rc;\n}\n\nstatic int SysBind(struct Machine *m, int fd, i64 aa, u32 as) {\n  return SysConnectBind(m, fd, aa, as, VfsBind);\n}\n\nstatic int SysConnect(struct Machine *m, int fd, i64 aa, u32 as) {\n  return SysConnectBind(m, fd, aa, as, VfsConnect);\n}\n\nstatic int UnXlatSocketType(int x) {\n  if (x == SOCK_STREAM) return SOCK_STREAM_LINUX;\n  if (x == SOCK_DGRAM) return SOCK_DGRAM_LINUX;\n  LOGF(\"%s %d not supported yet\", \"socket type\", x);\n  return einval();\n}\n\nstatic int GetsockoptInt32(struct Machine *m, i32 fd, int level, int optname,\n                           i64 optvaladdr, i64 optvalsizeaddr, int xlat(int)) {\n  u8 *psize;\n  u8 gval[4];\n  int rc, val;\n  socklen_t optvalsize;\n  u32 optvalsize_linux;\n  if (!(psize = (u8 *)SchlepRW(m, optvalsizeaddr, 4))) return -1;\n  optvalsize_linux = Read32(psize);\n  if (!IsValidMemory(m, optvaladdr, optvalsize_linux, PROT_WRITE)) return -1;\n  optvalsize = sizeof(val);\n  if ((rc = VfsGetsockopt(fd, level, optname, &val, &optvalsize)) != -1) {\n    if ((val = xlat(val)) == -1) return -1;\n    Write32(gval, val);\n    CopyToUserWrite(m, optvaladdr, &gval, MIN(sizeof(gval), optvalsize_linux));\n    Write32(psize, sizeof(gval));\n  }\n  return rc;\n}\n\nstatic int SetsockoptLinger(struct Machine *m, i32 fildes, i64 optvaladdr,\n                            u32 optvalsize) {\n  struct linger hl;\n  const struct linger_linux *gl;\n  if (optvalsize < sizeof(*gl)) return einval();\n  if (!(gl =\n            (const struct linger_linux *)SchlepR(m, optvaladdr, sizeof(*gl)))) {\n    return -1;\n  }\n  hl.l_onoff = (i32)Read32(gl->onoff);\n  hl.l_linger = (i32)Read32(gl->linger);\n  return VfsSetsockopt(fildes, SOL_SOCKET, SO_LINGER_, &hl, sizeof(hl));\n}\n\nstatic int GetsockoptLinger(struct Machine *m, i32 fd, i64 optvaladdr,\n                            i64 optvalsizeaddr) {\n  int rc;\n  u8 *psize;\n  struct linger hl;\n  socklen_t optvalsize;\n  u32 optvalsize_linux;\n  struct linger_linux gl;\n  if (!(psize = (u8 *)SchlepRW(m, optvalsizeaddr, 4))) return -1;\n  optvalsize_linux = Read32(psize);\n  if (!IsValidMemory(m, optvaladdr, optvalsize_linux, PROT_WRITE)) return -1;\n  optvalsize = sizeof(hl);\n  if ((rc = VfsGetsockopt(fd, SOL_SOCKET, SO_LINGER_, &hl, &optvalsize)) !=\n      -1) {\n    Write32(gl.onoff, hl.l_onoff);\n    Write32(gl.linger, hl.l_linger);\n    CopyToUserWrite(m, optvaladdr, &gl, MIN(sizeof(gl), optvalsize_linux));\n    Write32(psize, sizeof(gl));\n  }\n  return rc;\n}\n\nstatic int SysSetsockopt(struct Machine *m, i32 fildes, i32 level, i32 optname,\n                         i64 optvaladdr, u32 optvalsize) {\n  int rc;\n  void *optval;\n  struct Fd *fd;\n  int syslevel, sysoptname;\n  switch (level) {\n    case SOL_SOCKET_LINUX:\n      switch (optname) {\n        case SO_LINGER_LINUX:\n          return SetsockoptLinger(m, fildes, optvaladdr, optvalsize);\n        default:\n          break;\n      }\n      break;\n    default:\n      break;\n  }\n  if (optvalsize > 256) return einval();\n  if (XlatSocketLevel(level, &syslevel) == -1) return -1;\n  if ((sysoptname = XlatSocketOptname(level, optname)) == -1) return -1;\n  if (!(optval = SchlepR(m, optvaladdr, optvalsize))) return -1;\n  rc = VfsSetsockopt(fildes, syslevel, sysoptname, optval, optvalsize);\n  if (rc != -1 &&                      //\n      level == SOL_SOCKET_LINUX &&     //\n      optname == SO_RCVTIMEO_LINUX &&  //\n      optvalsize >= 4) {\n    LOCK(&m->system->fds.lock);\n    if ((fd = GetFd(&m->system->fds, fildes))) {\n      fd->norestart = !!Read32((u8 *)optval);\n    }\n    UNLOCK(&m->system->fds.lock);\n  }\n  return rc;\n}\n\nstatic int SysGetsockopt(struct Machine *m, i32 fildes, i32 level, i32 optname,\n                         i64 optvaladdr, i64 optvalsizeaddr) {\n  int rc;\n  void *optval;\n  socklen_t optvalsize;\n  u8 optvalsize_linux[4];\n  int syslevel, sysoptname;\n  switch (level) {\n    case SOL_SOCKET_LINUX:\n      switch (optname) {\n        case SO_TYPE_LINUX:\n          return GetsockoptInt32(m, fildes, SOL_SOCKET, SO_TYPE, optvaladdr,\n                                 optvalsizeaddr, UnXlatSocketType);\n        case SO_ERROR_LINUX:\n          return GetsockoptInt32(m, fildes, SOL_SOCKET, SO_ERROR, optvaladdr,\n                                 optvalsizeaddr, XlatErrno);\n        case SO_LINGER_LINUX:\n          return GetsockoptLinger(m, fildes, optvaladdr, optvalsizeaddr);\n        default:\n          break;\n      }\n      break;\n    default:\n      break;\n  }\n  if (XlatSocketLevel(level, &syslevel) == -1) return -1;\n  if ((sysoptname = XlatSocketOptname(level, optname)) == -1) return -1;\n  if (CopyFromUserRead(m, optvalsize_linux, optvalsizeaddr,\n                       sizeof(optvalsize_linux)) == -1) {\n    return -1;\n  }\n  optvalsize = Read32(optvalsize_linux);\n  if (optvalsize > 256) return einval();\n  if (!(optval = AddToFreeList(m, calloc(1, optvalsize)))) return -1;\n  rc = VfsGetsockopt(fildes, syslevel, sysoptname, optval, &optvalsize);\n  Write32(optvalsize_linux, optvalsize);\n  CopyToUserWrite(m, optvaladdr, optval, optvalsize);\n  CopyToUserWrite(m, optvalsizeaddr, optvalsize_linux,\n                  sizeof(optvalsize_linux));\n  return rc;\n}\n\nstatic i64 SysRead(struct Machine *m, i32 fildes, i64 addr, u64 size) {\n  i64 rc;\n  int oflags;\n  struct Fd *fd;\n  struct Iovs iv;\n  ssize_t (*readv_impl)(int, const struct iovec *, int);\n  if (size > NUMERIC_MAX(size_t)) return eoverflow();\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    unassert(fd->cb);\n    unassert(readv_impl = fd->cb->readv);\n    oflags = fd->oflags;\n  } else {\n    readv_impl = 0;\n    oflags = 0;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!fd) return -1;\n  if ((oflags & O_ACCMODE) == O_WRONLY) return ebadf();\n  if (size) {\n    InitIovs(&iv);\n    if ((rc = AppendIovsReal(m, &iv, addr, size, PROT_WRITE)) != -1) {\n      RESTARTABLE(rc = readv_impl(fildes, iv.p, iv.i));\n      if (rc != -1) SetWriteAddr(m, addr, rc);\n    }\n    FreeIovs(&iv);\n  } else {\n    rc = 0;\n  }\n  return rc;\n}\n\nstatic i64 SysWrite(struct Machine *m, i32 fildes, i64 addr, u64 size) {\n  i64 rc;\n  int oflags;\n  struct Fd *fd;\n  struct Iovs iv;\n  ssize_t (*writev_impl)(int, const struct iovec *, int);\n  if (size > NUMERIC_MAX(size_t)) return eoverflow();\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    unassert(fd->cb);\n    unassert(writev_impl = fd->cb->writev);\n    oflags = fd->oflags;\n  } else {\n    writev_impl = 0;\n    oflags = 0;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!fd) return -1;\n  if ((oflags & O_ACCMODE) == O_RDONLY) return ebadf();\n  if (size) {\n    InitIovs(&iv);\n    if ((rc = AppendIovsReal(m, &iv, addr, size, PROT_READ)) != -1) {\n      RESTARTABLE(rc = writev_impl(fildes, iv.p, iv.i));\n      if (rc != -1) SetReadAddr(m, addr, rc);\n    }\n    FreeIovs(&iv);\n  } else {\n    rc = 0;\n  }\n  return HandleSigpipe(m, rc, 0);\n}\n\n// FreeBSD doesn't do access mode check on read/write to pipes.\n// Cygwin generally doesn't do access checks or is inconsistent.\nstatic long CheckFdAccess(struct Machine *m, i32 fildes, bool writable,\n                          int errno_if_check_fails) {\n  int oflags;\n  struct Fd *fd;\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    oflags = fd->oflags;\n  } else {\n    oflags = 0;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!fd) return -1;\n  if ((writable && ((oflags & O_ACCMODE) == O_RDONLY)) ||\n      (!writable && ((oflags & O_ACCMODE) == O_WRONLY))) {\n    errno = errno_if_check_fails;\n    return -1;\n  }\n  return 0;\n}\n\nstatic i64 SysPread(struct Machine *m, i32 fildes, i64 addr, u64 size,\n                    u64 offset) {\n  ssize_t rc;\n  struct Iovs iv;\n  if (size > NUMERIC_MAX(size_t)) return eoverflow();\n  if (CheckFdAccess(m, fildes, false, EBADF) == -1) return -1;\n  if (size) {\n    InitIovs(&iv);\n    if ((rc = AppendIovsReal(m, &iv, addr, size, PROT_WRITE)) != -1) {\n      RESTARTABLE(rc = VfsPreadv(fildes, iv.p, iv.i, offset));\n      if (rc != -1) SetWriteAddr(m, addr, rc);\n    }\n    FreeIovs(&iv);\n  } else {\n    rc = 0;\n  }\n  return rc;\n}\n\nstatic i64 SysPwrite(struct Machine *m, i32 fildes, i64 addr, u64 size,\n                     u64 offset) {\n  ssize_t rc;\n  struct Iovs iv;\n  if (size > NUMERIC_MAX(size_t)) return eoverflow();\n  if (CheckFdAccess(m, fildes, true, EBADF) == -1) return -1;\n  if (size) {\n    InitIovs(&iv);\n    if ((rc = AppendIovsReal(m, &iv, addr, size, PROT_READ)) != -1) {\n      RESTARTABLE(rc = VfsPwritev(fildes, iv.p, iv.i, offset));\n      if (rc != -1) SetReadAddr(m, addr, rc);\n    }\n    FreeIovs(&iv);\n  } else {\n    rc = 0;\n  }\n  return rc;\n}\n\nstatic i64 SysPreadv2(struct Machine *m, i32 fildes, i64 iovaddr, u32 iovlen,\n                      i64 offset, i32 flags) {\n  i64 rc;\n  int oflags;\n  struct Fd *fd;\n  struct Iovs iv;\n  ssize_t (*readv_impl)(int, const struct iovec *, int);\n  if (flags) {\n    LOGF(\"%s flags not supported yet: %#\" PRIx32, \"preadv2\", flags);\n    return einval();\n  }\n  if (iovlen > IOV_MAX_LINUX) return einval();\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    unassert(fd->cb);\n    unassert(readv_impl = fd->cb->readv);\n    oflags = fd->oflags;\n  } else {\n    readv_impl = 0;\n    oflags = 0;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!fd) return -1;\n  if ((oflags & O_ACCMODE) == O_WRONLY) return ebadf();\n  if (iovlen) {\n    InitIovs(&iv);\n    if ((rc = AppendIovsGuest(m, &iv, iovaddr, iovlen, PROT_WRITE)) != -1) {\n      if (iv.i) {\n        if (offset == -1) {\n          RESTARTABLE(rc = readv_impl(fildes, iv.p, iv.i));\n        } else if (offset < 0) {\n          return einval();\n        } else if (offset > NUMERIC_MAX(off_t)) {\n          return eoverflow();\n        } else {\n          RESTARTABLE(rc = VfsPreadv(fildes, iv.p, iv.i, offset));\n        }\n      } else {\n        rc = 0;\n      }\n    }\n    FreeIovs(&iv);\n  } else {\n    rc = 0;\n  }\n  return rc;\n}\n\nstatic i64 SysPwritev2(struct Machine *m, i32 fildes, i64 iovaddr, u32 iovlen,\n                       i64 offset, i32 flags) {\n  i64 rc;\n  int oflags;\n  struct Fd *fd;\n  struct Iovs iv;\n  ssize_t (*writev_impl)(int, const struct iovec *, int);\n  if (flags) {\n    LOGF(\"%s flags not supported yet: %#\" PRIx32, \"pwritev2\", flags);\n    return einval();\n  }\n  if (iovlen > IOV_MAX_LINUX) return einval();\n  LOCK(&m->system->fds.lock);\n  if ((fd = GetFd(&m->system->fds, fildes))) {\n    unassert(fd->cb);\n    unassert(writev_impl = fd->cb->writev);\n    oflags = fd->oflags;\n  } else {\n    writev_impl = 0;\n    oflags = 0;\n  }\n  UNLOCK(&m->system->fds.lock);\n  if (!fd) return -1;\n  if ((oflags & O_ACCMODE) == O_RDONLY) return ebadf();\n  if (iovlen) {\n    InitIovs(&iv);\n    if ((rc = AppendIovsGuest(m, &iv, iovaddr, iovlen, PROT_READ)) != -1) {\n      if (iv.i) {\n        if (offset == -1) {\n          RESTARTABLE(rc = writev_impl(fildes, iv.p, iv.i));\n          rc = HandleSigpipe(m, rc, 0);\n        } else if (offset < 0) {\n          return einval();\n        } else if (offset > NUMERIC_MAX(off_t)) {\n          return eoverflow();\n        } else {\n          RESTARTABLE(rc = VfsPwritev(fildes, iv.p, iv.i, offset));\n        }\n      } else {\n        rc = 0;\n      }\n    }\n    FreeIovs(&iv);\n  } else {\n    rc = 0;\n  }\n  return rc;\n}\n\nstatic i64 SysReadv(struct Machine *m, i32 fildes, i64 iovaddr, u32 iovlen) {\n  return SysPreadv2(m, fildes, iovaddr, iovlen, -1, 0);\n}\n\nstatic i64 SysWritev(struct Machine *m, i32 fildes, i64 iovaddr, u32 iovlen) {\n  return SysPwritev2(m, fildes, iovaddr, iovlen, -1, 0);\n}\n\nstatic i64 SysPreadv(struct Machine *m, i32 fildes, i64 iovaddr, u32 iovlen,\n                     i64 offset) {\n  if (offset < 0) return einval();\n  return SysPreadv2(m, fildes, iovaddr, iovlen, offset, 0);\n}\n\nstatic i64 SysPwritev(struct Machine *m, i32 fildes, i64 iovaddr, u32 iovlen,\n                      i64 offset) {\n  if (offset < 0) return einval();\n  return SysPwritev2(m, fildes, iovaddr, iovlen, offset, 0);\n}\n\nstatic i64 SysSendfile(struct Machine *m, i32 out_fd, i32 in_fd, i64 offsetaddr,\n                       u64 count) {\n  u64 toto, offset;\n  ssize_t got, wrote;\n  u8 *buf, *offsetp = 0;\n  size_t chunk, maxchunk = 16384;\n  if (CheckFdAccess(m, out_fd, true, EBADF) == -1) return -1;\n  if (CheckFdAccess(m, in_fd, false, EBADF) == -1) return -1;\n  if (offsetaddr && !(offsetp = (u8 *)SchlepRW(m, offsetaddr, 8))) return -1;\n  if (!(buf = (u8 *)AddToFreeList(m, malloc(maxchunk)))) return -1;\n  if (offsetp) {\n    offset = Read64(offsetp);\n    if ((i64)offset < 0) return einval();\n    if (Read64(offsetp) + count < count ||\n        Read64(offsetp) + count > NUMERIC_MAX(off_t)) {\n      return eoverflow();\n    }\n  }\n  for (toto = 0; toto < count;) {\n    chunk = MIN(count - toto, maxchunk);\n    if (offsetp) {\n      got = VfsPread(in_fd, buf, chunk, offset + toto);\n    } else {\n      got = VfsRead(in_fd, buf, chunk);\n    }\n    if (got == -1) goto OnFailure;\n    if (offsetp) Write64(offsetp, offset + toto + got);\n    if (got == 0) break;\n    while (got > 0) {\n      if ((wrote = VfsWrite(out_fd, buf, got)) == -1) goto OnFailure;\n      toto += wrote;\n      got -= wrote;\n    }\n  }\n  return toto;\nOnFailure:\n  if (toto) {\n    LOGF(\"sendfile() partial failure: %s\", DescribeHostErrno(errno));\n    return toto;\n  } else {\n    return -1;\n  }\n}\n\nstatic int UnXlatDt(int x) {\n#ifndef DT_UNKNOWN\n  return DT_UNKNOWN_LINUX;\n#else\n  switch (x) {\n    XLAT(DT_UNKNOWN, DT_UNKNOWN_LINUX);\n    XLAT(DT_FIFO, DT_FIFO_LINUX);\n    XLAT(DT_CHR, DT_CHR_LINUX);\n    XLAT(DT_DIR, DT_DIR_LINUX);\n    XLAT(DT_BLK, DT_BLK_LINUX);\n    XLAT(DT_REG, DT_REG_LINUX);\n    XLAT(DT_LNK, DT_LNK_LINUX);\n    XLAT(DT_SOCK, DT_SOCK_LINUX);\n    default:\n      __builtin_unreachable();\n  }\n#endif\n}\n\nstatic i64 Getdents(struct Machine *m, i32 fildes, i64 addr, i64 size,\n                    struct Fd *fd) {\n  i64 i;\n  int type;\n  off_t off;\n  int reclen;\n  size_t len;\n  struct stat st;\n  struct dirent *ent;\n  struct dirent_linux rec;\n  if (size < sizeof(rec) - sizeof(rec.name)) return einval();\n  if ((fd->oflags & O_DIRECTORY) != O_DIRECTORY) return enotdir();\n  if (!IsValidMemory(m, addr, size, PROT_WRITE)) return -1;\n  if (VfsFstat(fildes, &st) || !st.st_nlink) return enoent();\n  if (!fd->dirstream && !(fd->dirstream = VfsOpendir(fd->fildes))) {\n    return -1;\n  }\n  for (i = 0; i + sizeof(rec) <= size; i += reclen) {\n    // telldir() can actually return negative on ARM/MIPS/i386\n#ifdef HAVE_SEEKDIR\n    long tell;\n    errno = 0;\n    tell = VfsTelldir(fd->dirstream);\n    unassert(tell != -1 || errno == 0);\n    off = tell;\n#else\n    off = -1;\n#endif\n    if (!(ent = VfsReaddir(fd->dirstream))) break;\n    len = strlen(ent->d_name);\n    if (len + 1 > sizeof(rec.name)) {\n      LOGF(\"ignoring %zu byte d_name: %s\", len, ent->d_name);\n      reclen = 0;\n      continue;\n    }\n#ifdef DT_UNKNOWN\n    type = UnXlatDt(ent->d_type);\n#else\n    struct stat st;\n    if (fstatat(fd->fildes, ent->d_name, &st, AT_SYMLINK_NOFOLLOW) == -1) {\n      LOGF(\"getdents() fstatat(%d, %s) failed: %s\", fd->fildes, ent->d_name,\n           DescribeHostErrno(errno));\n      type = DT_UNKNOWN_LINUX;\n    } else {\n      if (S_ISDIR(st.st_mode)) {\n        type = DT_DIR_LINUX;\n      } else if (S_ISCHR(st.st_mode)) {\n        type = DT_CHR_LINUX;\n      } else if (S_ISBLK(st.st_mode)) {\n        type = DT_BLK_LINUX;\n      } else if (S_ISFIFO(st.st_mode)) {\n        type = DT_FIFO_LINUX;\n      } else if (S_ISLNK(st.st_mode)) {\n        type = DT_LNK_LINUX;\n      } else if (S_ISSOCK(st.st_mode)) {\n        type = DT_SOCK_LINUX;\n      } else if (S_ISREG(st.st_mode)) {\n        type = DT_REG_LINUX;\n      } else {\n        LOGF(\"unknown st_mode %d\", st.st_mode);\n        type = DT_UNKNOWN_LINUX;\n      }\n    }\n#endif\n    reclen = ROUNDUP(8 + 8 + 2 + 1 + len + 1, 8);\n    memset(&rec, 0, sizeof(rec));\n    Write64(rec.ino, ent->d_ino);\n    Write64(rec.off, off);\n    Write16(rec.reclen, reclen);\n    Write8(rec.type, type);\n    strcpy(rec.name, ent->d_name);\n    CopyToUserWrite(m, addr + i, &rec, reclen);\n  }\n  return i;\n}\n\nstatic i64 SysGetdents(struct Machine *m, i32 fildes, i64 addr, i64 size) {\n  i64 rc;\n  struct Fd *fd;\n  if (!(fd = GetAndLockFd(m, fildes))) return -1;\n  rc = Getdents(m, fildes, addr, size, fd);\n  UnlockFd(fd);\n  return rc;\n}\n\nstatic int SysSetTidAddress(struct Machine *m, i64 ctid) {\n  m->ctid = ctid;\n  return m->tid;\n}\n\nstatic int SysFadvise(struct Machine *m, u32 fd, u64 offset, u64 len,\n                      i32 advice) {\n  return 0;\n}\n\nstatic i64 SysLseek(struct Machine *m, i32 fildes, i64 offset, int whence) {\n  i64 rc;\n  struct Fd *fd;\n  if (offset > NUMERIC_MAX(off_t)) return eoverflow();\n  if (offset < -NUMERIC_MAX(off_t) - 1) return eoverflow();\n  if (!(fd = GetAndLockFd(m, fildes))) return -1;\n  if (!fd->dirstream) {\n    rc = VfsSeek(fd->fildes, offset, XlatWhence(whence));\n  } else if (whence == SEEK_SET_LINUX) {\n    if (!offset) {\n      VfsRewinddir(fd->dirstream);\n      rc = 0;\n    } else {\n#ifdef HAVE_SEEKDIR\n      VfsSeekdir(fd->dirstream, offset);\n      rc = 0;\n#else\n      LOGF(\"host platform doesn't support seekdir()\");\n      rc = enotsup();\n#endif\n    }\n  } else {\n    rc = einval();\n  }\n  UnlockFd(fd);\n  return rc;\n}\n\nstatic i64 SysFtruncate(struct Machine *m, i32 fildes, i64 length) {\n  i64 rc;\n  if (length < 0) return einval();\n  if (length > NUMERIC_MAX(off_t)) return eoverflow();\n  if (CheckFdAccess(m, fildes, true, EINVAL) == -1) return -1;\n  RESTARTABLE(rc = VfsFtruncate(fildes, length));\n  return rc;\n}\n\nstatic int XlatFaccessatFlags(int x) {\n  int res = 0;\n  if (x & AT_EACCESS_LINUX) {\n#if !defined(__EMSCRIPTEN__) && !defined(__CYGWIN__)\n    res |= AT_EACCESS;\n#endif\n    x &= ~AT_EACCESS_LINUX;\n  }\n  if (x & AT_SYMLINK_FOLLOW_LINUX) {\n    x &= ~AT_SYMLINK_FOLLOW_LINUX;  // default behavior\n  }\n  if (x & AT_SYMLINK_NOFOLLOW_LINUX) {\n    res |= AT_SYMLINK_NOFOLLOW;\n    x &= ~AT_SYMLINK_NOFOLLOW_LINUX;\n  }\n  if (x) {\n    LOGF(\"%s() flags %d not supported\", \"faccessat\", x);\n    return -1;\n  }\n  return res;\n}\n\nstatic int SysFaccessat2(struct Machine *m, i32 dirfd, i64 path, i32 mode,\n                         i32 flags) {\n  return VfsAccess(GetDirFildes(dirfd), LoadStr(m, path), XlatAccess(mode),\n                   XlatFaccessatFlags(flags));\n}\n\nstatic int SysFaccessat(struct Machine *m, i32 dirfd, i64 path, i32 mode) {\n  return SysFaccessat2(m, dirfd, path, mode, 0);\n}\n\nstatic int SysFstat(struct Machine *m, i32 fd, i64 staddr) {\n  int rc;\n  struct stat st;\n  struct stat_linux gst;\n  if ((rc = VfsFstat(fd, &st)) != -1) {\n    XlatStatToLinux(&gst, &st);\n    if (CopyToUserWrite(m, staddr, &gst, sizeof(gst)) == -1) rc = -1;\n  }\n  return rc;\n}\n\nstatic int XlatFstatatFlags(int x) {\n  int res = 0;\n  if (x & AT_SYMLINK_FOLLOW_LINUX) {\n    x &= ~AT_SYMLINK_FOLLOW_LINUX;  // default behavior\n  }\n  if (x & AT_SYMLINK_NOFOLLOW_LINUX) {\n    res |= AT_SYMLINK_NOFOLLOW;\n    x &= ~AT_SYMLINK_NOFOLLOW_LINUX;\n  }\n#ifndef DISABLE_NONPOSIX\n  if (x & AT_NO_AUTOMOUNT_LINUX) {\n#if defined(AT_NO_AUTOMOUNT) && defined(DISABLE_VFS)\n    res |= AT_NO_AUTOMOUNT;\n#endif\n    x &= ~AT_NO_AUTOMOUNT_LINUX;\n  }\n#endif\n  if (x) {\n    LOGF(\"%s() flags %d not supported\", \"fstatat\", x);\n    return -1;\n  }\n  return res;\n}\n\nstatic int SysFstatat(struct Machine *m, i32 dirfd, i64 pathaddr, i64 staddr,\n                      i32 flags) {\n  int rc;\n  struct stat st;\n  const char *path;\n  struct stat_linux gst;\n  if (!(path = LoadStr(m, pathaddr))) return -1;\n#ifndef DISABLE_NONPOSIX\n  if (flags & AT_EMPTY_PATH_LINUX) {\n    flags &= ~AT_EMPTY_PATH_LINUX;\n    if (!*path) {\n      if (flags) {\n        LOGF(\"%s() flags %d not supported\", \"fstatat(AT_EMPTY_PATH)\", flags);\n        return -1;\n      }\n      return SysFstat(m, dirfd, staddr);\n    }\n  }\n#endif\n  if ((rc = VfsStat(GetDirFildes(dirfd), path, &st, XlatFstatatFlags(flags))) !=\n      -1) {\n    XlatStatToLinux(&gst, &st);\n    if (CopyToUserWrite(m, staddr, &gst, sizeof(gst)) == -1) rc = -1;\n  }\n  return rc;\n}\n\nstatic int XlatFchownatFlags(int x) {\n  int res = 0;\n  if (x & AT_SYMLINK_FOLLOW_LINUX) {\n    x &= ~AT_SYMLINK_FOLLOW_LINUX;  // default behavior\n  }\n  if (x & AT_SYMLINK_NOFOLLOW_LINUX) {\n    res |= AT_SYMLINK_NOFOLLOW;\n    x &= ~AT_SYMLINK_NOFOLLOW_LINUX;\n  }\n#ifdef AT_EMPTY_PATH\n#ifndef DISABLE_NONPOSIX\n  if (x & AT_EMPTY_PATH_LINUX) {\n    res |= AT_EMPTY_PATH;\n    x &= ~AT_EMPTY_PATH_LINUX;\n  }\n#endif\n#endif\n  if (x) {\n    LOGF(\"%s() flags %#x not supported\", \"fchownat\", x);\n    return -1;\n  }\n  return res;\n}\n\nstatic int SysFchown(struct Machine *m, i32 fildes, u32 uid, u32 gid) {\n  return VfsFchown(fildes, uid, gid);\n}\n\nstatic int SysFchownat(struct Machine *m, i32 dirfd, i64 pathaddr, u32 uid,\n                       u32 gid, i32 flags) {\n  const char *path;\n  if (!(path = LoadStr(m, pathaddr))) return -1;\n#ifndef DISABLE_NONPOSIX\n  if (flags & AT_EMPTY_PATH_LINUX) {\n    flags &= AT_EMPTY_PATH_LINUX;\n    if (!*path) {\n      if (flags) {\n        LOGF(\"%s() flags %d not supported\", \"fchownat(AT_EMPTY_PATH)\", flags);\n        return -1;\n      }\n      return SysFchown(m, dirfd, uid, gid);\n    }\n  }\n#endif\n  return VfsChown(GetDirFildes(dirfd), path, uid, gid,\n                  XlatFchownatFlags(flags));\n}\n\nstatic int SysChown(struct Machine *m, i64 pathaddr, u32 uid, u32 gid) {\n  return SysFchownat(m, AT_FDCWD_LINUX, pathaddr, uid, gid, 0);\n}\n\nstatic int SysLchown(struct Machine *m, i64 pathaddr, u32 uid, u32 gid) {\n  return SysFchownat(m, AT_FDCWD_LINUX, pathaddr, uid, gid,\n                     AT_SYMLINK_NOFOLLOW_LINUX);\n}\n\n#if !defined(DISABLE_OVERLAYS)\nstatic int SysChroot(struct Machine *m, i64 path) {\n  return SetOverlays(LoadStr(m, path), false);\n}\n#elif !defined(DISABLE_VFS)\nstatic int SysChroot(struct Machine *m, i64 path) {\n  return VfsChroot(LoadStr(m, path));\n}\n#endif\n\n#ifndef DISABLE_VFS\nstatic int SysMount(struct Machine *m, i64 source, i64 target, i64 fstype,\n                    i64 mountflags, i64 data) {\n  // No xlat, the VFS system will handle raw Linux options.\n  return VfsMount(LoadStr(m, source), LoadStr(m, target), LoadStr(m, fstype),\n                  mountflags, (void *)(uintptr_t)data);\n}\n#endif\n\nstatic int SysSync(struct Machine *m) {\n#ifdef HAVE_SYNC\n  sync();\n  return 0;\n#else\n  // sync() is an xsi extension to posix. not having sync() puts us in a\n  // difficult position because the libc wrapper for sync() can't report\n  // errors. the best we can do is sync what we know and report an error\n  struct Dll *e;\n  int *p2, *p = 0;\n  size_t i, n = 0;\n  LOGF(\"host platform doesn't support sync()\");\n  LOCK(&m->system->fds.lock);\n  for (e = dll_first(m->system->fds.list); e;\n       e = dll_next(m->system->fds.list, e)) {\n    if ((p2 = (int *)realloc(p, (n + 1) * sizeof(*p)))) {\n      (p = p2)[n++] = FD_CONTAINER(e)->fildes;\n    } else {\n      break;\n    }\n  }\n  UNLOCK(&m->system->fds.lock);\n  for (i = 0; i < n; ++i) {\n    VfsFsync(p[i]);\n  }\n  free(p);\n  return enosys();\n#endif\n}\n\nstatic int CheckSyncable(int fildes) {\n#ifndef __linux\n  // FreeBSD doesn't return EINVAL like Linux does when trying to\n  // synchronize character devices, e.g. /dev/null. An unresolved\n  // question though is if FreeBSD actually does something here.\n  struct stat st;\n  if (!VfsFstat(fildes, &st) &&  //\n      (S_ISCHR(st.st_mode) ||    //\n       S_ISFIFO(st.st_mode) ||   //\n       S_ISLNK(st.st_mode) ||    //\n       S_ISSOCK(st.st_mode))) {\n    return einval();\n  }\n#endif\n  return 0;\n}\n\nstatic int SysFsync(struct Machine *m, i32 fildes) {\n  if (CheckSyncable(fildes) == -1) return -1;\n#ifdef F_FULLSYNC\n  int rc;\n  // MacOS fsync() provides weaker guarantees than Linux fsync()\n  // https://mjtsai.com/blog/2022/02/17/apple-ssd-benchmarks-and-f_fullsync/\n  if ((rc = VfsFcntl(fildes, F_FULLFSYNC, 0))) {\n    // If the FULLFSYNC failed, fall back to attempting an fsync(). It\n    // shouldn't be possible for fullfsync to fail on the local file\n    // system (on OSX), so failure indicates that FULLFSYNC isn't\n    // supported for this file system. So, attempt an fsync and (for\n    // now) ignore the overhead of a superfluous fcntl call. It'd be\n    // better to detect fullfsync support once and avoid the fcntl call\n    // every time sync is called. ──Quoth SQLite (os_unix.c) It's also\n    // possible for F_FULLFSYNC to fail on Cosmopolitan Libc when our\n    // binary isn't running on MacOS.\n    rc = VfsFsync(fildes);\n  }\n  return rc;\n#else\n  return VfsFsync(fildes);\n#endif\n}\n\nstatic int SysFdatasync(struct Machine *m, i32 fildes) {\n  if (CheckSyncable(fildes) == -1) return -1;\n#ifdef F_FULLSYNC\n  int rc;\n  if ((rc = VfsFcntl(fildes, F_FULLFSYNC, 0))) {\n    rc = VfsFsync(fildes);\n  }\n  return rc;\n#elif defined(__APPLE__)\n  // fdatasync() on HFS+ doesn't yet flush the file size if it changed\n  // correctly so currently we default to the macro that redefines\n  // fdatasync() to fsync(). ──Quoth SQLite (os_unix.c)\n  return VfsFsync(fildes);\n#elif defined(__HAIKU__)\n  // Haiku doesn't have fdatasync() yet\n  return VfsFsync(fildes);\n#else\n  return VfsFdatasync(fildes);\n#endif\n}\n\nstatic int SysChdir(struct Machine *m, i64 path) {\n  return VfsChdir(LoadStr(m, path));\n}\n\nstatic int SysFchdir(struct Machine *m, i32 fildes) {\n  return VfsFchdir(fildes);\n}\n\nstatic int XlatLock(int x) {\n  switch (x) {\n    case LOCK_UN_LINUX:\n      return LOCK_UN;\n    case LOCK_SH_LINUX:\n      return LOCK_SH;\n    case LOCK_SH_LINUX | LOCK_NB_LINUX:\n      return LOCK_SH | LOCK_NB;\n    case LOCK_EX_LINUX:\n      return LOCK_EX;\n    case LOCK_EX_LINUX | LOCK_NB_LINUX:\n      return LOCK_EX | LOCK_NB;\n    default:\n      LOGF(\"bad flock() type: %#x\", x);\n      return einval();\n  }\n}\n\nstatic int SysFlock(struct Machine *m, i32 fd, i32 lock) {\n  if ((lock = XlatLock(lock)) == -1) return -1;\n  return VfsFlock(fd, lock);\n}\n\nstatic int SysShutdown(struct Machine *m, i32 fd, i32 how) {\n  return VfsShutdown(fd, XlatShutdown(how));\n}\n\nstatic int SysListen(struct Machine *m, i32 fd, i32 backlog) {\n  return VfsListen(fd, backlog);\n}\n\nstatic int SysMkdirat(struct Machine *m, i32 dirfd, i64 path, i32 mode) {\n  return VfsMkdir(GetDirFildes(dirfd), LoadStr(m, path), mode);\n}\n\nstatic int SysMkdir(struct Machine *m, i64 path, i32 mode) {\n  return SysMkdirat(m, AT_FDCWD_LINUX, path, mode);\n}\n\nstatic int SysFchmod(struct Machine *m, i32 fd, u32 mode) {\n  return VfsFchmod(fd, mode);\n}\n\nstatic int SysFchmodat(struct Machine *m, i32 dirfd, i64 path, u32 mode) {\n  return VfsChmod(GetDirFildes(dirfd), LoadStr(m, path), mode, 0);\n}\n\nstatic int SysFcntlLock(struct Machine *m, int systemfd, int cmd, i64 arg) {\n  int rc;\n  int whence;\n  int syscmd;\n  struct flock flock;\n  struct flock_linux flock_linux;\n  if (CopyFromUserRead(m, &flock_linux, arg, sizeof(flock_linux))) {\n    return -1;\n  }\n  if (cmd == F_SETLK_LINUX) {\n    syscmd = F_SETLK;\n  } else if (cmd == F_SETLKW_LINUX) {\n    syscmd = F_SETLKW;\n  } else {\n    syscmd = F_GETLK;\n  }\n  memset(&flock, 0, sizeof(flock));\n  if (Read16(flock_linux.type) == F_RDLCK_LINUX) {\n    flock.l_type = F_RDLCK;\n  } else if (Read16(flock_linux.type) == F_WRLCK_LINUX) {\n    flock.l_type = F_WRLCK;\n  } else if (Read16(flock_linux.type) == F_UNLCK_LINUX) {\n    flock.l_type = F_UNLCK;\n  } else {\n    return einval();\n  }\n  if ((whence = XlatWhence(Read16(flock_linux.whence))) == -1) return -1;\n  flock.l_whence = whence;\n  flock.l_start = Read64(flock_linux.start);\n  flock.l_len = Read64(flock_linux.len);\n  RESTARTABLE(rc = VfsFcntl(systemfd, syscmd, &flock));\n  if (rc != -1 && syscmd == F_GETLK) {\n    if (flock.l_type == F_RDLCK) {\n      Write16(flock_linux.type, F_RDLCK_LINUX);\n    } else if (flock.l_type == F_WRLCK) {\n      Write16(flock_linux.type, F_WRLCK_LINUX);\n    } else {\n      Write16(flock_linux.type, F_UNLCK_LINUX);\n    }\n    if (flock.l_whence == SEEK_END) {\n      Write16(flock_linux.whence, SEEK_END_LINUX);\n    } else if (flock.l_whence == SEEK_CUR) {\n      Write16(flock_linux.whence, SEEK_CUR_LINUX);\n    } else {\n      Write16(flock_linux.whence, SEEK_SET_LINUX);\n    }\n    Write64(flock_linux.start, flock.l_start);\n    Write64(flock_linux.len, flock.l_len);\n    Write32(flock_linux.pid, flock.l_pid);\n    CopyToUserWrite(m, arg, &flock_linux, sizeof(flock_linux));\n  }\n  return rc;\n}\n\n#ifdef HAVE_F_GETOWN_EX\nstatic int UnxlatFownerType(int type) {\n  if (type == F_OWNER_TID) return F_OWNER_TID_LINUX;\n  if (type == F_OWNER_PID) return F_OWNER_PID_LINUX;\n  if (type == F_OWNER_PGRP) return F_OWNER_PGRP_LINUX;\n  LOGF(\"unknown f_owner_ex::type %d\", type);\n  return einval();\n}\n#endif\n\n#ifdef F_SETOWN\nstatic int SysFcntlSetownEx(struct Machine *m, i32 fildes, i64 addr) {\n  const struct f_owner_ex_linux *gowner;\n  if (!(gowner = (const struct f_owner_ex_linux *)SchlepR(m, addr,\n                                                          sizeof(*gowner)))) {\n    return -1;\n  }\n#ifdef HAVE_F_GETOWN_EX\n  struct f_owner_ex howner;\n  switch (Read32(gowner->type)) {\n    case F_OWNER_TID_LINUX:\n      howner.type = F_OWNER_TID;\n      howner.pid = (i32)Read32(gowner->pid);\n      break;\n    case F_OWNER_PID_LINUX:\n      howner.type = F_OWNER_PID;\n      howner.pid = (i32)Read32(gowner->pid);\n      break;\n    case F_OWNER_PGRP_LINUX:\n      howner.type = F_OWNER_PGRP;\n      howner.pid = (i32)Read32(gowner->pid);\n      break;\n    default:\n      LOGF(\"unknown f_owner_ex::type %\" PRId32, Read32(gowner->type));\n      return einval();\n  }\n  return VfsFcntl(fildes, F_SETOWN_EX, &howner);\n#else\n  pid_t pid;\n  switch (Read32(gowner->type)) {\n    case F_OWNER_PID_LINUX:\n      pid = (i32)Read32(gowner->pid);\n      break;\n    case F_OWNER_PGRP_LINUX:\n      pid = (i32)-Read32(gowner->pid);\n      break;\n    case F_OWNER_TID_LINUX:\n      // POSIX doesn't specify fcntl() as applying per-thread\n      if (!(pid = (i32)Read32(gowner->pid)) || pid == m->system->pid) {\n        break;\n      }\n      // fallthrough\n    default:\n      LOGF(\"unknown f_owner_ex::type %\" PRId32, Read32(gowner->type));\n      return einval();\n  }\n  return VfsFcntl(fildes, F_SETOWN, pid);\n#endif\n}\n#endif\n\n#ifdef F_GETOWN\nstatic int SysFcntlGetownEx(struct Machine *m, i32 fildes, i64 addr) {\n  int rc;\n  struct f_owner_ex_linux gowner;\n  if (!IsValidMemory(m, addr, sizeof(gowner), PROT_WRITE)) return -1;\n#ifdef HAVE_F_GETOWN_EX\n  int type;\n  struct f_owner_ex howner;\n  if ((rc = VfsFcntl(fildes, F_GETOWN_EX, &howner)) != -1) {\n    if ((type = UnxlatFownerType(howner.type)) != -1) {\n      Write32(gowner.type, type);\n      Write32(gowner.pid, howner.pid);\n      CopyToUserWrite(m, addr, &gowner, sizeof(gowner));\n    } else {\n      rc = -1;\n    }\n  }\n#else\n  if ((rc = VfsFcntl(fildes, F_GETOWN)) != -1) {\n    if (rc >= 0) {\n      Write32(gowner.type, F_OWNER_PID_LINUX);\n      Write32(gowner.pid, rc);\n    } else {\n      Write32(gowner.type, F_OWNER_PGRP_LINUX);\n      Write32(gowner.pid, -rc);\n    }\n    CopyToUserWrite(m, addr, &gowner, sizeof(gowner));\n  }\n#endif\n  return rc;\n}\n#endif\n\nstatic int SysFcntl(struct Machine *m, i32 fildes, i32 cmd, i64 arg) {\n  int rc, fl;\n  struct Fd *fd;\n  if (cmd == F_DUPFD_LINUX) {\n    return SysDupf(m, fildes, arg, F_DUPFD);\n  } else if (cmd == F_DUPFD_CLOEXEC_LINUX) {\n    return SysDupf(m, fildes, arg, F_DUPFD_CLOEXEC);\n  }\n  if (!(fd = GetAndLockFd(m, fildes))) return -1;\n  if (cmd == F_GETFD_LINUX) {\n    rc = (fd->oflags & O_CLOEXEC) ? FD_CLOEXEC_LINUX : 0;\n  } else if (cmd == F_GETFL_LINUX) {\n    rc = UnXlatOpenFlags(fd->oflags);\n  } else if (cmd == F_SETFD_LINUX) {\n    if (!(arg & ~FD_CLOEXEC_LINUX)) {\n      if (VfsFcntl(fd->fildes, F_SETFD, arg ? FD_CLOEXEC : 0) != -1) {\n        fd->oflags &= ~O_CLOEXEC;\n        if (arg) fd->oflags |= O_CLOEXEC;\n        rc = 0;\n      } else {\n        rc = -1;\n      }\n    } else {\n      rc = einval();\n    }\n  } else if (cmd == F_SETFL_LINUX) {\n    fl = XlatOpenFlags(arg & (O_APPEND_LINUX | O_ASYNC_LINUX | O_DIRECT_LINUX |\n                              O_NOATIME_LINUX | O_NDELAY_LINUX));\n    if (VfsFcntl(fd->fildes, F_SETFL, fl) != -1) {\n      fd->oflags &= ~SETFL_FLAGS;\n      fd->oflags |= fl;\n      rc = 0;\n    } else {\n      rc = -1;\n    }\n  } else if (cmd == F_SETLK_LINUX ||   //\n             cmd == F_SETLKW_LINUX ||  //\n             cmd == F_GETLK_LINUX) {\n    UnlockFd(fd);\n    return SysFcntlLock(m, fildes, cmd, arg);\n#ifdef F_SETOWN\n  } else if (cmd == F_SETOWN_LINUX) {\n    rc = VfsFcntl(fd->fildes, F_SETOWN, arg);\n#endif\n#ifdef F_GETOWN\n  } else if (cmd == F_GETOWN_LINUX) {\n    rc = VfsFcntl(fd->fildes, F_GETOWN);\n#endif\n#ifndef DISABLE_NONPOSIX\n#ifdef HAVE_F_GETOWN_EX\n  } else if (cmd == F_SETOWN_EX_LINUX) {\n    rc = SysFcntlSetownEx(m, fd->fildes, arg);\n#endif\n#ifdef HAVE_F_GETOWN_EX\n  } else if (cmd == F_GETOWN_EX_LINUX) {\n    rc = SysFcntlGetownEx(m, fd->fildes, arg);\n#endif\n#endif\n  } else {\n    LOGF(\"missing fcntl() command %\" PRId32, cmd);\n    rc = einval();\n  }\n  UnlockFd(fd);\n  return rc;\n}\n\nstatic ssize_t SysReadlinkat(struct Machine *m, int dirfd, i64 path,\n                             i64 bufaddr, i64 bufsiz) {\n  char *buf;\n  ssize_t rc;\n  // This system call raises EINVAL when \"bufsiz is not positive.\"\n  // ──Quoth the Linux Programmer's Manual § readlink(2). Some libc\n  // implementations (e.g. Musl) consider it to be posixly incorrect.\n  if (bufsiz <= 0) return einval();\n  if (!(buf = (char *)AddToFreeList(m, malloc(bufsiz)))) return -1;\n  if ((rc = VfsReadlink(GetDirFildes(dirfd), LoadStr(m, path), buf, bufsiz)) !=\n      -1) {\n    if (CopyToUserWrite(m, bufaddr, buf, rc) == -1) rc = -1;\n  }\n  return rc;\n}\n\nstatic int SysChmod(struct Machine *m, i64 path, u32 mode) {\n  return SysFchmodat(m, AT_FDCWD_LINUX, path, mode);\n}\n\nstatic int SysTruncate(struct Machine *m, i64 pathaddr, i64 length) {\n  int rc, fd;\n  const char *path;\n  if (length < 0) return einval();\n  if (length > NUMERIC_MAX(off_t)) return eoverflow();\n  if (!(path = LoadStr(m, pathaddr))) return -1;\n  RESTARTABLE(fd = VfsOpen(AT_FDCWD, path, O_RDWR | O_CLOEXEC, 0));\n  if (fd == -1) return -1;\n  rc = VfsFtruncate(fd, length);\n  VfsClose(fd);\n  return rc;\n}\n\nstatic int SysSymlinkat(struct Machine *m, i64 targetpath, i32 newdirfd,\n                        i64 linkpath) {\n  return VfsSymlink(LoadStr(m, targetpath), GetDirFildes(newdirfd),\n                    LoadStr(m, linkpath));\n}\n\nstatic int SysSymlink(struct Machine *m, i64 targetpath, i64 linkpath) {\n  return SysSymlinkat(m, targetpath, AT_FDCWD_LINUX, linkpath);\n}\n\nstatic int SysReadlink(struct Machine *m, i64 path, i64 bufaddr, u64 size) {\n  return SysReadlinkat(m, AT_FDCWD_LINUX, path, bufaddr, size);\n}\n\nstatic int SysMknodat(struct Machine *m, i32 dirfd, i64 path, i32 mode,\n                      u64 dev) {\n  _Static_assert(S_IFIFO == 0010000, \"\");   // pipe\n  _Static_assert(S_IFCHR == 0020000, \"\");   // character device\n  _Static_assert(S_IFDIR == 0040000, \"\");   // directory\n  _Static_assert(S_IFBLK == 0060000, \"\");   // block device\n  _Static_assert(S_IFREG == 0100000, \"\");   // regular file\n  _Static_assert(S_IFLNK == 0120000, \"\");   // symbolic link\n  _Static_assert(S_IFSOCK == 0140000, \"\");  // socket\n  _Static_assert(S_IFMT == 0170000, \"\");    // mask of file types above\n  if ((mode & S_IFMT) == S_IFIFO) {\n    return VfsMkfifo(GetDirFildes(dirfd), LoadStr(m, path), mode & ~S_IFMT);\n  } else {\n    LOGF(\"mknod mode %#o not supported yet\", mode);\n    return enosys();\n  }\n}\n\nstatic int SysMknod(struct Machine *m, i64 path, i32 mode, u64 dev) {\n  return SysMknodat(m, AT_FDCWD_LINUX, path, mode, dev);\n}\n\nstatic int XlatPrio(int x) {\n  switch (x) {\n    XLAT(0, PRIO_PROCESS);\n    XLAT(1, PRIO_PGRP);\n    XLAT(2, PRIO_USER);\n    default:\n      return -1;\n  }\n}\n\nstatic int SysGetpriority(struct Machine *m, i32 which, u32 who) {\n  int rc;\n  errno = 0;\n  rc = getpriority(XlatPrio(which), who);\n  if (rc == -1 && errno) return -1;\n  return MAX(-20, MIN(19, rc)) + 20;\n}\n\nstatic int SysSetpriority(struct Machine *m, i32 which, u32 who, int prio) {\n  return setpriority(XlatPrio(which), who, prio);\n}\n\nstatic int XlatUnlinkatFlags(int x) {\n  int res = 0;\n  if (x & AT_REMOVEDIR_LINUX) {\n    res |= AT_REMOVEDIR;\n    x &= ~AT_REMOVEDIR_LINUX;\n  }\n  if (x) {\n    LOGF(\"%s() flags %#x not supported\", \"unlinkat\", x);\n    return einval();\n  }\n  return res;\n}\n\nstatic int SysUnlinkat(struct Machine *m, i32 dirfd, i64 pathaddr, i32 flags) {\n  int rc;\n  const char *path;\n  dirfd = GetDirFildes(dirfd);\n  if ((flags = XlatUnlinkatFlags(flags)) == -1) return -1;\n  if (!(path = LoadStr(m, pathaddr))) return -1;\n  rc = VfsUnlink(dirfd, path, flags);\n#ifndef __linux\n  // POSIX.1 says unlink(directory) raises EPERM but on Linux\n  // it always raises EISDIR, which is so much less ambiguous\n  if (rc == -1 && !flags && errno == EPERM) {\n    struct stat st;\n    if (!fstatat(dirfd, path, &st, 0) && S_ISDIR(st.st_mode)) {\n      errno = EISDIR;\n    } else {\n      errno = EPERM;\n    }\n  }\n#endif\n  return rc;\n}\n\nstatic int SysUnlink(struct Machine *m, i64 pathaddr) {\n  return SysUnlinkat(m, AT_FDCWD_LINUX, pathaddr, 0);\n}\n\nstatic int SysRmdir(struct Machine *m, i64 path) {\n  return SysUnlinkat(m, AT_FDCWD_LINUX, path, AT_REMOVEDIR_LINUX);\n}\n\nstatic int SysRenameat2(struct Machine *m, int srcdirfd, i64 srcpath,\n                        int dstdirfd, i64 dstpathaddr, i32 flags) {\n  struct stat st;\n  i32 unsupported;\n  const char *dstpath;\n  i32 supported = RENAME_NOREPLACE_LINUX;\n  if ((unsupported = flags & ~supported)) {\n    LOGF(\"%s flags not supported yet: %#\" PRIx32, \"renameat2\", unsupported);\n    return einval();\n  }\n  if (!(dstpath = LoadStr(m, dstpathaddr))) return -1;\n  // TODO: check for renameat2 in configure script\n  if ((flags & RENAME_NOREPLACE_LINUX) &&\n      !VfsStat(GetDirFildes(dstdirfd), dstpath, &st, AT_SYMLINK_NOFOLLOW)) {\n    errno = EEXIST;\n    return -1;\n  }\n  return VfsRename(GetDirFildes(srcdirfd), LoadStr(m, srcpath),\n                   GetDirFildes(dstdirfd), dstpath);\n}\n\nstatic int SysRenameat(struct Machine *m, int srcdirfd, i64 srcpath,\n                       int dstdirfd, i64 dstpath) {\n  return SysRenameat2(m, srcdirfd, srcpath, dstdirfd, dstpath, 0);\n}\n\nstatic int SysRename(struct Machine *m, i64 src, i64 dst) {\n  return SysRenameat(m, AT_FDCWD_LINUX, src, AT_FDCWD_LINUX, dst);\n}\n\nstatic int XlatLinkatFlags(int x) {\n  int res = 0;\n  if (x & AT_SYMLINK_NOFOLLOW_LINUX) {\n    x &= ~AT_SYMLINK_NOFOLLOW_LINUX;  // default behavior\n  }\n  if (x & AT_SYMLINK_FOLLOW_LINUX) {\n    res |= AT_SYMLINK_FOLLOW;\n    x &= ~AT_SYMLINK_FOLLOW_LINUX;\n  }\n  if (x) {\n    LOGF(\"%s() flags %d not supported\", \"linkat\", x);\n    return -1;\n  }\n  return res;\n}\n\nstatic i32 SysLinkat(struct Machine *m,  //\n                     i32 olddirfd,       //\n                     i64 oldpath,        //\n                     i32 newdirfd,       //\n                     i64 newpath,        //\n                     i32 flags) {\n  return VfsLink(GetDirFildes(olddirfd), LoadStr(m, oldpath),\n                 GetDirFildes(newdirfd), LoadStr(m, newpath),\n                 XlatLinkatFlags(flags));\n}\n\nstatic int SysLink(struct Machine *m, i64 existingpath, i64 newpath) {\n  return SysLinkat(m, AT_FDCWD_LINUX, existingpath, AT_FDCWD_LINUX, newpath, 0);\n}\n\nstatic bool IsBlinkSig(struct System *s, int sig) {\n  unassert(1 <= sig && sig <= 64);\n  return !!(s->blinksigs & ((u64)1 << (sig - 1)));\n}\n\nstatic void ResetTimerDispositions(struct System *s) {\n  struct itimerval it;\n  memset(&it, 0, sizeof(it));\n  setitimer(ITIMER_REAL, &it, 0);\n}\n\nstatic void ResetSignalDispositions(struct System *s) {\n  int sig;\n  int syssig;\n  LOCK(&s->sig_lock);\n  for (sig = 1; sig <= 64; ++sig) {\n    if (!IsBlinkSig(s, sig) &&\n        Read64(s->hands[sig - 1].handler) != SIG_IGN_LINUX &&\n        Read64(s->hands[sig - 1].handler) != SIG_DFL_LINUX &&\n        (syssig = XlatSignal(sig)) != -1) {\n      Write64(s->hands[sig - 1].handler, SIG_DFL_LINUX);\n      signal(syssig, SIG_DFL);\n    }\n  }\n  UNLOCK(&s->sig_lock);\n}\n\nstatic void ExecveBlink(struct Machine *m, char *prog, char **argv,\n                        char **envp) {\n  char *execfn;\n  sigset_t block;\n  if (m->system->exec) {\n    // it's worth blocking signals on the outside of the if statement\n    // since open() during the executable check, might possibly EINTR\n    // and the same could apply to calling close() on our cloexec fds\n    execfn = prog;\n    sigfillset(&block);\n    unassert(!pthread_sigmask(SIG_BLOCK, &block, &m->system->exec_sigmask));\n    if (CanEmulateExecutable(m, &prog, &argv)) {\n      // point of no return\n      // prog/argv/envp are copied onto the freelist\n      m->sysdepth = 0;\n      CollectPageLocks(m);\n      // TODO(jart): Prevent possibility of stack overflow.\n      SYS_LOGF(\"m->system->exec(%s)\", prog);\n      SysCloseExec(m->system);\n      ResetTimerDispositions(m->system);\n      ResetSignalDispositions(m->system);\n      _Exit(m->system->exec(execfn, prog, argv, envp));\n    }\n    unassert(!pthread_sigmask(SIG_SETMASK, &m->system->exec_sigmask, 0));\n  }\n}\n\nstatic int SysExecve(struct Machine *m, i64 pa, i64 aa, i64 ea) {\n  char *prog, **argv, **envp;\n  if (!(prog = CopyStr(m, pa))) return -1;\n  if (!(argv = CopyStrList(m, aa))) return -1;\n  if (!(envp = CopyStrList(m, ea))) return -1;\n  LOCK(&m->system->exec_lock);\n  ExecveBlink(m, prog, argv, envp);\n  SYS_LOGF(\"execve(%s)\", prog);\n  VfsExecve(prog, argv, envp);\n  UNLOCK(&m->system->exec_lock);\n  return -1;\n}\n\nstatic int SysWait4(struct Machine *m, int pid, i64 opt_out_wstatus_addr,\n                    int options, i64 opt_out_rusage_addr) {\n  int rc;\n  int wstatus;\n  i32 gwstatus;\n  u8 gwstatusb[4];\n  struct rusage hrusage;\n  struct rusage_linux grusage;\n  if ((options = XlatWait(options)) == -1) return -1;\n  if ((opt_out_wstatus_addr && !IsValidMemory(m, opt_out_wstatus_addr,\n                                              sizeof(gwstatusb), PROT_WRITE)) ||\n      (opt_out_rusage_addr &&\n       !IsValidMemory(m, opt_out_rusage_addr, sizeof(grusage), PROT_WRITE))) {\n    return -1;\n  }\n#ifdef HAVE_WAIT4\n  RESTARTABLE(rc = wait4(pid, &wstatus, options, &hrusage));\n#else\n  memset(&hrusage, 0, sizeof(hrusage));\n  if (opt_out_rusage_addr && (!pid || pid == -1)) {\n    LOGF(\"wait4(rusage) with indeterminate pid not possible on this platform\");\n  } else {\n    getrusage(pid < 0 ? -pid : pid, &hrusage);\n  }\n  RESTARTABLE(rc = waitpid(pid, &wstatus, options));\n#endif\n  if (rc != -1 && rc != 0) {\n    if (opt_out_wstatus_addr) {\n#ifdef WIFCONTINUED\n      if (WIFCONTINUED(wstatus)) {\n        gwstatus = 0xffff;\n        SYS_LOGF(\"pid %d continued\", rc);\n      } else\n#endif\n          if (WIFEXITED(wstatus)) {\n        int exitcode;\n        exitcode = WEXITSTATUS(wstatus) & 255;\n        gwstatus = exitcode << 8;\n        SYS_LOGF(\"pid %d exited %d\", rc, exitcode);\n      } else if (WIFSTOPPED(wstatus)) {\n        int stopsig;\n        stopsig = UnXlatSignal(WSTOPSIG(wstatus));\n        gwstatus = stopsig << 8 | 127;\n        SYS_LOGF(\"pid %d stopped %s\", rc, DescribeSignal(stopsig));\n      } else {\n        int termsig;\n        unassert(WIFSIGNALED(wstatus));\n        termsig = UnXlatSignal(WTERMSIG(wstatus));\n        SYS_LOGF(\"pid %d terminated %s\", rc, DescribeSignal(termsig));\n        gwstatus = termsig & 127;\n      }\n      Write32(gwstatusb, gwstatus);\n      CopyToUserWrite(m, opt_out_wstatus_addr, gwstatusb, sizeof(gwstatusb));\n    }\n    if (opt_out_rusage_addr) {\n      XlatRusageToLinux(&grusage, &hrusage);\n      CopyToUserWrite(m, opt_out_rusage_addr, &grusage, sizeof(grusage));\n    }\n  }\n  return rc;\n}\n\nstatic int SysGetrusage(struct Machine *m, i32 resource, i64 rusageaddr) {\n  int rc;\n  struct rusage hrusage;\n  struct rusage_linux grusage;\n  if ((rc = getrusage(XlatRusage(resource), &hrusage)) != -1) {\n    XlatRusageToLinux(&grusage, &hrusage);\n    if (CopyToUserWrite(m, rusageaddr, &grusage, sizeof(grusage)) == -1) {\n      rc = -1;\n    }\n  }\n  return rc;\n}\n\nstatic bool IsSupportedResourceLimit(int resource) {\n  return resource == RLIMIT_AS_LINUX ||    //\n         resource == RLIMIT_DATA_LINUX ||  //\n         resource == RLIMIT_NOFILE_LINUX;\n}\n\nstatic void GetResourceLimit_(struct Machine *m, int resource,\n                              struct rlimit_linux *lux) {\n  LOCK(&m->system->mmap_lock);\n  memcpy(lux, m->system->rlim + resource, sizeof(*lux));\n  UNLOCK(&m->system->mmap_lock);\n}\n\nstatic int SetResourceLimit(struct Machine *m, int resource,\n                            const struct rlimit_linux *lux) {\n  int rc;\n  LOCK(&m->system->mmap_lock);\n  if (Read64(lux->cur) <= Read64(m->system->rlim[resource].max) &&\n      Read64(lux->max) <= Read64(m->system->rlim[resource].max)) {\n    memcpy(m->system->rlim + resource, lux, sizeof(*lux));\n    rc = 0;\n  } else {\n    rc = eperm();\n  }\n  UNLOCK(&m->system->mmap_lock);\n  return rc;\n}\n\nstatic int SysGetrlimit(struct Machine *m, i32 resource, i64 rlimitaddr) {\n  int rc;\n  struct rlimit rlim;\n  struct rlimit_linux lux;\n  if (IsSupportedResourceLimit(resource)) {\n    GetResourceLimit_(m, resource, &lux);\n    return CopyToUserWrite(m, rlimitaddr, &lux, sizeof(lux));\n  }\n  if ((rc = getrlimit(XlatResource(resource), &rlim)) != -1) {\n    XlatRlimitToLinux(&lux, &rlim);\n    if (CopyToUserWrite(m, rlimitaddr, &lux, sizeof(lux)) == -1) rc = -1;\n  }\n  return rc;\n}\n\nstatic int SysSetrlimit(struct Machine *m, i32 resource, i64 rlimitaddr) {\n  int sysresource;\n  struct rlimit rlim;\n  const struct rlimit_linux *lux;\n  if (!(lux = (const struct rlimit_linux *)SchlepR(m, rlimitaddr,\n                                                   sizeof(*lux)))) {\n    return -1;\n  }\n  if (IsSupportedResourceLimit(resource)) {\n    return SetResourceLimit(m, resource, lux);\n  }\n  if ((sysresource = XlatResource(resource)) == -1) return -1;\n  XlatLinuxToRlimit(sysresource, &rlim, lux);\n  return setrlimit(sysresource, &rlim);\n}\n\nstatic int SysPrlimit(struct Machine *m, i32 pid, i32 resource,\n                      i64 new_rlimit_addr, i64 old_rlimit_addr) {\n  if (pid && pid != m->system->pid) {\n    return eperm();\n  }\n#ifndef TINY\n  if ((old_rlimit_addr &&\n       !IsValidMemory(m, old_rlimit_addr, sizeof(struct rlimit_linux),\n                      PROT_WRITE)) &&\n      (new_rlimit_addr &&\n       !IsValidMemory(m, new_rlimit_addr, sizeof(struct rlimit_linux),\n                      PROT_READ))) {\n    return -1;\n  }\n#endif\n  if ((old_rlimit_addr && SysGetrlimit(m, resource, old_rlimit_addr) == -1) ||\n      (new_rlimit_addr && SysSetrlimit(m, resource, new_rlimit_addr) == -1)) {\n    return -1;\n  }\n  return 0;\n}\n\nstatic int SysSysinfo(struct Machine *m, i64 siaddr) {\n  struct sysinfo_linux si;\n  if (sysinfo_linux(&si) == -1) return -1;\n  CopyToUserWrite(m, siaddr, &si, sizeof(si));\n  return 0;\n}\n\nstatic i64 SysGetcwd(struct Machine *m, i64 bufaddr, i64 size) {\n  i64 res;\n  size_t n;\n  char buf[PATH_MAX + 1];\n  if (size < 0) return enomem();\n  if (VfsGetcwd(buf, sizeof(buf))) {\n    n = strlen(buf) + 1;\n    if (size < n) {\n      res = erange();\n    } else if (CopyToUserWrite(m, bufaddr, buf, n) != -1) {\n      res = n;\n    } else {\n      res = -1;\n    }\n  } else {\n    res = -1;\n  }\n  return res;\n}\n\nstatic ssize_t SysGetrandom(struct Machine *m, i64 a, size_t n, int f) {\n  char *p;\n  ssize_t rc;\n  int besteffort, unsupported;\n  besteffort = GRND_NONBLOCK_LINUX | GRND_RANDOM_LINUX;\n  if ((unsupported = f & ~besteffort)) {\n    LOGF(\"%s() flags %d not supported\", \"getrandom\", unsupported);\n    return einval();\n  }\n  if (n) {\n    if (!(p = (char *)AddToFreeList(m, malloc(n)))) return -1;\n    RESTARTABLE(rc = GetRandom(p, n, f));\n    if (rc != -1) {\n      if (CopyToUserWrite(m, a, p, rc) == -1) {\n        rc = -1;\n      }\n    }\n  } else {\n    rc = 0;\n  }\n  return rc;\n}\n\nvoid OnSignal(int sig, siginfo_t *si, void *uc) {\n  SIG_LOGF(\"OnSignal(%s)\", DescribeSignal(UnXlatSignal(sig)));\n  EnqueueSignal(g_machine, UnXlatSignal(sig));\n}\n\nstatic int SysSigaction(struct Machine *m, int sig, i64 act, i64 old,\n                        u64 sigsetsize) {\n  int syssig;\n  u64 flags = 0;\n  i64 handler = 0;\n  bool isignored = false;\n  struct sigaction syshand;\n  struct sigaction_linux hand;\n  u32 supported = SA_SIGINFO_LINUX |    //\n                  SA_RESTART_LINUX |    //\n                  SA_ONSTACK_LINUX |    //\n                  SA_NODEFER_LINUX |    //\n                  SA_RESTORER_LINUX |   //\n                  SA_RESETHAND_LINUX |  //\n#ifdef SA_NOCLDWAIT\n                  SA_NOCLDWAIT_LINUX |  //\n#endif\n                  SA_NOCLDSTOP_LINUX;\n  if (sigsetsize != 8) return einval();\n  if (!(1 <= sig && sig <= 64)) return einval();\n  if (sig == SIGKILL_LINUX || sig == SIGSTOP_LINUX) return einval();\n  if (old && !IsValidMemory(m, old, sizeof(hand), PROT_WRITE)) return -1;\n  memset(&hand, 0, sizeof(hand));\n  if (act) {\n    if (CopyFromUserRead(m, &hand, act, sizeof(hand)) == -1) return -1;\n    flags = Read64(hand.flags);\n    handler = Read64(hand.handler);\n    if (handler == SIG_IGN_LINUX) {\n      flags &= ~SA_NOCLDWAIT_LINUX;\n    }\n    if (flags & ~supported) {\n      LOGF(\"unrecognized sigaction() flags: %#\" PRIx64, flags & ~supported);\n      return einval();\n    }\n    switch (handler) {\n      case SIG_DFL_LINUX:\n        isignored = IsSignalIgnoredByDefault(sig);\n        break;\n      case SIG_IGN_LINUX:\n        isignored = true;\n        break;\n      default:\n        if (!(flags & SA_RESTORER_LINUX)) {\n          LOGF(\"sigaction() flags missing SA_RESTORER\");\n          return einval();\n        }\n        if (!IsValidMemory(m, Read64(hand.restorer), 1, PROT_EXEC)) {\n          LOGF(\"sigaction() SA_RESTORER at %\" PRIx64 \" isn't executable\",\n               Read64(hand.restorer));\n          return -1;\n        }\n        break;\n    }\n  }\n  LOCK(&m->system->sig_lock);\n  if (old) {\n    CopyToUserWrite(m, old, &m->system->hands[sig - 1], sizeof(hand));\n  }\n  if (act) {\n    m->system->hands[sig - 1] = hand;\n    if (isignored) {\n      m->signals &= ~((u64)1 << (sig - 1));\n    }\n    if ((syssig = XlatSignal(sig)) != -1 && !IsBlinkSig(m->system, sig)) {\n      sigfillset(&syshand.sa_mask);\n      syshand.sa_flags = SA_SIGINFO;\n      if (flags & SA_NOCLDSTOP_LINUX) syshand.sa_flags |= SA_NOCLDSTOP;\n#ifdef SA_NOCLDWAIT\n      if (flags & SA_NOCLDWAIT_LINUX) syshand.sa_flags |= SA_NOCLDWAIT;\n#endif\n      switch (handler) {\n        case SIG_DFL_LINUX:\n          syshand.sa_handler = SIG_DFL;\n          break;\n        case SIG_IGN_LINUX:\n          syshand.sa_handler = SIG_IGN;\n          break;\n        default:\n          syshand.sa_sigaction = OnSignal;\n          break;\n      }\n      if (sigaction(syssig, &syshand, 0)) {\n        LOGF(\"system sigaction(%s) returned %s\", DescribeSignal(sig),\n             DescribeHostErrno(errno));\n      }\n    }\n  }\n  UNLOCK(&m->system->sig_lock);\n  return 0;\n}\n\nstatic int SysGetitimer(struct Machine *m, int which, i64 curvaladdr) {\n  int rc;\n  struct itimerval it;\n  struct itimerval_linux git;\n  if ((rc = getitimer(UnXlatItimer(which), &it)) != -1) {\n    XlatItimervalToLinux(&git, &it);\n    CopyToUserWrite(m, curvaladdr, &git, sizeof(git));\n  }\n  return rc;\n}\n\nstatic int SysSetitimer(struct Machine *m, int which, i64 neuaddr,\n                        i64 oldaddr) {\n  int rc;\n  struct itimerval_linux gold;\n  struct itimerval neu, *neup, old;\n  const struct itimerval_linux *git = 0;\n  if ((neuaddr && !(git = (const struct itimerval_linux *)SchlepR(\n                        m, neuaddr, sizeof(*git)))) ||\n      (oldaddr && !IsValidMemory(m, oldaddr, sizeof(gold), PROT_WRITE))) {\n    return -1;\n  }\n  if (git) {\n    XlatLinuxToItimerval(&neu, git);\n    neup = &neu;\n  } else {\n    neup = 0;\n  }\n  if ((rc = setitimer(UnXlatItimer(which), neup, &old)) != -1) {\n    if (oldaddr) {\n      XlatItimervalToLinux(&gold, &old);\n      CopyToUserWrite(m, oldaddr, &gold, sizeof(gold));\n    }\n  }\n  return rc;\n}\n\nstatic int SysNanosleep(struct Machine *m, i64 req, i64 rem) {\n  struct timespec_linux gt;\n  const struct timespec_linux *gtp;\n  struct timespec ts, now, deadline;\n  now = GetTime();\n  if ((rem && !IsValidMemory(m, rem, sizeof(gtp), PROT_WRITE)) ||\n      !(gtp = (const struct timespec_linux *)SchlepR(m, req, sizeof(*gtp)))) {\n    return -1;\n  }\n  ts.tv_sec = Read64(gtp->sec);\n  ts.tv_nsec = Read64(gtp->nsec);\n  if (ts.tv_sec < 0) return einval();\n  if (!(0 <= ts.tv_nsec && ts.tv_nsec < 1000000000)) return einval();\n  deadline = AddTime(now, ts);\n  for (;;) {\n    if (CompareTime(now, deadline) >= 0) return 0;\n    ts = SubtractTime(deadline, now);\n    if (nanosleep(&ts, 0)) {\n      unassert(errno == EINTR);\n      // this may run a guest signal handler before returning\n      if (CheckInterrupt(m, false)) {\n        // a signal was delivered or is about to be delivered\n        if (rem) {\n          // rem is only updated when -1 w/ eintr is returned\n          now = GetTime();\n          if (CompareTime(now, deadline) < 0) {\n            ts = SubtractTime(deadline, now);\n          } else {\n            ts = GetZeroTime();\n          }\n          Write64(gt.sec, ts.tv_sec);\n          Write64(gt.nsec, ts.tv_nsec);\n          CopyToUserWrite(m, rem, &gt, sizeof(gt));\n        }\n        return -1;\n      }\n    }\n    // sleep apis aren't nearly as fast and reliable as time apis\n    // even if nanosleep() claims it slept the full time we check\n    now = GetTime();\n  }\n}\n\nstatic int SysClockNanosleep(struct Machine *m, int clock, int flags,\n                             i64 reqaddr, i64 remaddr) {\n  int rc;\n  clock_t sysclock;\n  struct timespec req, rem;\n  struct timespec_linux gtimespec;\n  if (XlatClock(clock, &sysclock) == -1) return -1;\n  if (flags & ~TIMER_ABSTIME_LINUX) return einval();\n  if (CopyFromUserRead(m, &gtimespec, reqaddr, sizeof(gtimespec)) == -1) {\n    return -1;\n  }\n  req.tv_sec = Read64(gtimespec.sec);\n  req.tv_nsec = Read64(gtimespec.nsec);\nTryAgain:\n#if defined(TIMER_ABSTIME) && !defined(__OpenBSD__)\n  flags = flags & TIMER_ABSTIME_LINUX ? TIMER_ABSTIME : 0;\n  if ((rc = clock_nanosleep(sysclock, flags, &req, &rem))) {\n    errno = rc;\n    rc = -1;\n  }\n#else\n  if (!flags) {\n    if (sysclock == CLOCK_REALTIME) {\n      rc = nanosleep(&req, &rem);\n    } else {\n      rc = einval();\n    }\n  } else {\n    struct timespec now;\n    if (!(rc = clock_gettime(sysclock, &now))) {\n      if (CompareTime(now, req) < 0) {\n        req = SubtractTime(req, now);\n        rc = nanosleep(&req, &rem);\n      } else {\n        rc = 0;\n      }\n    }\n  }\n#endif\n  if (rc == -1 && errno == EINTR) {\n    if (CheckInterrupt(m, false)) {\n      if (!flags && remaddr) {\n        Write64(gtimespec.sec, rem.tv_sec);\n        Write64(gtimespec.nsec, rem.tv_nsec);\n        CopyToUserWrite(m, remaddr, &gtimespec, sizeof(gtimespec));\n      }\n    } else {\n      if (!flags) {\n        req = rem;\n      }\n      goto TryAgain;\n    }\n  }\n  return rc;\n}\n\nstatic int SigsuspendActual(struct Machine *m, u64 mask) {\n  int rc;\n  u64 oldmask;\n  sigset_t block_host, oldmask_host;\n  oldmask = m->sigmask;\n  unassert(!sigfillset(&block_host));\n  unassert(!pthread_sigmask(SIG_BLOCK, &block_host, &oldmask_host));\n  m->sigmask = mask;\n  SIG_LOGF(\"sigmask push %\" PRIx64, m->sigmask);\n  m->issigsuspend = true;\n  NORESTART(rc, sigsuspend(&oldmask_host));\n  m->issigsuspend = false;\n  unassert(!pthread_sigmask(SIG_SETMASK, &oldmask_host, 0));\n  m->sigmask = oldmask;\n  SIG_LOGF(\"sigmask pop %\" PRIx64, m->sigmask);\n  return rc;\n}\n\nstatic int SigsuspendPolyfill(struct Machine *m, u64 mask) {\n  long nanos;\n  u64 oldmask;\n  struct timespec ts;\n  oldmask = m->sigmask;\n  m->sigmask = mask;\n  nanos = 1;\n  while (!CheckInterrupt(m, false)) {\n    if (nanos > 256) {\n      if (nanos < 10 * 1000) {\n#ifdef HAVE_SCHED_YIELD\n        sched_yield();\n#endif\n      } else {\n        ts = FromNanoseconds(nanos);\n        if (nanosleep(&ts, 0)) {\n          unassert(errno == EINTR);\n          continue;\n        }\n      }\n    }\n    if (nanos < 100 * 1000 * 1000) {\n      nanos <<= 1;\n    }\n  }\n  m->sigmask = oldmask;\n  return -1;\n}\n\nstatic int SysSigsuspend(struct Machine *m, i64 maskaddr, i64 sigsetsize) {\n  u8 word[8];\n  if (sigsetsize != 8) return einval();\n  if (CopyFromUserRead(m, word, maskaddr, 8) == -1) return -1;\n#ifdef __EMSCRIPTEN__\n  return SigsuspendPolyfill(m, Read64(word));\n#else\n  return SigsuspendActual(m, Read64(word));\n#endif\n}\n\nstatic int SysSigaltstack(struct Machine *m, i64 newaddr, i64 oldaddr) {\n  bool isonstack;\n  int supported, unsupported;\n  const struct sigaltstack_linux *ss = 0;\n  supported = SS_ONSTACK_LINUX | SS_DISABLE_LINUX | SS_AUTODISARM_LINUX;\n  isonstack =\n      (~Read32(m->sigaltstack.flags) & SS_DISABLE_LINUX) &&\n      Read64(m->sp) >= Read64(m->sigaltstack.sp) &&\n      Read64(m->sp) <= Read64(m->sigaltstack.sp) + Read64(m->sigaltstack.size);\n  if (newaddr) {\n    if (isonstack) {\n      LOGF(\"can't change sigaltstack whilst on sigaltstack\");\n      return eperm();\n    }\n    if (!(ss = (const struct sigaltstack_linux *)SchlepR(m, newaddr,\n                                                         sizeof(*ss)))) {\n      LOGF(\"couldn't schlep new sigaltstack: %#\" PRIx64, newaddr);\n      return -1;\n    }\n    if ((unsupported = Read32(ss->flags) & ~supported)) {\n      LOGF(\"unsupported %s flags: %#x\", \"sigaltstack\", unsupported);\n      return einval();\n    }\n    if (~Read32(ss->flags) & SS_DISABLE_LINUX) {\n      if (Read64(ss->size) < MINSIGSTKSZ_LINUX) {\n        LOGF(\"sigaltstack ss_size=%#\" PRIx64 \" must be at least %#x\",\n             Read64(ss->size), MINSIGSTKSZ_LINUX);\n        return enomem();\n      }\n      if (!IsValidMemory(m, Read64(ss->sp), Read64(ss->size),\n                         PROT_READ | PROT_WRITE)) {\n        LOGF(\"sigaltstack ss_sp=%#\" PRIx64 \" ss_size=%#\" PRIx64\n             \" didn't exist with read+write permission\",\n             Read64(ss->sp), Read64(ss->size));\n        return -1;\n      }\n    }\n  }\n  if (oldaddr) {\n    Write32(m->sigaltstack.flags,\n            Read32(m->sigaltstack.flags) & ~SS_ONSTACK_LINUX);\n    if (isonstack) {\n      Write32(m->sigaltstack.flags,\n              Read32(m->sigaltstack.flags) | SS_ONSTACK_LINUX);\n    }\n    CopyToUserWrite(m, oldaddr, &m->sigaltstack, sizeof(m->sigaltstack));\n  }\n  if (ss) {\n    memcpy(&m->sigaltstack, ss, sizeof(*ss));\n  }\n  return 0;\n}\n\nstatic int SysClockGettime(struct Machine *m, int clock, i64 ts) {\n  int rc;\n  clock_t sysclock;\n  struct timespec htimespec;\n  struct timespec_linux gtimespec;\n  if (clock == CLOCK_REALTIME_LINUX) {\n    sysclock = CLOCK_REALTIME;\n  } else if (XlatClock(clock, &sysclock) == -1) {\n    return -1;\n  }\n  if ((rc = clock_gettime(sysclock, &htimespec)) != -1) {\n    if (ts) {\n      Write64(gtimespec.sec, htimespec.tv_sec);\n      Write64(gtimespec.nsec, htimespec.tv_nsec);\n      CopyToUserWrite(m, ts, &gtimespec, sizeof(gtimespec));\n    }\n  }\n  return rc;\n}\n\n#ifdef HAVE_CLOCK_SETTIME\nstatic int SysClockSettime(struct Machine *m, int clock, i64 ts) {\n  clock_t sysclock;\n  struct timespec ht;\n  const struct timespec_linux *gt;\n  if (XlatClock(clock, &sysclock) == -1) return -1;\n  if ((gt = (const struct timespec_linux *)SchlepR(m, ts, sizeof(*gt)))) {\n    ht.tv_sec = Read64(gt->sec);\n    ht.tv_nsec = Read64(gt->nsec);\n  }\n  return clock_settime(sysclock, &ht);\n}\n#endif\n\nstatic int SysClockGetres(struct Machine *m, int clock, i64 ts) {\n  int rc;\n  clock_t sysclock;\n  struct timespec htimespec;\n  struct timespec_linux gtimespec;\n  if (XlatClock(clock, &sysclock) == -1) return -1;\n  if ((rc = clock_getres(sysclock, &htimespec)) != -1) {\n    if (ts) {\n      Write64(gtimespec.sec, htimespec.tv_sec);\n      Write64(gtimespec.nsec, htimespec.tv_nsec);\n      CopyToUserWrite(m, ts, &gtimespec, sizeof(gtimespec));\n    }\n  }\n  return rc;\n}\n\nstatic int SysGettimeofday(struct Machine *m, i64 tv, i64 tz) {\n  int rc;\n  void *htimezonep;\n  struct timeval htimeval;\n  struct timeval_linux gtimeval;\n#ifdef HAVE_STRUCT_TIMEZONE\n  struct timezone htimezone;\n  struct timezone_linux gtimezone;\n  memset(&htimezone, 0, sizeof(htimezone));\n  htimezonep = tz ? &htimezone : 0;\n#else\n  htimezonep = 0;\n#endif\n  if ((rc = gettimeofday(&htimeval, htimezonep)) != -1) {\n    Write64(gtimeval.sec, htimeval.tv_sec);\n    Write64(gtimeval.usec, htimeval.tv_usec);\n    if (CopyToUserWrite(m, tv, &gtimeval, sizeof(gtimeval)) == -1) {\n      return -1;\n    }\n    // \"If tzp is not a null pointer, the behavior is unspecified.\"\n    // ──Quoth the POSIX.1 IEEE Std 1003.1-2017 for gettimeofday().\n    if (tz) {\n#ifdef HAVE_STRUCT_TIMEZONE\n      Write32(gtimezone.minuteswest, htimezone.tz_minuteswest);\n      Write32(gtimezone.dsttime, htimezone.tz_dsttime);\n      if (CopyToUserWrite(m, tz, &gtimezone, sizeof(gtimezone)) == -1) {\n        return -1;\n      }\n#else\n      rc = enotsup();\n#endif\n    }\n  }\n  return rc;\n}\n\nstatic i64 SysTime(struct Machine *m, i64 addr) {\n  u8 buf[8];\n  time_t secs;\n  if ((secs = time(0)) == (time_t)-1) return -1;\n  if (addr) {\n    Write64(buf, secs);\n    if (CopyToUserWrite(m, addr, buf, sizeof(buf)) == -1) return -1;\n  }\n  return secs;\n}\n\nstatic i64 SysTimes(struct Machine *m, i64 bufaddr) {\n  // no conversion needed thanks to getauxval(AT_CLKTCK)\n  clock_t res;\n  struct tms tms;\n  struct tms_linux gtms;\n  if ((res = times(&tms)) == (clock_t)-1) return -1;\n  Write64(gtms.utime, tms.tms_utime);\n  Write64(gtms.stime, tms.tms_stime);\n  Write64(gtms.cutime, tms.tms_cutime);\n  Write64(gtms.cstime, tms.tms_cstime);\n  if (CopyToUserWrite(m, bufaddr, &gtms, sizeof(gtms)) == -1) return -1;\n  return res;\n}\n\nstatic struct timespec ConvertUtimeTimespec(const struct timespec_linux *tv) {\n  struct timespec ts;\n  switch (Read64(tv->nsec)) {\n    case UTIME_NOW_LINUX:\n      ts.tv_sec = 0;\n      ts.tv_nsec = UTIME_NOW;\n      return ts;\n    case UTIME_OMIT_LINUX:\n      ts.tv_sec = 0;\n      ts.tv_nsec = UTIME_OMIT;\n      return ts;\n    default:\n      ts.tv_sec = Read64(tv->sec);\n      ts.tv_nsec = Read64(tv->nsec);\n      return ts;\n  }\n}\n\nstatic struct timespec ConvertUtimeTimeval(const struct timeval_linux *tv) {\n  i64 x;\n  struct timespec ts;\n  switch ((x = Read64(tv->usec))) {\n    case UTIME_NOW_LINUX:\n      ts.tv_sec = 0;\n      ts.tv_nsec = UTIME_NOW;\n      return ts;\n    case UTIME_OMIT_LINUX:\n      ts.tv_sec = 0;\n      ts.tv_nsec = UTIME_OMIT;\n      return ts;\n    default:\n      ts.tv_sec = Read64(tv->sec);\n      if (0 <= x && x < 1000000) {\n        ts.tv_nsec = x * 1000;\n      } else {\n        // make sure system call will einval\n        // should not overlap with magnums above\n        ts.tv_nsec = 1000000666;\n      }\n      return ts;\n  }\n}\n\nstatic void ConvertUtimeTimespecs(struct timespec *ts,\n                                  const struct timespec_linux *tv) {\n  ts[0] = ConvertUtimeTimespec(tv + 0);\n  ts[1] = ConvertUtimeTimespec(tv + 1);\n}\n\nstatic void ConvertUtimeTimevals(struct timespec *ts,\n                                 const struct timeval_linux *tv) {\n  ts[0] = ConvertUtimeTimeval(tv + 0);\n  ts[1] = ConvertUtimeTimeval(tv + 1);\n}\n\nstatic int XlatUtimensatFlags(int x) {\n  int res = 0;\n  if (x & AT_SYMLINK_FOLLOW_LINUX) {\n    x &= ~AT_SYMLINK_FOLLOW_LINUX;  // default behavior\n  }\n  if (x & AT_SYMLINK_NOFOLLOW_LINUX) {\n    res |= AT_SYMLINK_NOFOLLOW;\n    x &= ~AT_SYMLINK_NOFOLLOW_LINUX;\n  }\n  if (x) {\n    LOGF(\"%s() flags %d not supported\", \"utimensat\", x);\n    return -1;\n  }\n  return res;\n}\n\nstatic int SysUtime(struct Machine *m, i64 pathaddr, i64 timesaddr) {\n  const char *path;\n  struct timespec ts[2];\n  const struct utimbuf_linux *t;\n  if (!(path = LoadStr(m, pathaddr))) return -1;\n  if (!timesaddr) return VfsUtime(AT_FDCWD, path, 0, 0);\n  if ((t = (const struct utimbuf_linux *)SchlepR(m, timesaddr, sizeof(*t)))) {\n    ts[0].tv_sec = Read64(t->actime);\n    ts[0].tv_nsec = 0;\n    ts[1].tv_sec = Read64(t->modtime);\n    ts[1].tv_nsec = 0;\n    return VfsUtime(AT_FDCWD, path, ts, 0);\n  } else {\n    return -1;\n  }\n}\n\nstatic int SysUtimes(struct Machine *m, i64 pathaddr, i64 tvsaddr) {\n  const char *path;\n  struct timespec ts[2];\n  const struct timeval_linux *tv;\n  if (!(path = LoadStr(m, pathaddr))) return -1;\n  if (!tvsaddr) return VfsUtime(AT_FDCWD, path, 0, 0);\n  if ((tv = (const struct timeval_linux *)SchlepR(\n           m, tvsaddr, sizeof(struct timeval_linux) * 2))) {\n    ConvertUtimeTimevals(ts, tv);\n    return VfsUtime(AT_FDCWD, path, ts, 0);\n  } else {\n    return -1;\n  }\n}\n\nstatic int SysFutimesat(struct Machine *m, i32 dirfd, i64 pathaddr,\n                        i64 tvsaddr) {\n  const char *path;\n  struct timespec ts[2];\n  const struct timeval_linux *tv;\n  if (!(path = LoadStr(m, pathaddr))) return -1;\n  if (!tvsaddr) return VfsUtime(GetDirFildes(dirfd), path, 0, 0);\n  if ((tv = (const struct timeval_linux *)SchlepR(\n           m, tvsaddr, sizeof(struct timeval_linux) * 2))) {\n    ConvertUtimeTimevals(ts, tv);\n    return VfsUtime(GetDirFildes(dirfd), path, ts, 0);\n  } else {\n    return -1;\n  }\n}\n\nstatic int SysUtimensat(struct Machine *m, i32 fd, i64 pathaddr, i64 tvsaddr,\n                        i32 flags) {\n  const char *path;\n  struct timespec ts[2], *tsp;\n  const struct timespec_linux *tv;\n  if (!pathaddr) {\n    path = 0;\n  } else if (!(path = LoadStr(m, pathaddr))) {\n    return -1;\n  }\n  if (tvsaddr) {\n    if ((tv = (const struct timespec_linux *)SchlepR(\n             m, tvsaddr, sizeof(struct timespec_linux) * 2))) {\n      ConvertUtimeTimespecs(ts, tv);\n      tsp = ts;\n    } else {\n      return -1;\n    }\n  } else {\n    tsp = 0;\n  }\n  if ((flags = XlatUtimensatFlags(flags)) == -1) return -1;\n  if (path) {\n    return VfsUtime(GetDirFildes(fd), path, tsp, flags);\n  } else {\n    if (flags) {\n      LOGF(\"%s() flags %d not supported\", \"utimensat(path=null)\", flags);\n      return einval();\n    }\n    return VfsFutime(fd, tsp);\n  }\n}\n\nstatic int LoadFdSet(struct Machine *m, int nfds, fd_set *fds, i64 addr) {\n  u64 w;\n  int fd;\n  unsigned o;\n  const u64 *p;\n  if ((p = (const u64 *)SchlepRW(m, addr, FD_SETSIZE_LINUX / 8))) {\n    FD_ZERO(fds);\n    for (fd = 0; fd < nfds; fd += 64) {\n      w = p[fd >> 6];\n      while (w) {\n        o = bsr(w);\n        w &= ~((u64)1 << o);\n        if (fd + o < nfds) {\n          FD_SET(fd + o, fds);\n        }\n      }\n    }\n    return 0;\n  } else {\n    return -1;\n  }\n}\n\nstatic int SaveFdSet(struct Machine *m, int nfds, const fd_set *fds, i64 addr) {\n  int fd;\n  u8 p[FD_SETSIZE_LINUX / 8] = {0};\n  for (fd = 0; fd < nfds; ++fd) {\n    if (FD_ISSET(fd, fds)) {\n      p[fd >> 3] |= 1 << (fd & 7);\n    }\n  }\n  return CopyToUserWrite(m, addr, p, FD_SETSIZE_LINUX / 8);\n}\n\nstatic i32 Select(struct Machine *m,          //\n                  i32 nfds,                   //\n                  i64 readfds_addr,           //\n                  i64 writefds_addr,          //\n                  i64 exceptfds_addr,         //\n                  struct timespec *timeoutp,  //\n                  const u64 *sigmaskp_guest) {\n  int fildes, rc;\n  i32 setsize;\n  u64 oldmask_guest = 0;\n  fd_set readfds, writefds, exceptfds, readyreadfds, readywritefds,\n      readyexceptfds;\n  struct pollfd hfds[1];\n  struct timespec now, wait, remain, deadline = {0};\n  struct Fd *fd;\n  int (*poll_impl)(struct pollfd *, nfds_t, int);\n  if (timeoutp) {\n    deadline = AddTime(GetTime(), *timeoutp);\n  }\n  setsize = MIN(FD_SETSIZE, FD_SETSIZE_LINUX);\n  if (nfds < 0 || nfds > setsize) {\n    LOGF(\"select() nfds=%d can't exceed %d on this platform\", nfds, setsize);\n    return einval();\n  }\n  if (readfds_addr) {\n    if (LoadFdSet(m, nfds, &readfds, readfds_addr) == -1) {\n      return -1;\n    }\n  } else {\n    FD_ZERO(&readfds);\n  }\n  if (writefds_addr) {\n    if (LoadFdSet(m, nfds, &writefds, writefds_addr) == -1) {\n      return -1;\n    }\n  } else {\n    FD_ZERO(&writefds);\n  }\n  if (exceptfds_addr) {\n    if (LoadFdSet(m, nfds, &exceptfds, exceptfds_addr) == -1) {\n      return -1;\n    }\n  } else {\n    FD_ZERO(&exceptfds);\n  }\n  FD_ZERO(&readyreadfds);\n  FD_ZERO(&readywritefds);\n  FD_ZERO(&readyexceptfds);\n  if (sigmaskp_guest) {\n    oldmask_guest = m->sigmask;\n    m->sigmask = *sigmaskp_guest;\n    SIG_LOGF(\"sigmask push %\" PRIx64, m->sigmask);\n  }\n  for (;;) {\n    if (CheckInterrupt(m, false)) {\n      rc = eintr();\n      break;\n    }\n    rc = 0;\n    for (fildes = 0; fildes < nfds; ++fildes) {\n      if (!FD_ISSET(fildes, &readfds) && !FD_ISSET(fildes, &writefds) &&\n          !FD_ISSET(fildes, &exceptfds)) {\n        continue;\n      }\n    TryAgain:\n      if (CheckInterrupt(m, false)) {\n        rc = eintr();\n        break;\n      }\n      LOCK(&m->system->fds.lock);\n      if ((fd = GetFd(&m->system->fds, fildes))) {\n        unassert(fd->cb);\n        unassert(poll_impl = fd->cb->poll);\n      } else {\n        poll_impl = 0;\n      }\n      UNLOCK(&m->system->fds.lock);\n      if (fd) {\n        hfds[0].fd = fildes;\n        hfds[0].events = ((FD_ISSET(fildes, &readfds) ? POLLIN : 0) |\n                          (FD_ISSET(fildes, &writefds) ? POLLOUT : 0) |\n                          (FD_ISSET(fildes, &exceptfds) ? POLLPRI : 0));\n        switch (poll_impl(hfds, 1, 0)) {\n          case 0:\n            break;\n          case 1:\n            if (FD_ISSET(fildes, &readfds) && (hfds[0].revents & POLLIN)) {\n              ++rc;\n              FD_SET(fildes, &readyreadfds);\n              FD_CLR(fildes, &readfds);\n            }\n            if (FD_ISSET(fildes, &writefds) && (hfds[0].revents & POLLOUT)) {\n              ++rc;\n              FD_SET(fildes, &readywritefds);\n              FD_CLR(fildes, &writefds);\n            }\n            if (FD_ISSET(fildes, &exceptfds) && (hfds[0].revents & POLLPRI)) {\n              ++rc;\n              FD_SET(fildes, &readyexceptfds);\n              FD_CLR(fildes, &exceptfds);\n            }\n            break;\n          case -1:\n            if (errno == EINTR) {\n              goto TryAgain;\n            }\n            rc = -1;\n            goto BreakLoop;\n        }\n      } else {\n        rc = ebadf();\n        break;\n      }\n    }\n  BreakLoop:\n    if (rc || (timeoutp && CompareTime(now = GetTime(), deadline) >= 0)) {\n      break;\n    }\n    if (timeoutp) {\n      wait = FromMilliseconds(kPollingMs);\n      remain = SubtractTime(deadline, now);\n      if (CompareTime(remain, wait) < 0) {\n        wait = remain;\n      }\n    } else {\n      wait = FromMilliseconds(kPollingMs);\n    }\n    nanosleep(&wait, 0);\n  }\n  if (sigmaskp_guest) {\n    m->sigmask = oldmask_guest;\n    SIG_LOGF(\"sigmask pop %\" PRIx64, m->sigmask);\n  }\n  if (rc != -1) {\n    if ((readfds_addr &&\n         SaveFdSet(m, nfds, &readyreadfds, readfds_addr) == -1) ||\n        (writefds_addr &&\n         SaveFdSet(m, nfds, &readywritefds, writefds_addr) == -1) ||\n        (exceptfds_addr &&\n         SaveFdSet(m, nfds, &readyexceptfds, exceptfds_addr) == -1)) {\n      return -1;\n    }\n  }\n#ifndef DISABLE_NONPOSIX\n  if (timeoutp) {\n    now = GetTime();\n    if (CompareTime(now, deadline) < 0) {\n      *timeoutp = SubtractTime(deadline, now);\n    } else {\n      *timeoutp = GetZeroTime();\n    }\n  }\n#endif\n  return rc;\n}\n\nstatic i32 SysSelect(struct Machine *m, i32 nfds, i64 readfds_addr,\n                     i64 writefds_addr, i64 exceptfds_addr, i64 timeout_addr) {\n  i32 rc;\n  struct timespec timeout, *timeoutp;\n#ifndef DISABLE_NONPOSIX\n  struct timeval_linux timeout_linux;\n#endif\n  const struct timeval_linux *timeoutp_linux;\n  if (timeout_addr) {\n    if ((timeoutp_linux = (const struct timeval_linux *)SchlepRW(\n             m, timeout_addr, sizeof(*timeoutp_linux)))) {\n      timeout.tv_sec = Read64(timeoutp_linux->sec);\n      timeout.tv_nsec = Read64(timeoutp_linux->usec);\n      if (0 <= timeout.tv_sec &&\n          (0 <= timeout.tv_nsec && timeout.tv_nsec < 1000000)) {\n        timeout.tv_nsec *= 1000;\n        timeoutp = &timeout;\n      } else {\n        return einval();\n      }\n    } else {\n      return -1;\n    }\n  } else {\n    timeoutp = 0;\n    memset(&timeout, 0, sizeof(timeout));\n  }\n  rc =\n      Select(m, nfds, readfds_addr, writefds_addr, exceptfds_addr, timeoutp, 0);\n#ifndef DISABLE_NONPOSIX\n  if (timeout_addr) {\n    Write64(timeout_linux.sec, timeout.tv_sec);\n    Write64(timeout_linux.usec, (timeout.tv_nsec + 999) / 1000);\n    CopyToUserWrite(m, timeout_addr, &timeout_linux, sizeof(timeout_linux));\n  }\n#endif\n  return rc;\n}\n\nstatic i32 SysPselect(struct Machine *m, i32 nfds, i64 readfds_addr,\n                      i64 writefds_addr, i64 exceptfds_addr, i64 timeout_addr,\n                      i64 pselect6_addr) {\n  i32 rc;\n  u64 sigmask, *sigmaskp;\n  const struct sigset_linux *sm;\n  const struct pselect6_linux *ps;\n  struct timespec timeout, *timeoutp;\n#ifndef DISABLE_NONPOSIX\n  struct timespec_linux timeout_linux;\n#endif\n  if (timeout_addr) {\n    if (LoadTimespecRW(m, timeout_addr, &timeout) == -1) return -1;\n    timeoutp = &timeout;\n  } else {\n    timeoutp = 0;\n    memset(&timeout, 0, sizeof(timeout));\n  }\n  if (pselect6_addr) {\n    if ((ps = (const struct pselect6_linux *)SchlepR(m, pselect6_addr,\n                                                     sizeof(*ps)))) {\n      if (Read64(ps->sigmaskaddr)) {\n        if (Read64(ps->sigmasksize) == 8) {\n          if ((sm = (const struct sigset_linux *)SchlepR(\n                   m, Read64(ps->sigmaskaddr), sizeof(*sm)))) {\n            sigmask = Read64(sm->sigmask);\n            sigmaskp = &sigmask;\n          } else {\n            return -1;\n          }\n        } else {\n          return einval();\n        }\n      } else {\n        sigmaskp = 0;\n      }\n    } else {\n      return -1;\n    }\n  } else {\n    sigmaskp = 0;\n  }\n  rc = Select(m, nfds, readfds_addr, writefds_addr, exceptfds_addr, timeoutp,\n              sigmaskp);\n#ifndef DISABLE_NONPOSIX\n  if (timeout_addr) {\n    Write64(timeout_linux.sec, timeout.tv_sec);\n    Write64(timeout_linux.nsec, timeout.tv_nsec);\n    CopyToUserWrite(m, timeout_addr, &timeout_linux, sizeof(timeout_linux));\n  }\n#endif\n  return rc;\n}\n\nstatic int Poll(struct Machine *m, i64 fdsaddr, u64 nfds,\n                struct timespec deadline) {\n  long i;\n  u64 gfdssize;\n  struct Fd *fd;\n  int fildes, rc, ev;\n  struct pollfd hfds[1];\n  struct pollfd_linux *gfds;\n  struct timespec now, wait, remain;\n  int (*poll_impl)(struct pollfd *, nfds_t, int);\n  if (!ckd_mul(&gfdssize, nfds, sizeof(struct pollfd_linux)) &&\n      gfdssize <= 0x7ffff000) {\n    if ((gfds = (struct pollfd_linux *)AddToFreeList(m, malloc(gfdssize)))) {\n      rc = 0;\n      CopyFromUserRead(m, gfds, fdsaddr, gfdssize);\n      for (;;) {\n        for (i = 0; i < nfds; ++i) {\n        TryAgain:\n          if (CheckInterrupt(m, false)) {\n            rc = eintr();\n            break;\n          }\n          fildes = Read32(gfds[i].fd);\n          LOCK(&m->system->fds.lock);\n          if ((fd = GetFd(&m->system->fds, fildes))) {\n            unassert(fd->cb);\n            unassert(poll_impl = fd->cb->poll);\n          } else {\n            poll_impl = 0;\n          }\n          UNLOCK(&m->system->fds.lock);\n          if (fd) {\n            hfds[0].fd = fildes;\n            ev = Read16(gfds[i].events);\n            hfds[0].events = (((ev & POLLIN_LINUX) ? POLLIN : 0) |\n                              ((ev & POLLOUT_LINUX) ? POLLOUT : 0) |\n                              ((ev & POLLPRI_LINUX) ? POLLPRI : 0));\n            switch (poll_impl(hfds, 1, 0)) {\n              case 0:\n                Write16(gfds[i].revents, 0);\n                break;\n              case 1:\n                ++rc;\n                ev = 0;\n                if (hfds[0].revents & POLLIN) ev |= POLLIN_LINUX;\n                if (hfds[0].revents & POLLPRI) ev |= POLLPRI_LINUX;\n                if (hfds[0].revents & POLLOUT) ev |= POLLOUT_LINUX;\n                if (hfds[0].revents & POLLERR) ev |= POLLERR_LINUX;\n                if (hfds[0].revents & POLLHUP) ev |= POLLHUP_LINUX;\n                if (hfds[0].revents & POLLNVAL) ev |= POLLERR_LINUX;\n                if (!ev) ev |= POLLERR_LINUX;\n                Write16(gfds[i].revents, ev);\n                break;\n              case -1:\n                if (errno == EINTR) {\n                  goto TryAgain;\n                }\n                ++rc;\n                Write16(gfds[i].revents, POLLERR_LINUX);\n                break;\n              default:\n                break;\n            }\n          } else {\n            Write16(gfds[i].revents, POLLNVAL_LINUX);\n          }\n        }\n        if (rc || CompareTime((now = GetTime()), deadline) >= 0) {\n          break;\n        }\n        wait = FromMilliseconds(kPollingMs);\n        remain = SubtractTime(deadline, now);\n        if (CompareTime(remain, wait) < 0) {\n          wait = remain;\n        }\n        nanosleep(&wait, 0);\n      }\n      if (rc != -1) {\n        CopyToUserWrite(m, fdsaddr, gfds, nfds * sizeof(*gfds));\n      }\n    } else {\n      rc = enomem();\n    }\n    return rc;\n  } else {\n    return einval();\n  }\n}\n\nstatic int SysPoll(struct Machine *m, i64 fdsaddr, u64 nfds, i32 timeout_ms) {\n  struct timespec deadline;\n  if (timeout_ms < 0) {\n    deadline = GetMaxTime();\n  } else {\n    deadline = AddTime(GetTime(), FromMilliseconds(timeout_ms));\n  }\n  return Poll(m, fdsaddr, nfds, deadline);\n}\n\nstatic int SysPpoll(struct Machine *m, i64 fdsaddr, u64 nfds, i64 timeoutaddr,\n                    i64 sigmaskaddr, u64 sigsetsize) {\n  int rc;\n  u64 oldmask = 0;\n  const struct sigset_linux *sm;\n  struct timespec_linux timeout_linux;\n  struct timespec now, timeout, remain, deadline;\n  if (sigmaskaddr) {\n    if (sigsetsize != 8) return einval();\n    if ((sm = (const struct sigset_linux *)SchlepR(m, sigmaskaddr,\n                                                   sizeof(*sm)))) {\n      oldmask = m->sigmask;\n      m->sigmask = Read64(sm->sigmask);\n      SIG_LOGF(\"sigmask push %\" PRIx64, m->sigmask);\n    } else {\n      return -1;\n    }\n  }\n  if (!CheckInterrupt(m, false)) {\n    if (timeoutaddr) {\n      if (LoadTimespecRW(m, timeoutaddr, &timeout) == -1) return -1;\n      deadline = AddTime(GetTime(), timeout);\n      rc = Poll(m, fdsaddr, nfds, deadline);\n      now = GetTime();\n      if (CompareTime(now, deadline) >= 0) {\n        remain = FromMilliseconds(0);\n      } else {\n        remain = SubtractTime(deadline, now);\n      }\n      Write64(timeout_linux.sec, remain.tv_sec);\n      Write64(timeout_linux.nsec, remain.tv_nsec);\n      CopyToUserWrite(m, timeoutaddr, &timeout_linux, sizeof(timeout_linux));\n    } else {\n      rc = Poll(m, fdsaddr, nfds, GetMaxTime());\n    }\n  } else {\n    rc = -1;\n  }\n  if (sigmaskaddr) {\n    m->sigmask = oldmask;\n    SIG_LOGF(\"sigmask pop %\" PRIx64, m->sigmask);\n  }\n  return rc;\n}\n\nstatic int SysSigprocmask(struct Machine *m, int how, i64 setaddr,\n                          i64 oldsetaddr, u64 sigsetsize) {\n  u64 set;\n  u8 word[8];\n  sigset_t ss;\n  const u8 *neu;\n  int sig, delivered;\n  if (sigsetsize != 8) {\n    return einval();\n  }\n  if (how != SIG_BLOCK_LINUX &&    //\n      how != SIG_UNBLOCK_LINUX &&  //\n      how != SIG_SETMASK_LINUX) {\n    return einval();\n  }\n  if (setaddr) {\n    if (!(neu = (const u8 *)SchlepR(m, setaddr, 8))) {\n      return -1;\n    }\n  } else {\n    neu = 0;\n  }\n  if (oldsetaddr) {\n    SIG_LOGF(\"sigmask read %\" PRIx64, m->sigmask);\n    Write64(word, m->sigmask);\n    if (CopyToUserWrite(m, oldsetaddr, word, 8) == -1) {\n      return -1;\n    }\n  }\n  if (setaddr) {\n    set = Read64(neu);\n    if (how == SIG_BLOCK_LINUX) {\n      m->sigmask |= set;\n    } else if (how == SIG_UNBLOCK_LINUX) {\n      m->sigmask &= ~set;\n    } else if (how == SIG_SETMASK_LINUX) {\n      m->sigmask = set;\n    } else {\n      __builtin_unreachable();\n    }\n    XlatLinuxToSigset(&ss, m->sigmask & ((u64)1 << (SIGTSTP_LINUX - 1) |\n                                         (u64)1 << (SIGTTIN_LINUX - 1) |\n                                         (u64)1 << (SIGTTOU_LINUX - 1)));\n    sigprocmask(SIG_BLOCK, &ss, 0);\n  }\n  Put64(m->ax, 0);\n  do {\n    if ((sig = ConsumeSignal(m, &delivered, 0))) {\n      TerminateSignal(m, sig, 0);\n    }\n  } while (delivered && DeliverSignalRecursively(m, delivered));\n  return 0;\n}\n\nstatic int SysSigpending(struct Machine *m, i64 setaddr) {\n  u8 word[8];\n  Write64(word, m->signals);\n  return CopyToUserWrite(m, setaddr, word, 8);\n}\n\nstatic int SysKill(struct Machine *m, int pid, int sig) {\n  return kill(pid, sig ? XlatSignal(sig) : 0);\n}\n\nstatic bool IsValidThreadId(struct System *s, int tid) {\n  return tid == s->pid ||\n         (kMinThreadId <= tid && tid < kMinThreadId + kMaxThreadIds);\n}\n\nstatic int SysTkill(struct Machine *m, int tid, int sig) {\n#if defined(HAVE_FORK) || defined(HAVE_THREADS)\n  bool found;\n  int rc, err;\n  if (tid < 0) return einval();\n  if (!(0 <= sig && sig <= 64)) {\n    LOGF(\"tkill(%d, %d) failed due to bogus signal\", tid, sig);\n    return einval();\n  }\n  // trigger signal immediately if possible\n  if (tid == m->tid) {\n    if (sig == SIGSTOP_LINUX || sig == SIGKILL_LINUX) {\n      return raise(XlatSignal(sig));\n    } else if (~m->sigmask & ((u64)1 << (sig - 1))) {\n      LOCK(&m->system->sig_lock);\n      switch (Read64(m->system->hands[sig - 1].handler)) {\n        case SIG_DFL_LINUX:\n          if (!IsSignalIgnoredByDefault(sig)) {\n            UNLOCK(&m->system->sig_lock);\n            TerminateSignal(m, sig, 0);\n            return 0;\n          }\n          // fallthrough\n        case SIG_IGN_LINUX:\n          rc = 0;\n          break;\n        default:\n          Put64(m->ax, 0);\n          m->interrupted = true;\n          DeliverSignal(m, sig, SI_TKILL_LINUX);\n          rc = -1;\n          break;\n      }\n      UNLOCK(&m->system->sig_lock);\n      return rc;\n    } else {\n      m->signals |= (u64)1 << (sig - 1);\n      return 0;\n    }\n  }\n  if (!IsValidThreadId(m->system, tid)) {\n    LOGF(\"tkill(%d, %d) failed due to bogus thread id\", tid, sig);\n    return esrch();\n  }\n  err = 0;\n  found = 0;\n#ifndef DISABLE_THREADS\n  {\n    struct Dll *e;\n    LOCK(&m->system->machines_lock);\n    for (e = dll_first(m->system->machines); e;\n         e = dll_next(m->system->machines, e)) {\n      struct Machine *m2;\n      m2 = MACHINE_CONTAINER(e);\n      if (m2->tid == tid) {\n        if (sig) {\n          EnqueueSignal(m2, sig);\n          err = pthread_kill(m2->thread, SIGSYS);\n        } else {\n          err = pthread_kill(m2->thread, 0);\n        }\n        found = true;\n        break;\n      }\n    }\n    UNLOCK(&m->system->machines_lock);\n  }\n#endif\n  if (!found) {\n    return SysKill(m, tid, sig);\n  }\n  if (!err) {\n    return 0;\n  } else {\n    errno = err;\n    return -1;\n  }\n#else\n  return SysKill(m, tid, sig);\n#endif /* HAVE_THREADS */\n}\n\nstatic int SysTgkill(struct Machine *m, int pid, int tid, int sig) {\n  if (pid < 1 || tid < 1) return einval();\n  if (pid != m->system->pid) return eperm();\n#ifdef HAVE_THREADS\n  return SysTkill(m, tid, sig);\n#else\n  if (tid != pid) return esrch();\n  return SysKill(m, tid, sig);\n#endif\n}\n\nstatic int SysPause(struct Machine *m) {\n  int rc;\n  NORESTART(rc, pause());\n  return rc;\n}\n\nstatic int SysSetsid(struct Machine *m) {\n  return setsid();\n}\n\nstatic i32 SysGetsid(struct Machine *m, i32 pid) {\n  return getsid(pid);\n}\n\nstatic int SysGetpid(struct Machine *m) {\n  return m->system->pid;\n}\n\nstatic int SysGettid(struct Machine *m) {\n  return m->tid;\n}\n\nstatic int SysGetppid(struct Machine *m) {\n  return getppid();\n}\n\nstatic int SysGetuid(struct Machine *m) {\n  return getuid();\n}\n\nstatic int SysGetgid(struct Machine *m) {\n  return getgid();\n}\n\nstatic int SysGeteuid(struct Machine *m) {\n  return geteuid();\n}\n\nstatic int SysGetegid(struct Machine *m) {\n  return getegid();\n}\n\nstatic i32 SysGetgroups(struct Machine *m, i32 size, i64 addr) {\n  gid_t *group;\n  u8 i32buf[4];\n  int i, ngroups;\n  long ngroups_max;\n  if (!size) {\n    return getgroups(0, 0);\n  } else {\n    // POSIX.1 recommends adding 1 to ngroups_max but the Linux manual\n    // says this can result in EINVAL. Apple M1 says NGROUPS_MAX is 16\n    // even though it usually returns 18 groups or more...\n#ifdef __APPLE__\n    ngroups_max = size;\n#else\n    ngroups_max = sysconf(_SC_NGROUPS_MAX);\n#endif\n    size = MIN(size, ngroups_max);\n    if (!IsValidMemory(m, addr, (size_t)size * 4, PROT_WRITE)) return -1;\n    if (!(group = (gid_t *)AddToFreeList(m, malloc(size * sizeof(gid_t))))) {\n      return -1;\n    }\n    if ((ngroups = getgroups(size, group)) != -1) {\n      for (i = 0; i < ngroups; ++i) {\n        Write32(i32buf, group[i]);\n        CopyToUserWrite(m, addr + (size_t)i * 4, i32buf, 4);\n      }\n    }\n    return ngroups;\n  }\n}\n\nstatic i32 SysSetgroups(struct Machine *m, i32 size, i64 addr) {\n#ifdef HAVE_SETGROUPS\n  int i;\n  gid_t *group;\n  const u8 *group_linux;\n  if (!(group_linux = (const u8 *)SchlepR(m, addr, (size_t)size * 4)) ||\n      !(group = (gid_t *)AddToFreeList(m, malloc(size * sizeof(gid_t))))) {\n    return -1;\n  }\n  for (i = 0; i < size; ++i) {\n    group[i] = Read32(group_linux + (size_t)i * 4);\n  }\n  return setgroups(size, group);\n#else\n  return enosys();\n#endif\n}\n\nstatic i32 SysSetresuid(struct Machine *m,  //\n                        u32 real,           //\n                        u32 effective,      //\n                        u32 saved) {\n#ifdef HAVE_SETRESUID\n  return setresuid(real, effective, saved);\n#elif defined(HAVE_SETREUID)\n  // we're going to assume \"saved uids\" don't exist if the platform\n  // doesn't provide the api for changing them. this lets us ignore\n  // complexity regarding how setruid() vs. setresuid() impact uids\n  return setreuid(real, effective);\n#else\n  if (real == -1 && effective == -1) return 0;\n  if (real == -1) return seteuid(effective);\n  if (real != effective) return enosys();\n  return setuid(real);\n#endif\n}\n\nstatic i32 SysSetresgid(struct Machine *m,  //\n                        u32 real,           //\n                        u32 effective,      //\n                        u32 saved) {\n#ifdef HAVE_SETRESGID\n  return setresgid(real, effective, saved);\n#elif defined(HAVE_SETREGID)\n  // we're going to assume \"saved gids\" don't exist if the platform\n  // doesn't provide the api for changing them. this lets us ignore\n  // complexity regarding how setrgid() vs. setresgid() impact gids\n  return setregid(real, effective);\n#else\n  if (real == -1 && effective == -1) return 0;\n  if (real == -1) return setegid(effective);\n  if (real != effective) return enosys();\n  return setgid(real);\n#endif\n}\n\nstatic int SysSetreuid(struct Machine *m, u32 real, u32 effective) {\n#ifdef HAVE_SETRESUID\n  // If the real user ID is set (i.e., ruid is not -1) or the effective\n  // user ID is set to a value not equal to the previous real user ID,\n  // the saved set-user-ID will be set to the new effective user ID.\n  // ──Quoth the Linux Programmer's Manual § setreuid()\n  if (real != -1 || (effective != -1 && effective != getuid())) {\n    if (effective == -1) effective = geteuid();\n    return setresuid(real, effective, effective);\n  } else {\n    return setresuid(real, effective, -1);\n  }\n#else\n  return SysSetresuid(m, real, effective, -1);\n#endif\n}\n\nstatic int SysSetregid(struct Machine *m, u32 real, u32 effective) {\n#ifdef HAVE_SETRESUID\n  if (real != -1 || (effective != -1 && effective != getgid())) {\n    if (effective == -1) effective = getegid();\n    return setresgid(real, effective, effective);\n  } else {\n    return setresgid(real, effective, -1);\n  }\n#else\n  return SysSetresgid(m, real, effective, -1);\n#endif\n}\n\nstatic i32 SysGetresuid(struct Machine *m,  //\n                        i64 realaddr,       //\n                        i64 effectiveaddr,  //\n                        i64 savedaddr) {\n  u8 *real = 0;\n  u8 *saved = 0;\n  u8 *effective = 0;\n  uid_t uid, euid, suid;\n  if ((realaddr && !(real = (u8 *)SchlepW(m, realaddr, 4))) ||\n      (savedaddr && !(saved = (u8 *)SchlepW(m, savedaddr, 4))) ||\n      (effectiveaddr && !(effective = (u8 *)SchlepW(m, effectiveaddr, 4)))) {\n    return -1;\n  }\n#ifdef HAVE_SETRESUID\n  if (getresuid(&uid, &euid, &suid) == -1) return -1;\n#else\n  uid = getuid();\n  euid = geteuid();\n  suid = euid;\n#endif\n  if (real) Write32(real, uid);\n  if (saved) Write32(saved, suid);\n  if (effective) Write32(effective, euid);\n  return 0;\n}\n\nstatic i32 SysGetresgid(struct Machine *m,  //\n                        i64 realaddr,       //\n                        i64 effectiveaddr,  //\n                        i64 savedaddr) {\n  u8 *real = 0;\n  u8 *saved = 0;\n  u8 *effective = 0;\n  gid_t gid, egid, sgid;\n  if ((realaddr && !(real = (u8 *)SchlepW(m, realaddr, 4))) ||\n      (savedaddr && !(saved = (u8 *)SchlepW(m, savedaddr, 4))) ||\n      (effectiveaddr && !(effective = (u8 *)SchlepW(m, effectiveaddr, 4)))) {\n    return -1;\n  }\n#ifdef HAVE_SETRESUID\n  if (getresgid(&gid, &egid, &sgid) == -1) return -1;\n#else\n  gid = getgid();\n  egid = getegid();\n  sgid = egid;\n#endif\n  if (real) Write32(real, gid);\n  if (saved) Write32(saved, sgid);\n  if (effective) Write32(effective, egid);\n  return 0;\n}\n\nstatic int SysSchedYield(struct Machine *m) {\n#ifdef HAVE_SCHED_YIELD\n  return sched_yield();\n#else\n  return 0;\n#endif\n}\n\nstatic int SysUmask(struct Machine *m, int mask) {\n  return umask(mask);\n}\n\nstatic int SysSetuid(struct Machine *m, int uid) {\n  return setuid(uid);\n}\n\nstatic int SysSetgid(struct Machine *m, int gid) {\n  return setgid(gid);\n}\n\nstatic int SysGetpgid(struct Machine *m, int pid) {\n  return getpgid(pid);\n}\n\nstatic int SysGetpgrp(struct Machine *m) {\n  return getpgid(0);\n}\n\nstatic int SysAlarm(struct Machine *m, unsigned seconds) {\n  return alarm(seconds);\n}\n\nstatic int SysSetpgid(struct Machine *m, int pid, int gid) {\n  return setpgid(pid, gid);\n}\n\nstatic int SysCreat(struct Machine *m, i64 path, int mode) {\n  return SysOpenat(m, AT_FDCWD_LINUX, path,\n                   O_WRONLY_LINUX | O_CREAT_LINUX | O_TRUNC_LINUX, mode);\n}\n\nstatic int SysAccess(struct Machine *m, i64 path, int mode) {\n  return SysFaccessat(m, AT_FDCWD_LINUX, path, mode);\n}\n\nstatic int SysStat(struct Machine *m, i64 path, i64 st) {\n  return SysFstatat(m, AT_FDCWD_LINUX, path, st, 0);\n}\n\nstatic int SysLstat(struct Machine *m, i64 path, i64 st) {\n  return SysFstatat(m, AT_FDCWD_LINUX, path, st, AT_SYMLINK_NOFOLLOW_LINUX);\n}\n\nstatic int SysOpen(struct Machine *m, i64 path, int flags, int mode) {\n  return SysOpenat(m, AT_FDCWD_LINUX, path, flags, mode);\n}\n\nstatic int SysAccept(struct Machine *m, int fd, i64 sa, i64 sas) {\n  return SysAccept4(m, fd, sa, sas, 0);\n}\n\nstatic int SysSchedSetparam(struct Machine *m, int pid, i64 paramaddr) {\n  if (pid < 0 || !paramaddr) return einval();\n  return 0;\n}\n\nstatic int SysSchedGetparam(struct Machine *m, int pid, i64 paramaddr) {\n  u8 param[8];\n  if (pid < 0 || !paramaddr) return einval();\n  Write32(param, 0);\n  CopyToUserWrite(m, paramaddr, param, 8);\n  return 0;\n}\n\nstatic int SysSchedSetscheduler(struct Machine *m, int pid, int policy,\n                                i64 paramaddr) {\n  if (pid < 0 || !paramaddr) return einval();\n  return 0;\n}\n\nstatic int SysSchedGetscheduler(struct Machine *m, int pid) {\n  if (pid < 0) return einval();\n  return SCHED_OTHER_LINUX;\n}\n\nstatic int SysSchedGetPriorityMax(struct Machine *m, int policy) {\n  return 0;\n}\n\nstatic int SysSchedGetPriorityMin(struct Machine *m, int policy) {\n  return 0;\n}\n\nstatic int SysPipe(struct Machine *m, i64 pipefds_addr) {\n  return SysPipe2(m, pipefds_addr, 0);\n}\n\n#ifdef HAVE_EPOLL_PWAIT1\n\nstatic i32 SysEpollCreate1(struct Machine *m, i32 flags) {\n  int lim, fildes, oflags, sysflags;\n  oflags = 0;\n  sysflags = 0;\n  if (flags & EPOLL_CLOEXEC_LINUX) {\n    oflags |= O_CLOEXEC;\n    sysflags |= EPOLL_CLOEXEC;\n    flags &= ~EPOLL_CLOEXEC_LINUX;\n  }\n  if (flags) {\n    LOGF(\"unsupported %s flags: %#x\", \"epoll_create1\", flags);\n    return einval();\n  }\n  if (!(lim = GetFileDescriptorLimit(m->system))) return emfile();\n  if ((fildes = epoll_create1(sysflags)) != -1) {\n    if (fildes >= lim) {\n      close(fildes);\n      fildes = emfile();\n    } else {\n      LOCK(&m->system->fds.lock);\n      unassert(AddFd(&m->system->fds, fildes, oflags));\n      UNLOCK(&m->system->fds.lock);\n    }\n  }\n  return fildes;\n}\n\nstatic i32 SysEpollCreate(struct Machine *m, i32 size) {\n  if (size <= 0) return einval();\n  return SysEpollCreate1(m, 0);\n}\n\nstatic i32 SysEpollCtl(struct Machine *m, i32 epfd, i32 op, i32 fd,\n                       i64 eventaddr) {\n  struct epoll_event epe, *pepe;\n  const struct epoll_event_linux *gepe;\n  switch (op) {\n    case EPOLL_CTL_DEL_LINUX:\n      pepe = 0;\n      break;\n    case EPOLL_CTL_ADD_LINUX:\n    case EPOLL_CTL_MOD_LINUX:\n      if (!(gepe = (const struct epoll_event_linux *)SchlepR(m, eventaddr,\n                                                             sizeof(*gepe)))) {\n        return -1;\n      }\n      epe.events = Read32(gepe->events);\n      epe.data.u64 = Read64(gepe->data);\n      pepe = &epe;\n      break;\n    default:\n      return einval();\n  }\n  return epoll_ctl(epfd, op, fd, pepe);\n}\n\nstatic i32 EpollPwait(struct Machine *m, i32 epfd, i64 eventsaddr,\n                      i32 maxevents, struct timespec deadline, i64 sigmaskaddr,\n                      u64 sigsetsize) {\n  i32 i, rc;\n  u64 oldmask_guest = 0;\n  sigset_t block, oldmask;\n  struct epoll_event *events;\n  struct timespec now, waitfor;\n  struct epoll_event_linux *gevents;\n  const struct sigset_linux *sigmaskp_guest = 0;\n  if (maxevents <= 0) return einval();\n  if (sigmaskaddr) {\n    if (sigsetsize != 8) return einval();\n    if (!(sigmaskp_guest = (const struct sigset_linux *)SchlepR(\n              m, sigmaskaddr, sizeof(*sigmaskp_guest)))) {\n      return -1;\n    }\n  }\n  if (!IsValidMemory(m, eventsaddr,\n                     maxevents * sizeof(struct epoll_event_linux),\n                     PROT_WRITE) ||\n      !(events = (struct epoll_event *)AddToFreeList(\n            m, calloc(maxevents, sizeof(struct epoll_event)))) ||\n      !(gevents = (struct epoll_event_linux *)AddToFreeList(\n            m, calloc(maxevents, sizeof(struct epoll_event_linux))))) {\n    return -1;\n  }\n  unassert(!sigfillset(&block));\n  unassert(!pthread_sigmask(SIG_BLOCK, &block, &oldmask));\n  if (sigmaskp_guest) {\n    oldmask_guest = m->sigmask;\n    m->sigmask = Read64(sigmaskp_guest->sigmask);\n    SIG_LOGF(\"sigmask push %\" PRIx64, m->sigmask);\n  }\n  if (!CheckInterrupt(m, false)) {\n    do {\n      now = GetTime();\n      if (CompareTime(now, deadline) < 0) {\n        waitfor = SubtractTime(deadline, now);\n      } else {\n        waitfor = GetZeroTime();\n      }\n#if defined(HAVE_EPOLL_PWAIT2) && !defined(MUSL_CROSS_MAKE)\n      rc = epoll_pwait2(epfd, events, maxevents, &waitfor, &oldmask);\n#else\n      rc = epoll_pwait(epfd, events, maxevents,\n                       ConvertTimeToInt(ToMilliseconds(waitfor)), &oldmask);\n#endif\n      if (rc == -1 && errno == EINTR) {\n        if (CheckInterrupt(m, false)) {\n          break;\n        }\n      } else {\n        break;\n      }\n    } while (1);\n  } else {\n    rc = -1;\n  }\n  if (sigmaskp_guest) {\n    m->sigmask = oldmask_guest;\n    SIG_LOGF(\"sigmask pop %\" PRIx64, m->sigmask);\n  }\n  unassert(!pthread_sigmask(SIG_SETMASK, &oldmask, 0));\n  if (rc != -1) {\n    for (i = 0; i < rc; ++i) {\n      Write32(gevents[i].events, events[i].events);\n      Write64(gevents[i].data, events[i].data.u64);\n    }\n    unassert(!CopyToUserWrite(m, eventsaddr, gevents,\n                              rc * sizeof(struct epoll_event_linux)));\n  }\n  return rc;\n}\n\nstatic i32 SysEpollPwait(struct Machine *m, i32 epfd, i64 eventsaddr,\n                         i32 maxevents, i32 timeout, i64 sigmaskaddr,\n                         u64 sigsetsize) {\n  struct timespec deadline;\n  if (timeout >= 0) {\n    deadline = AddTime(GetTime(), FromMilliseconds(timeout));\n  } else {\n    deadline = GetMaxTime();\n  }\n  return EpollPwait(m, epfd, eventsaddr, maxevents, deadline, sigmaskaddr,\n                    sigsetsize);\n}\n\nstatic i32 SysEpollPwait2(struct Machine *m, i32 epfd, i64 eventsaddr,\n                          i32 maxevents, i64 timeoutaddr, i64 sigmaskaddr,\n                          u64 sigsetsize) {\n  struct timespec ts, deadline;\n  if (timeoutaddr) {\n    if (LoadTimespecR(m, timeoutaddr, &ts) == -1) return -1;\n    deadline = AddTime(GetTime(), ts);\n  } else {\n    deadline = GetMaxTime();\n  }\n  return EpollPwait(m, epfd, eventsaddr, maxevents, deadline, sigmaskaddr,\n                    sigsetsize);\n}\n\nstatic int SysEpollWait(struct Machine *m, i32 epfd, i64 eventsaddr,\n                        i32 maxevents, i32 timeout) {\n  return SysEpollPwait(m, epfd, eventsaddr, maxevents, timeout, 0, 8);\n}\n\n#endif /* HAVE_EPOLL_PWAIT1 */\n\nvoid OpSyscall(P) {\n  size_t mark;\n  u64 ax, di, si, dx, r0, r8, r9;\n  unassert(!m->nofault);\n  if (Get64(m->ax) == 0xE4) {\n    // clock_gettime() is\n    //   1) called frequently,\n    //   2) latency sensitive, and\n    //   3) usually implemented as a VDSO.\n    // Therefore we exempt it from system call tracing.\n    ax = SysClockGettime(m, Get64(m->di), Get64(m->si));\n    Put64(m->ax, ax != -1 ? ax : -(XlatErrno(errno) & 0xfff));\n    return;\n  }\n  STATISTIC(++syscalls);\n  // make sure blinkenlights display is up to date before performing any\n  // potentially blocking operations which would otherwise freeze things\n  if (m->system->redraw && m->tid == m->system->pid) {\n    m->system->redraw(true);\n  }\n  // unlike pure opcodes where we'll confidently longjmp out of segfault\n  // handlers, system calls are too complex to do that safely, and it is\n  // therefore of the highest importance that they never crash under any\n  // circumstances. in order to do ensure that we need to lock any pages\n  // the system call accesses, so the user can't munmap() them away from\n  // some other thread. since we don't want to slow down instructions by\n  // adding locking logic to the tranlation lookaside buffer, we need to\n  // ensure any memory references the system call performs will tlb miss\n  m->insyscall = true;\n  if (!m->sysdepth++) {\n    atomic_store_explicit(&m->invalidated, true, memory_order_relaxed);\n  }\n  // to make system calls simpler and safer, any temporary memory that's\n  // allocated will be added to a free list to be collected later. since\n  // OpSyscall() is potentially recursive when SA_RESTART signals happen\n  // we need to save the current mark, so we don't collect parent's data\n  mark = m->freelist.n;\n  m->interrupted = false;\n  ax = Get64(m->ax);\n  di = Get64(m->di);\n  si = Get64(m->si);\n  dx = Get64(m->dx);\n  r0 = Get64(m->r10);\n  r8 = Get64(m->r8);\n  r9 = Get64(m->r9);\n  switch (ax & 0xfff) {\n    SYSCALL(3, 0x000, \"read\", SysRead, STRACE_READ);\n    SYSCALL(3, 0x001, \"write\", SysWrite, STRACE_WRITE);\n    SYSCALL(3, 0x002, \"open\", SysOpen, STRACE_OPEN);\n    SYSCALL(1, 0x003, \"close\", SysClose, STRACE_CLOSE);\n    SYSCALL(2, 0x004, \"stat\", SysStat, STRACE_STAT);\n    SYSCALL(2, 0x005, \"fstat\", SysFstat, STRACE_FSTAT);\n    SYSCALL(2, 0x006, \"lstat\", SysLstat, STRACE_LSTAT);\n    SYSCALL(3, 0x007, \"poll\", SysPoll, STRACE_3);\n    SYSCALL(3, 0x008, \"lseek\", SysLseek, STRACE_LSEEK);\n    SYSCALL(6, 0x009, \"mmap\", SysMmap, STRACE_MMAP);\n    SYSCALL(4, 0x011, \"pread\", SysPread, STRACE_PREAD);\n    SYSCALL(4, 0x012, \"pwrite\", SysPwrite, STRACE_PWRITE);\n    SYSCALL(5, 0x017, \"select\", SysSelect, STRACE_SELECT);\n    SYSCALL(5, 0x019, \"mremap\", SysMremap, STRACE_5);\n    SYSCALL(6, 0x10E, \"pselect6\", SysPselect, STRACE_6);\n    SYSCALL(3, 0x01A, \"msync\", SysMsync, STRACE_3);\n    SYSCALL(3, 0x00A, \"mprotect\", SysMprotect, STRACE_MPROTECT);\n    SYSCALL(2, 0x00B, \"munmap\", SysMunmap, STRACE_MUNMAP);\n    SYSCALL(4, 0x00D, \"rt_sigaction\", SysSigaction, STRACE_SIGACTION);\n    SYSCALL(4, 0x00E, \"rt_sigprocmask\", SysSigprocmask, STRACE_SIGPROCMASK);\n    SYSCALL(3, 0x010, \"ioctl\", SysIoctl, STRACE_3);\n    SYSCALL(3, 0x013, \"readv\", SysReadv, STRACE_READV);\n    SYSCALL(3, 0x014, \"writev\", SysWritev, STRACE_WRITEV);\n    SYSCALL(2, 0x015, \"access\", SysAccess, STRACE_ACCESS);\n    SYSCALL(3, 0x10D, \"faccessat\", SysFaccessat, STRACE_FACCESSAT);\n    SYSCALL(4, 0x1b7, \"faccessat2\", SysFaccessat2, STRACE_FACCESSAT2);\n    SYSCALL(0, 0x018, \"sched_yield\", SysSchedYield, STRACE_0);\n    SYSCALL(3, 0x01C, \"madvise\", SysMadvise, STRACE_3);\n    SYSCALL(1, 0x020, \"dup\", SysDup1, STRACE_DUP);\n    SYSCALL(2, 0x021, \"dup2\", SysDup2, STRACE_DUP2);\n    SYSCALL(0, 0x022, \"pause\", SysPause, STRACE_PAUSE);\n    SYSCALL(2, 0x023, \"nanosleep\", SysNanosleep, STRACE_NANOSLEEP);\n    SYSCALL(2, 0x024, \"getitimer\", SysGetitimer, STRACE_2);\n    SYSCALL(1, 0x025, \"alarm\", SysAlarm, STRACE_ALARM);\n    SYSCALL(3, 0x026, \"setitimer\", SysSetitimer, STRACE_3);\n    SYSCALL(0, 0x027, \"getpid\", SysGetpid, STRACE_GETPID);\n    SYSCALL(0, 0x0BA, \"gettid\", SysGettid, STRACE_GETTID);\n    SYSCALL(1, 0x03F, \"uname\", SysUname, STRACE_1);\n    SYSCALL(3, 0x048, \"fcntl\", SysFcntl, STRACE_FCNTL);\n    SYSCALL(2, 0x049, \"flock\", SysFlock, STRACE_2);\n    SYSCALL(1, 0x04A, \"fsync\", SysFsync, STRACE_FSYNC);\n    SYSCALL(1, 0x04B, \"fdatasync\", SysFdatasync, STRACE_FDATASYNC);\n    SYSCALL(2, 0x04C, \"truncate\", SysTruncate, STRACE_TRUNCATE);\n    SYSCALL(2, 0x04D, \"ftruncate\", SysFtruncate, STRACE_FTRUNCATE);\n    SYSCALL(2, 0x04F, \"getcwd\", SysGetcwd, STRACE_GETCWD);\n    SYSCALL(1, 0x050, \"chdir\", SysChdir, STRACE_CHDIR);\n    SYSCALL(1, 0x051, \"fchdir\", SysFchdir, STRACE_FCHOWN);\n    SYSCALL(2, 0x052, \"rename\", SysRename, STRACE_RENAME);\n    SYSCALL(2, 0x053, \"mkdir\", SysMkdir, STRACE_MKDIR);\n    SYSCALL(1, 0x054, \"rmdir\", SysRmdir, STRACE_RMDIR);\n    SYSCALL(2, 0x055, \"creat\", SysCreat, STRACE_CREAT);\n    SYSCALL(2, 0x056, \"link\", SysLink, STRACE_LINK);\n    SYSCALL(1, 0x057, \"unlink\", SysUnlink, STRACE_UNLINK);\n    SYSCALL(2, 0x058, \"symlink\", SysSymlink, STRACE_SYMLINK);\n    SYSCALL(3, 0x059, \"readlink\", SysReadlink, STRACE_READLINK);\n    SYSCALL(2, 0x05A, \"chmod\", SysChmod, STRACE_CHMOD);\n    SYSCALL(2, 0x05B, \"fchmod\", SysFchmod, STRACE_FCHOWN);\n    SYSCALL(3, 0x05C, \"chown\", SysChown, STRACE_CHOWN);\n    SYSCALL(3, 0x05D, \"fchown\", SysFchown, STRACE_FCHOWN);\n    SYSCALL(3, 0x05E, \"lchown\", SysLchown, STRACE_LCHOWN);\n    SYSCALL(5, 0x104, \"fchownat\", SysFchownat, STRACE_CHOWNAT);\n    SYSCALL(1, 0x05F, \"umask\", SysUmask, STRACE_UMASK);\n    SYSCALL(2, 0x060, \"gettimeofday\", SysGettimeofday, STRACE_2);\n    SYSCALL(2, 0x061, \"getrlimit\", SysGetrlimit, STRACE_GETRLIMIT);\n    SYSCALL(2, 0x062, \"getrusage\", SysGetrusage, STRACE_2);\n    SYSCALL(1, 0x064, \"times\", SysTimes, STRACE_1);\n    SYSCALL(0, 0x06F, \"getpgrp\", SysGetpgrp, STRACE_GETPGRP);\n    SYSCALL(0, 0x070, \"setsid\", SysSetsid, STRACE_SETSID);\n    SYSCALL(2, 0x073, \"getgroups\", SysGetgroups, STRACE_2);\n    SYSCALL(1, 0x079, \"getpgid\", SysGetpgid, STRACE_GETPGID);\n    SYSCALL(1, 0x07C, \"getsid\", SysGetsid, STRACE_1);\n    SYSCALL(1, 0x07F, \"rt_sigpending\", SysSigpending, STRACE_1);\n    SYSCALL(2, 0x089, \"statfs\", SysStatfs, STRACE_2);\n    SYSCALL(2, 0x08A, \"fstatfs\", SysFstatfs, STRACE_2);\n    SYSCALL(2, 0x06D, \"setpgid\", SysSetpgid, STRACE_2);\n    SYSCALL(0, 0x066, \"getuid\", SysGetuid, STRACE_GETUID);\n    SYSCALL(0, 0x068, \"getgid\", SysGetgid, STRACE_GETGID);\n    SYSCALL(1, 0x069, \"setuid\", SysSetuid, STRACE_SETUID);\n    SYSCALL(1, 0x06A, \"setgid\", SysSetgid, STRACE_SETGID);\n    SYSCALL(0, 0x06B, \"geteuid\", SysGeteuid, STRACE_GETEUID);\n    SYSCALL(0, 0x06C, \"getegid\", SysGetegid, STRACE_GETEGID);\n    SYSCALL(0, 0x06E, \"getppid\", SysGetppid, STRACE_GETPPID);\n    SYSCALL(2, 0x071, \"setreuid\", SysSetreuid, STRACE_SETREUID);\n    SYSCALL(2, 0x072, \"setregid\", SysSetregid, STRACE_SETREGID);\n    SYSCALL(2, 0x082, \"rt_sigsuspend\", SysSigsuspend, STRACE_SIGSUSPEND);\n    SYSCALL(2, 0x083, \"sigaltstack\", SysSigaltstack, STRACE_2);\n    SYSCALL(3, 0x085, \"mknod\", SysMknod, STRACE_3);\n    SYSCALL(2, 0x09E, \"arch_prctl\", SysArchPrctl, STRACE_2);\n    SYSCALL(2, 0x0A0, \"setrlimit\", SysSetrlimit, STRACE_SETRLIMIT);\n    SYSCALL(0, 0x0A2, \"sync\", SysSync, STRACE_SYNC);\n    SYSCALL(3, 0x0D9, \"getdents\", SysGetdents, STRACE_3);\n    SYSCALL(1, 0x0DA, \"set_tid_address\", SysSetTidAddress, STRACE_1);\n    SYSCALL(4, 0x0DD, \"fadvise\", SysFadvise, STRACE_4);\n#ifdef HAVE_CLOCK_SETTIME\n    SYSCALL(2, 0x0E3, \"clock_settime\", SysClockSettime, STRACE_2);\n#endif\n    SYSCALL(2, 0x0E5, \"clock_getres\", SysClockGetres, STRACE_2);\n    SYSCALL(4, 0x0E6, \"clock_nanosleep\", SysClockNanosleep, STRACE_CLOCK_SLEEP);\n    SYSCALL(2, 0x084, \"utime\", SysUtime, STRACE_2);\n    SYSCALL(2, 0x0EB, \"utimes\", SysUtimes, STRACE_2);\n    SYSCALL(3, 0x105, \"futimesat\", SysFutimesat, STRACE_3);\n    SYSCALL(4, 0x118, \"utimensat\", SysUtimensat, STRACE_UTIMENSAT);\n    SYSCALL(4, 0x101, \"openat\", SysOpenat, STRACE_OPENAT);\n    SYSCALL(3, 0x102, \"mkdirat\", SysMkdirat, STRACE_MKDIRAT);\n    SYSCALL(4, 0x106, \"fstatat\", SysFstatat, STRACE_FSTATAT);\n    SYSCALL(3, 0x107, \"unlinkat\", SysUnlinkat, STRACE_UNLINKAT);\n    SYSCALL(4, 0x108, \"renameat\", SysRenameat, STRACE_RENAMEAT);\n    SYSCALL(5, 0x109, \"linkat\", SysLinkat, STRACE_LINKAT);\n    SYSCALL(3, 0x10A, \"symlinkat\", SysSymlinkat, STRACE_SYMLINKAT);\n    SYSCALL(4, 0x10B, \"readlinkat\", SysReadlinkat, STRACE_READLINKAT);\n    SYSCALL(3, 0x10C, \"fchmodat\", SysFchmodat, STRACE_FCHMODAT);\n#ifndef DISABLE_SOCKETS\n    SYSCALL(3, 0x029, \"socket\", SysSocket, STRACE_SOCKET);\n    SYSCALL(3, 0x02A, \"connect\", SysConnect, STRACE_CONNECT);\n    SYSCALL(3, 0x02B, \"accept\", SysAccept, STRACE_ACCEPT);\n    SYSCALL(4, 0x120, \"accept4\", SysAccept4, STRACE_ACCEPT4);\n    SYSCALL(6, 0x02C, \"sendto\", SysSendto, STRACE_SENDTO);\n    SYSCALL(6, 0x02D, \"recvfrom\", SysRecvfrom, STRACE_RECVFROM);\n    SYSCALL(3, 0x02E, \"sendmsg\", SysSendmsg, STRACE_3);\n    SYSCALL(3, 0x02F, \"recvmsg\", SysRecvmsg, STRACE_3);\n#ifndef DISABLE_NONPOSIX\n    SYSCALL(4, 0x133, \"sendmmsg\", SysSendmmsg, STRACE_4);\n    SYSCALL(5, 0x12B, \"recvmmsg\", SysRecvmmsg, STRACE_5);\n#endif\n    SYSCALL(2, 0x030, \"shutdown\", SysShutdown, STRACE_2);\n    SYSCALL(3, 0x031, \"bind\", SysBind, STRACE_BIND);\n    SYSCALL(2, 0x032, \"listen\", SysListen, STRACE_LISTEN);\n    SYSCALL(3, 0x033, \"getsockname\", SysGetsockname, STRACE_GETSOCKNAME);\n    SYSCALL(3, 0x034, \"getpeername\", SysGetpeername, STRACE_GETPEERNAME);\n    SYSCALL(5, 0x036, \"setsockopt\", SysSetsockopt, STRACE_5);\n    SYSCALL(5, 0x037, \"getsockopt\", SysGetsockopt, STRACE_5);\n#endif /* DISABLE_SOCKETS */\n#ifdef HAVE_FORK\n    SYSCALL(0, 0x039, \"fork\", SysFork, STRACE_FORK);\n#ifndef DISABLE_NONPOSIX\n    SYSCALL(0, 0x03A, \"vfork\", SysVfork, STRACE_VFORK);\n#endif\n    SYSCALL(4, 0x03D, \"wait4\", SysWait4, STRACE_WAIT4);\n    SYSCALL(2, 0x03E, \"kill\", SysKill, STRACE_KILL);\n#endif /* HAVE_FORK */\n#ifdef HAVE_THREADS\n    SYSCALL(6, 0x0CA, \"futex\", SysFutex, STRACE_FUTEX);\n#endif\n#if defined(HAVE_FORK) || defined(HAVE_THREADS)\n    SYSCALL(1, 0x016, \"pipe\", SysPipe, STRACE_PIPE);\n#ifndef DISABLE_NONPOSIX\n    SYSCALL(2, 0x125, \"pipe2\", SysPipe2, STRACE_PIPE2);\n#endif\n    SYSCALL(6, 0x038, \"clone\", SysClone, STRACE_CLONE);\n    SYSCALL(2, 0x0C8, \"tkill\", SysTkill, STRACE_TKILL);\n    SYSCALL(3, 0x0EA, \"tgkill\", SysTgkill, STRACE_3);\n    SYSCALL(3, 0x03B, \"execve\", SysExecve, STRACE_3);\n    SYSCALL(4, 0x035, \"socketpair\", SysSocketpair, STRACE_SOCKETPAIR);\n    SYSCALL(2, 0x111, \"set_robust_list\", SysSetRobustList, STRACE_2);\n    SYSCALL(3, 0x112, \"get_robust_list\", SysGetRobustList, STRACE_3);\n    SYSCALL(2, 0x08C, \"getpriority\", SysGetpriority, STRACE_2);\n    SYSCALL(3, 0x08D, \"setpriority\", SysSetpriority, STRACE_3);\n    SYSCALL(2, 0x08E, \"sched_set_param\", SysSchedSetparam, STRACE_2);\n    SYSCALL(2, 0x08F, \"sched_get_param\", SysSchedGetparam, STRACE_2);\n    SYSCALL(3, 0x090, \"sched_set_scheduler\", SysSchedSetscheduler, STRACE_3);\n    SYSCALL(1, 0x091, \"sched_get_scheduler\", SysSchedGetscheduler, STRACE_1);\n    SYSCALL(1, 0x092, \"sched_get_priority_max\", SysSchedGetPriorityMax,\n            STRACE_1);\n    SYSCALL(1, 0x093, \"sched_get_priority_min\", SysSchedGetPriorityMin,\n            STRACE_1);\n#ifndef DISABLE_NONPOSIX\n    SYSCALL(3, 0x0CB, \"sched_set_affinity\", SysSchedSetaffinity, STRACE_3);\n#endif\n#endif /* defined(HAVE_FORK) || defined(HAVE_THREADS) */\n#ifndef DISABLE_NONPOSIX\n    SYSCALL(4, 0x028, \"sendfile\", SysSendfile, STRACE_4);\n    SYSCALL(3, 0x0CC, \"sched_get_affinity\", SysSchedGetaffinity, STRACE_3);\n    SYSCALL(1, 0x00C, \"brk\", SysBrk, STRACE_1);\n    SYSCALL(1, 0x063, \"sysinfo\", SysSysinfo, STRACE_1);\n    SYSCALL(2, 0x074, \"setgroups\", SysSetgroups, STRACE_2);\n    SYSCALL(3, 0x075, \"setresuid\", SysSetresuid, STRACE_SETRESUID);\n    SYSCALL(3, 0x076, \"getresuid\", SysGetresuid, STRACE_3);\n    SYSCALL(3, 0x077, \"setresgid\", SysSetresgid, STRACE_SETRESGID);\n    SYSCALL(3, 0x078, \"getresgid\", SysGetresgid, STRACE_3);\n    SYSCALL(5, 0x09D, \"prctl\", SysPrctl, STRACE_5);\n#if !defined(DISABLE_OVERLAYS) || !defined(DISABLE_VFS)\n    SYSCALL(1, 0x0A1, \"chroot\", SysChroot, STRACE_CHROOT);\n#endif\n#ifndef DISABLE_VFS\n    SYSCALL(5, 0x0A5, \"mount\", SysMount, STRACE_MOUNT);\n#endif\n    SYSCALL(3, 0x124, \"dup3\", SysDup3, STRACE_DUP3);\n    SYSCALL(4, 0x103, \"mknodat\", SysMknodat, STRACE_4);\n    SYSCALL(4, 0x127, \"preadv\", SysPreadv, STRACE_PREADV);\n    SYSCALL(4, 0x128, \"pwritev\", SysPwritev, STRACE_PWRITEV);\n    SYSCALL(4, 0x12E, \"prlimit\", SysPrlimit, STRACE_PRLIMIT);\n    SYSCALL(5, 0x10F, \"ppoll\", SysPpoll, STRACE_5);\n    SYSCALL(5, 0x13C, \"renameat2\", SysRenameat2, STRACE_RENAMEAT2);\n    SYSCALL(3, 0x13E, \"getrandom\", SysGetrandom, STRACE_GETRANDOM);\n    SYSCALL(5, 0x147, \"preadv2\", SysPreadv2, STRACE_PREADV2);\n    SYSCALL(5, 0x148, \"pwritev2\", SysPwritev2, STRACE_PWRITEV2);\n    SYSCALL(3, 0x1B4, \"close_range\", SysCloseRange, STRACE_3);\n#ifdef HAVE_EPOLL_PWAIT1\n    SYSCALL(1, 0x0D5, \"epoll_create\", SysEpollCreate, STRACE_1);\n    SYSCALL(1, 0x123, \"epoll_create1\", SysEpollCreate1, STRACE_1);\n    SYSCALL(4, 0x0E9, \"epoll_ctl\", SysEpollCtl, STRACE_4);\n    SYSCALL(4, 0x0E8, \"epoll_wait\", SysEpollWait, STRACE_4);\n    SYSCALL(6, 0x119, \"epoll_pwait\", SysEpollPwait, STRACE_6);\n    SYSCALL(6, 0x1B9, \"epoll_pwait2\", SysEpollPwait2, STRACE_6);\n#endif /* HAVE_EPOLL_PWAIT1 */\n#endif /* DISABLE_NONPOSIX */\n    case 0x3C:\n      SYS_LOGF(\"%s(%#\" PRIx64 \")\", \"exit\", di);\n      SysExit(m, di);\n    case 0xE7:\n      SYS_LOGF(\"%s(%#\" PRIx64 \")\", \"exit_group\", di);\n      SysExitGroup(m, di);\n    case 0x00F:\n      SigRestore(m);\n      m->interrupted = true;  // preevnt ax clobber\n      break;\n    case 0x146:\n      // avoid noisy copy_file_range() feature check in cosmo\n    case 0x1BC:\n      // avoid noisy landlock_create_ruleset() feature check in cosmo\n    case 0x500:\n      // Cosmopolitan uses this number to trigger ENOSYS for testing.\n      if (!m->system->iscosmo) goto DefaultCase;\n      ax = enosys();\n      break;\n    case 0x0C9:\n      // time() is also noisy in some environments.\n      ax = SysTime(m, di);\n      break;\n    default:\n    DefaultCase:\n      LOGF(\"missing syscall 0x%03\" PRIx64, ax);\n      ax = enosys();\n      break;\n  }\n  if (!m->interrupted) {\n    Put64(m->ax, ax != -1 ? ax : -(XlatErrno(errno) & 0xfff));\n  }\n  unassert(--m->sysdepth >= 0);\n  CollectPageLocks(m);\n  unassert(!m->pagelocks.i || m->sysdepth);\n  CollectGarbage(m, mark);\n  m->insyscall = false;\n}\n"
  },
  {
    "path": "blink/syscall.h",
    "content": "#ifndef BLINK_SYSCALL_H_\n#define BLINK_SYSCALL_H_\n#include <fcntl.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/fds.h\"\n#include \"blink/machine.h\"\n#include \"blink/ndelay.h\"\n#include \"blink/types.h\"\n\n#ifdef O_ASYNC\n#define O_ASYNC_SETFL O_ASYNC\n#else\n#define O_ASYNC_SETFL 0\n#endif\n#ifdef O_DIRECT\n#define O_DIRECT_SETFL O_DIRECT\n#else\n#define O_DIRECT_SETFL 0\n#endif\n#ifdef O_NOATIME\n#define O_NOATIME_SETFL O_NOATIME\n#else\n#define O_NOATIME_SETFL 0\n#endif\n\n#define SETFL_FLAGS \\\n  (O_APPEND | O_NDELAY | O_ASYNC_SETFL | O_DIRECT_SETFL | O_NOATIME_SETFL)\n\n#define INTERRUPTIBLE(restartable, x)       \\\n  do {                                      \\\n    int rc_;                                \\\n    rc_ = (x);                              \\\n    if (rc_ == -1 && errno == EINTR) {      \\\n      if (CheckInterrupt(m, restartable)) { \\\n        break;                              \\\n      }                                     \\\n    } else {                                \\\n      break;                                \\\n    }                                       \\\n  } while (1)\n\n#define RESTARTABLE(x) INTERRUPTIBLE(true, x)\n\n#define NORESTART(rc, x)             \\\n  do {                               \\\n    if (!CheckInterrupt(m, false)) { \\\n      INTERRUPTIBLE(false, rc = x);  \\\n    } else {                         \\\n      rc = -1;                       \\\n    }                                \\\n  } while (0)\n\nextern char *g_blink_path;\n\nvoid OpSyscall(P);\n\nvoid SysCloseExec(struct System *);\nint SysClose(struct Machine *, i32);\nint SysCloseRange(struct Machine *, u32, u32, u32);\nint SysDup(struct Machine *, i32, i32, i32, i32);\nint SysOpenat(struct Machine *, i32, i64, i32, i32);\nint SysPipe2(struct Machine *, i64, i32);\nint SysIoctl(struct Machine *, int, u64, i64);\n_Noreturn void SysExitGroup(struct Machine *, int);\n_Noreturn void SysExit(struct Machine *, int);\n\nint GetDirFildes(int);\nvoid AddStdFd(struct Fds *, int);\nint GetOflags(struct Machine *, int);\nint GetFildes(struct Machine *, int);\nstruct Fd *GetAndLockFd(struct Machine *, int);\nbool CheckInterrupt(struct Machine *, bool);\nint SysStatfs(struct Machine *, i64, i64);\nint SysFstatfs(struct Machine *, i32, i64);\nint mkfifoat_(int, const char *, mode_t);\nint mkfifo_(const char *, mode_t);\n\nvoid Strace(struct Machine *, const char *, bool, const char *, ...);\n\n#ifndef HAVE_MKFIFOAT\n#ifdef mkfifoat\n#undef mkfifoat\n#endif\n#define mkfifoat mkfifoat_\n#endif\n\n#ifndef HAVE_MKFIFO\n#ifdef mkfifo\n#undef mkfifo\n#endif\n#define mkfifo mkfifo_\n#endif\n\n#endif /* BLINK_SYSCALL_H_ */\n"
  },
  {
    "path": "blink/sysinfo.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <string.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <sys/types.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/linux.h\"\n#include \"blink/macros.h\"\n#include \"blink/timespec.h\"\n#include \"blink/types.h\"\n\n#ifdef HAVE_SYSINFO\n#include <sys/sysinfo.h>\n#endif\n#ifdef HAVE_SYSCTL\n#include <sys/sysctl.h>\n#endif\n\n#ifdef HAVE_SYSCTL\n\nstatic i64 GetUptime(void) {\n  struct timeval x;\n  size_t n = sizeof(x);\n  int mib[] = {CTL_KERN, KERN_BOOTTIME};\n  if (sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1) return 0;\n  return GetTime().tv_sec - x.tv_sec;\n}\n\nstatic i64 GetPhysmem(void) {\n  u64 x = 0;\n  size_t n = sizeof(x);\n  int mib[] = {\n      CTL_HW,\n#ifdef HW_MEMSIZE\n      HW_MEMSIZE,  // u64 version of HW_PHYSMEM on Apple platforms\n#else\n      HW_PHYSMEM,\n#endif\n  };\n  if (sysctl(mib, ARRAYLEN(mib), &x, &n, 0, 0) == -1) return 0;\n  return x;\n}\n\n#endif /* HAVE_SYSCTL */\n\nint sysinfo_linux(struct sysinfo_linux *si) {\n  memset(si, 0, sizeof(*si));\n#ifdef HAVE_SYSINFO\n  struct sysinfo syssi;\n  if (sysinfo(&syssi) == -1) return -1;\n  Write64(si->uptime, syssi.uptime);\n  Write64(si->loads[0], syssi.loads[0]);\n  Write64(si->loads[1], syssi.loads[1]);\n  Write64(si->loads[2], syssi.loads[2]);\n  Write64(si->totalram, syssi.totalram);\n  Write64(si->freeram, syssi.freeram);\n  Write64(si->sharedram, syssi.sharedram);\n  Write64(si->bufferram, syssi.bufferram);\n  Write64(si->totalswap, syssi.totalswap);\n  Write64(si->freeswap, syssi.freeswap);\n  Write16(si->procs, syssi.procs);\n  Write64(si->totalhigh, syssi.totalhigh);\n  Write64(si->freehigh, syssi.freehigh);\n  Write32(si->mem_unit, syssi.mem_unit);\n#elif defined(HAVE_SYSCTL)\n  Write64(si->uptime, GetUptime());\n  Write64(si->totalram, GetPhysmem());\n  Write16(si->procs, 1);\n  Write32(si->mem_unit, 1);\n#else\n  Write64(si->totalram, 1 * 1024 * 1024 * 1024);\n  Write16(si->procs, 1);\n  Write32(si->mem_unit, 1);\n#endif\n  return 0;\n}\n"
  },
  {
    "path": "blink/tainted.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <unistd.h>\n#ifdef __linux\n#include <sys/auxv.h>\n#endif\n#include \"blink/util.h\"\n\nlong IsProcessTainted(void) {\n#if (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \\\n     defined(__APPLE__) || defined(__COSMOPOLITAN__)) &&                    \\\n    !defined(_POSIX_C_SOURCE)\n  return issetugid();\n#elif defined(__linux) && !defined(_POSIX_C_SOURCE)\n  return getauxval(AT_SECURE);\n#else\n  return 0;\n#endif\n}\n"
  },
  {
    "path": "blink/thompike.h",
    "content": "#ifndef BLINK_THOMPIKE_H_\n#define BLINK_THOMPIKE_H_\n#include \"blink/bitscan.h\"\n\n#define ThomPikeCont(x)     (((x)&0300) == 0200)\n#define ThomPikeByte(x)     ((x) & (((1 << ThomPikeMsb(x)) - 1) | 3))\n#define ThomPikeLen(x)      (7 - ThomPikeMsb(x))\n#define ThomPikeMsb(x)      (((x)&0xff) < 252 ? bsr(~(x)&0xff) : 1)\n#define ThomPikeMerge(x, y) ((x) << 6 | ((y)&077))\n\n#endif /* BLINK_THOMPIKE_H_ */\n"
  },
  {
    "path": "blink/thread.h",
    "content": "#ifndef BLINK_LOCK_H_\n#define BLINK_LOCK_H_\n#include \"blink/builtin.h\"\n#ifndef DISABLE_THREADS\n#define HAVE_THREADS\n#include <pthread.h>\n\n#include \"blink/assert.h\"\n#include \"blink/log.h\"\n\n#define LOCK(x)   unassert(!pthread_mutex_lock(x))\n#define UNLOCK(x) unassert(!pthread_mutex_unlock(x))\n\n#ifdef __HAIKU__\n#include <OS.h>\n#undef UNLOCK\n#define UNLOCK(x)                       \\\n  do {                                  \\\n    (x)->owner = find_thread(NULL);     \\\n    unassert(!pthread_mutex_unlock(x)); \\\n  } while (0)\n#endif\n\n#define PTHREAD_ONCE_INIT_         PTHREAD_ONCE_INIT\n#define PTHREAD_MUTEX_INITIALIZER_ PTHREAD_MUTEX_INITIALIZER\n\n#define pthread_once_        pthread_once\n#define pthread_once_t_      pthread_once_t\n#define pthread_cond_t_      pthread_cond_t\n#define pthread_mutex_t_     pthread_mutex_t\n#define pthread_condattr_t_  pthread_condattr_t\n#define pthread_mutexattr_t_ pthread_mutexattr_t\n\n#else /* HAVE_THREADS */\n#include <signal.h>\n\n#ifdef _Thread_local\n#undef _Thread_local\n#endif\n#define _Thread_local\n\n#define LOCK(x)   (void)0\n#define UNLOCK(x) (void)0\n\n#define PTHREAD_ONCE_INIT_         0\n#define PTHREAD_MUTEX_INITIALIZER_ 0\n\n#define pthread_once_t_      char\n#define pthread_cond_t_      char\n#define pthread_mutex_t_     char\n#define pthread_condattr_t_  char\n#define pthread_mutexattr_t_ char\n\n#define pthread_self()                     0\n#define pthread_sigmask(x, y, z)           sigprocmask(x, y, z)\n#define pthread_setcancelstate(x, y)       ((void)(y), 0)\n#define pthread_mutex_init(x, y)           ((void)(y), 0)\n#define pthread_mutex_destroy(x)           0\n#define pthread_cond_init(x, y)            ((void)(y), 0)\n#define pthread_cond_wait(x, y)            0\n#define pthread_cond_signal(x)             0\n#define pthread_cond_broadcast(x)          0\n#define pthread_cond_timedwait(x, y, z)    ((void)(z), 0)\n#define pthread_cond_destroy(x)            0\n#define pthread_condattr_init(x)           0\n#define pthread_condattr_setpshared(x, y)  0\n#define pthread_condattr_destroy(x)        0\n#define pthread_mutexattr_init(x)          0\n#define pthread_mutexattr_setpshared(x, y) 0\n#define pthread_mutexattr_destroy(x)       0\n#define pthread_mutexattr_settype(x, y)    0\n#define pthread_atfork(a, b, c)            0\n#define pthread_create(a, b, c, d)         0\n#define pthread_join(a, b)                 0\n\nstatic inline int pthread_once_(pthread_once_t_ *once_control,\n                                void (*init_routine)(void)) {\n  if (!*once_control) {\n    init_routine();\n    *once_control = 1;\n  }\n  return 0;\n}\n\n#endif /* DISABLE_THREADS */\n#endif /* BLINK_LOCK_H_ */\n"
  },
  {
    "path": "blink/throw.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <inttypes.h>\n#include <sched.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/assert.h\"\n#include \"blink/debug.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/linux.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/signal.h\"\n\nvoid RestoreIp(struct Machine *m) {\n  if (m) {\n    m->ip -= m->oplen;\n    m->oplen = 0;\n  }\n}\n\nvoid DeliverSignalToUser(struct Machine *m, int sig, int code) {\n  if (m->sigmask & ((u64)1 << (sig - 1))) {\n    TerminateSignal(m, sig, code);\n  }\n  LOCK(&m->system->sig_lock);\n  switch (Read64(m->system->hands[sig - 1].handler)) {\n    case SIG_IGN_LINUX:\n    case SIG_DFL_LINUX:\n      UNLOCK(&m->system->sig_lock);\n      TerminateSignal(m, sig, code);\n      return;\n    default:\n      DeliverSignal(m, sig, code);\n      break;\n  }\n  UNLOCK(&m->system->sig_lock);\n  if ((sig = ConsumeSignal(m, 0, 0))) {\n    TerminateSignal(m, sig, code);\n  }\n}\n\nvoid HaltMachine(struct Machine *m, int code) {\n  SIG_LOGF(\"HaltMachine(%d) at %#\" PRIx64, code, m->ip);\n  switch ((m->trapno = code)) {\n    case kMachineDivideError:\n      RestoreIp(m);\n      m->faultaddr = m->ip;\n      DeliverSignalToUser(m, SIGFPE_LINUX, FPE_INTDIV_LINUX);\n      break;\n    case kMachineFpuException:\n    case kMachineSimdException:\n      RestoreIp(m);\n      m->faultaddr = m->ip;\n      DeliverSignalToUser(m, SIGFPE_LINUX, FPE_FLTINV_LINUX);\n      break;\n    case kMachineHalt:\n    case kMachineDecodeError:\n    case kMachineUndefinedInstruction:\n      RestoreIp(m);\n      m->faultaddr = m->ip;\n      DeliverSignalToUser(m, SIGILL_LINUX, ILL_ILLOPC_LINUX);\n      break;\n    case kMachineProtectionFault:\n      RestoreIp(m);\n      m->faultaddr = m->ip;\n      DeliverSignalToUser(m, SIGILL_LINUX, ILL_PRVOPC_LINUX);\n      break;\n    case kMachineSegmentationFault:\n      RestoreIp(m);\n      DeliverSignalToUser(m, SIGSEGV_LINUX,\n                          m->segvcode ? m->segvcode : SEGV_MAPERR_LINUX);\n      break;\n    case 1:\n    case 3:\n      m->faultaddr = m->ip - m->oplen;\n      DeliverSignalToUser(m, SIGTRAP_LINUX, SI_KERNEL_LINUX);\n      break;\n    case 4:\n      m->faultaddr = 0;\n      DeliverSignalToUser(m, SIGSEGV_LINUX, SI_KERNEL_LINUX);\n      break;\n    case kMachineExitTrap:\n      RestoreIp(m);\n      break;\n    default:\n      if (code >= 0) {\n        if (!m->metal) {\n          RestoreIp(m);\n          m->faultaddr = 0;\n          DeliverSignalToUser(m, SIGSEGV_LINUX, SI_KERNEL_LINUX);\n        }\n      } else {\n        unassert(!\"not possible\");\n      }\n  }\n  unassert(m->canhalt);\n  siglongjmp(m->onhalt, code);\n}\n\nvoid RaiseDivideError(struct Machine *m) {\n  HaltMachine(m, kMachineDivideError);\n}\n\nvoid ThrowProtectionFault(struct Machine *m) {\n  HaltMachine(m, kMachineProtectionFault);\n}\n\nvoid ThrowSegmentationFault(struct Machine *m, i64 va) {\n  RestoreIp(m);\n  m->faultaddr = va;\n  HaltMachine(m, kMachineSegmentationFault);\n}\n\nvoid OpUdImpl(struct Machine *m) {\n  RestoreIp(m);\n  HaltMachine(m, kMachineUndefinedInstruction);\n}\n\nvoid OpUd(P) {\n  OpUdImpl(m);\n}\n\nvoid OpHlt(P) {\n  if (Cpl(m) == 0 && GetFlag(m->flags, FLAGS_IF)) {\n    sched_yield();\n  } else {\n    HaltMachine(m, kMachineHalt);\n  }\n}\n"
  },
  {
    "path": "blink/time.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/time.h\"\n\n#include <time.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/jit.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n\n#ifdef HAVE_SCHED_H\n#include <sched.h>\n#endif\n\nvoid OpPause(P) {\n#if defined(__GNUC__) && defined(__aarch64__) && !defined(__FILC__)\n  asm volatile(\"yield\");\n#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) && \\\n    !defined(__FILC__)\n  asm volatile(\"pause\");\n#elif defined(HAVE_SCHED_YIELD)\n  sched_yield();\n#endif\n  if (IsMakingPath(m)) {\n    AppendJitPause(m->path.jb);\n  }\n}\n\nvoid OpRdtsc(P) {\n  u64 c;\n  if (m->traprdtsc) {\n    ThrowSegmentationFault(m, 0);\n  }\n#if defined(__GNUC__) && defined(__aarch64__) && !defined(__FILC__)\n  asm volatile(\"mrs %0, cntvct_el0\" : \"=r\"(c));\n  c *= 48;  // the fudge factor\n#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) && \\\n    !defined(__FILC__)\n  u32 ax, dx;\n  asm volatile(\"rdtsc\" : \"=a\"(ax), \"=d\"(dx));\n  c = (u64)dx << 32 | ax;\n#else\n  struct timespec ts;\n  unassert(!clock_gettime(CLOCK_MONOTONIC, &ts));\n  c = ts.tv_sec;\n  c *= 1000000000;\n  c += ts.tv_nsec;\n  c *= 3;  // the fudge factor\n#endif\n  Put64(m->ax, (c & 0x00000000ffffffff) >> 000);\n  Put64(m->dx, (c & 0xffffffff00000000) >> 040);\n}\n\nstatic i64 GetTscAux(struct Machine *m) {\n  u32 core, node;\n  core = 0;\n  node = 0;\n  return (node & 0xfff) << 12 | (core & 0xfff);\n}\n\nvoid OpRdtscp(P) {\n  OpRdtsc(A);\n  Put64(m->cx, GetTscAux(m));\n}\n\nvoid OpRdpid(P) {\n  Put64(RegRexbRm(m, rde), GetTscAux(m));\n}\n"
  },
  {
    "path": "blink/time.h",
    "content": "#ifndef BLINK_TIME_H_\n#define BLINK_TIME_H_\n#include \"blink/machine.h\"\n\nvoid OpPause(P);\nvoid OpRdtsc(P);\nvoid OpRdtscp(P);\nvoid OpRdpid(P);\n\n#endif /* BLINK_TIME_H_ */\n"
  },
  {
    "path": "blink/timespec.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/timespec.h\"\n\nint CompareTime(struct timespec a, struct timespec b) {\n  int cmp;\n  if (!(cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec))) {\n    cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec);\n  }\n  return cmp;\n}\n\nstruct timespec AddTime(struct timespec x, struct timespec y) {\n  x.tv_sec += y.tv_sec;\n  x.tv_nsec += y.tv_nsec;\n  if (x.tv_nsec >= 1000000000) {\n    x.tv_nsec -= 1000000000;\n    x.tv_sec += 1;\n  }\n  return x;\n}\n\nstruct timespec SubtractTime(struct timespec a, struct timespec b) {\n  a.tv_sec -= b.tv_sec;\n  if (a.tv_nsec < b.tv_nsec) {\n    a.tv_nsec += 1000000000;\n    a.tv_sec--;\n  }\n  a.tv_nsec -= b.tv_nsec;\n  return a;\n}\n"
  },
  {
    "path": "blink/timespec.h",
    "content": "#ifndef BLINK_TIMESPEC_H_\n#define BLINK_TIMESPEC_H_\n#include <errno.h>\n#include <time.h>\n\n#include \"blink/assert.h\"\n#include \"blink/limits.h\"\n\nstatic inline struct timespec GetTime(void) {\n  struct timespec ts;\n  unassert(!clock_gettime(CLOCK_REALTIME, &ts));\n  return ts;\n}\n\nstatic inline struct timespec GetMonotonic(void) {\n  struct timespec ts;\n  unassert(!clock_gettime(CLOCK_MONOTONIC, &ts));\n  return ts;\n}\n\nstatic inline struct timespec GetMaxTime(void) {\n  struct timespec ts;\n  ts.tv_sec = NUMERIC_MAX(time_t);\n  ts.tv_nsec = 999999999;\n  return ts;\n}\n\nstatic inline struct timespec GetZeroTime(void) {\n  struct timespec ts;\n  ts.tv_sec = 0;\n  ts.tv_nsec = 0;\n  return ts;\n}\n\nstatic inline struct timespec FromSeconds(time_t x) {\n  struct timespec ts;\n  ts.tv_sec = x;\n  ts.tv_nsec = 0;\n  return ts;\n}\n\nstatic inline struct timespec FromMilliseconds(time_t x) {\n  struct timespec ts;\n  ts.tv_sec = x / 1000;\n  ts.tv_nsec = x % 1000 * 1000000;\n  return ts;\n}\n\nstatic inline struct timespec FromMicroseconds(time_t x) {\n  struct timespec ts;\n  ts.tv_sec = x / 1000000;\n  ts.tv_nsec = x % 1000000 * 1000;\n  return ts;\n}\n\nstatic inline struct timespec FromNanoseconds(time_t x) {\n  struct timespec ts;\n  ts.tv_sec = x / 1000000000;\n  ts.tv_nsec = x % 1000000000;\n  return ts;\n}\n\nstatic inline struct timespec SleepTime(struct timespec dur) {\n  struct timespec unslept;\n  if (!nanosleep(&dur, &unslept)) {\n    unslept.tv_sec = 0;\n    unslept.tv_nsec = 0;\n  } else {\n    unassert(errno == EINTR);\n  }\n  return unslept;\n}\n\nstatic inline int ConvertTimeToInt(time_t x) {\n  if (x > INT_MAX) return INT_MAX;\n  return x;\n}\n\nstatic inline time_t ToSeconds(struct timespec ts) {\n  unassert(ts.tv_nsec < 1000000000);\n  if (ts.tv_sec < NUMERIC_MAX(time_t)) {\n    if (ts.tv_nsec) {\n      ts.tv_sec += 1;\n    }\n    return ts.tv_sec;\n  } else {\n    return NUMERIC_MAX(time_t);\n  }\n}\n\nstatic inline time_t ToMilliseconds(struct timespec ts) {\n  unassert(ts.tv_nsec < 1000000000);\n  if (ts.tv_sec < NUMERIC_MAX(time_t) / 1000 - 999) {\n    if (ts.tv_nsec <= 999000000) {\n      ts.tv_nsec = (ts.tv_nsec + 999999) / 1000000;\n    } else {\n      ts.tv_sec += 1;\n      ts.tv_nsec = 0;\n    }\n    return ts.tv_sec * 1000 + ts.tv_nsec;\n  } else {\n    return NUMERIC_MAX(time_t);\n  }\n}\n\nstatic inline time_t ToMicroseconds(struct timespec ts) {\n  unassert(ts.tv_nsec < 1000000000);\n  if (ts.tv_sec < NUMERIC_MAX(time_t) / 1000000 - 999999) {\n    if (ts.tv_nsec <= 999999000) {\n      ts.tv_nsec = (ts.tv_nsec + 999) / 1000;\n    } else {\n      ts.tv_sec += 1;\n      ts.tv_nsec = 0;\n    }\n    return ts.tv_sec * 1000000 + ts.tv_nsec;\n  } else {\n    return NUMERIC_MAX(time_t);\n  }\n}\n\nstatic inline time_t ToNanoseconds(struct timespec ts) {\n  unassert(ts.tv_nsec < 1000000000);\n  if (ts.tv_sec < NUMERIC_MAX(time_t) / 1000000000 - 999999999) {\n    return ts.tv_sec * 1000000000 + ts.tv_nsec;\n  } else {\n    return NUMERIC_MAX(time_t);\n  }\n}\n\nint CompareTime(struct timespec, struct timespec);\nstruct timespec AddTime(struct timespec, struct timespec);\nstruct timespec SubtractTime(struct timespec, struct timespec);\n\n#endif /* BLINK_TIMESPEC_H_ */\n"
  },
  {
    "path": "blink/tpenc.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/bitscan.h\"\n#include \"blink/util.h\"\n\nstatic const u16 kTpEnc[32 - 7] = {\n    1 | 0300 << 8, 1 | 0300 << 8, 1 | 0300 << 8, 1 | 0300 << 8, 2 | 0340 << 8,\n    2 | 0340 << 8, 2 | 0340 << 8, 2 | 0340 << 8, 2 | 0340 << 8, 3 | 0360 << 8,\n    3 | 0360 << 8, 3 | 0360 << 8, 3 | 0360 << 8, 3 | 0360 << 8, 4 | 0370 << 8,\n    4 | 0370 << 8, 4 | 0370 << 8, 4 | 0370 << 8, 4 | 0370 << 8, 5 | 0374 << 8,\n    5 | 0374 << 8, 5 | 0374 << 8, 5 | 0374 << 8, 5 | 0374 << 8, 5 | 0374 << 8,\n};\n\nu64 tpenc(uint32_t c) {\n  int e, n;\n  u64 w;\n  if (0 <= c && c <= 127) return c;\n  e = kTpEnc[bsr(c) - 7];\n  n = e & 0xff;\n  w = 0;\n  do {\n    w |= 0200 | (c & 077);\n    w <<= 8;\n    c >>= 6;\n  } while (--n);\n  return c | w | e >> 8;\n}\n"
  },
  {
    "path": "blink/tsan.h",
    "content": "#ifndef TSAN_H_\n#define TSAN_H_\n// Thread Safety Analysis, complements of Google\n#include \"blink/builtin.h\"\n\n#if defined(__cplusplus) && defined(__clang__)\n#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))\n#else\n#define THREAD_ANNOTATION_ATTRIBUTE__(x)\n#endif\n\n// GUARDED_BY()\n//\n// Documents if a shared field or global variable needs to be protected by a\n// mutex. GUARDED_BY() allows the user to specify a particular mutex that\n// should be held when accessing the annotated variable.\n//\n// Example:\n//\n//   Mutex mu;\n//   int p1 GUARDED_BY(mu);\n#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))\n\n// PT_GUARDED_BY()\n//\n// Documents if the memory location pointed to by a pointer should be guarded\n// by a mutex when dereferencing the pointer.\n//\n// Example:\n//   Mutex mu;\n//   int *p1 PT_GUARDED_BY(mu);\n//\n// Note that a pointer variable to a shared memory location could itself be a\n// shared variable.\n//\n// Example:\n//\n//     // `q`, guarded by `mu1`, points to a shared memory location that is\n//     // guarded by `mu2`:\n//     int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2);\n#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))\n\n// ACQUIRED_AFTER() / ACQUIRED_BEFORE()\n//\n// Documents the acquisition order between locks that can be held\n// simultaneously by a thread. For any two locks that need to be annotated\n// to establish an acquisition order, only one of them needs the annotation.\n// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER\n// and ACQUIRED_BEFORE.)\n//\n// Example:\n//\n//   Mutex m1;\n//   Mutex m2 ACQUIRED_AFTER(m1);\n#define ACQUIRED_AFTER(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))\n#define ACQUIRED_BEFORE(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))\n\n// EXCLUSIVE_LOCKS_REQUIRED() / SHARED_LOCKS_REQUIRED()\n//\n// Documents a function that expects a mutex to be held prior to entry.\n// The mutex is expected to be held both on entry to, and exit from, the\n// function.\n//\n// Example:\n//\n//   Mutex mu1, mu2;\n//   int a GUARDED_BY(mu1);\n//   int b GUARDED_BY(mu2);\n//\n//   void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... };\n#define EXCLUSIVE_LOCKS_REQUIRED(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))\n#define SHARED_LOCKS_REQUIRED(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))\n\n// LOCKS_EXCLUDED()\n//\n// Documents the locks acquired in the body of the function. These locks\n// cannot be held when calling this function (as Abseil's `Mutex` locks are\n// non-reentrant).\n#define LOCKS_EXCLUDED(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))\n\n// LOCK_RETURNED()\n//\n// Documents a function that returns a mutex without acquiring it.  For example,\n// a public getter method that returns a pointer to a private mutex should\n// be annotated with LOCK_RETURNED.\n#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))\n\n// LOCKABLE\n//\n// Documents if a class/type is a lockable type (such as the `Mutex` class).\n#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable)\n\n// SCOPED_LOCKABLE\n//\n// Documents if a class does RAII locking (such as the `MutexLock` class).\n// The constructor should use `LOCK_FUNCTION()` to specify the mutex that is\n// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no\n// arguments; the analysis will assume that the destructor unlocks whatever the\n// constructor locked.\n#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)\n\n// EXCLUSIVE_LOCK_FUNCTION()\n//\n// Documents functions that acquire a lock in the body of a function, and do\n// not release it.\n#define EXCLUSIVE_LOCK_FUNCTION(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))\n\n// SHARED_LOCK_FUNCTION()\n//\n// Documents functions that acquire a shared (reader) lock in the body of a\n// function, and do not release it.\n#define SHARED_LOCK_FUNCTION(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))\n\n// UNLOCK_FUNCTION()\n//\n// Documents functions that expect a lock to be held on entry to the function,\n// and release it in the body of the function.\n#define UNLOCK_FUNCTION(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))\n\n// EXCLUSIVE_TRYLOCK_FUNCTION() / SHARED_TRYLOCK_FUNCTION()\n//\n// Documents functions that try to acquire a lock, and return success or failure\n// (or a non-boolean value that can be interpreted as a boolean).\n// The first argument should be `true` for functions that return `true` on\n// success, or `false` for functions that return `false` on success. The second\n// argument specifies the mutex that is locked on success. If unspecified, this\n// mutex is assumed to be `this`.\n#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))\n#define SHARED_TRYLOCK_FUNCTION(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))\n\n// ASSERT_EXCLUSIVE_LOCK() / ASSERT_SHARED_LOCK()\n//\n// Documents functions that dynamically check to see if a lock is held, and fail\n// if it is not held.\n#define ASSERT_EXCLUSIVE_LOCK(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))\n#define ASSERT_SHARED_LOCK(...) \\\n  THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))\n\n// NO_THREAD_SAFETY_ANALYSIS\n//\n// Turns off thread safety checking within the body of a particular function.\n// This annotation is used to mark functions that are known to be correct, but\n// the locking behavior is more complicated than the analyzer can handle.\n#define NO_THREAD_SAFETY_ANALYSIS \\\n  THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)\n\n#ifdef __SANITIZE_THREAD__\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nvoid AnnotateIgnoreWritesBegin(const char *file, int line);\nvoid AnnotateIgnoreWritesEnd(const char *file, int line);\nvoid AnnotateIgnoreReadsBegin(const char *file, int line);\nvoid AnnotateIgnoreReadsEnd(const char *file, int line);\n#ifdef __cplusplus\n}\n#endif\n#define IGNORE_RACES_START()                       \\\n  do {                                             \\\n    AnnotateIgnoreReadsBegin(__FILE__, __LINE__);  \\\n    AnnotateIgnoreWritesBegin(__FILE__, __LINE__); \\\n  } while (0)\n#define IGNORE_RACES_END()                       \\\n  do {                                           \\\n    AnnotateIgnoreWritesEnd(__FILE__, __LINE__); \\\n    AnnotateIgnoreReadsEnd(__FILE__, __LINE__);  \\\n  } while (0)\n#else\n#define IGNORE_RACES_START()\n#define IGNORE_RACES_END()\n#endif\n\n#endif /* TSAN_H_ */\n"
  },
  {
    "path": "blink/tunables.h",
    "content": "#ifndef BLINK_TUNABLES_H_\n#define BLINK_TUNABLES_H_\n#include <stdint.h>\n\n#include \"blink/builtin.h\"\n\n#define BLINK_MAJOR 1\n#define BLINK_MINOR 1\n#define BLINK_PATCH 0\n\n#define LINUX_MAJOR 4\n#define LINUX_MINOR 5\n#define LINUX_PATCH 0\n\n#define MKVERSION_(x, y, z) #x \".\" #y \".\" #z\n#define MKVERSION(x, y, z)  MKVERSION_(x, y, z)\n#define LINUX_VERSION       MKVERSION(LINUX_MAJOR, LINUX_MINOR, LINUX_PATCH)\n#define BLINK_VERSION       MKVERSION(BLINK_MAJOR, BLINK_MINOR, BLINK_PATCH)\n\n#if CAN_64BIT && defined(__APPLE__)\n#define kSkew 0x088800000000\n#else\n#define kSkew 0x000000000000\n#endif\n\n#define kAslrMask      0x03ffff000000  // 16mb before pointers get nasty\n#define kImageStart    0x110001000000\n#define kAutomapStart  0x200000000000\n#define kAutomapEnd    0x400000000000\n#define kDynInterpAddr 0x454000000000\n#define kStackTop      0x500000000000\n\n#define kRealSize  (16 * 1024 * 1024)  // size of ram for real mode\n#define kStackSize (8 * 1024 * 1024)   // size of stack for user mode\n#define kNullSize  (2 * 1024 * 1024)   // minimum user mode image address\n\n#define kMinBlinkFd   123  // fds owned by the vm start here\n#define kPollingMs    50   // busy loop for futex(), poll(), etc.\n#define kBusCount     256  // # load balanced semaphores in virtual bus\n#define kBusRegion    128  // 16 is sufficient for 8-byte loads/stores\n#define kFutexMax     100\n#define kRedzoneSize  128\n#define kSmcQueueSize 32\n#define kMaxMapSize   (UINT64_C(8) * 1024 * 1024 * 1024)\n#define kMaxResident  (UINT64_C(8) * 1024 * 1024 * 1024)\n#define kMaxVirtual   (kMaxResident * 8)\n#define kMaxAncillary 1000\n#define kMaxShebang   512\n#define kMaxSigDepth  8\n\n#define kStraceArgMax 256\n#define kStraceBufMax 32\n\n#endif /* BLINK_TUNABLES_H_ */\n"
  },
  {
    "path": "blink/types.h",
    "content": "#ifndef BLINK_TYPES_H_\n#define BLINK_TYPES_H_\n#include <stdint.h>\n\ntypedef int8_t i8;\ntypedef uint8_t u8;\ntypedef int16_t i16;\ntypedef uint16_t u16;\ntypedef int32_t i32;\ntypedef uint32_t u32;\ntypedef int64_t i64;\ntypedef uint64_t u64;\n\n#endif /* BLINK_TYPES_H_ */\n"
  },
  {
    "path": "blink/uart.h",
    "content": "#ifndef BLINK_UART_H_\n#define BLINK_UART_H_\n\n#define UART_DLAB   (1 << 7) /* serial line conf mode bit */\n#define UART_DLL    0        /* divisor latch register */\n#define UART_DLM    1        /* divisor latch register */\n#define UART_IIR    2        /* interrupt identification register */\n#define UART_LCR    3        /* line control register */\n#define UART_MCR    4        /* modem control register */\n#define UART_LSR    5        /* line status register */\n#define UART_TTYDA  (1 << 0) /* data available (rx ready) */\n#define UART_TTYOE  (1 << 1) /* overrun error */\n#define UART_TTYPE  (1 << 2) /* parity error */\n#define UART_TTYFE  (1 << 3) /* framing error */\n#define UART_TTYBSR (1 << 4) /* break signal received */\n#define UART_TTYTXR (1 << 5) /* serial thr empty (tx ready) */\n#define UART_TTYIDL (1 << 6) /* serial thr empty and line idle */\n#define UART_TTYEDF (1 << 7) /* erroneous data in fifo */\n\n#endif /* BLINK_UART_H_ */\n"
  },
  {
    "path": "blink/uop.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdlib.h>\n\n#include \"blink/alu.h\"\n#include \"blink/assert.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/intrin.h\"\n#include \"blink/jit.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/macros.h\"\n#include \"blink/modrm.h\"\n#include \"blink/pun.h\"\n#include \"blink/rde.h\"\n#include \"blink/stats.h\"\n#include \"blink/swap.h\"\n#include \"blink/thread.h\"\n#include \"blink/types.h\"\n#include \"blink/x86.h\"\n#include \"blink/xmm.h\"\n\n/**\n * @fileoverview X86 Micro-Operations w/ Printf RPN Glue-Generating DSL.\n */\n\n#define kMaxOps 256\n\n////////////////////////////////////////////////////////////////////////////////\n// ESSENTIAL\n\nMICRO_OP static void Sax64(P) {\n  Put64(m->ax, (i32)Get32(m->ax));\n}\nMICRO_OP static void Sax32(P) {\n  Put64(m->ax, (u32)(i16)Get16(m->ax));\n}\nMICRO_OP static void Sax16(P) {\n  Put16(m->ax, (i8)Get8(m->ax));\n}\nconst nexgen32e_f kSax[] = {Sax16, Sax32, Sax64};\n\nMICRO_OP i64 Not8(struct Machine *m, u64 x, u64 y) {\n  return ~x & 0xFF;\n}\nMICRO_OP i64 Not16(struct Machine *m, u64 x, u64 y) {\n  return ~x & 0xFFFF;\n}\nMICRO_OP i64 Not32(struct Machine *m, u64 x, u64 y) {\n  return ~x & 0xFFFFFFFF;\n}\nMICRO_OP i64 Not64(struct Machine *m, u64 x, u64 y) {\n  return ~x & 0xFFFFFFFFFFFFFFFF;\n}\n\nMICRO_OP static void Convert64(P) {\n  Put64(m->dx, Get64(m->ax) & 0x8000000000000000 ? 0xffffffffffffffff : 0);\n}\nMICRO_OP static void Convert32(P) {\n  Put64(m->dx, Get32(m->ax) & 0x80000000 ? 0xffffffff : 0);\n}\nMICRO_OP static void Convert16(P) {\n  Put16(m->dx, Get16(m->ax) & 0x8000 ? 0xffff : 0);\n}\nconst nexgen32e_f kConvert[] = {Convert16, Convert32, Convert64};\n\n#ifndef DISABLE_BMI2\n\n#if X86_INTRINSICS\nMICRO_OP i64 Adcx32(u64 x, u64 y, struct Machine *m) {\n  u32 z;\n  _Static_assert(CF == 1, \"\");\n  asm(\"btr\\t$0,%1\\n\\t\"\n      \"adc\\t%3,%0\\n\\t\"\n      \"adc\\t$0,%1\"\n      : \"=&r\" (z), \"+&g\" (m->flags) : \"%0\" ((u32)x), \"g\" ((u32)y) : \"cc\");\n  return z;\n}\nMICRO_OP i64 Adcx64(u64 x, u64 y, struct Machine *m) {\n  u64 z;\n  _Static_assert(CF == 1, \"\");\n  asm(\"btr\\t$0,%1\\n\\t\"\n      \"adc\\t%3,%0\\n\\t\"\n      \"adc\\t$0,%1\"\n      : \"=&r\" (z), \"+&g\" (m->flags) : \"%0\" (x), \"g\" (y) : \"cc\");\n  return z;\n}\nMICRO_OP i64 Adox32(u64 x, u64 y, struct Machine *m) {\n  u32 z, t;\n  asm(\"btr\\t%5,%1\\n\\t\"\n      \"adc\\t%4,%0\\n\\t\"\n      \"sbb\\t%2,%2\\n\\t\"\n      \"and\\t%6,%2\\n\\t\"\n      \"or\\t%2,%1\"\n      : \"=&r\" (z), \"+&g\" (m->flags), \"=&r\" (t)\n      : \"%0\" ((u32)x), \"g\" ((u32)y), \"i\" (FLAGS_OF), \"i\" (OF)\n      : \"cc\");\n  return z;\n}\nMICRO_OP i64 Adox64(u64 x, u64 y, struct Machine *m) {\n  u64 z;\n  u32 t;\n  asm(\"btr\\t%5,%1\\n\\t\"\n      \"adc\\t%4,%0\\n\\t\"\n      \"sbb\\t%2,%2\\n\\t\"\n      \"and\\t%6,%2\\n\\t\"\n      \"or\\t%2,%1\"\n      : \"=&r\" (z), \"+&g\" (m->flags), \"=&r\" (t)\n      : \"%0\" (x), \"g\" (y), \"i\" (FLAGS_OF), \"i\" (OF)\n      : \"cc\");\n  return z;\n}\n#elif ARM_INTRINSICS /* !X86_INTRINSICS */\nMICRO_OP i64 Adcx32(u64 x, u64 y, struct Machine *m) {\n  u64 f = m->flags, z;\n  _Static_assert(CF == 1, \"\");\n  asm(\"ror\\t%1,%1,#1\\n\\t\"\n      \"adds\\t%1,%1,%1\\n\\t\"\n      \"adcs\\t%w0,%w2,%w3\\n\\t\"\n      \"adc\\t%1,%1,xzr\"\n      : \"=&r\" (z), \"+&r\" (f) : \"%0\" (x), \"r\" (y) : \"cc\");\n  m->flags = f;\n  return z;\n}\nMICRO_OP i64 Adcx64(u64 x, u64 y, struct Machine *m) {\n  u64 f = m->flags, z;\n  _Static_assert(CF == 1, \"\");\n  asm(\"ror\\t%1,%1,#1\\n\\t\"\n      \"adds\\t%1,%1,%1\\n\\t\"\n      \"adcs\\t%0,%2,%3\\n\\t\"\n      \"adc\\t%1,%1,xzr\"\n      : \"=&r\" (z), \"+&r\" (f) : \"%0\" (x), \"r\" (y) : \"cc\");\n  m->flags = f;\n  return z;\n}\nMICRO_OP i64 Adox32(u64 x, u64 y, struct Machine *m) {\n  u64 f = m->flags, z;\n  asm(\"ror\\t%1,%1,%4\\n\\t\"\n      \"adds\\t%1,%1,%1\\n\\t\"\n      \"adcs\\t%w0,%w2,%w3\\n\\t\"\n      \"adc\\t%1,%1,xzr\\n\\t\"\n      \"ror\\t%1,%1,%5\"\n      : \"=&r\" (z), \"+&r\" (f)\n      : \"%0\" (x), \"r\" (y), \"i\" (FLAGS_OF + 1), \"i\" (64 - FLAGS_OF)\n      : \"cc\");\n  m->flags = f;\n  return z;\n}\nMICRO_OP i64 Adox64(u64 x, u64 y, struct Machine *m) {\n  u64 f = m->flags, z;\n  asm(\"ror\\t%1,%1,%4\\n\\t\"\n      \"adds\\t%1,%1,%1\\n\\t\"\n      \"adcs\\t%0,%2,%3\\n\\t\"\n      \"adc\\t%1,%1,xzr\\n\\t\"\n      \"ror\\t%1,%1,%5\"\n      : \"=&r\" (z), \"+&r\" (f)\n      : \"%0\" (x), \"r\" (y), \"i\" (FLAGS_OF + 1), \"i\" (64 - FLAGS_OF)\n      : \"cc\");\n  m->flags = f;\n  return z;\n}\n#else /* !ARM_INTRINSICS */\nMICRO_OP i64 Adcx32(u64 x, u64 y, struct Machine *m) {\n  u32 t = x + !!(m->flags & CF);\n  u32 z = t + y;\n  int c = (t < x) | (z < y);\n  m->flags = (m->flags & ~CF) | c << FLAGS_CF;\n  return z;\n}\nMICRO_OP i64 Adcx64(u64 x, u64 y, struct Machine *m) {\n  u64 t = x + !!(m->flags & CF);\n  u64 z = t + y;\n  int c = (t < x) | (z < y);\n  m->flags = (m->flags & ~CF) | c << FLAGS_CF;\n  return z;\n}\n\nMICRO_OP i64 Adox32(u64 x, u64 y, struct Machine *m) {\n  u32 t = x + !!(m->flags & OF);\n  u32 z = t + y;\n  int c = (t < x) | (z < y);\n  m->flags = (m->flags & ~OF) | c << FLAGS_OF;\n  return z;\n}\nMICRO_OP i64 Adox64(u64 x, u64 y, struct Machine *m) {\n  u64 t = x + !!(m->flags & OF);\n  u64 z = t + y;\n  int c = (t < x) | (z < y);\n  m->flags = (m->flags & ~OF) | c << FLAGS_OF;\n  return z;\n}\n#endif /* !ARM_INTRINSICS */\n\n#endif /* !DISABLE_BMI2 */\n\n////////////////////////////////////////////////////////////////////////////////\n// BRANCHING\n\nMICRO_OP void FastJmp(struct Machine *m, u64 disp) {\n  m->ip += disp;\n}\nMICRO_OP void FastJmpAbs(u64 addr, struct Machine *m) {\n  m->ip = addr;\n}\n\nMICRO_OP static u32 Jb(struct Machine *m) {\n  return !!(m->flags & CF);\n}\nMICRO_OP static u32 Jae(struct Machine *m) {\n  return !!(~m->flags & CF);\n}\nMICRO_OP static u32 Je(struct Machine *m) {\n  return !!(m->flags & ZF);\n}\nMICRO_OP static u32 Jne(struct Machine *m) {\n  return !!(~m->flags & ZF);\n}\nMICRO_OP static u32 Js(struct Machine *m) {\n  return !!(m->flags & SF);\n}\nMICRO_OP static u32 Jns(struct Machine *m) {\n  return !!(~m->flags & SF);\n}\nMICRO_OP static u32 Jo(struct Machine *m) {\n  return !!(m->flags & OF);\n}\nMICRO_OP static u32 Jno(struct Machine *m) {\n  return !!(~m->flags & OF);\n}\nMICRO_OP static u32 Ja(struct Machine *m) {\n  return IsAbove(m);\n}\nMICRO_OP static u32 Jbe(struct Machine *m) {\n  return IsBelowOrEqual(m);\n}\nMICRO_OP static u32 Jg(struct Machine *m) {\n  return IsGreater(m);\n}\nMICRO_OP static u32 Jge(struct Machine *m) {\n  return IsGreaterOrEqual(m);\n}\nMICRO_OP static u32 Jl(struct Machine *m) {\n  return IsLess(m);\n}\nMICRO_OP static u32 Jle(struct Machine *m) {\n  return IsLessOrEqual(m);\n}\n\nconst cc_f kConditionCode[16] = {\n    Jo,   //\n    Jno,  //\n    Jb,   //\n    Jae,  //\n    Je,   //\n    Jne,  //\n    Jbe,  //\n    Ja,   //\n    Js,   //\n    Jns,  //\n    0,    //\n    0,    //\n    Jl,   //\n    Jge,  //\n    Jle,  //\n    Jg,   //\n};\n\nMICRO_OP u64 Pick(u32 p, u64 x, u64 y) {\n  return p ? x : y;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// FLOATING POINT\n\nMICRO_OP void OpPsdMuls1(u8 *p, struct Machine *m, long reg) {\n  union FloatPun x, y;\n  y.i = Read32(p);\n  x.i = Read32(m->xmm[reg]);\n  x.f = x.f * y.f;\n  Write32(m->xmm[reg], x.i);\n}\n\nMICRO_OP void OpPsdMuld1(u8 *p, struct Machine *m, long reg) {\n  union DoublePun x, y;\n  y.i = Read64(p);\n  x.i = Read64(m->xmm[reg]);\n  x.f = x.f * y.f;\n  Write64(m->xmm[reg], x.i);\n}\n\nMICRO_OP void OpPsdAdds1(u8 *p, struct Machine *m, long reg) {\n  union FloatPun x, y;\n  y.i = Read32(p);\n  x.i = Read32(m->xmm[reg]);\n  x.f = x.f + y.f;\n  Write32(m->xmm[reg], x.i);\n}\n\nMICRO_OP void OpPsdAddd1(u8 *p, struct Machine *m, long reg) {\n  union DoublePun x, y;\n  y.i = Read64(p);\n  x.i = Read64(m->xmm[reg]);\n  x.f = x.f + y.f;\n  Write64(m->xmm[reg], x.i);\n}\n\nMICRO_OP void OpPsdSubs1(u8 *p, struct Machine *m, long reg) {\n  union FloatPun x, y;\n  y.i = Read32(p);\n  x.i = Read32(m->xmm[reg]);\n  x.f = x.f - y.f;\n  Write32(m->xmm[reg], x.i);\n}\n\nMICRO_OP void OpPsdSubd1(u8 *p, struct Machine *m, long reg) {\n  union DoublePun x, y;\n  y.i = Read64(p);\n  x.i = Read64(m->xmm[reg]);\n  x.f = x.f - y.f;\n  Write64(m->xmm[reg], x.i);\n}\n\nMICRO_OP void OpPsdDivs1(u8 *p, struct Machine *m, long reg) {\n  union FloatPun x, y;\n  y.i = Read32(p);\n  x.i = Read32(m->xmm[reg]);\n  x.f = x.f / y.f;\n  Write32(m->xmm[reg], x.i);\n}\n\nMICRO_OP void OpPsdDivd1(u8 *p, struct Machine *m, long reg) {\n  union DoublePun x, y;\n  y.i = Read64(p);\n  x.i = Read64(m->xmm[reg]);\n  x.f = x.f / y.f;\n  Write64(m->xmm[reg], x.i);\n}\n\nMICRO_OP void OpPsdMins1(u8 *p, struct Machine *m, long reg) {\n  union FloatPun x, y;\n  y.i = Read32(p);\n  x.i = Read32(m->xmm[reg]);\n  x.f = MIN(x.f, y.f);\n  Write32(m->xmm[reg], x.i);\n}\n\nMICRO_OP void OpPsdMind1(u8 *p, struct Machine *m, long reg) {\n  union DoublePun x, y;\n  y.i = Read64(p);\n  x.i = Read64(m->xmm[reg]);\n  x.f = MIN(x.f, y.f);\n  Write64(m->xmm[reg], x.i);\n}\n\nMICRO_OP void OpPsdMaxs1(u8 *p, struct Machine *m, long reg) {\n  union FloatPun x, y;\n  y.i = Read32(p);\n  x.i = Read32(m->xmm[reg]);\n  x.f = MAX(x.f, y.f);\n  Write32(m->xmm[reg], x.i);\n}\n\nMICRO_OP void OpPsdMaxd1(u8 *p, struct Machine *m, long reg) {\n  union DoublePun x, y;\n  y.i = Read64(p);\n  x.i = Read64(m->xmm[reg]);\n  x.f = MAX(x.f, y.f);\n  Write64(m->xmm[reg], x.i);\n}\n\nMICRO_OP void Int64ToDouble(i64 x, struct Machine *m, long reg) {\n  union DoublePun d;\n  d.f = x;\n  Put64(m->xmm[reg], d.i);\n}\n\nMICRO_OP void Int32ToDouble(i32 x, struct Machine *m, long reg) {\n  union DoublePun d;\n  d.f = x;\n  Put64(m->xmm[reg], d.i);\n}\n\nMICRO_OP void Int64ToFloat(i64 x, struct Machine *m, long reg) {\n  union FloatPun d;\n  d.f = x;\n  Put32(m->xmm[reg], d.i);\n}\n\nMICRO_OP void Int32ToFloat(i32 x, struct Machine *m, long reg) {\n  union FloatPun d;\n  d.f = x;\n  Put32(m->xmm[reg], d.i);\n}\n\n#ifdef HAVE_JIT\n\n////////////////////////////////////////////////////////////////////////////////\n// ACCOUNTING\n\nMICRO_OP void CountOp(long *instructions_jitted_ptr) {\n  STATISTIC(++*instructions_jitted_ptr);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// PROGRAM COUNTER\n\nMICRO_OP void AddIp(struct Machine *m, long oplen) {\n  m->oplen = oplen;\n  m->ip += oplen;\n}\n\nMICRO_OP void SkewIp(struct Machine *m, long oplen, long delta) {\n  m->oplen = oplen;\n  m->ip += delta;\n}\n\nMICRO_OP void AdvanceIp(struct Machine *m, long oplen) {\n  m->ip += oplen;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// READING FROM REGISTER FILE\n\nMICRO_OP static u64 GetCl(struct Machine *m) {\n  return m->cl;\n}\nMICRO_OP static u64 GetReg8(struct Machine *m, long b) {\n  return Get8(m->beg + b);\n}\nMICRO_OP static u64 GetReg16(struct Machine *m, long i) {\n  return Get16(m->weg[i]);\n}\nMICRO_OP static u64 GetReg32(struct Machine *m, long i) {\n  return Get32(m->weg[i]);\n}\nMICRO_OP static u64 GetReg64(struct Machine *m, long i) {\n  return Get64(m->weg[i]);\n}\nMICRO_OP static XMM_TYPE GetReg128(struct Machine *m, long i) {\n  RETURN_XMM(Get64(m->xmm[i]), Get64(m->xmm[i] + 8));\n}\ntypedef u64 (*getreg_f)(struct Machine *, long);\nstatic const getreg_f kGetReg[] = {GetReg8, GetReg16,   //\n                                   GetReg32, GetReg64,  //\n                                   (getreg_f)GetReg128};\n\nMICRO_OP static u64 GetReg32_0(struct Machine *m) {\n  return Get32(m->weg[0]);\n}\nMICRO_OP static u64 GetReg32_1(struct Machine *m) {\n  return Get32(m->weg[1]);\n}\nMICRO_OP static u64 GetReg32_2(struct Machine *m) {\n  return Get32(m->weg[2]);\n}\nMICRO_OP static u64 GetReg32_3(struct Machine *m) {\n  return Get32(m->weg[3]);\n}\nMICRO_OP static u64 GetReg32_4(struct Machine *m) {\n  return Get32(m->weg[4]);\n}\nMICRO_OP static u64 GetReg32_5(struct Machine *m) {\n  return Get32(m->weg[5]);\n}\nMICRO_OP static u64 GetReg32_6(struct Machine *m) {\n  return Get32(m->weg[6]);\n}\nMICRO_OP static u64 GetReg32_7(struct Machine *m) {\n  return Get32(m->weg[7]);\n}\nMICRO_OP static u64 GetReg32_8(struct Machine *m) {\n  return Get32(m->weg[8]);\n}\nMICRO_OP static u64 GetReg32_9(struct Machine *m) {\n  return Get32(m->weg[9]);\n}\nMICRO_OP static u64 GetReg32_10(struct Machine *m) {\n  return Get32(m->weg[10]);\n}\nMICRO_OP static u64 GetReg32_11(struct Machine *m) {\n  return Get32(m->weg[11]);\n}\nMICRO_OP static u64 GetReg32_12(struct Machine *m) {\n  return Get32(m->weg[12]);\n}\nMICRO_OP static u64 GetReg32_13(struct Machine *m) {\n  return Get32(m->weg[13]);\n}\nMICRO_OP static u64 GetReg32_14(struct Machine *m) {\n  return Get32(m->weg[14]);\n}\nMICRO_OP static u64 GetReg32_15(struct Machine *m) {\n  return Get32(m->weg[15]);\n}\ntypedef u64 (*getreg32_f)(struct Machine *);\nconst getreg32_f kGetReg32[] = {\n    GetReg32_0,   //\n    GetReg32_1,   //\n    GetReg32_2,   //\n    GetReg32_3,   //\n    GetReg32_4,   //\n    GetReg32_5,   //\n    GetReg32_6,   //\n    GetReg32_7,   //\n    GetReg32_8,   //\n    GetReg32_9,   //\n    GetReg32_10,  //\n    GetReg32_11,  //\n    GetReg32_12,  //\n    GetReg32_13,  //\n    GetReg32_14,  //\n    GetReg32_15,  //\n};\n\nMICRO_OP static u64 GetReg64_0(struct Machine *m) {\n  return Get64(m->weg[0]);\n}\nMICRO_OP static u64 GetReg64_1(struct Machine *m) {\n  return Get64(m->weg[1]);\n}\nMICRO_OP static u64 GetReg64_2(struct Machine *m) {\n  return Get64(m->weg[2]);\n}\nMICRO_OP static u64 GetReg64_3(struct Machine *m) {\n  return Get64(m->weg[3]);\n}\nMICRO_OP static u64 GetReg64_4(struct Machine *m) {\n  return Get64(m->weg[4]);\n}\nMICRO_OP static u64 GetReg64_5(struct Machine *m) {\n  return Get64(m->weg[5]);\n}\nMICRO_OP static u64 GetReg64_6(struct Machine *m) {\n  return Get64(m->weg[6]);\n}\nMICRO_OP static u64 GetReg64_7(struct Machine *m) {\n  return Get64(m->weg[7]);\n}\nMICRO_OP static u64 GetReg64_8(struct Machine *m) {\n  return Get64(m->weg[8]);\n}\nMICRO_OP static u64 GetReg64_9(struct Machine *m) {\n  return Get64(m->weg[9]);\n}\nMICRO_OP static u64 GetReg64_10(struct Machine *m) {\n  return Get64(m->weg[10]);\n}\nMICRO_OP static u64 GetReg64_11(struct Machine *m) {\n  return Get64(m->weg[11]);\n}\nMICRO_OP static u64 GetReg64_12(struct Machine *m) {\n  return Get64(m->weg[12]);\n}\nMICRO_OP static u64 GetReg64_13(struct Machine *m) {\n  return Get64(m->weg[13]);\n}\nMICRO_OP static u64 GetReg64_14(struct Machine *m) {\n  return Get64(m->weg[14]);\n}\nMICRO_OP static u64 GetReg64_15(struct Machine *m) {\n  return Get64(m->weg[15]);\n}\ntypedef u64 (*getreg64_f)(struct Machine *);\nconst getreg64_f kGetReg64[] = {\n    GetReg64_0,   //\n    GetReg64_1,   //\n    GetReg64_2,   //\n    GetReg64_3,   //\n    GetReg64_4,   //\n    GetReg64_5,   //\n    GetReg64_6,   //\n    GetReg64_7,   //\n    GetReg64_8,   //\n    GetReg64_9,   //\n    GetReg64_10,  //\n    GetReg64_11,  //\n    GetReg64_12,  //\n    GetReg64_13,  //\n    GetReg64_14,  //\n    GetReg64_15,  //\n};\n\n////////////////////////////////////////////////////////////////////////////////\n// WRITING TO REGISTER FILE\n\nMICRO_OP void ZeroRegFlags(struct Machine *m, long i) {\n  Put64(m->weg[i], 0);\n  m->flags &= ~(CF | ZF | SF | OF | AF | 0xFF000000u);\n  m->flags |= 1 << FLAGS_ZF;\n}\n\nMICRO_OP static void PutReg8(struct Machine *m, long i, u64 x) {\n  Put8(m->beg + i, x);\n}\nMICRO_OP static void PutReg16(struct Machine *m, long i, u64 x) {\n  Put16(m->weg[i], x);\n}\nMICRO_OP static void PutReg32(struct Machine *m, long i, u64 x) {\n  Put64(m->weg[i], x & 0xffffffff);\n}\nMICRO_OP static void PutReg64(struct Machine *m, long i, u64 x) {\n  Put64(m->weg[i], x);\n}\nMICRO_OP static void PutReg128(u64 x, u64 y, struct Machine *m, long i) {\n  Put64(m->xmm[i], x);\n  Put64(m->xmm[i] + 8, y);\n}\ntypedef void (*putreg_f)(struct Machine *, long, u64);\nstatic const putreg_f kPutReg[] = {PutReg8, PutReg16,   //\n                                   PutReg32, PutReg64,  //\n                                   (putreg_f)PutReg128};\n\nMICRO_OP static void PutReg32_0(u64 x, struct Machine *m) {\n  Put64(m->weg[0], (u32)x);\n}\nMICRO_OP static void PutReg32_1(u64 x, struct Machine *m) {\n  Put64(m->weg[1], (u32)x);\n}\nMICRO_OP static void PutReg32_2(u64 x, struct Machine *m) {\n  Put64(m->weg[2], (u32)x);\n}\nMICRO_OP static void PutReg32_3(u64 x, struct Machine *m) {\n  Put64(m->weg[3], (u32)x);\n}\nMICRO_OP static void PutReg32_4(u64 x, struct Machine *m) {\n  Put64(m->weg[4], (u32)x);\n}\nMICRO_OP static void PutReg32_5(u64 x, struct Machine *m) {\n  Put64(m->weg[5], (u32)x);\n}\nMICRO_OP static void PutReg32_6(u64 x, struct Machine *m) {\n  Put64(m->weg[6], (u32)x);\n}\nMICRO_OP static void PutReg32_7(u64 x, struct Machine *m) {\n  Put64(m->weg[7], (u32)x);\n}\nMICRO_OP static void PutReg32_8(u64 x, struct Machine *m) {\n  Put64(m->weg[8], (u32)x);\n}\nMICRO_OP static void PutReg32_9(u64 x, struct Machine *m) {\n  Put64(m->weg[9], (u32)x);\n}\nMICRO_OP static void PutReg32_10(u64 x, struct Machine *m) {\n  Put64(m->weg[10], (u32)x);\n}\nMICRO_OP static void PutReg32_11(u64 x, struct Machine *m) {\n  Put64(m->weg[11], (u32)x);\n}\nMICRO_OP static void PutReg32_12(u64 x, struct Machine *m) {\n  Put64(m->weg[12], (u32)x);\n}\nMICRO_OP static void PutReg32_13(u64 x, struct Machine *m) {\n  Put64(m->weg[13], (u32)x);\n}\nMICRO_OP static void PutReg32_14(u64 x, struct Machine *m) {\n  Put64(m->weg[14], (u32)x);\n}\nMICRO_OP static void PutReg32_15(u64 x, struct Machine *m) {\n  Put64(m->weg[15], (u32)x);\n}\ntypedef void (*putreg32_f)(u64, struct Machine *);\nconst putreg32_f kPutReg32[] = {\n    PutReg32_0,   //\n    PutReg32_1,   //\n    PutReg32_2,   //\n    PutReg32_3,   //\n    PutReg32_4,   //\n    PutReg32_5,   //\n    PutReg32_6,   //\n    PutReg32_7,   //\n    PutReg32_8,   //\n    PutReg32_9,   //\n    PutReg32_10,  //\n    PutReg32_11,  //\n    PutReg32_12,  //\n    PutReg32_13,  //\n    PutReg32_14,  //\n    PutReg32_15,  //\n};\n\nMICRO_OP static void PutReg64_0(u64 x, struct Machine *m) {\n  Put64(m->weg[0], x);\n}\nMICRO_OP static void PutReg64_1(u64 x, struct Machine *m) {\n  Put64(m->weg[1], x);\n}\nMICRO_OP static void PutReg64_2(u64 x, struct Machine *m) {\n  Put64(m->weg[2], x);\n}\nMICRO_OP static void PutReg64_3(u64 x, struct Machine *m) {\n  Put64(m->weg[3], x);\n}\nMICRO_OP static void PutReg64_4(u64 x, struct Machine *m) {\n  Put64(m->weg[4], x);\n}\nMICRO_OP static void PutReg64_5(u64 x, struct Machine *m) {\n  Put64(m->weg[5], x);\n}\nMICRO_OP static void PutReg64_6(u64 x, struct Machine *m) {\n  Put64(m->weg[6], x);\n}\nMICRO_OP static void PutReg64_7(u64 x, struct Machine *m) {\n  Put64(m->weg[7], x);\n}\nMICRO_OP static void PutReg64_8(u64 x, struct Machine *m) {\n  Put64(m->weg[8], x);\n}\nMICRO_OP static void PutReg64_9(u64 x, struct Machine *m) {\n  Put64(m->weg[9], x);\n}\nMICRO_OP static void PutReg64_10(u64 x, struct Machine *m) {\n  Put64(m->weg[10], x);\n}\nMICRO_OP static void PutReg64_11(u64 x, struct Machine *m) {\n  Put64(m->weg[11], x);\n}\nMICRO_OP static void PutReg64_12(u64 x, struct Machine *m) {\n  Put64(m->weg[12], x);\n}\nMICRO_OP static void PutReg64_13(u64 x, struct Machine *m) {\n  Put64(m->weg[13], x);\n}\nMICRO_OP static void PutReg64_14(u64 x, struct Machine *m) {\n  Put64(m->weg[14], x);\n}\nMICRO_OP static void PutReg64_15(u64 x, struct Machine *m) {\n  Put64(m->weg[15], x);\n}\nconst putreg64_f kPutReg64[] = {\n    PutReg64_0,   //\n    PutReg64_1,   //\n    PutReg64_2,   //\n    PutReg64_3,   //\n    PutReg64_4,   //\n    PutReg64_5,   //\n    PutReg64_6,   //\n    PutReg64_7,   //\n    PutReg64_8,   //\n    PutReg64_9,   //\n    PutReg64_10,  //\n    PutReg64_11,  //\n    PutReg64_12,  //\n    PutReg64_13,  //\n    PutReg64_14,  //\n    PutReg64_15,  //\n};\n\n////////////////////////////////////////////////////////////////////////////////\n// MEMORY OPERATIONS\n\ntypedef i64 (*load_f)(const u8 *);\ntypedef void (*store_f)(u8 *, u64);\n\nMICRO_OP static u8 *ResolveHost(i64 v) {\n  return ToHost(v);\n}\n\nMICRO_OP static u8 *GetBegPtr(struct Machine *m, long i) {\n  return m->beg + i;\n}\n\nMICRO_OP static u8 *GetWegPtr(struct Machine *m, long i) {\n  return m->weg[i];\n}\n\nMICRO_OP static u8 *GetXmmPtr(struct Machine *m, long i) {\n  return m->xmm[i];\n}\n\nMICRO_OP void MovsdWpsVpsOp(u8 *p, struct Machine *m, long reg) {\n  Write64(p, Read64(m->xmm[reg]));\n}\n\n#if (defined(__x86_64__) || defined(__aarch64__)) && \\\n    defined(TRIVIALLY_RELOCATABLE)\n#define LOADSTORE \"m\"\n\nMICRO_OP static i64 NativeLoad8(const u8 *p) {\n  return *p;\n}\nMICRO_OP static i64 NativeLoad16(const u8 *p) {\n  return *(const u16 *)p;\n}\nMICRO_OP static i64 NativeLoad32(const u8 *p) {\n  return *(const u32 *)p;\n}\nMICRO_OP static i64 NativeLoad64(const u8 *p) {\n  return *(const u64 *)p;\n}\nMICRO_OP static XMM_TYPE NativeLoad128(u8 *p) {\n  RETURN_XMM(((const u64 *)p)[0], ((const u64 *)p)[1]);\n}\n\nMICRO_OP static void NativeStore8(u8 *p, u64 x) {\n  *p = x;\n}\nMICRO_OP static void NativeStore16(u8 *p, u64 x) {\n  *(u16 *)p = x;\n}\nMICRO_OP static void NativeStore32(u8 *p, u64 x) {\n  *(u32 *)p = x;\n}\nMICRO_OP static void NativeStore64(u8 *p, u64 x) {\n  *(u64 *)p = x;\n}\nMICRO_OP static void NativeStore128(u8 *p, u64 x, u64 y) {\n  ((u64 *)p)[0] = x;\n  ((u64 *)p)[1] = y;\n}\n\nstatic const load_f kLoad[] = {\n    (load_f)NativeLoad8,    //\n    (load_f)NativeLoad16,   //\n    (load_f)NativeLoad32,   //\n    (load_f)NativeLoad64,   //\n    (load_f)NativeLoad128,  //\n};\n\nstatic const store_f kStore[] = {\n    (store_f)NativeStore8,    //\n    (store_f)NativeStore16,   //\n    (store_f)NativeStore32,   //\n    (store_f)NativeStore64,   //\n    (store_f)NativeStore128,  //\n};\n\n#else\n#define LOADSTORE \"c\"\n\nMICRO_OP static XMM_TYPE Load128(u8 *p) {\n  RETURN_XMM(Read64(p), Read64(p + 8));\n}\n\nMICRO_OP static void Store128(u8 *p, u64 x, u64 y) {\n  Write64(p, x);\n  Write64(p + 8, y);\n}\n\nstatic const load_f kLoad[] = {Load8, Load16,   //\n                               Load32, Load64,  //\n                               (load_f)Load128};\nstatic const store_f kStore[] = {Store8, Store16,   //\n                                 Store32, Store64,  //\n                                 (store_f)Store128};\n\n#endif /* __GNUC__ */\n\n////////////////////////////////////////////////////////////////////////////////\n// ARITHMETIC\n\nMICRO_OP i64 JustAdd(struct Machine *m, u64 x, u64 y) {\n  return x + y;\n}\nMICRO_OP i64 JustOr(struct Machine *m, u64 x, u64 y) {\n  return x | y;\n}\nMICRO_OP i64 JustAdc(struct Machine *m, u64 x, u64 y) {\n  return x + y + !!(m->flags & CF);\n}\nMICRO_OP i64 JustSbb(struct Machine *m, u64 x, u64 y) {\n  return x - y - !!(m->flags & CF);\n}\nMICRO_OP i64 JustAnd(struct Machine *m, u64 x, u64 y) {\n  return x & y;\n}\nMICRO_OP i64 JustSub(struct Machine *m, u64 x, u64 y) {\n  return x - y;\n}\nMICRO_OP i64 JustXor(struct Machine *m, u64 x, u64 y) {\n  return x ^ y;\n}\nconst aluop_f kJustAlu[8] = {\n    JustAdd,  //\n    JustOr,   //\n    JustAdc,  //\n    JustSbb,  //\n    JustAnd,  //\n    JustSub,  //\n    JustXor,  //\n    JustSub,  //\n};\n\nMICRO_OP i64 JustRol(u64 x, int ign1, int ign2, u64 y) {\n  return x << y | x >> (64 - y);\n}\nMICRO_OP i64 JustRor(u64 x, int ign1, int ign2, u64 y) {\n  return x >> y | x << (64 - y);\n}\nMICRO_OP i64 JustShl(u64 x, int ign1, int ign2, u64 y) {\n  return x << y;\n}\nMICRO_OP i64 JustShr(u64 x, int ign1, int ign2, u64 y) {\n  return x >> y;\n}\nMICRO_OP i64 JustSar(u64 x, int ign1, int ign2, u64 y) {\n  return (i64)x >> y;\n}\nconst aluop_f kJustBsu[8] = {\n    (aluop_f)JustRol,  //\n    (aluop_f)JustRor,  //\n    0,                 //\n    0,                 //\n    (aluop_f)JustShl,  //\n    (aluop_f)JustShr,  //\n    (aluop_f)JustShl,  //\n    (aluop_f)JustSar,  //\n};\n\nMICRO_OP i64 JustRolCl64(u64 x, struct Machine *m) {\n  return x << (m->cl & 63) | x >> ((64 - m->cl) & 63);\n}\nMICRO_OP i64 JustRorCl64(u64 x, struct Machine *m) {\n  return x >> (m->cl & 63) | x << ((64 - m->cl) & 63);\n}\nMICRO_OP i64 JustShlCl64(u64 x, struct Machine *m) {\n  return x << (m->cl & 63);\n}\nMICRO_OP i64 JustShrCl64(u64 x, struct Machine *m) {\n  return x >> (m->cl & 63);\n}\nMICRO_OP i64 JustSarCl64(u64 x, struct Machine *m) {\n  return (i64)x >> (m->cl & 63);\n}\nconst aluop_f kJustBsuCl64[8] = {\n    (aluop_f)JustRolCl64,  //\n    (aluop_f)JustRorCl64,  //\n    0,                     //\n    0,                     //\n    (aluop_f)JustShlCl64,  //\n    (aluop_f)JustShrCl64,  //\n    (aluop_f)JustShlCl64,  //\n    (aluop_f)JustSarCl64,  //\n};\n\nMICRO_OP i32 JustRolCl32(u32 x, struct Machine *m) {\n  return x << (m->cl & 31) | x >> ((32 - m->cl) & 31);\n}\nMICRO_OP i32 JustRorCl32(u32 x, struct Machine *m) {\n  return x >> (m->cl & 31) | x << ((32 - m->cl) & 31);\n}\nMICRO_OP i32 JustShlCl32(u32 x, struct Machine *m) {\n  return x << (m->cl & 31);\n}\nMICRO_OP i32 JustShrCl32(u32 x, struct Machine *m) {\n  return x >> (m->cl & 31);\n}\nMICRO_OP i32 JustSarCl32(u32 x, struct Machine *m) {\n  return (i32)x >> (m->cl & 31);\n}\nconst aluop_f kJustBsuCl32[8] = {\n    (aluop_f)JustRolCl32,  //\n    (aluop_f)JustRorCl32,  //\n    0,                     //\n    0,                     //\n    (aluop_f)JustShlCl32,  //\n    (aluop_f)JustShrCl32,  //\n    (aluop_f)JustShlCl32,  //\n    (aluop_f)JustSarCl32,  //\n};\n\nMICRO_OP i32 JustRol32(u32 x, int ign1, int ign2, u32 y) {\n  return x << y | x >> (32 - y);\n}\nMICRO_OP i32 JustRor32(u32 x, int ign1, int ign2, u32 y) {\n  return x >> y | x << (32 - y);\n}\nMICRO_OP i32 JustShl32(u32 x, int ign1, int ign2, u32 y) {\n  return x << y;\n}\nMICRO_OP i32 JustShr32(u32 x, int ign1, int ign2, u32 y) {\n  return x >> y;\n}\nMICRO_OP i32 JustSar32(u32 x, int ign1, int ign2, u32 y) {\n  return (i32)x >> y;\n}\nconst aluop_f kJustBsu32[8] = {\n    (aluop_f)JustRol32,  //\n    (aluop_f)JustRor32,  //\n    0,                   //\n    0,                   //\n    (aluop_f)JustShl32,  //\n    (aluop_f)JustShr32,  //\n    (aluop_f)JustShl32,  //\n    (aluop_f)JustSar32,  //\n};\n\n#if X86_INTRINSICS\n#define ALU_FAST(M, TYPE, X, Y, OP, COMMUT)                             \\\n  ({                                                                    \\\n    TYPE Res;                                                           \\\n    u32 OldFlags = (M)->flags & ~(OF | SF | ZF | AF | CF);              \\\n    u64 NewFlags;                                                       \\\n    asm(OP \"\\t%3,%0\\n\\t\"                                                \\\n        \"pushfq\\n\\t\"                                                    \\\n        \"pop\\t%1\"                                                       \\\n        : \"=&r\" (Res), \"=r\" (NewFlags)                                  \\\n        : COMMUT \"0\" ((TYPE)(X)), \"g\" ((TYPE)(Y))                       \\\n        : \"cc\");                                                        \\\n    (M)->flags = OldFlags | ((u32)NewFlags & (OF | SF | ZF | AF | CF)); \\\n    Res;                                                                \\\n  })\n#define ALU_FAST_CF(M, TYPE, X, Y, OP, COMMUT)                          \\\n  ({                                                                    \\\n    TYPE Res;                                                           \\\n    u32 OldFlags = (M)->flags & ~(OF | SF | ZF | AF);                   \\\n    u64 NewFlags;                                                       \\\n    asm(\"btr\\t%5,%2\\n\\t\"                                                \\\n        OP \"\\t%4,%0\\n\\t\"                                                \\\n        \"pushfq\\n\\t\"                                                    \\\n        \"pop\\t%1\"                                                       \\\n        : \"=&r\" (Res), \"=r\" (NewFlags), \"+&r\" (OldFlags)                \\\n        : COMMUT \"0\" ((TYPE)(X)), \"g\" ((TYPE)(Y)),                      \\\n          \"i\" (FLAGS_CF)                                                \\\n        : \"cc\");                                                        \\\n    (M)->flags = OldFlags | ((u32)NewFlags & (OF | SF | ZF | AF | CF)); \\\n    Res;                                                                \\\n  })\nMICRO_OP static i64 FastXor64(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u64, x, y, \"xor\", \"%\");\n}\nMICRO_OP static i64 FastOr64(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u64, x, y, \"or\", \"%\");\n}\nMICRO_OP static i64 FastAnd64(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u64, x, y, \"and\", \"%\");\n}\nMICRO_OP static i64 FastSub64(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u64, x, y, \"sub\", \"\");\n}\nMICRO_OP static i64 FastAdd64(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u64, x, y, \"add\", \"%\");\n}\nMICRO_OP static i64 FastAdc64(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST_CF(m, u64, x, y, \"adc\", \"%\");\n}\nMICRO_OP static i64 FastSbb64(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST_CF(m, u64, x, y, \"sbb\", \"\");\n}\nMICRO_OP static i64 FastXor32(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u32, x, y, \"xor\", \"%\");\n}\nMICRO_OP static i64 FastOr32(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u32, x, y, \"or\", \"%\");\n}\nMICRO_OP static i64 FastAnd32(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u32, x, y, \"and\", \"%\");\n}\nMICRO_OP static i64 FastSub32(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u32, x, y, \"sub\", \"\");\n}\nMICRO_OP static i64 FastAdd32(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u32, x, y, \"add\", \"%\");\n}\nMICRO_OP static i64 FastAdc32(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST_CF(m, u32, x, y, \"adc\", \"%\");\n}\nMICRO_OP static i64 FastSbb32(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST_CF(m, u32, x, y, \"sbb\", \"\");\n}\nMICRO_OP static i64 FastXor16(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u16, x, y, \"xor\", \"%\");\n}\nMICRO_OP static i64 FastOr16(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u16, x, y, \"or\", \"%\");\n}\nMICRO_OP static i64 FastAnd16(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u16, x, y, \"and\", \"%\");\n}\nMICRO_OP static i64 FastSub16(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u16, x, y, \"sub\", \"\");\n}\nMICRO_OP static i64 FastAdd16(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u16, x, y, \"add\", \"%\");\n}\nMICRO_OP static i64 FastAdc16(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST_CF(m, u16, x, y, \"adc\", \"%\");\n}\nMICRO_OP static i64 FastSbb16(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST_CF(m, u16, x, y, \"sbb\", \"\");\n}\nMICRO_OP static i64 FastXor8(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u8, x, y, \"xor\", \"%\");\n}\nMICRO_OP static i64 FastOr8(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u8, x, y, \"or\", \"%\");\n}\nMICRO_OP static i64 FastAnd8(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u8, x, y, \"and\", \"%\");\n}\nMICRO_OP static i64 FastSub8(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u8, x, y, \"sub\", \"\");\n}\nMICRO_OP static i64 FastAdd8(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST(m, u8, x, y, \"add\", \"%\");\n}\nMICRO_OP static i64 FastAdc8(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST_CF(m, u8, x, y, \"adc\", \"%\");\n}\nMICRO_OP static i64 FastSbb8(struct Machine *m, u64 x, u64 y) {\n  return ALU_FAST_CF(m, u8, x, y, \"sbb\", \"\");\n}\n#else /* !X86_INTRINSICS */\nMICRO_OP static i64 FastXor64(struct Machine *m, u64 x, u64 y) {\n  u64 z = x ^ y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastOr64(struct Machine *m, u64 x, u64 y) {\n  u64 z = x | y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastAnd64(struct Machine *m, u64 x, u64 y) {\n  u64 z = x & y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastSub64(struct Machine *m, u64 x, u64 y) {\n  u64 z = x - y;\n  int c = x < z;\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastAdd64(struct Machine *m, u64 x, u64 y) {\n  u64 z = x + y;\n  int c = z < y;\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastAdc64(struct Machine *m, u64 x, u64 y) {\n  u64 t = x + !!(m->flags & CF);\n  u64 z = t + y;\n  int c = (t < x) | (z < y);\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastSbb64(struct Machine *m, u64 x, u64 y) {\n  u64 t = x - !!(m->flags & CF);\n  u64 z = t - y;\n  int c = (x < t) | (t < z);\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\n\nMICRO_OP static i64 FastXor32(struct Machine *m, u64 x, u64 y) {\n  u32 z = x ^ y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastOr32(struct Machine *m, u64 x, u64 y) {\n  u32 z = x | y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastAnd32(struct Machine *m, u64 x, u64 y) {\n  u32 z = x & y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastSub32(struct Machine *m, u64 x, u64 y) {\n  u32 z = x - y;\n  int c = x < z;\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastAdd32(struct Machine *m, u64 x, u64 y) {\n  u32 z = x + y;\n  int c = z < y;\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastAdc32(struct Machine *m, u64 x, u64 y) {\n  u32 t = x + !!(m->flags & CF);\n  u32 z = t + y;\n  int c = (t < x) | (z < y);\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastSbb32(struct Machine *m, u64 x, u64 y) {\n  u32 t = x - !!(m->flags & CF);\n  u32 z = t - y;\n  int c = (x < t) | (t < z);\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\n\nMICRO_OP static i64 FastXor16(struct Machine *m, u64 x, u64 y) {\n  u16 z = x ^ y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastOr16(struct Machine *m, u64 x, u64 y) {\n  u16 z = x | y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastAnd16(struct Machine *m, u64 x, u64 y) {\n  u16 z = x & y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastSub16(struct Machine *m, u64 x, u64 y) {\n  u16 z = x - y;\n  int c = x < z;\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastAdd16(struct Machine *m, u64 x, u64 y) {\n  u16 z = x + y;\n  int c = z < y;\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastAdc16(struct Machine *m, u64 x, u64 y) {\n  u16 t = x + !!(m->flags & CF);\n  u16 z = t + y;\n  int c = (t < x) | (z < y);\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastSbb16(struct Machine *m, u64 x, u64 y) {\n  u16 t = x - !!(m->flags & CF);\n  u16 z = t - y;\n  int c = (x < t) | (t < z);\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\n\nMICRO_OP static i64 FastXor8(struct Machine *m, u64 x, u64 y) {\n  u8 z = x ^ y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastOr8(struct Machine *m, u64 x, u64 y) {\n  u8 z = x | y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP i64 FastAnd8(struct Machine *m, u64 x, u64 y) {\n  u8 z = x & y;\n  m->flags = (m->flags & ~(CF | ZF)) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP i64 FastSub8(struct Machine *m, u64 x, u64 y) {\n  u8 z = x - y;\n  int c = x < z;\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastAdd8(struct Machine *m, u64 x, u64 y) {\n  u8 z = x + y;\n  int c = z < y;\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastAdc8(struct Machine *m, u64 x, u64 y) {\n  u8 t = x + !!(m->flags & CF);\n  u8 z = t + y;\n  int c = (t < x) | (z < y);\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastSbb8(struct Machine *m, u64 x, u64 y) {\n  u8 t = x - !!(m->flags & CF);\n  u8 z = t - y;\n  int c = (x < t) | (t < z);\n  m->flags = (m->flags & ~(CF | ZF)) | c << FLAGS_CF | !z << FLAGS_ZF;\n  return z;\n}\n#endif /* !X86_INTRINSICS */\n\nconst aluop_f kAluFast[8][4] = {\n    {FastAdd8, FastAdd16, FastAdd32, FastAdd64},  //\n    {FastOr8, FastOr16, FastOr32, FastOr64},      //\n    {FastAdc8, FastAdc16, FastAdc32, FastAdc64},  //\n    {FastSbb8, FastSbb16, FastSbb32, FastSbb64},  //\n    {FastAnd8, FastAnd16, FastAnd32, FastAnd64},  //\n    {FastSub8, FastSub16, FastSub32, FastSub64},  //\n    {FastXor8, FastXor16, FastXor32, FastXor64},  //\n    {FastSub8, FastSub16, FastSub32, FastSub64},  //\n};\n\nMICRO_OP u32 JustMul32(u32 x, u32 y, struct Machine *m) {\n  return x * y;\n}\nMICRO_OP u64 JustMul64(u64 x, u64 y, struct Machine *m) {\n  return x * y;\n}\n\nMICRO_OP i32 Imul32(i32 x, i32 y, struct Machine *m) {\n  int o;\n  i64 z;\n  z = (i64)x * y;\n  o = z != (i32)z;\n  m->flags = (m->flags & ~(CF | OF)) | o << FLAGS_CF | o << FLAGS_OF;\n  return z;\n}\n#ifdef HAVE_INT128\nMICRO_OP i64 Imul64(i64 x, i64 y, struct Machine *m) {\n  int o;\n  __int128 z;\n  z = (__int128)x * y;\n  o = z != (i64)z;\n  m->flags = (m->flags & ~(CF | OF)) | o << FLAGS_CF | o << FLAGS_OF;\n  return z;\n}\nMICRO_OP void JustMulAxDx(u64 x, struct Machine *m) {\n  unsigned __int128 z;\n  z = (unsigned __int128)x * Get64(m->ax);\n  Put64(m->ax, z);\n  Put64(m->dx, z >> 64);\n}\nMICRO_OP void MulAxDx(u64 x, struct Machine *m) {\n  int o;\n  unsigned __int128 z;\n  z = (unsigned __int128)x * Get64(m->ax);\n  o = z != (u64)z;\n  m->flags = (m->flags & ~(CF | OF)) | o << FLAGS_CF | o << FLAGS_OF;\n  Put64(m->ax, z);\n  Put64(m->dx, z >> 64);\n}\n#ifndef DISABLE_BMI2\nMICRO_OP void Mulx64(u64 x,              //\n                     struct Machine *m,  //\n                     long vreg,          //\n                     long rexrreg) {\n  unsigned __int128 z;\n  z = (unsigned __int128)x * Get64(m->dx);\n  Put64(m->weg[vreg], z);\n  Put64(m->weg[rexrreg], z >> 64);\n}\n#endif /* !DISABLE_BMI2 */\n#endif /* HAVE_INT128 */\n\nMICRO_OP i64 JustNeg(u64 x) {\n  return -x;\n}\n\nMICRO_OP i64 JustDec(u64 x) {\n  return x - 1;\n}\n\nMICRO_OP static i64 FastDec64(u64 x, struct Machine *m) {\n  u64 z;\n  z = x - 1;\n  m->flags = (m->flags & ~ZF) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastDec32(u64 x64, struct Machine *m) {\n  u32 x, z;\n  x = x64;\n  z = x - 1;\n  m->flags = (m->flags & ~ZF) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastDec16(u64 x64, struct Machine *m) {\n  u16 x, z;\n  x = x64;\n  z = x - 1;\n  m->flags = (m->flags & ~ZF) | !z << FLAGS_ZF;\n  return z;\n}\nMICRO_OP static i64 FastDec8(u64 x64, struct Machine *m) {\n  u8 x, z;\n  x = x64;\n  z = x - 1;\n  m->flags = (m->flags & ~ZF) | !z << FLAGS_ZF;\n  return z;\n}\n\nconst aluop_f kFastDec[4] = {\n    (aluop_f)FastDec8,   //\n    (aluop_f)FastDec16,  //\n    (aluop_f)FastDec32,  //\n    (aluop_f)FastDec64,  //\n};\n\n////////////////////////////////////////////////////////////////////////////////\n// STACK OPERATIONS\n\nMICRO_OP void FastPush(struct Machine *m, long rexbsrm) {\n  u64 v, x = Get64(m->weg[rexbsrm]);\n  Put64(m->sp, (v = Get64(m->sp) - 8));\n  Write64(ToHost(v), x);\n}\n\nMICRO_OP void FastPop(struct Machine *m, long rexbsrm) {\n  u64 v = Get64(m->sp);\n  Put64(m->sp, v + 8);\n  Put64(m->weg[rexbsrm], Read64(ToHost(v)));\n}\n\nMICRO_OP void FastCall(struct Machine *m, u64 disp) {\n  u64 v, x = m->ip + disp;\n  Put64(m->sp, (v = Get64(m->sp) - 8));\n  Write64(ToHost(v), m->ip);\n  m->ip = x;\n}\n\nMICRO_OP void FastCallAbs(u64 x, struct Machine *m) {\n  u64 v;\n  Put64(m->sp, (v = Get64(m->sp) - 8));\n  Write64(ToHost(v), m->ip);\n  m->ip = x;\n}\n\nMICRO_OP void FastLeave(struct Machine *m) {\n  u64 v = Get64(m->bp);\n  Put64(m->sp, v + 8);\n  Put64(m->bp, Read64(ToHost(v)));\n}\n\nMICRO_OP i64 PredictRet(struct Machine *m, i64 prediction) {\n  u64 v = Get64(m->sp);\n  Put64(m->sp, v + 8);\n  m->ip = Read64(ToHost(v));\n  return m->ip ^ prediction;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// SIGN EXTENDING\n\nMICRO_OP static u64 Sex8(u64 x) {\n  return (i8)x;\n}\nMICRO_OP static u64 Sex16(u64 x) {\n  return (i16)x;\n}\nMICRO_OP static u64 Sex32(u64 x) {\n  return (i32)x;\n}\ntypedef u64 (*sex_f)(u64);\nstatic const sex_f kSex[] = {Sex8, Sex16, Sex32};\n\n////////////////////////////////////////////////////////////////////////////////\n// ADDRESSING\n\nMICRO_OP static u64 Truncate32(u64 x) {\n  return (u32)x;\n}\nMICRO_OP static i64 Seg(struct Machine *m, u64 d, long s) {\n  return d + m->seg[s].base;\n}\nMICRO_OP static i64 Base(struct Machine *m, u64 d, long i) {\n  return d + Get64(m->weg[i]);\n}\nMICRO_OP static i64 Index(struct Machine *m, u64 d, long i, int z) {\n  return d + (Get64(m->weg[i]) << z);\n}\nMICRO_OP static i64 BaseIndex0(struct Machine *m, u64 d, long b, long i) {\n  return d + Get64(m->weg[b]) + Get64(m->weg[i]);\n}\nMICRO_OP static i64 BaseIndex1(struct Machine *m, u64 d, long b, long i) {\n  return d + Get64(m->weg[b]) + (Get64(m->weg[i]) << 1);\n}\nMICRO_OP static i64 BaseIndex2(struct Machine *m, u64 d, long b, long i) {\n  return d + Get64(m->weg[b]) + (Get64(m->weg[i]) << 2);\n}\nMICRO_OP static i64 BaseIndex3(struct Machine *m, u64 d, long b, long i) {\n  return d + Get64(m->weg[b]) + (Get64(m->weg[i]) << 3);\n}\n\ntypedef i64 (*baseindex_f)(struct Machine *, u64, long, long);\nstatic const baseindex_f kBaseIndex[] = {\n    BaseIndex0,  //\n    BaseIndex1,  //\n    BaseIndex2,  //\n    BaseIndex3,  //\n};\n\n////////////////////////////////////////////////////////////////////////////////\n// JIT DEBUGGING UTILITIES\n\nstatic pureconst bool UsesStaticMemory(u64 rde) {\n  return !IsModrmRegister(rde) &&  //\n         !SibExists(rde) &&        //\n         IsRipRelative(rde);       //\n}\n\nstatic void ClobberEverythingExceptResult(struct Machine *m) {\n#ifdef DEBUG\n// clobber everything except result registers\n#if defined(__x86_64__) && !defined(__CYGWIN__)\n  AppendJitSetReg(m->path.jb, kAmdDi, 0x666);\n  AppendJitSetReg(m->path.jb, kAmdSi, 0x666);\n  AppendJitSetReg(m->path.jb, kAmdCx, 0x666);\n  AppendJitSetReg(m->path.jb, 8, 0x666);\n  AppendJitSetReg(m->path.jb, 9, 0x666);\n  AppendJitSetReg(m->path.jb, 10, 0x666);\n  AppendJitSetReg(m->path.jb, 11, 0x666);\n#elif defined(__aarch64__)\n  AppendJitSetReg(m->path.jb, 2, 0x666);\n  AppendJitSetReg(m->path.jb, 3, 0x666);\n  AppendJitSetReg(m->path.jb, 4, 0x666);\n  AppendJitSetReg(m->path.jb, 5, 0x666);\n  AppendJitSetReg(m->path.jb, 6, 0x666);\n  AppendJitSetReg(m->path.jb, 7, 0x666);\n  AppendJitSetReg(m->path.jb, 9, 0x666);\n  AppendJitSetReg(m->path.jb, 10, 0x666);\n  AppendJitSetReg(m->path.jb, 11, 0x666);\n  AppendJitSetReg(m->path.jb, 12, 0x666);\n  AppendJitSetReg(m->path.jb, 13, 0x666);\n  AppendJitSetReg(m->path.jb, 14, 0x666);\n  AppendJitSetReg(m->path.jb, 15, 0x666);\n#endif\n#endif\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// FUNCTION BODY EXTRACTOR\n\nstatic bool IsRet(u8 *p) {\n#if defined(__aarch64__)\n  return Get32(p) == kArmRet;\n#elif defined(__x86_64__)\n  return *p == kAmdRet;\n#else\n  __builtin_unreachable();\n#endif\n}\n\nstatic long GetInstructionLength(u8 *p) {\n#if defined(__aarch64__)\n  // on AArch64, do not recognize instructions which are known to be not\n  // trivially relocatable i.e. opcodes which do PC-relative addressing;\n  // but as exceptions, allow CBZ, CBNZ, TBZ, TBNZ, & B.cond\n  u32 ins = Get32(p);\n  if ((ins & ~kArmDispMask) == kArmJmp) return -1;\n  if ((ins & ~kArmDispMask) == kArmCall) return -1;\n  if ((ins & kArmAdrMask) == kArmAdr) return -1;\n  if ((ins & kArmAdrpMask) == kArmAdrp) return -1;\n  if ((ins & kArmLdrPcMask) == kArmLdrPc) return -1;\n  if ((ins & kArmLdrswPcMask) == kArmLdrswPc) return -1;\n  if ((ins & kArmPrfmPcMask) == kArmPrfmPc) return -1;\n  return 4;\n#elif defined(__x86_64__) /* !__aarch64__ */\n  struct XedDecodedInst x;\n  unassert(!DecodeInstruction(&x, p, 15, XED_MODE_LONG));\n#ifndef NDEBUG\n  if (ClassifyOp(x.op.rde) == kOpBranching) return -1;\n  if (UsesStaticMemory(x.op.rde)) return -1;\n#endif /* NDEBUG */\n  return x.length;\n#else /* !__x86_64__ */\n  __builtin_unreachable();\n#endif /* !__x86_64__ */\n}\n\nstatic long GetMicroOpLengthImpl(void *uop) {\n  long k, n = 0;\n  for (;;) {\n    if (IsRet((u8 *)uop + n)) return n;\n    k = GetInstructionLength((u8 *)uop + n);\n    if (k == -1) return -1;\n    n += k;\n  }\n}\n\nstatic long GetMicroOpLength(void *uop) {\n  _Static_assert(IS2POW(kMaxOps), \"\");\n  static unsigned count;\n  static void *ops[kMaxOps * 2];\n  static short len[kMaxOps * 2];\n  long res;\n  unsigned hash, i, step;\n  i = 0;\n  step = 0;\n  hash = ((uintptr_t)uop * 0x9e3779b1u) >> 16;\n  do {\n    i = (hash + step * (step + 1) / 2) & (kMaxOps - 1);\n    if (ops[i] == uop) return len[i];\n    ++step;\n  } while (ops[i]);\n  res = GetMicroOpLengthImpl(uop);\n  unassert(count++ < kMaxOps);\n  ops[i] = uop;\n  len[i] = res;\n  return res;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// PRINTF-STYLE X86 MICROCODING WITH POSTFIX NOTATION\n\n#define ItemsRequired(n) unassert(i >= n)\n\n_Thread_local static long i;\n_Thread_local static u8 stack[8];\n\nstatic inline unsigned CheckBelow(unsigned x, unsigned n) {\n  unassert(x < n);\n  return x;\n}\n\nstatic void CallFunction(struct Machine *m, void *fun) {\n  AppendJitCall(m->path.jb, fun);\n  ClobberEverythingExceptResult(m);\n}\n\nstatic void CallMicroOp(struct Machine *m, void *fun) {\n#ifdef TRIVIALLY_RELOCATABLE\n  long len;\n  if ((len = GetMicroOpLength(fun)) > 0) {\n    AppendJit(m->path.jb, fun, len);\n  } else {\n    LOG_ONCE(LOGF(\"jit micro-operation at address %\" PRIxPTR\n                  \" has branches or static memory references\",\n                  (uintptr_t)fun));\n    CallFunction(m, fun);\n  }\n#else\n  CallFunction(m, fun);\n#endif\n}\n\nstatic void GetReg_32_64(struct Machine *m, void *fun) {\n  AppendJitMovReg(m->path.jb, kJitArg0, kJitSav0);\n  CallMicroOp(m, fun);\n}\n\nstatic void GetReg(P, unsigned log2sz, unsigned reg, unsigned breg) {\n  switch (log2sz) {\n    case 0:\n      Jitter(A,\n             \"q\"    // arg0 = machine\n             \"a1i\"  // arg1 = register index\n             \"m\",   // call micro-op\n             (u64)kByteReg[breg], kGetReg[0]);\n      break;\n    case 2:\n      GetReg_32_64(m, kGetReg32[reg]);\n      break;\n    case 3:\n      GetReg_32_64(m, kGetReg64[reg]);\n      break;\n    default:\n      Jitter(A,\n             \"q\"    // arg0 = machine\n             \"a1i\"  // arg1 = register index\n             \"m\",   // call micro-op\n             (u64)reg, kGetReg[log2sz]);\n      break;\n  }\n}\n\nstatic void PutReg_32_64(struct Machine *m, void *fun) {\n  ItemsRequired(1);\n  AppendJitMovReg(m->path.jb, kJitArg1, kJitSav0);\n  AppendJitMovReg(m->path.jb, kJitArg0, stack[i - 1]);\n  CallMicroOp(m, fun);\n  --i;\n}\n\nstatic void PutReg(P, unsigned log2sz, unsigned reg, unsigned breg) {\n  switch (log2sz) {\n    case 0:\n      ItemsRequired(1);\n      Jitter(A,\n             \"a2=\"  // arg2 = <pop>\n             \"a1i\"  // arg1 = register index\n             \"q\"    // arg0 = machine\n             \"m\",   // call micro-op\n             (u64)kByteReg[breg], kPutReg[0]);\n      break;\n    case 1:\n      ItemsRequired(1);\n      Jitter(A,\n             \"a2=\"  // arg2 = <pop>\n             \"a1i\"  // arg1 = register index\n             \"q\"    // arg0 = machine\n             \"m\",   // call micro-op\n             (u64)reg, kPutReg[1]);\n      break;\n    case 2:\n      PutReg_32_64(m, kPutReg32[reg]);\n      break;\n    case 3:\n      PutReg_32_64(m, kPutReg64[reg]);\n      break;\n    case 4:\n      // note: r0 == a0 on aarch64\n      // note: r1 == a1 on aarch64\n      // note: r1 == a2 on system five\n      // note: r1 == a1 on cygwin\n      Jitter(A,\n             \"a3i\"    // arg3 = register index\n             \"r1a1=\"  // arg1 = res1\n             \"s0a2=\"  // arg2 = machine\n             \"t\"      // arg0 = res0\n             \"m\",     // call micro-op\n             (u64)reg, kPutReg[log2sz]);\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic unsigned JitterImpl(P, const char *fmt, va_list va, unsigned k,\n                           unsigned depth) {\n  unsigned c, log2sz;\n  log2sz = RegLog2(rde);\n  LogCodOp(m, fmt);\n  while ((c = fmt[k++])) {\n    switch (c) {\n\n      case ' ':  // nop\n        break;\n\n      case 'u':  // unpop\n        i += 1;\n        break;\n\n      case '!':  // trap\n        AppendJitTrap(m->path.jb);\n        break;\n\n      case '%':  // register\n        switch ((c = fmt[k++])) {\n          case 'c':\n            switch ((c = fmt[k++])) {\n              case 'l':\n                Jitter(A,\n                       \"q\"   // arg0 = machine\n                       \"m\",  // call micro-op\n                       GetCl);\n                break;\n              default:\n                unassert(!\"bad register\");\n            }\n            break;\n          default:\n            unassert(!\"bad register\");\n        }\n        break;\n\n      case 'm':  // micro-op\n        CallMicroOp(m, va_arg(va, void *));\n        break;\n\n      case 'c':  // call\n        CallFunction(m, va_arg(va, void *));\n        break;\n\n      case 'r':  // push res reg\n        stack[i++] = kJitRes[CheckBelow(fmt[k++] - '0', ARRAYLEN(kJitRes))];\n        break;\n\n      case 'a':  // push arg reg\n        stack[i++] = kJitArg[CheckBelow(fmt[k++] - '0', ARRAYLEN(kJitArg))];\n        break;\n\n      case 's':  // push sav reg\n        stack[i++] = kJitSav[CheckBelow(fmt[k++] - '0', ARRAYLEN(kJitSav))];\n        break;\n\n      case 'i':  // set reg imm, e.g. (\"a1i\", 123) [mov $123,%rsi]\n        ItemsRequired(1);\n        AppendJitSetReg(m->path.jb, stack[--i], va_arg(va, u64));\n        break;\n\n      case '=':  // <src><dst>= mov reg, e.g. s0a0= [mov %rbx,%rdi]\n        ItemsRequired(2);\n        AppendJitMovReg(m->path.jb, stack[i - 1], stack[i - 2]);\n        i -= 2;\n        break;\n\n      case 'q':  // s0a0= [shortcut]\n        AppendJitMovReg(m->path.jb, kJitArg0, kJitSav0);\n        break;\n\n      case 't':  // r0a0= [shortcut]\n        AppendJitMovReg(m->path.jb, kJitArg0, kJitRes0);\n        break;\n\n      case 'A':  // res0 = GetReg(RexrReg)\n        GetReg(A, log2sz, RexrReg(rde), RexRexr(rde));\n        break;\n\n      case 'C':  // PutReg(RexrReg, <pop>)\n        PutReg(A, log2sz, RexrReg(rde), RexRexr(rde));\n        break;\n\n      case 'B':  // res0 = GetRegOrMem(RexbRm)\n        if (IsModrmRegister(rde)) {\n          GetReg(A, log2sz, RexbRm(rde), RexRexb(rde));\n        } else if (HasLinearMapping()) {\n          if (!kSkew) {\n            Jitter(A,\n                   \"L\"         // load effective address\n                   \"t\"         // arg0 = pointer\n                   LOADSTORE,  // call function (read word shared memory)\n                   kLoad[log2sz]);\n          } else {\n            Jitter(A,\n                   \"L\"         // load effective address\n                   \"t\"         // arg0 = virtual address\n                   \"m\"         // call micro-op (turn virtual into pointer)\n                   \"t\"         // arg0 = pointer\n                   LOADSTORE,  // call function (read word shared memory)\n                   ResolveHost, kLoad[log2sz]);\n          }\n        } else {\n          Jitter(A,\n                 \"L\"         // load effective address\n                 \"a3i\"       // arg3 = false\n                 \"a2i\"       // arg2 = bytes to read\n                 \"r0a1=\"     // arg1 = virtual address\n                 \"q\"         // arg0 = machine\n                 \"c\"         // call function (turn virtual into pointer)\n                 \"t\"         // arg0 = pointer\n                 LOADSTORE,  // call micro-op (read vector shared memory)\n                 (u64)0, (u64)(1 << log2sz), ReserveAddress, kLoad[log2sz]);\n        }\n        break;\n\n      case 'D':  // PutRegOrMem(RexbRm, <pop>), e.g. c r0 D\n        if (log2sz < 4) {\n          ItemsRequired(1);\n          if (IsModrmRegister(rde)) {\n            PutReg(A, log2sz, RexbRm(rde), RexRexb(rde));\n          } else if (HasLinearMapping()) {\n            if (!kSkew) {\n              Jitter(A,\n                     \"s3=\"       // sav3 = <pop>\n                     \"L\"         // load effective address\n                     \"s3a1=\"     // arg1 = sav3\n                     \"t\"         // arg0 = res0\n                     LOADSTORE,  // call micro-op (write word to shared memory)\n                     kStore[log2sz]);\n            } else {\n              Jitter(A,\n                     \"s3=\"       // sav3 = <pop>\n                     \"L\"         // load effective address\n                     \"t\"         // arg0 = virtual address\n                     \"m\"         // call micro-op\n                     \"s3a1=\"     // arg1 = sav3\n                     \"t\"         // arg0 = res0\n                     LOADSTORE,  // call micro-op (write word to shared memory)\n                     ResolveHost, kStore[log2sz]);\n            }\n          } else {\n            Jitter(A,\n                   \"s3=\"       // sav3 = <pop>\n                   \"L\"         // load effective address\n                   \"a3i\"       // arg3 = true\n                   \"a2i\"       // arg2 = byte width of write operation\n                   \"r0a1=\"     // arg1 = res0\n                   \"q\"         // arg0 = machine\n                   \"c\"         // call function (turn virtual into pointer)\n                   \"s3a1=\"     // arg1 = sav3\n                   \"t\"         // arg0 = res0\n                   LOADSTORE,  // call function (write word to shared memory)\n                   (u64)1, (u64)(1 << log2sz), ReserveAddress, kStore[log2sz]);\n          }\n        } else {\n          if (IsModrmRegister(rde)) {\n            // note: r0 == a0 on aarch64\n            // note: r1 == a1 on aarch64\n            // note: r1 == a2 on system five\n            // note: r1 == a1 on cygwin\n            Jitter(A,\n                   \"a3i\"    // arg3 = index of register\n                   \"r1a1=\"  // arg1 = res1\n                   \"s0a3=\"  // arg2 = machine\n                   \"t\"      // arg0 = res0\n                   \"m\",     // call micro-op (xmm put register)\n                   RexbRm(rde), kPutReg[log2sz]);\n          } else if (HasLinearMapping()) {\n            if (!kSkew) {\n              Jitter(\n                  A,\n                  \"r1s4=\"     // sav4 = res1\n                  \"r0s3=\"     // sav3 = res0\n                  \"L\"         // load effective address\n                  \"s4a2=\"     // arg2 = sav4\n                  \"s3a1=\"     // arg1 = sav3\n                  \"t\"         // arg0 = res0\n                  LOADSTORE,  // call micro-op (store vector to shared memory)\n                  kStore[log2sz]);\n            } else {\n              Jitter(\n                  A,\n                  \"r1s4=\"     // sav4 = res1\n                  \"r0s3=\"     // sav3 = res0\n                  \"L\"         // load effective address\n                  \"t\"         // arg0 = virtual address\n                  \"m\"         // call micro-op\n                  \"s4a2=\"     // arg2 = sav4\n                  \"s3a1=\"     // arg1 = sav3\n                  \"t\"         // arg0 = res0\n                  LOADSTORE,  // call micro-op (store vector to shared memory)\n                  ResolveHost, kStore[log2sz]);\n            }\n          } else {\n            Jitter(A,\n                   \"r1s4=\"     // sav4 = res1\n                   \"r0s3=\"     // sav3 = res0\n                   \"L\"         // load effective address\n                   \"a3i\"       // arg3 = true\n                   \"a2i\"       // arg2 = bytes to write\n                   \"r0a1=\"     // arg1 = res0\n                   \"q\"         // arg0 = machine\n                   \"c\"         // call function (turn virtual into pointer)\n                   \"s4a2=\"     // arg2 = sav4\n                   \"s3a1=\"     // arg1 = sav3\n                   \"t\"         // arg0 = res0\n                   LOADSTORE,  // call micro-op (store vector to shared memory)\n                   (u64)1, (u64)(1 << log2sz), ReserveAddress, kStore[log2sz]);\n          }\n        }\n        break;\n\n      case 'L':  // load effective address\n        if (!SibExists(rde) && IsRipRelative(rde)) {\n          AppendJitSetReg(m->path.jb, kJitRes0, disp + m->ip);\n        } else if (!SibExists(rde)) {\n          if (disp) {\n            Jitter(A,\n                   \"a2i\"  // arg2 = address base register index\n                   \"a1i\"  // arg1 = displacement\n                   \"q\"    // arg0 = machine\n                   \"m\",   // call micro-op\n                   RexbRm(rde), disp, Base);\n          } else {\n            Jitter(A,\n                   \"q\"   // arg0 = machine\n                   \"m\",  // call micro-op\n                   kGetReg64[RexbRm(rde)]);\n          }\n        } else if (!SibHasBase(rde) && !SibHasIndex(rde)) {\n          Jitter(A, \"r0i\", disp);  // res0 = absolute\n        } else if (SibHasBase(rde) && !SibHasIndex(rde)) {\n          if (disp) {\n            AppendJitSetReg(m->path.jb, kJitArg2, RexbBase(rde));\n            AppendJitSetReg(m->path.jb, kJitArg1, disp);\n            AppendJitMovReg(m->path.jb, kJitArg0, kJitSav0);\n            CallMicroOp(m, Base);\n          } else {\n            Jitter(A,\n                   \"q\"   // arg0 = machine\n                   \"m\",  // call micro-op\n                   kGetReg64[RexbBase(rde)]);\n          }\n        } else if (!SibHasBase(rde) && SibHasIndex(rde)) {\n          Jitter(A,\n                 \"a3i\"  // arg3 = log2(address index scale)\n                 \"a2i\"  // arg2 = address index register index\n                 \"a1i\"  // arg1 = displacement\n                 \"q\"    // arg0 = machine\n                 \"m\",   // call micro-op\n                 SibScale(rde), Rexx(rde) << 3 | SibIndex(rde), disp, Index);\n        } else {\n          Jitter(A,\n                 \"a3i\"  // arg4 = address index register index\n                 \"a2i\"  // arg2 = address base register index\n                 \"a1i\"  // arg1 = displacement\n                 \"q\"    // arg0 = machine\n                 \"m\",   // call micro-op\n                 Rexx(rde) << 3 | SibIndex(rde), RexbBase(rde), disp,\n                 kBaseIndex[SibScale(rde)]);\n        }\n        if (Eamode(rde) == XED_MODE_LEGACY) {\n          Jitter(A,\n                 \"t\"   // arg0 = res0\n                 \"m\",  // call micro-op\n                 Truncate32);\n        }\n        if (Sego(rde)) {\n          Jitter(A,\n                 \"a2i\"    // arg2 = segment register index\n                 \"r0a1=\"  // arg1 = res0\n                 \"q\"      // arg0 = machine\n                 \"m\",     // call micro-op\n                 Sego(rde) - 1, Seg);\n        }\n        break;\n\n      case 'Q':  // res0 = GetRegPointer(RexrReg)\n        Jitter(A,\n               \"a1i\"  // arg1 = register index\n               \"q\"    // arg0 = machine\n               \"m\",   // call micro-op\n               !log2sz ? (u64)kByteReg[RexrReg(rde)] : RexrReg(rde),\n               !log2sz      ? GetBegPtr\n               : log2sz < 4 ? GetWegPtr\n                            : GetXmmPtr);\n        break;\n\n      case 'P':  // res0 = GetRegOrMemPointer(RexbRm)\n        if (IsModrmRegister(rde)) {\n          Jitter(A,\n                 \"a1i\"  // arg1 = register index\n                 \"q\"    // arg0 = machine\n                 \"m\",   // call micro-op\n                 !log2sz ? (u64)kByteReg[RexbRm(rde)] : RexbRm(rde),\n                 !log2sz      ? GetBegPtr\n                 : log2sz < 4 ? GetWegPtr\n                              : GetXmmPtr);\n        } else if (HasLinearMapping()) {\n          if (!kSkew) {\n            Jitter(A, \"L\");  // load effective address\n          } else {\n            Jitter(A,\n                   \"L\"   // load effective address\n                   \"t\"   // arg0 = virtual address\n                   \"m\",  // res0 = call micro-op (turn virtual into pointer)\n                   ResolveHost);\n          }\n        } else {\n          Jitter(A,\n                 \"L\"      // load effective address\n                 \"a3i\"    // arg3 = false\n                 \"a2i\"    // arg2 = bytes to read\n                 \"r0a1=\"  // arg1 = virtual address\n                 \"q\"      // arg0 = machine\n                 \"c\",     // res0 = call function (turn virtual into pointer)\n                 (u64)0, (u64)(1 << log2sz), ReserveAddress);\n        }\n        break;\n\n      case 'E':  // r0 = GetReg(RexbSrm)\n        GetReg(A, log2sz, RexbSrm(rde), RexRexbSrm(rde));\n        break;\n\n      case 'F':  // PutReg(RexbSrm, <pop>)\n        PutReg(A, log2sz, RexbSrm(rde), RexRexbSrm(rde));\n        break;\n\n      case 'G':  // r0 = GetReg(AX)\n        GetReg(A, log2sz, 0, 0);\n        break;\n\n      case 'H':  // PutReg(AX, <pop>)\n        PutReg(A, log2sz, 0, 0);\n        break;\n\n      case 'w':  // prevents byte operation\n        log2sz = WordLog2(rde);\n        continue;\n\n      case 'z':  // force size\n        log2sz = CheckBelow(fmt[k++] - '0', 5);\n        continue;\n\n      case 'x':  // sign extend\n        ItemsRequired(1);\n        unassert(log2sz < 4);\n        if (log2sz < 3) {\n          Jitter(A,\n                 \"a0=\"  // arg0 = machine\n                 \"m\",   // call micro-op (sign extend)\n                 kSex[log2sz]);\n        } else {\n          Jitter(A, \"r0=\");  // result = <pop>\n        }\n        break;\n\n      default:\n        LOGF(\"%s %c index %d of '%s'\", \"bad jitter directive\", c, k - 1, fmt);\n        unassert(!\"bad jitter directive\");\n    }\n    unassert(i <= ARRAYLEN(stack));\n    log2sz = RegLog2(rde);\n  }\n  return k;\n}\n\n/**\n * Generates JIT code that implements x86 instructions.\n */\nvoid Jitter(P, const char *fmt, ...) {\n  va_list va;\n  if (!IsMakingPath(m)) return;\n  va_start(va, fmt);\n  JitterImpl(A, fmt, va, 0, 0);\n  unassert(!i);\n  va_end(va);\n}\n\n#endif /* HAVE_JIT */\n"
  },
  {
    "path": "blink/util.h",
    "content": "#ifndef BLINK_UTIL_H_\n#define BLINK_UTIL_H_\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <sys/types.h>\n#include <wchar.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/types.h\"\n\ntypedef void aborthook_f(void);\n\nextern int optind_;\nextern char *optarg_;\nextern const short kCp437[256];\n\n_Noreturn void Abort(void);\nvoid AtAbort(aborthook_f *);\nchar *GetStartDir(void);\nint GetOpt(int, char *const[], const char *);\nu64 tpenc(uint32_t);\nconst char *DescribeSignal(int);\nconst char *DescribeHostErrno(int);\nbool EndsWith(const char *, const char *);\nbool StartsWith(const char *, const char *);\nconst char *doublenul(const char *, unsigned);\nssize_t readansi(int, char *, size_t);\nchar *FormatInt64(char *, int64_t);\nchar *FormatUint64(char *, uint64_t);\nchar *FormatInt64Thousands(char *, int64_t);\nchar *FormatUint64Thousands(char *, uint64_t);\nchar *FormatSize(char *, uint64_t, uint64_t);\nchar *Commandv(const char *, char *, size_t);\nchar *Demangle(char *, const char *, size_t);\nvoid *Deflate(const void *, unsigned, unsigned *);\nvoid Inflate(void *, unsigned, const void *, unsigned);\nssize_t UninterruptibleWrite(int, const void *, size_t);\nlong IsProcessTainted(void);\nlong Magikarp(u8 *, long);\nint GetCpuCount(void);\nchar *strchrnul_(const char *, int);\nint vasprintf_(char **, const char *, va_list);\nchar *realpath_(const char *, char *);\nvoid *memccpy_(void *, const void *, int, size_t);\nint wcwidth_(wchar_t);\nu64 Vigna(u64[1]);\n\n#ifndef HAVE_STRCHRNUL\n#ifdef strchrnul\n#undef strchrnul\n#endif\n#define strchrnul strchrnul_\n#endif\n\n#ifndef HAVE_VASPRINTF\n#ifdef vasprintf\n#undef vasprintf\n#endif\n#define vasprintf vasprintf_\n#endif\n\n#ifndef HAVE_REALPATH\n#ifdef realpath\n#undef realpath\n#endif\n#define realpath realpath_\n#endif\n\n#if !defined(HAVE_MEMCCPY) || defined(TINY)\n#ifdef memccpy\n#undef memccpy\n#endif\n#define memccpy memccpy_\n#endif\n\n#ifndef HAVE_WCWIDTH\n#ifdef wcwidth\n#undef wcwidth\n#endif\n#define wcwidth wcwidth_\n#endif\n\n#endif /* BLINK_UTIL_H_ */\n"
  },
  {
    "path": "blink/vasprintf.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <stdio.h>\n#include <stdlib.h>\n\n#include \"blink/assert.h\"\n#include \"blink/util.h\"\n\nint vasprintf_(char **strp, const char *fmt, va_list va) {\n  va_list vb;\n  size_t size;\n  char *p, *p2;\n  int wrote, rc = -1;\n  if ((p = (char *)malloc((size = 512)))) {\n    va_copy(vb, va);\n    wrote = vsnprintf(p, size, fmt, va);\n    if (wrote < size) {\n      if ((p2 = (char *)realloc(p, wrote + 1))) {\n        p = p2;\n        rc = wrote;\n      }\n    } else {\n      size = wrote + 1;\n      if ((p2 = (char *)realloc(p, size))) {\n        p = p2;\n        wrote = vsnprintf(p, size, fmt, vb);\n        unassert(wrote == size - 1);\n        rc = wrote;\n      }\n    }\n    va_end(vb);\n  }\n  if (rc != -1) {\n    *strp = p;\n    return rc;\n  } else {\n    return -1;\n  }\n}\n"
  },
  {
    "path": "blink/vfs.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Trung Nguyen                                                  │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/vfs.h\"\n\n#include <errno.h>\n#include <fcntl.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/devfs.h\"\n#include \"blink/errno.h\"\n#include \"blink/hostfs.h\"\n#include \"blink/linux.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/procfs.h\"\n#include \"blink/thread.h\"\n#include \"blink/tunables.h\"\n\n#ifndef DISABLE_VFS\n\n#define VFS_UNREACHABLE        \"(unreachable)\"\n#define VFS_TRAVERSE_MAX_LINKS 40\n\nstruct VfsFd {\n  struct Dll elem;\n  struct VfsInfo *data;\n  int fd;\n};\n\nstruct VfsMap {\n  struct Dll elem;\n  struct VfsInfo *data;\n  void *addr;\n  size_t len;\n  off_t offset;\n  int prot;\n  int flags;\n};\n\n#define VFS_FD_CONTAINER(e)  DLL_CONTAINER(struct VfsFd, elem, (e))\n#define VFS_MAP_CONTAINER(e) DLL_CONTAINER(struct VfsMap, elem, (e))\n\nstatic struct VfsDevice g_rootdevice = {\n    .mounts = NULL,\n    .ops = NULL,\n    .data = NULL,\n    .dev = 0,\n    .refcount = 1u,\n};\n\nstatic struct VfsInfo g_initialrootinfo = {\n    .device = &g_rootdevice,\n    .parent = NULL,\n    .data = NULL,\n    .ino = 0,\n    .dev = 0,\n    .mode = S_IFDIR | 0755,\n    .refcount = 1u,\n};\n\nstruct VfsInfo *g_cwdinfo;\nstruct VfsInfo *g_rootinfo;\nstruct VfsInfo *g_actualrootinfo;\n\nstruct Vfs g_vfs = {\n    .devices = NULL,\n    .systems = NULL,\n    .fds = NULL,\n    .maps = NULL,\n    .lock = PTHREAD_MUTEX_INITIALIZER_,\n    .mapslock = PTHREAD_MUTEX_INITIALIZER_,\n};\n\nint VfsInit(const char *prefix) {\n  struct stat st;\n  char *cwd, hostcwd[PATH_MAX], *bprefix = NULL;\n  struct VfsInfo *info;\n  size_t hostcwdlen, prefixlen;\n  int fd;\n\n  // Register built-in filesystems\n  unassert(!VfsRegister(&g_hostfs));\n  unassert(!VfsRegister(&g_devfs));\n  unassert(!VfsRegister(&g_procfs));\n\n  dll_init(&g_rootdevice.elem);\n  dll_make_first(&g_vfs.devices, &g_rootdevice.elem);\n\n  // Initialize the root directory\n  unassert(!VfsAcquireInfo(&g_initialrootinfo, &g_rootinfo));\n  unassert(!VfsAcquireInfo(&g_initialrootinfo, &g_actualrootinfo));\n  if (prefix) {\n    bprefix = realpath(prefix, NULL);\n  }\n  if (bprefix) {\n    if (stat(bprefix, &st) == -1) {\n      ERRF(\"Failed to stat BLINK_PREFIX %s, %s\", bprefix, strerror(errno));\n      free(bprefix);\n      bprefix = NULL;\n    } else if (!S_ISDIR(st.st_mode)) {\n      ERRF(\"BLINK_PREFIX %s is not a directory\", bprefix);\n      free(bprefix);\n      bprefix = NULL;\n    }\n  }\n  if (bprefix) {\n    unassert(!VfsMount(bprefix, \"/\", \"hostfs\", 0, NULL));\n  } else {\n    unassert(!VfsMount(\"/\", \"/\", \"hostfs\", 0, NULL));\n  }\n  unassert(!VfsFreeInfo(g_rootinfo));\n  unassert(!VfsTraverse(\"/\", &g_rootinfo, false));\n\n  // Temporary cwd for syscalls to work during initialization\n  unassert(!VfsChdir(\"/\"));\n\n  // Mount the host's root.\n  if (VfsMkdir(AT_FDCWD, VFS_SYSTEM_ROOT_MOUNT, 0755) == -1 &&\n      errno != EEXIST) {\n    ERRF(\"Failed to create system root mount directory, %s\", strerror(errno));\n    goto cleananddie;\n  }\n  unassert(VfsMount(\"/\", VFS_SYSTEM_ROOT_MOUNT, \"hostfs\", 0, NULL) != -1);\n  unassert(!VfsTraverse(\"/\", &g_actualrootinfo, false));\n\n  // devfs, procfs\n  if (VfsMkdir(AT_FDCWD, \"/dev\", 0755) == -1 && errno != EEXIST) {\n    ERRF(\"Failed to create /dev, %s\", strerror(errno));\n    goto cleananddie;\n  }\n  unassert(!VfsMount(\"\", \"/dev\", \"devfs\", 0, NULL));\n  if (VfsMkdir(AT_FDCWD, \"/proc\", 0755) == -1 && errno != EEXIST) {\n    ERRF(\"Failed to create /proc, %s\", strerror(errno));\n    goto cleananddie;\n  }\n  unassert(!VfsMount(\"proc\", \"/proc\", \"proc\", 0, NULL));\n\n  // Initialize the current working directory\n  unassert(getcwd(hostcwd, sizeof(hostcwd)));\n  if (bprefix && !strncmp(hostcwd, bprefix, (prefixlen = strlen(bprefix)))) {\n    hostcwdlen = strlen(hostcwd);\n    if (hostcwdlen == prefixlen) {\n      cwd = strdup(\"/\");\n    } else {\n      cwd = (char *)malloc(hostcwdlen - prefixlen + 1);\n      if (cwd == NULL) {\n        enomem();\n        goto cleananddie;\n      }\n      memcpy(cwd, hostcwd + prefixlen, hostcwdlen - prefixlen + 1);\n    }\n  } else {\n    cwd = (char *)malloc(PATH_MAX + sizeof(VFS_SYSTEM_ROOT_MOUNT));\n    if (cwd == NULL) {\n      enomem();\n      goto cleananddie;\n    }\n    memcpy(cwd, VFS_SYSTEM_ROOT_MOUNT, sizeof(VFS_SYSTEM_ROOT_MOUNT));\n    strcat(cwd, hostcwd);\n  }\n\n  unassert(!VfsChdir(cwd));\n  free(cwd);\n  free(bprefix);\n\n  // stdin, stdout, stderr\n  unassert(!HostfsWrapFd(0, false, &info));\n  unassert(VfsAddFd(info) == 0);\n  unassert(!HostfsWrapFd(1, false, &info));\n  unassert(VfsAddFd(info) == 1);\n  unassert(!HostfsWrapFd(2, false, &info));\n  unassert(VfsAddFd(info) == 2);\n\n  // Some Linux tests require that when EMFILE occurs,\n  // the fd returned before it must be the maximum possible.\n\n  // Force initialization of the logger fd.\n  LogInfo(__FILE__, __LINE__, \"Initializing VFS\");\n  for (fd = kMinBlinkFd; HostfsWrapFd(fd, false, &info) != -1; ++fd) {\n    unassert(!VfsSetFd(fd, info));\n  }\n\n  VFS_LOGF(\"Initialized VFS\");\n\n  return 0;\ncleananddie:\n  free(bprefix);\n  return -1;\n}\n\nint VfsRegister(struct VfsSystem *system) {\n  if (system == NULL) {\n    efault();\n    return -1;\n  }\n  LOCK(&g_vfs.lock);\n  VFS_LOGF(\"Registering filesystem %s\", system->name);\n  dll_init(&system->elem);\n  dll_make_last(&g_vfs.systems, &system->elem);\n  UNLOCK(&g_vfs.lock);\n  return 0;\n}\n\nint VfsMount(const char *source, const char *target, const char *fstype,\n             u64 flags, const void *data) {\n  struct VfsInfo *targetinfo;\n  struct VfsSystem *newsystem, *s;\n  struct VfsDevice *targetdevice = 0, *newdevice, *d;\n  struct VfsMount *newmount;\n  struct Dll *e;\n  char *newname = 0;\n  i64 nextdev;\n  if (flags & MS_SILENT_LINUX) {\n    flags &= ~MS_SILENT_LINUX;\n  }\n  if (flags) {\n    // Theoretically, we can support a lot of the Linux flags without\n    // changing the current design. However, as the major intended\n    // usecase is to simply mount hostfs, this is currently not supported.\n    LOGF(\"Unsupported mount flags: 0x%llx\", (unsigned long long)flags);\n  }\n  if (VfsTraverse(target, &targetinfo, true) == -1) {\n    return -1;\n  }\n  if (!S_ISDIR(targetinfo->mode)) {\n    return enotdir();\n  }\n  // Allow mounting once to \"/\" during initialization only.\n  if ((targetinfo->dev != g_initialrootinfo.dev ||\n       targetinfo->ino != g_initialrootinfo.ino) &&\n      (targetinfo->dev == g_actualrootinfo->dev &&\n       targetinfo->ino == g_actualrootinfo->ino)) {\n    errno = EBUSY;\n    return -1;\n  }\n  LOCK(&g_vfs.lock);\n  newsystem = NULL;\n  for (e = dll_first(g_vfs.systems); e; e = dll_next(g_vfs.systems, e)) {\n    s = VFS_SYSTEM_CONTAINER(e);\n    if (strcmp(s->name, fstype) == 0) {\n      newsystem = s;\n      break;\n    }\n  }\n  if (newsystem == NULL) {\n    VFS_LOGF(\"Unknown filesystem type: %s\", fstype);\n    UNLOCK(&g_vfs.lock);\n    return enodev();\n  }\n  for (e = dll_first(g_vfs.devices); e; e = dll_next(g_vfs.devices, e)) {\n    d = VFS_DEVICE_CONTAINER(e);\n    if (d->dev == targetinfo->dev) {\n      targetdevice = d;\n      break;\n    }\n  }\n  if (targetdevice == NULL) {\n    // Might have been unmounted after VfsTraverse by another thread\n    UNLOCK(&g_vfs.lock);\n    return enoent();\n  }\n  if (targetinfo->name != NULL) {\n    newname = strdup(targetinfo->name);\n    if (newname == NULL) {\n      UNLOCK(&g_vfs.lock);\n      return enomem();\n    }\n  }\n  if (newsystem->ops.Init(source, flags, data, &newdevice, &newmount) == -1) {\n    UNLOCK(&g_vfs.lock);\n    return -1;\n  }\n  nextdev = 0;\n  for (e = dll_first(g_vfs.devices); e; e = dll_next(g_vfs.devices, e)) {\n    d = VFS_DEVICE_CONTAINER(e);\n    if (d->dev == nextdev) {\n      ++nextdev;\n    } else {\n      break;\n    }\n  }\n  newdevice->dev = nextdev;\n  if (e == NULL) {\n    dll_make_last(&g_vfs.devices, &newdevice->elem);\n  } else {\n    dll_splice_after(dll_prev(g_vfs.devices, e), &newdevice->elem);\n  }\n  newdevice->flags = flags;\n  newmount->baseino = targetinfo->ino;\n  newmount->root->dev = nextdev;\n  newmount->root->name = newname;\n  newmount->root->namelen = targetinfo->namelen;\n  unassert(!VfsAcquireInfo(targetinfo->parent, &newmount->root->parent));\n  dll_init(&newmount->elem);\n  dll_make_last(&targetdevice->mounts, &newmount->elem);\n  UNLOCK(&g_vfs.lock);\n  unassert(!VfsFreeInfo(targetinfo));\n  VFS_LOGF(\"Mounted a new device at %s, dev=%ld\", target, nextdev);\n  return 0;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nint VfsCreateDevice(struct VfsDevice **output) {\n  struct VfsDevice *device;\n  if (output == NULL) {\n    return efault();\n  }\n  device = (struct VfsDevice *)malloc(sizeof(struct VfsDevice));\n  if (device == NULL) {\n    return enomem();\n  }\n  device->dev = 0;\n  device->refcount = 1;\n  device->data = NULL;\n  device->ops = NULL;\n  device->mounts = NULL;\n  device->refcount = 1;\n  unassert(!pthread_mutex_init(&device->lock, NULL));\n  dll_init(&device->elem);\n  *output = device;\n  return 0;\n}\n\nint VfsFreeDevice(struct VfsDevice *device) {\n  struct Dll *e;\n  struct VfsMount *mount;\n  int rc;\n  if (device == NULL) {\n    return 0;\n  }\n  if ((rc = atomic_fetch_sub(&device->refcount, 1)) != 1) {\n    return 0;\n  }\n  LOCK(&device->lock);\n  if (device->ops && device->ops->Freedevice) {\n    if (device->ops->Freedevice(device->data) == -1) {\n      UNLOCK(&device->lock);\n      return -1;\n    }\n  }\n  device->data = NULL;\n  device->ops = NULL;\n  // Don't free root, it's a weak reference.\n  device->root = NULL;\n  for (e = dll_first(device->mounts); e; e = dll_next(device->mounts, e)) {\n    mount = VFS_MOUNT_CONTAINER(e);\n    unassert(!VfsFreeInfo(mount->root));\n    mount->root = NULL;\n    free(mount);\n  }\n  UNLOCK(&device->lock);\n  unassert(!pthread_mutex_destroy(&device->lock));\n  free(device);\n  return 0;\n}\n\nint VfsAcquireDevice(struct VfsDevice *device, struct VfsDevice **output) {\n  int rc;\n  if (output == NULL) {\n    return efault();\n  }\n  if (device == NULL) {\n    *output = NULL;\n    return 0;\n  }\n  rc = atomic_fetch_add(&device->refcount, 1);\n  unassert(rc > 0);\n  *output = device;\n  return 0;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nint VfsCreateInfo(struct VfsInfo **output) {\n  struct VfsInfo *info;\n  if (output == NULL) {\n    return efault();\n  }\n  info = (struct VfsInfo *)malloc(sizeof(struct VfsInfo));\n  if (info == NULL) {\n    return enomem();\n  }\n  info->parent = NULL;\n  info->device = NULL;\n  info->name = NULL;\n  info->namelen = 0;\n  info->data = NULL;\n  info->ino = 0;\n  info->dev = 0;\n  info->mode = 0;\n  info->refcount = 1;\n  *output = info;\n  return 0;\n}\n\nint VfsAcquireInfo(struct VfsInfo *info, struct VfsInfo **output) {\n  int rc;\n  if (output == NULL) {\n    return efault();\n  }\n  if (info == NULL) {\n    *output = NULL;\n    return 0;\n  }\n  rc = atomic_fetch_add(&info->refcount, 1);\n  unassert(rc > 0);\n  VFS_LOGF(\"Acquired VfsInfo %p, refcount now %i.\", info, rc + 1);\n  *output = info;\n  return 0;\n}\n\nint VfsFreeInfo(struct VfsInfo *info) {\n  int rc;\n  if (info == NULL) {\n    return 0;\n  }\n  if ((rc = atomic_fetch_sub(&info->refcount, 1)) != 1) {\n    VFS_LOGF(\"Freeing VfsInfo %p, refcount now %i.\", info, rc - 1);\n    return 0;\n  }\n  if (VfsFreeInfo(info->parent) == -1) {\n    return -1;\n  }\n  info->parent = NULL;\n  if (info->device->ops && info->device->ops->Freeinfo) {\n    if (info->device->ops->Freeinfo(info->data) == -1) {\n      return -1;\n    }\n  }\n  unassert(!VfsFreeDevice(info->device));\n  info->data = NULL;\n  if (info->name) {\n    free((void *)info->name);\n    info->name = NULL;\n  }\n  free(info);\n  return 0;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic int VfsTraverseMount(struct VfsInfo **info,\n                            char childname[VFS_NAME_MAX]) {\n  struct VfsMount *mount;\n  struct Dll *e;\n  if (info == NULL) {\n    return efault();\n  }\n  if (!S_ISDIR((*info)->mode)) {\n    return 0;\n  }\n  LOCK(&g_vfs.lock);\n  for (e = dll_first((*info)->device->mounts); e;\n       e = dll_next((*info)->device->mounts, e)) {\n    mount = VFS_MOUNT_CONTAINER(e);\n    if (!childname) {\n      // Checking info itself.\n      if (mount->baseino == (*info)->ino) {\n        VFS_LOGF(\"VfsTraverseMount: switching from dev=%d to dev=%d\",\n                 (*info)->dev, mount->root->dev);\n        unassert(!VfsFreeInfo(*info));\n        unassert(!VfsAcquireInfo(mount->root, info));\n        break;\n      }\n    } else {\n      // Checking child node \"childname\" of info.\n      VFS_LOGF(\"VfsTraverseMount: checking mount %s\", mount->root->name);\n      if (mount->root->parent && mount->root->parent->ino == (*info)->ino &&\n          !strcmp(mount->root->name, childname)) {\n        unassert(mount->root->parent->dev == (*info)->dev);\n        VFS_LOGF(\"VfsTraverseMount: switching from dev=%d to dev=%d\",\n                 (*info)->dev, mount->root->dev);\n        strcpy(childname, \".\");\n        unassert(!VfsFreeInfo(*info));\n        unassert(!VfsAcquireInfo(mount->root, info));\n        break;\n      }\n    }\n  }\n  UNLOCK(&g_vfs.lock);\n  return 0;\n}\n\nstatic int VfsTraverseStackBuild(struct VfsInfo **stack, const char *path,\n                                 struct VfsInfo *root, bool follow, int level) {\n  struct VfsInfo *next, *origin;\n  const char *end;\n  char filename[VFS_NAME_MAX];\n  char *link;\n  VFS_LOGF(\"VfsTraverseStackBuild(%p, \\\"%s\\\", %p, %d)\", stack, path, root,\n           follow);\n  if (stack == NULL || path == NULL) {\n    return efault();\n  }\n  if (level > VFS_TRAVERSE_MAX_LINKS) {\n    return eloop();\n  }\n  origin = *stack;\n  if (*stack == NULL) {\n    unassert(!VfsAcquireInfo(&g_initialrootinfo, stack));\n  }\n  if (root == NULL) {\n    root = &g_initialrootinfo;\n  }\n  while (*path) {\n    if (!S_ISDIR((*stack)->mode)) {\n      enotdir();\n      goto cleananddie;\n    }\n    unassert(!VfsTraverseMount(stack, NULL));\n    if ((*stack)->device->ops && (*stack)->device->ops->Traverse) {\n      if ((*stack)->device->ops->Traverse(stack, &path, root) == -1) {\n        goto cleananddie;\n      }\n    } else {\n      while (*path == '/') {\n        ++path;\n      }\n      end = path;\n      while (end[0] && end[0] != '/') {\n        ++end;\n      }\n      if (end == path) {\n        break;\n      }\n      if (end - path >= VFS_NAME_MAX) {\n        enametoolong();\n        goto cleananddie;\n      }\n      memcpy(filename, path, end - path);\n      filename[end - path] = '\\0';\n      path = end;\n      if (!strcmp(filename, \".\")) {\n        continue;\n      }\n      if (!strcmp(filename, \"..\")) {\n        if (*stack != root && (*stack)->parent != NULL) {\n          unassert(!VfsAcquireInfo((*stack)->parent, &next));\n          unassert(!VfsFreeInfo(*stack));\n          *stack = next;\n        }\n        continue;\n      }\n      if ((*stack)->device->ops->Finddir(*stack, filename, &next) == -1) {\n        goto cleananddie;\n      }\n      unassert(!VfsFreeInfo(*stack));\n      *stack = next;\n    }\n    if (follow) {\n      while (S_ISLNK((*stack)->mode)) {\n        if ((*stack)->device->ops->Readlink(*stack, &link) == -1) {\n          goto cleananddie;\n        }\n        VFS_LOGF(\"VfsTraverseStackBuild: symlink to %s\", link);\n        if (link[0] == '/') {\n          unassert(!VfsFreeInfo(*stack));\n          unassert(!VfsAcquireInfo(root, stack));\n        } else {\n          unassert(!VfsAcquireInfo((*stack)->parent, &next));\n          unassert(!VfsFreeInfo(*stack));\n          *stack = next;\n        }\n        if (VfsTraverseStackBuild(stack, link, root, follow, level + 1) == -1) {\n          free(link);\n          goto cleananddie;\n        }\n        free(link);\n      }\n    }\n  }\n  unassert(!VfsTraverseMount(stack, NULL));\n  return 0;\ncleananddie:\n  while (*stack != origin) {\n    unassert(!VfsAcquireInfo((*stack)->parent, &next));\n    unassert(!VfsFreeInfo(*stack));\n    *stack = next;\n  }\n  return -1;\n}\n\nint VfsTraverse(const char *path, struct VfsInfo **output, bool follow) {\n  struct VfsInfo *root;\n  VFS_LOGF(\"VfsTraverse(\\\"%s\\\", %p, %d)\", path, output, follow);\n  if (path == NULL || output == NULL) {\n    efault();\n    return -1;\n  }\n  root = NULL;\n  if (path[0] != '/') {\n    unassert(!VfsAcquireInfo(g_cwdinfo, output));\n  } else {\n    unassert(!VfsAcquireInfo(g_rootinfo, output));\n  }\n  if (VfsTraverseStackBuild(output, path, root, follow, 0) == -1) {\n    unassert(!VfsFreeInfo(*output));\n    return -1;\n  }\n  return 0;\n}\n\nssize_t VfsPathBuildFull(struct VfsInfo *info, struct VfsInfo *root,\n                         char **output) {\n  struct VfsInfo *current;\n  size_t len, currentlen;\n  len = 0;\n  current = info;\n  if (root == NULL) {\n    root = g_rootinfo;\n  }\n  if (current->dev == root->dev && current->ino == root->ino) {\n    *output = strdup(\"/\");\n    if (*output == NULL) {\n      return enomem();\n    }\n    return 1;\n  }\n  while (current && (current->dev != root->dev || current->ino != root->ino)) {\n    len += current->namelen + 1;\n    current = current->parent;\n  }\n  if (current == NULL) {\n    *output = strdup(VFS_UNREACHABLE);\n    if (*output == NULL) {\n      return enomem();\n    }\n    return sizeof(VFS_UNREACHABLE) - 1;\n  }\n  *output = (char *)malloc(len + 1);\n  if (*output == NULL) {\n    return enomem();\n  }\n  (*output)[len] = '\\0';\n  current = info;\n  currentlen = len;\n  while (current && (current->dev != root->dev || current->ino != root->ino)) {\n    currentlen -= current->namelen;\n    memcpy(*output + currentlen, current->name, current->namelen);\n    if (currentlen != 0) {\n      --currentlen;\n      (*output)[currentlen] = '/';\n    }\n    current = current->parent;\n  }\n  return len;\n}\n\nssize_t VfsPathBuild(struct VfsInfo *info, struct VfsInfo *root, bool absolute,\n                     char output[VFS_PATH_MAX]) {\n  struct VfsInfo *current;\n  size_t len, currentlen;\n  len = 0;\n  current = info;\n  VFS_LOGF(\"VfsPathBuild(%p, %p, %d, %p)\", info, root, absolute, output);\n  if (root == NULL) {\n    root = g_rootinfo;\n  }\n  if (current->dev == root->dev && current->ino == root->ino) {\n    if (absolute) {\n      memcpy(output, \"/\", 2);\n      return 1;\n    } else {\n      output[0] = '\\0';\n      return 0;\n    }\n  }\n  while (current && (current->dev != root->dev || current->ino != root->ino)) {\n    len += current->namelen + 1;\n    current = current->parent;\n  }\n  if (current == NULL) {\n    memcpy(output, VFS_UNREACHABLE, sizeof(VFS_UNREACHABLE));\n    return sizeof(VFS_UNREACHABLE) - 1;\n  }\n  len -= !absolute;\n  if (len >= PATH_MAX) {\n    return enametoolong();\n  }\n  current = info;\n  currentlen = len;\n  output[currentlen] = '\\0';\n  while (current && (current->dev != root->dev || current->ino != root->ino)) {\n    currentlen -= current->namelen;\n    memcpy(output + currentlen, current->name, current->namelen);\n    if (currentlen != 0) {\n      --currentlen;\n      output[currentlen] = '/';\n    }\n    current = current->parent;\n  }\n  return len;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nint VfsAddFdAtOrAfter(struct VfsInfo *data, int minfd) {\n  struct VfsFd *vfsfd;\n  struct Dll *e;\n  vfsfd = (struct VfsFd *)malloc(sizeof(*vfsfd));\n  if (vfsfd == NULL) {\n    return -1;\n  }\n  vfsfd->data = data;\n  LOCK(&g_vfs.lock);\n  for (e = dll_first(g_vfs.fds); e; e = dll_next(g_vfs.fds, e)) {\n    if (VFS_FD_CONTAINER(e)->fd < minfd) {\n      continue;\n    } else if (VFS_FD_CONTAINER(e)->fd == minfd) {\n      ++minfd;\n    } else {\n      break;\n    }\n  }\n  vfsfd->fd = minfd;\n  dll_init(&vfsfd->elem);\n  if (e == NULL) {\n    dll_make_last(&g_vfs.fds, &vfsfd->elem);\n  } else {\n    e = dll_prev(g_vfs.fds, e);\n    if (e == NULL) {\n      dll_make_first(&g_vfs.fds, &vfsfd->elem);\n    } else {\n      dll_splice_after(e, &vfsfd->elem);\n    }\n  }\n  UNLOCK(&g_vfs.lock);\n  return vfsfd->fd;\n}\n\nint VfsAddFd(struct VfsInfo *data) {\n  return VfsAddFdAtOrAfter(data, 0);\n}\n\n/**\n * Closes the emulated file descriptor fd and returns the data associated with\n * it.\n */\nint VfsFreeFd(int fd, struct VfsInfo **data) {\n  struct Dll *e;\n  struct VfsFd *vfsfd;\n  LOCK(&g_vfs.lock);\n  for (e = dll_first(g_vfs.fds); e;) {\n    vfsfd = VFS_FD_CONTAINER(e);\n    if (VFS_FD_CONTAINER(e)->fd == fd) {\n      *data = vfsfd->data;\n      dll_remove(&g_vfs.fds, &vfsfd->elem);\n      free(vfsfd);\n      VFS_LOGF(\"VfsFreeFd(%d)\", fd);\n      UNLOCK(&g_vfs.lock);\n      return 0;\n    }\n    e = dll_next(g_vfs.fds, e);\n  }\n  UNLOCK(&g_vfs.lock);\n  return ebadf();\n}\n\nint VfsGetFd(int fd, struct VfsInfo **output) {\n  struct Dll *e;\n  LOCK(&g_vfs.lock);\n  for (e = dll_first(g_vfs.fds); e; e = dll_next(g_vfs.fds, e)) {\n    if (VFS_FD_CONTAINER(e)->fd == fd) {\n      UNLOCK(&g_vfs.lock);\n      unassert(!VfsAcquireInfo(VFS_FD_CONTAINER(e)->data, output));\n      return 0;\n    }\n  }\n  UNLOCK(&g_vfs.lock);\n  return ebadf();\n}\n\nint VfsSetFd(int fd, struct VfsInfo *data) {\n  struct Dll *e;\n  struct VfsFd *vfsfd;\n  LOCK(&g_vfs.lock);\n  for (e = dll_first(g_vfs.fds); e; e = dll_next(g_vfs.fds, e)) {\n    if (VFS_FD_CONTAINER(e)->fd == fd) {\n      unassert(!VfsFreeInfo(VFS_FD_CONTAINER(e)->data));\n      VFS_FD_CONTAINER(e)->data = data;\n      UNLOCK(&g_vfs.lock);\n      return 0;\n    } else if (VFS_FD_CONTAINER(e)->fd > fd) {\n      break;\n    }\n  }\n  vfsfd = (struct VfsFd *)malloc(sizeof(*vfsfd));\n  if (vfsfd == NULL) {\n    UNLOCK(&g_vfs.lock);\n    return enomem();\n  }\n  vfsfd->data = data;\n  vfsfd->fd = fd;\n  dll_init(&vfsfd->elem);\n  if (e == NULL) {\n    dll_make_last(&g_vfs.fds, &vfsfd->elem);\n  } else if ((e = dll_prev(g_vfs.fds, e))) {\n    dll_splice_after(e, &vfsfd->elem);\n  } else {\n    dll_make_first(&g_vfs.fds, &vfsfd->elem);\n  }\n  UNLOCK(&g_vfs.lock);\n  return 0;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nint VfsChdir(const char *path) {\n  struct VfsInfo *info, *tmp;\n  int ret = 0;\n  VFS_LOGF(\"VfsChdir(\\\"%s\\\")\", path);\n  if (path == NULL) {\n    return efault();\n  }\n  if (*path == '\\0') {\n    return enoent();\n  }\n  if (VfsTraverse(path, &info, true) == -1) {\n    return -1;\n  }\n  if (!S_ISDIR(info->mode)) {\n    ret = enotdir();\n  } else {\n    tmp = g_cwdinfo;\n    g_cwdinfo = info;\n    info = tmp;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsFchdir(int fd) {\n  struct VfsInfo *info, *tmp;\n  int ret = 0;\n  VFS_LOGF(\"VfsFchdir(%d)\", fd);\n  if (VfsGetFd(fd, &info) != 0) {\n    return -1;\n  }\n  if (!S_ISDIR(info->mode)) {\n    ret = enotdir();\n  } else {\n    tmp = g_cwdinfo;\n    g_cwdinfo = info;\n    info = tmp;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsChroot(const char *path) {\n  struct VfsInfo *info, *tmp;\n  int ret = 0;\n  VFS_LOGF(\"VfsChroot(\\\"%s\\\")\", path);\n  if (path == NULL) {\n    return efault();\n  }\n  if (*path == '\\0') {\n    return enoent();\n  }\n  if (VfsTraverse(path, &info, true) != 0) {\n    return -1;\n  }\n  if (!S_ISDIR(info->mode)) {\n    ret = enotdir();\n  } else {\n    tmp = g_rootinfo;\n    g_rootinfo = info;\n    info = tmp;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nchar *VfsGetcwd(char *buf, size_t size) {\n  char cwd[VFS_PATH_MAX];\n  if (buf == NULL) {\n    efault();\n    return NULL;\n  }\n  if (size == 0) {\n    return buf;\n  }\n  if (VfsPathBuild(g_cwdinfo, NULL, true, cwd) == -1) {\n    return NULL;\n  }\n  strncpy(buf, cwd, size);\n  buf[size - 1] = '\\0';\n  return buf;\n}\n\nstatic int VfsHandleDirfdName(int dirfd, const char *name,\n                              struct VfsInfo **parent,\n                              char leaf[VFS_NAME_MAX]) {\n  struct VfsInfo *dir = NULL, *tmp = NULL;\n  const char *p, *q;\n  char *parentname = NULL;\n  if (name[0] == '/') {\n    unassert(!VfsAcquireInfo(g_rootinfo, &dir));\n  } else if (dirfd == AT_FDCWD) {\n    unassert(!VfsAcquireInfo(g_cwdinfo, &dir));\n  } else {\n    if (VfsGetFd(dirfd, &dir) == -1) {\n      goto cleananddie;\n    }\n  }\n  if (!strcmp(name, \"/\")) {\n    strcpy(leaf, \"/\");\n    *parent = dir;\n    return 0;\n  }\n  if (!S_ISDIR(dir->mode)) {\n    enotdir();\n    goto cleananddie;\n  }\n  for (p = name, q = name; *p; ++p) {\n    if (*p == '/' && p[1]) {\n      q = p + 1;\n    }\n  }\n  if (p - q >= VFS_NAME_MAX) {\n    enametoolong();\n    goto cleananddie;\n  }\n  parentname = strndup(name, q - name);\n  if (parentname == NULL) {\n    goto cleananddie;\n  }\n  if (VfsTraverseStackBuild(&dir, parentname, g_rootinfo, true, 0) == -1) {\n    goto cleananddie;\n  }\n  if (!strcmp(q, \"..\") && dir->parent) {\n    unassert(!VfsAcquireInfo(dir->parent, &tmp));\n    unassert(!VfsFreeInfo(dir));\n    dir = tmp;\n    memcpy(leaf, \".\", 2);\n  } else {\n    memcpy(leaf, q, p - q + 1);\n  }\n  *parent = dir;\n  free(parentname);\n  return 0;\ncleananddie:\n  free(parentname);\n  unassert(!VfsFreeInfo(dir));\n  return -1;\n}\n\nstatic int VfsHandleDirfdSymlink(struct VfsInfo **dir,\n                                 char name[VFS_NAME_MAX]) {\n  int level = 0;\n  char *buf, *s;\n  struct VfsInfo *tmp;\n  ssize_t linklen;\n  VFS_LOGF(\"VfsHandleDirfdSymlink(%p, %p)\", dir, name);\n  buf = NULL;\n  tmp = NULL;\n  while (true) {\n    if (++level > VFS_TRAVERSE_MAX_LINKS) {\n      return eloop();\n    }\n    if (!(*dir)->device->ops->Finddir || !(*dir)->device->ops->Readlink) {\n      return eperm();\n    }\n    if ((*dir)->device->ops->Finddir(*dir, name, &tmp) == -1) {\n      if (errno != ENOENT) {\n        return -1;\n      } else {\n        break;\n      }\n    }\n    if (!S_ISLNK(tmp->mode)) {\n      unassert(!VfsFreeInfo(tmp));\n      break;\n    }\n    if ((linklen = (*dir)->device->ops->Readlink(tmp, &buf)) == -1) {\n      goto cleananddie;\n    }\n    unassert(!VfsFreeInfo(tmp));\n    tmp = NULL;\n    if (buf[0] == '/') {\n      if (VfsHandleDirfdName(AT_FDCWD, buf, &tmp, name) == -1) {\n        goto cleananddie;\n      }\n      unassert(!VfsFreeInfo(*dir));\n      *dir = tmp;\n    } else {\n      for (s = buf + linklen; s >= buf; --s) {\n        if (*s == '/') {\n          break;\n        }\n      }\n      ++s;\n      if (buf + linklen - s >= VFS_NAME_MAX) {\n        enametoolong();\n        goto cleananddie;\n      }\n      memmove(name, s, buf + linklen - s + 1);\n      *s = '\\0';\n      if (s != buf) {\n        if (VfsTraverseStackBuild(dir, buf, NULL, true, 0) == -1) {\n          goto cleananddie;\n        }\n      }\n    }\n    free(buf);\n    buf = NULL;\n  }\n  return 0;\ncleananddie:\n  free(buf);\n  unassert(!VfsFreeInfo(tmp));\n  return -1;\n}\n\nint VfsUnlink(int dirfd, const char *name, int flags) {\n  struct VfsInfo *dir;\n  char newname[VFS_NAME_MAX];\n  int ret;\n  VFS_LOGF(\"VfsUnlink(%d, \\\"%s\\\", %d)\", dirfd, name, flags);\n  if (name == NULL) {\n    return efault();\n  }\n  if (!*name) {\n    return enoent();\n  }\n  if (VfsHandleDirfdName(dirfd, name, &dir, newname) == -1) {\n    return -1;\n  }\n  unassert(!VfsTraverseMount(&dir, newname));\n  if (dir->device->ops->Unlink) {\n    ret = dir->device->ops->Unlink(dir, newname, flags);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(dir));\n  return ret;\n}\n\nint VfsMkdir(int dirfd, const char *name, mode_t mode) {\n  struct VfsInfo *dir;\n  char newname[VFS_NAME_MAX];\n  int ret;\n  VFS_LOGF(\"VfsMkdir(%d, \\\"%s\\\", %d)\", dirfd, name, mode);\n  if (name == NULL) {\n    return efault();\n  }\n  if (!*name) {\n    return enoent();\n  }\n  if (VfsHandleDirfdName(dirfd, name, &dir, newname) == -1) {\n    return -1;\n  }\n  unassert(!VfsTraverseMount(&dir, newname));\n  if (dir->device->ops->Mkdir) {\n    ret = dir->device->ops->Mkdir(dir, newname, mode);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(dir));\n  return ret;\n}\n\nint VfsMkfifo(int dirfd, const char *name, mode_t mode) {\n  struct VfsInfo *dir;\n  char newname[VFS_NAME_MAX];\n  int ret;\n  VFS_LOGF(\"VfsMkfifo(%d, \\\"%s\\\", %d)\", dirfd, name, mode);\n  if (name == NULL) {\n    return efault();\n  }\n  if (!*name) {\n    return enoent();\n  }\n  if (VfsHandleDirfdName(dirfd, name, &dir, newname) == -1) {\n    return -1;\n  }\n  unassert(!VfsTraverseMount(&dir, newname));\n  if (dir->device->ops->Mkfifo) {\n    ret = dir->device->ops->Mkfifo(dir, newname, mode);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(dir));\n  return ret;\n}\n\nint VfsOpen(int dirfd, const char *name, int flags, int mode) {\n  struct VfsInfo *dir, *out;\n  char newname[VFS_NAME_MAX];\n  int ret = 0;\n  VFS_LOGF(\"VfsOpen(%d, \\\"%s\\\", %d, %d)\", dirfd, name, flags, mode);\n  if (name == NULL) {\n    return efault();\n  }\n  if (!*name) {\n    return enoent();\n  }\n  if (VfsHandleDirfdName(dirfd, name, &dir, newname) == -1) {\n    return -1;\n  }\n  if (!(flags & O_NOFOLLOW)) {\n    ret = VfsHandleDirfdSymlink(&dir, newname);\n  }\n  unassert(!VfsTraverseMount(&dir, newname));\n  if (ret != -1) {\n    if (dir->device->ops->Open) {\n      if (dir->device->ops->Open(dir, newname, flags, mode, &out) == -1) {\n        ret = -1;\n      } else {\n        ret = VfsAddFd(out);\n      }\n    } else {\n      ret = eperm();\n    }\n  }\n  unassert(!VfsFreeInfo(dir));\n  return ret;\n}\n\nint VfsChmod(int dirfd, const char *name, mode_t mode, int flags) {\n  struct VfsInfo *dir;\n  char newname[VFS_NAME_MAX];\n  int ret = 0;\n  VFS_LOGF(\"VfsChmod(%d, \\\"%s\\\", %d, %d)\", dirfd, name, mode, flags);\n  if (name == NULL) {\n    return efault();\n  }\n  if (!*name) {\n    return enoent();\n  }\n  if (VfsHandleDirfdName(dirfd, name, &dir, newname) == -1) {\n    return -1;\n  }\n  if (!(flags & AT_SYMLINK_NOFOLLOW)) {\n    ret = VfsHandleDirfdSymlink(&dir, newname);\n  }\n  unassert(!VfsTraverseMount(&dir, newname));\n  if (ret != -1) {\n    if (dir->device->ops->Chmod) {\n      ret = dir->device->ops->Chmod(dir, newname, mode, flags);\n    } else {\n      ret = eperm();\n    }\n  }\n  unassert(!VfsFreeInfo(dir));\n  return ret;\n}\n\nint VfsFchmod(int fd, mode_t mode) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsFchmod(%d, %d)\", fd, mode);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Fchmod) {\n    ret = info->device->ops->Fchmod(info, mode);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsAccess(int dirfd, const char *name, mode_t mode, int flags) {\n  struct VfsInfo *dir;\n  char newname[VFS_NAME_MAX];\n  int ret = 0;\n  VFS_LOGF(\"VfsAccess(%d, \\\"%s\\\", %d, %d)\", dirfd, name, mode, flags);\n  if (name == NULL) {\n    return efault();\n  }\n  if (!*name) {\n    return enoent();\n  }\n  if (VfsHandleDirfdName(dirfd, name, &dir, newname) == -1) {\n    return -1;\n  }\n  if (!(flags & AT_SYMLINK_NOFOLLOW)) {\n    ret = VfsHandleDirfdSymlink(&dir, newname);\n  }\n  unassert(!VfsTraverseMount(&dir, newname));\n  if (ret != -1) {\n    if (dir->device->ops->Access) {\n      ret = dir->device->ops->Access(dir, newname, mode, flags);\n    } else {\n      ret = eperm();\n    }\n  }\n  unassert(!VfsFreeInfo(dir));\n  return ret;\n}\n\nint VfsSymlink(const char *target, int dirfd, const char *name) {\n  struct VfsInfo *dir;\n  char newname[VFS_NAME_MAX];\n  int ret;\n  VFS_LOGF(\"VfsSymlink(\\\"%s\\\", %d, \\\"%s\\\")\", target, dirfd, name);\n  if (target == NULL || name == NULL) {\n    return efault();\n  }\n  if (!*name) {\n    return enoent();\n  }\n  if (VfsHandleDirfdName(dirfd, name, &dir, newname) == -1) {\n    return -1;\n  }\n  unassert(!VfsTraverseMount(&dir, newname));\n  if (dir->device->ops->Symlink) {\n    ret = dir->device->ops->Symlink(target, dir, newname);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(dir));\n  return ret;\n}\n\nint VfsStat(int dirfd, const char *name, struct stat *st, int flags) {\n  struct VfsInfo *dir;\n  char newname[VFS_NAME_MAX];\n  int ret = 0;\n  VFS_LOGF(\"VfsStat(%d, \\\"%s\\\", %p, %d)\", dirfd, name, st, flags);\n  if (name == NULL || st == NULL) {\n    return efault();\n  }\n  if (VfsHandleDirfdName(dirfd, name, &dir, newname) == -1) {\n    return -1;\n  }\n  if (!(flags & AT_SYMLINK_NOFOLLOW)) {\n    ret = VfsHandleDirfdSymlink(&dir, newname);\n  }\n  unassert(!VfsTraverseMount(&dir, newname));\n  if (ret != -1) {\n    if (dir->device->ops->Stat) {\n      ret = dir->device->ops->Stat(dir, newname, st, flags);\n    } else {\n      ret = eperm();\n    }\n  }\n  unassert(!VfsFreeInfo(dir));\n  return ret;\n}\n\nint VfsChown(int dirfd, const char *name, uid_t uid, gid_t gid, int flags) {\n  struct VfsInfo *dir;\n  char newname[VFS_NAME_MAX];\n  int ret = 0;\n  VFS_LOGF(\"VfsChown(%d, \\\"%s\\\", %d, %d, %d)\", dirfd, name, uid, gid, flags);\n  if (name == NULL) {\n    return efault();\n  }\n  if (VfsHandleDirfdName(dirfd, name, &dir, newname) == -1) {\n    return -1;\n  }\n  if (!(flags & AT_SYMLINK_NOFOLLOW)) {\n    ret = VfsHandleDirfdSymlink(&dir, newname);\n  }\n  unassert(!VfsTraverseMount(&dir, newname));\n  if (ret != -1) {\n    if (dir->device->ops->Chown) {\n      ret = dir->device->ops->Chown(dir, newname, uid, gid, flags);\n    } else {\n      ret = eperm();\n    }\n  }\n  unassert(!VfsFreeInfo(dir));\n  return ret;\n}\n\nint VfsFchown(int fd, uid_t uid, gid_t gid) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsFchown(%d, %d, %d)\", fd, uid, gid);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Fchown) {\n    ret = info->device->ops->Fchown(info, uid, gid);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsRename(int olddirfd, const char *oldname, int newdirfd,\n              const char *newname) {\n  struct VfsInfo *olddir, *newdir;\n  char newoldname[VFS_NAME_MAX], newnewname[VFS_NAME_MAX];\n  int ret;\n  VFS_LOGF(\"VfsRename(%d, \\\"%s\\\", %d, \\\"%s\\\")\", olddirfd, oldname, newdirfd,\n           newname);\n  if (oldname == NULL || newname == NULL) {\n    return efault();\n  }\n  if (!*oldname || !*newname) {\n    return enoent();\n  }\n  if (VfsHandleDirfdName(olddirfd, oldname, &olddir, newoldname) == -1) {\n    return -1;\n  }\n  if (VfsHandleDirfdName(newdirfd, newname, &newdir, newnewname) == -1) {\n    unassert(!VfsFreeInfo(olddir));\n    return -1;\n  }\n  unassert(!VfsTraverseMount(&olddir, newoldname));\n  unassert(!VfsTraverseMount(&newdir, newnewname));\n  if (olddir->device->ops->Rename) {\n    ret = olddir->device->ops->Rename(olddir, newoldname, newdir, newnewname);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(olddir));\n  unassert(!VfsFreeInfo(newdir));\n  return ret;\n}\n\nssize_t VfsReadlink(int dirfd, const char *name, char *buf, size_t bufsiz) {\n  struct VfsInfo *dir, *file;\n  ssize_t ret;\n  char *tmp;\n  char newname[VFS_NAME_MAX];\n  VFS_LOGF(\"VfsReadlink(%d, \\\"%s\\\", %p, %zu)\", dirfd, name, buf, bufsiz);\n  if (name == NULL || buf == NULL) {\n    return efault();\n  }\n  if (*name == '\\0') {\n    dir = NULL;\n    if (VfsGetFd(dirfd, &file) == -1) {\n      return -1;\n    }\n  } else {\n    if (VfsHandleDirfdName(dirfd, name, &dir, newname) == -1) {\n      return -1;\n    }\n    if (!dir->device->ops->Finddir ||\n        dir->device->ops->Finddir(dir, newname, &file) == -1) {\n      unassert(!VfsFreeInfo(dir));\n      return -1;\n    }\n  }\n  if (file->device->ops->Readlink) {\n    ret = file->device->ops->Readlink(file, &tmp);\n    if (ret != -1) {\n      memcpy(buf, tmp, MIN(ret, bufsiz));\n      ret = MIN(ret, bufsiz);\n      free(tmp);\n    }\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(dir));\n  unassert(!VfsFreeInfo(file));\n  return ret;\n}\n\nint VfsLink(int olddirfd, const char *oldname, int newdirfd,\n            const char *newname, int flags) {\n  struct VfsInfo *olddir, *newdir;\n  char newoldname[VFS_NAME_MAX], newnewname[VFS_NAME_MAX];\n  int ret;\n  VFS_LOGF(\"VfsLink(%d, \\\"%s\\\", %d, \\\"%s\\\", %d)\", olddirfd, oldname, newdirfd,\n           newname, flags);\n  if (oldname == NULL || newname == NULL) {\n    return efault();\n  }\n  if (!*oldname || !*newname) {\n    return enoent();\n  }\n  // AT_EMPTY_PATH currently not supported by blink's syscall subsystem.\n  if (VfsHandleDirfdName(olddirfd, oldname, &olddir, newoldname) == -1) {\n    return -1;\n  }\n  if (flags & AT_SYMLINK_FOLLOW) {\n    if (VfsHandleDirfdName(olddirfd, oldname, &olddir, newoldname) == -1) {\n      unassert(!VfsFreeInfo(olddir));\n      return -1;\n    }\n  }\n  unassert(!VfsTraverseMount(&olddir, newoldname));\n  if (VfsHandleDirfdName(newdirfd, newname, &newdir, newnewname) == -1) {\n    unassert(!VfsFreeInfo(olddir));\n    return -1;\n  }\n  unassert(!VfsTraverseMount(&newdir, newnewname));\n  if (olddir->device != newdir->device) {\n    ret = exdev();\n  } else if (olddir->device->ops->Link) {\n    ret = olddir->device->ops->Link(olddir, newoldname, newdir, newnewname,\n                                    flags);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(olddir));\n  unassert(!VfsFreeInfo(newdir));\n  return ret;\n}\n\nint VfsUtime(int dirfd, const char *name, const struct timespec times[2],\n             int flags) {\n  struct VfsInfo *dir;\n  char newname[VFS_NAME_MAX];\n  int ret = -1;\n  VFS_LOGF(\"VfsUtime(%d, \\\"%s\\\", %p, %d)\", dirfd, name, times, flags);\n  if (name == NULL) {\n    return efault();\n  }\n  if (!*name) {\n    return enoent();\n  }\n  if (VfsHandleDirfdName(dirfd, name, &dir, newname) == -1) {\n    return -1;\n  }\n  if (!(flags & AT_SYMLINK_NOFOLLOW)) {\n    ret = VfsHandleDirfdSymlink(&dir, newname);\n  }\n  unassert(!VfsTraverseMount(&dir, newname));\n  if (ret != -1) {\n    if (dir->device->ops->Utime) {\n      ret = dir->device->ops->Utime(dir, newname, times, flags);\n    } else {\n      ret = eperm();\n    }\n  }\n  unassert(!VfsFreeInfo(dir));\n  return ret;\n}\n\nint VfsFutime(int fd, const struct timespec times[2]) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsFutime(%d, %p)\", fd, times);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Futime) {\n    ret = info->device->ops->Futime(info, times);\n  } else {\n    unassert(!VfsFreeInfo(info));\n    return eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsFstat(int fd, struct stat *st) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsFstat(%d, %p)\", fd, st);\n  if (st == NULL) {\n    return efault();\n  }\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Fstat) {\n    ret = info->device->ops->Fstat(info, st);\n  } else {\n    unassert(!VfsFreeInfo(info));\n    return eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsFtruncate(int fd, off_t length) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsFtruncate(%d, %ld)\", fd, length);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Ftruncate) {\n    ret = info->device->ops->Ftruncate(info, length);\n  } else {\n    unassert(!VfsFreeInfo(info));\n    return eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsClose(int fd) {\n  struct VfsInfo *info;\n  int ret = 0;\n  VFS_LOGF(\"VfsClose(%d)\", fd);\n  if (VfsFreeFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Close) {\n    ret = info->device->ops->Close(info);\n  }\n  if (ret != -1) {\n    unassert(!VfsFreeInfo(info));\n  }\n  return ret;\n}\n\nssize_t VfsRead(int fd, void *buf, size_t nbyte) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsRead(%d, %p, %zu)\", fd, buf, nbyte);\n  if (buf == NULL) {\n    return efault();\n  }\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Read) {\n    ret = info->device->ops->Read(info, buf, nbyte);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nssize_t VfsWrite(int fd, const void *buf, size_t nbyte) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsWrite(%d, %p, %zu)\", fd, buf, nbyte);\n  if (buf == NULL) {\n    return efault();\n  }\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Write) {\n    ret = info->device->ops->Write(info, buf, nbyte);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nssize_t VfsPread(int fd, void *buf, size_t nbyte, off_t offset) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsPread(%d, %p, %zu, %ld)\", fd, buf, nbyte, offset);\n  if (buf == NULL) {\n    return efault();\n  }\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Pread) {\n    ret = info->device->ops->Pread(info, buf, nbyte, offset);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nssize_t VfsPwrite(int fd, const void *buf, size_t nbyte, off_t offset) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsPwrite(%d, %p, %zu, %ld)\", fd, buf, nbyte, offset);\n  if (buf == NULL) {\n    return efault();\n  }\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Pwrite) {\n    ret = info->device->ops->Pwrite(info, buf, nbyte, offset);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nssize_t VfsReadv(int fd, const struct iovec *iov, int iovcnt) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsReadv(%d, %p, %d)\", fd, iov, iovcnt);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Readv) {\n    ret = info->device->ops->Readv(info, iov, iovcnt);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nssize_t VfsWritev(int fd, const struct iovec *iov, int iovcnt) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsWritev(%d, %p, %d)\", fd, iov, iovcnt);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Writev) {\n    ret = info->device->ops->Writev(info, iov, iovcnt);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nssize_t VfsPreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsPreadv(%d, %p, %d, %ld)\", fd, iov, iovcnt, offset);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Preadv) {\n    ret = info->device->ops->Preadv(info, iov, iovcnt, offset);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nssize_t VfsPwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsPwritev(%d, %p, %d, %ld)\", fd, iov, iovcnt, offset);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Pwritev) {\n    ret = info->device->ops->Pwritev(info, iov, iovcnt, offset);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\noff_t VfsSeek(int fd, off_t offset, int whence) {\n  struct VfsInfo *info;\n  off_t ret;\n  VFS_LOGF(\"VfsSeek(%d, %ld, %d)\", fd, offset, whence);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Seek) {\n    ret = info->device->ops->Seek(info, offset, whence);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsFsync(int fd) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsFsync(%d)\", fd);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Fsync) {\n    ret = info->device->ops->Fsync(info);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsFdatasync(int fd) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsFdatasync(%d)\", fd);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Fdatasync) {\n    ret = info->device->ops->Fdatasync(info);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsFlock(int fd, int operation) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsFlock(%d, %d)\", fd, operation);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Flock) {\n    ret = info->device->ops->Flock(info, operation);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsFcntl(int fd, int cmd, ...) {\n  struct VfsInfo *info, *newinfo;\n  int ret;\n  va_list ap;\n  VFS_LOGF(\"VfsFcntl(%d, %d, ...)\", fd, cmd);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  va_start(ap, cmd);\n  // CLOEXEC is already handled by the syscall layer.\n  if (cmd == F_DUPFD || cmd == F_DUPFD_CLOEXEC) {\n    if (info->device->ops->Dup) {\n      ret = info->device->ops->Dup(info, &newinfo);\n      if (ret != -1) {\n        ret = VfsAddFdAtOrAfter(newinfo, va_arg(ap, int));\n        if (ret == -1) {\n          unassert(!VfsFreeInfo(newinfo));\n        }\n      }\n    } else {\n      unassert(!VfsFreeInfo(info));\n      ret = eperm();\n    }\n  } else {\n    if (info->device->ops->Fcntl) {\n      ret = info->device->ops->Fcntl(info, cmd, ap);\n    } else {\n      ret = eperm();\n    }\n  }\n  va_end(ap);\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsIoctl(int fd, unsigned long request, void *arg) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsIoctl(%d, %lu, %p)\", fd, request, arg);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Ioctl) {\n    ret = info->device->ops->Ioctl(info, request, arg);\n  } else {\n    errno = ENOTTY;\n    ret = -1;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsDup(int fd) {\n  struct VfsInfo *info, *newinfo;\n  int ret;\n  VFS_LOGF(\"VfsDup(%d)\", fd);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Dup) {\n    ret = info->device->ops->Dup(info, &newinfo);\n    if (ret != -1) {\n      ret = VfsAddFd(newinfo);\n      if (ret == -1) {\n        unassert(!VfsFreeInfo(newinfo));\n      }\n    }\n  } else {\n    unassert(!VfsFreeInfo(info));\n    return eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsDup2(int fd, int newfd) {\n  struct VfsInfo *info, *newinfo;\n  int ret;\n  VFS_LOGF(\"VfsDup2(%d, %d)\", fd, newfd);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (VfsFreeFd(newfd, &newinfo) == 0) {\n    unassert(!VfsFreeInfo(newinfo));\n  }\n  if (info->device->ops->Dup) {\n    ret = info->device->ops->Dup(info, &newinfo);\n    if (ret != -1) {\n      ret = VfsSetFd(newfd, newinfo);\n      if (ret != -1) {\n        ret = newfd;\n      }\n    }\n  } else {\n    unassert(!VfsFreeInfo(info));\n    return eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\n#ifdef HAVE_DUP3\nint VfsDup3(int fd, int newfd, int flags) {\n  struct VfsInfo *info, *newinfo;\n  int ret;\n  VFS_LOGF(\"VfsDup3(%d, %d, %d)\", fd, newfd, flags);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Dup3) {\n    ret = info->device->ops->Dup3(info, &newinfo, flags);\n    if (ret != -1) {\n      ret = VfsSetFd(newfd, newinfo);\n      if (ret != -1) {\n        ret = newfd;\n      }\n    }\n  } else {\n    unassert(!VfsFreeInfo(info));\n    return eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n#endif\n\nint VfsPoll(struct pollfd *fds, nfds_t nfds, int timeout) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsPoll(%p, %lld, %d)\", fds, (long long)nfds, timeout);\n  // Currently, blink only uses poll with nfds = 1 and timeout = 0\n  unassert(nfds == 1);\n  unassert(timeout == 0);\n  if (VfsGetFd(fds[0].fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Poll) {\n    ret = info->device->ops->Poll(&info, fds, 1, timeout);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsSelect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,\n              struct timespec *timeout, sigset_t *sigmask) {\n  VFS_LOGF(\"VfsSelect(%d, %p, %p, %p, %p, %p)\", nfds, readfds, writefds,\n           exceptfds, timeout, sigmask);\n  return enosys();\n}\n\nDIR *VfsOpendir(int fd) {\n  struct VfsInfo *info;\n  DIR *ret;\n  VFS_LOGF(\"VfsOpendir(%d)\", fd);\n  if (VfsGetFd(fd, &info) == -1) {\n    return NULL;\n  }\n  if (info->device->ops->Opendir) {\n    if (info->device->ops->Opendir(info, (struct VfsInfo **)&ret) == -1) {\n      ret = NULL;\n    }\n  } else {\n    eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\n#ifdef HAVE_SEEKDIR\nvoid VfsSeekdir(DIR *dir, long loc) {\n  struct VfsInfo *info;\n  VFS_LOGF(\"VfsSeekdir(%p, %ld)\", dir, loc);\n  info = (struct VfsInfo *)dir;\n  if (info->device->ops->Seekdir) {\n    info->device->ops->Seekdir(info, loc);\n  } else {\n    VFS_LOGF(\"seekdir() not supported by device %p.\", info->device);\n    eperm();\n    return;\n  }\n}\n\nlong VfsTelldir(DIR *dir) {\n  struct VfsInfo *info;\n  long ret;\n  VFS_LOGF(\"VfsTelldir(%p)\", dir);\n  info = (struct VfsInfo *)dir;\n  if (info->device->ops->Telldir) {\n    ret = info->device->ops->Telldir(info);\n  } else {\n    VFS_LOGF(\"telldir() not supported by device %p.\", info->device);\n    return eperm();\n  }\n  return ret;\n}\n#endif\n\nstruct dirent *VfsReaddir(DIR *dir) {\n  struct VfsInfo *info;\n  struct dirent *ret;\n  VFS_LOGF(\"VfsReaddir(%p)\", dir);\n  info = (struct VfsInfo *)dir;\n  if (info->device->ops->Readdir) {\n    ret = info->device->ops->Readdir(info);\n  } else {\n    VFS_LOGF(\"readdir() not supported by device %p.\", info->device);\n    eperm();\n    ret = NULL;\n  }\n  return ret;\n}\n\nvoid VfsRewinddir(DIR *dir) {\n  struct VfsInfo *info;\n  VFS_LOGF(\"VfsRewindDir(%p)\", dir);\n  info = (struct VfsInfo *)dir;\n  if (info->device->ops->Rewinddir) {\n    info->device->ops->Rewinddir(info);\n  } else {\n    VFS_LOGF(\"rewinddir() not supported by device %p.\", info->device);\n    eperm();\n    return;\n  }\n}\n\nint VfsClosedir(DIR *dir) {\n  struct VfsInfo *info;\n  struct Dll *e;\n  struct VfsFd *vfsfd;\n  int ret;\n  VFS_LOGF(\"VfsClosedir(%p)\", dir);\n  info = (struct VfsInfo *)dir;\n  if (info->device->ops->Closedir) {\n    ret = info->device->ops->Closedir(info);\n    if (ret != -1) {\n      LOCK(&g_vfs.lock);\n      for (e = dll_first(g_vfs.fds); e;) {\n        vfsfd = VFS_FD_CONTAINER(e);\n        e = dll_next(g_vfs.fds, e);\n        if (vfsfd->data == info) {\n          unassert(!VfsFreeInfo(vfsfd->data));\n          dll_remove(&g_vfs.fds, &vfsfd->elem);\n          free(vfsfd);\n          break;\n        }\n      }\n      UNLOCK(&g_vfs.lock);\n    }\n  } else {\n    ret = eperm();\n  }\n  return ret;\n}\n\nint VfsBind(int fd, const struct sockaddr *addr, socklen_t addrlen) {\n  struct VfsInfo *info, *dir, *oldparent;\n  struct VfsDevice *olddevice;\n  char newname[PATH_MAX];\n  int ret;\n  VFS_LOGF(\"VfsBind(%d, %p, %d)\", fd, addr, addrlen);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (addr->sa_family != AF_UNIX) {\n    ret = HostfsBind(info, addr, addrlen);\n  } else {\n    if (VfsHandleDirfdName(AT_FDCWD, addr->sa_data, &dir, newname) == -1) {\n      ret = -1;\n    } else {\n      oldparent = info->parent;\n      unassert(!VfsAcquireInfo(dir, &info->parent));\n      olddevice = info->device;\n      unassert(!VfsAcquireDevice(dir->device, &info->device));\n      info->name = strdup(newname);\n      if (!info->name) {\n        ret = enomem();\n      } else {\n        info->namelen = strlen(info->name);\n        // The new driver should know the info's parent, name and device.\n        // The data still belongs to hostfs, which should be freed and replaced\n        // with its own.\n        ret = dir->device->ops->Bind(info, addr, addrlen);\n        if (ret == -1) {\n          unassert(!VfsFreeInfo(info->parent));\n          info->parent = oldparent;\n          unassert(!VfsFreeDevice(info->device));\n          info->device = olddevice;\n          free((void *)info->name);\n          info->name = NULL;\n          info->namelen = 0;\n        } else {\n          unassert(!VfsFreeInfo(oldparent));\n          unassert(!VfsFreeDevice(olddevice));\n        }\n      }\n      unassert(!VfsFreeInfo(dir));\n    }\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsConnect(int fd, const struct sockaddr *addr, socklen_t addrlen) {\n  struct VfsInfo *info, *sock;\n  const char *name;\n  int ret;\n  VFS_LOGF(\"VfsConnect(%d, %p, %d)\", fd, addr, addrlen);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  // TODO: Handle abstract sockets (sa_data[0] == '\\0') on non-Linux\n  // platforms.\n  if (addr->sa_family != AF_UNIX || addr->sa_data[0] == '\\0') {\n    ret = HostfsConnect(info, addr, addrlen);\n  } else {\n    name = ((struct sockaddr_un *)addr)->sun_path;\n    if (VfsTraverse(name, &sock, false) == -1) {\n      ret = -1;\n    } else {\n      if (info->device->ops->Connectunix) {\n        ret = info->device->ops->Connectunix(\n            sock, info, (const struct sockaddr_un *)addr, addrlen);\n      } else {\n        ret = eperm();\n      }\n      unassert(!VfsFreeInfo(sock));\n    }\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsAccept(int fd, struct sockaddr *addr, socklen_t *addrlen) {\n  struct VfsInfo *info, *newinfo;\n  int ret;\n  VFS_LOGF(\"VfsAccept(%d, %p, %p)\", fd, addr, addrlen);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (addr->sa_family != AF_UNIX) {\n    ret = HostfsAccept(info, addr, addrlen, &newinfo);\n  } else {\n    if (info->device->ops->Accept) {\n      ret = info->device->ops->Accept(info, addr, addrlen, &newinfo);\n    } else {\n      ret = eperm();\n    }\n  }\n  if (ret != -1) {\n    ret = VfsAddFd(newinfo);\n    if (ret == -1) {\n      unassert(!VfsFreeInfo(newinfo));\n    }\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsListen(int fd, int backlog) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsListen(%d, %d)\", fd, backlog);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Listen) {\n    ret = info->device->ops->Listen(info, backlog);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsShutdown(int fd, int how) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsShutdown(%d, %d)\", fd, how);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Shutdown) {\n    ret = info->device->ops->Shutdown(info, how);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nssize_t VfsRecvmsg(int fd, struct msghdr *msg, int flags) {\n  struct VfsInfo *info, *sock;\n  const char *name;\n  int ret;\n  VFS_LOGF(\"VfsRecvmsg(%d, %p, %d)\", fd, msg, flags);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (msg->msg_name &&\n      ((struct sockaddr *)msg->msg_name)->sa_family == AF_UNIX) {\n    name = ((struct sockaddr_un *)msg->msg_name)->sun_path;\n    if (VfsTraverse(name, &sock, false) == -1) {\n      ret = -1;\n    } else {\n      if (sock->device->ops->Recvmsgunix) {\n        ret = sock->device->ops->Recvmsgunix(sock, info, msg, flags);\n      } else {\n        ret = eperm();\n      }\n      unassert(!VfsFreeInfo(sock));\n    }\n  }\n  if (info->device->ops->Recvmsg) {\n    ret = info->device->ops->Recvmsg(info, msg, flags);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nssize_t VfsSendmsg(int fd, const struct msghdr *msg, int flags) {\n  struct VfsInfo *info, *sock;\n  const char *name;\n  int ret;\n  VFS_LOGF(\"VfsSendmsg(%d, %p, %d)\", fd, msg, flags);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (msg->msg_name &&\n      ((struct sockaddr *)msg->msg_name)->sa_family == AF_UNIX) {\n    name = ((struct sockaddr_un *)msg->msg_name)->sun_path;\n    if (VfsTraverse(name, &sock, false) == -1) {\n      ret = -1;\n    } else {\n      if (sock->device->ops->Sendmsgunix) {\n        ret = sock->device->ops->Sendmsgunix(sock, info, msg, flags);\n      } else {\n        ret = eperm();\n      }\n      unassert(!VfsFreeInfo(sock));\n    }\n  } else {\n    if (info->device->ops->Sendmsg) {\n      ret = info->device->ops->Sendmsg(info, msg, flags);\n    } else {\n      ret = eperm();\n    }\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsGetsockopt(int fd, int level, int optname, void *optval,\n                  socklen_t *optlen) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsGetsockopt(%d, %d, %d, %p, %p)\", fd, level, optname, optval,\n           optlen);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Getsockopt) {\n    ret = info->device->ops->Getsockopt(info, level, optname, optval, optlen);\n  } else {\n    ret = eopnotsupp();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsSetsockopt(int fd, int level, int optname, const void *optval,\n                  socklen_t optlen) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsSetsockopt(%d, %d, %d, %p, %u)\", fd, level, optname, optval,\n           optlen);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Setsockopt) {\n    ret = info->device->ops->Setsockopt(info, level, optname, optval, optlen);\n  } else {\n    ret = eopnotsupp();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsGetsockname(int fd, struct sockaddr *addr, socklen_t *addrlen) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsGetsockname(%d, %p, %p)\", fd, addr, addrlen);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Getsockname) {\n    ret = info->device->ops->Getsockname(info, addr, addrlen);\n  } else {\n    ret = eopnotsupp();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsGetpeername(int fd, struct sockaddr *addr, socklen_t *addrlen) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsGetpeername(%d, %p, %p)\", fd, addr, addrlen);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Getpeername) {\n    ret = info->device->ops->Getpeername(info, addr, addrlen);\n  } else {\n    ret = eopnotsupp();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic bool VfsMemoryRangeOverlap(void *a, size_t alen, void *b, size_t blen) {\n  return ((uintptr_t)a <= (uintptr_t)b && (uintptr_t)b < (uintptr_t)a + alen) ||\n         ((uintptr_t)b <= (uintptr_t)a && (uintptr_t)a < (uintptr_t)b + blen);\n}\n\nstatic bool VfsMemoryRangeContains(void *a, size_t alen, void *b, size_t blen) {\n  return (uintptr_t)a <= (uintptr_t)b &&\n         (uintptr_t)b + blen <= (uintptr_t)a + alen;\n}\n\nstatic int VfsMapFree(struct VfsMap *map) {\n  if (map == NULL) {\n    return 0;\n  }\n  if (VfsFreeInfo(map->data) == -1) {\n    return -1;\n  }\n  free(map);\n  return 0;\n}\n\nstatic int VfsMapSplit(struct VfsMap *map, void *addr, size_t len,\n                       struct VfsMap **left, struct VfsMap **right) {\n  struct VfsMap *l, *r;\n  void *end, *mapend;\n  l = r = NULL;\n  unassert(VfsMemoryRangeOverlap(map->addr, map->len, addr, len));\n  if ((uintptr_t)map->addr + map->len > (uintptr_t)addr &&\n      (uintptr_t)map->addr < (uintptr_t)addr) {\n    l = (struct VfsMap *)malloc(sizeof(*l));\n    if (!l) return enomem();\n    l->addr = map->addr;\n    l->len = (uintptr_t)addr - (uintptr_t)map->addr;\n    l->offset = map->offset;\n    l->prot = map->prot;\n    l->flags = map->flags;\n    unassert(!VfsAcquireInfo(map->data, &l->data));\n    dll_init(&l->elem);\n  }\n  if ((uintptr_t)addr + len > (uintptr_t)map->addr &&\n      (uintptr_t)addr + len < (uintptr_t)map->addr + map->len) {\n    r = (struct VfsMap *)malloc(sizeof(*r));\n    if (!r) {\n      unassert(!VfsMapFree(l));\n      return enomem();\n    }\n    r->addr = (void *)((uintptr_t)addr + len);\n    r->len = (uintptr_t)map->addr + map->len - ((uintptr_t)addr + len);\n    r->offset = map->offset + ((uintptr_t)addr + len - (uintptr_t)map->addr);\n    r->prot = map->prot;\n    r->flags = map->flags;\n    unassert(!VfsAcquireInfo(map->data, &r->data));\n    dll_init(&r->elem);\n  }\n  end = (void *)((uintptr_t)addr + len);\n  mapend = (void *)((uintptr_t)map->addr + map->len);\n  map->addr = (void *)MAX((uintptr_t)map->addr, (uintptr_t)addr);\n  map->len = MIN((uintptr_t)mapend, (uintptr_t)end) - (uintptr_t)map->addr;\n  *left = l;\n  *right = r;\n  return 0;\n}\n\nstatic int VfsMapListExtractAffectedRange(struct Dll **maps, void *addr,\n                                          size_t len, struct Dll **original,\n                                          struct Dll **modified,\n                                          struct Dll **before) {\n  struct Dll *e, *f;\n  struct VfsMap *map, *newmap, *newmapleft = 0, *newmapright = 0;\n  e = dll_first(*maps);\n  while (e && !VfsMemoryRangeOverlap(VFS_MAP_CONTAINER(e)->addr,\n                                     VFS_MAP_CONTAINER(e)->len, addr, len)) {\n    e = dll_next(*maps, e);\n  }\n  if (!e) {\n    *original = *modified = *before = NULL;\n    return 0;\n  }\n  *original = *modified = NULL;\n  *before = dll_prev(*maps, e);\n  while (e && (map = VFS_MAP_CONTAINER(e)) &&\n         VfsMemoryRangeOverlap(map->addr, map->len, addr, len)) {\n    newmap = (struct VfsMap *)malloc(sizeof(*newmap));\n    if (!newmap) return enomem();\n    newmap->addr = map->addr;\n    newmap->len = map->len;\n    newmap->offset = map->offset;\n    newmap->prot = map->prot;\n    newmap->flags = map->flags;\n    unassert(!VfsAcquireInfo(map->data, &newmap->data));\n    dll_init(&newmap->elem);\n    if (VfsMapSplit(newmap, addr, len, &newmapleft, &newmapright) == -1) {\n      unassert(!VfsMapFree(newmap));\n      if (before == NULL) {\n        e = dll_first(*original);\n        dll_remove(original, e);\n        dll_make_first(maps, e);\n        dll_splice_after(e, dll_first(*original));\n      } else {\n        dll_splice_after(*before, dll_first(*original));\n      }\n      for (e = dll_first(*modified); e;) {\n        map = VFS_MAP_CONTAINER(e);\n        e = dll_next(*modified, e);\n        dll_remove(modified, &map->elem);\n        unassert(!VfsMapFree(map));\n      }\n      return -1;\n    }\n    if (newmapleft) {\n      dll_make_last(modified, &newmapleft->elem);\n    }\n    dll_make_last(modified, &newmap->elem);\n    if (newmapright) {\n      dll_make_last(modified, &newmapright->elem);\n    }\n    f = dll_next(*maps, e);\n    dll_remove(maps, e);\n    dll_make_last(original, e);\n    e = f;\n  }\n  return 0;\n}\n\nstatic void VfsMapListJoin(struct Dll **maps, struct Dll **tojoin,\n                           struct Dll *before) {\n  struct Dll *e;\n  if (*tojoin == NULL) {\n    return;\n  }\n  if (before == NULL) {\n    e = dll_first(*tojoin);\n    dll_remove(tojoin, e);\n    dll_make_first(&g_vfs.maps, e);\n    if (!dll_is_empty(*tojoin)) {\n      dll_splice_after(e, dll_first(*tojoin));\n    }\n  } else {\n    dll_splice_after(before, dll_first(*tojoin));\n  }\n}\n\nstatic void VfsMapListFree(struct Dll **tofree) {\n  struct Dll *e;\n  struct VfsMap *map;\n  for (e = dll_first(*tofree); e;) {\n    map = VFS_MAP_CONTAINER(e);\n    e = dll_next(*tofree, e);\n    dll_remove(tofree, &map->elem);\n    unassert(!VfsMapFree(map));\n  }\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nvoid *VfsMmap(void *addr, size_t len, int prot, int flags, int fd,\n              off_t offset) {\n  struct VfsInfo *info;\n  struct VfsMap *map, *newmap;\n  void *ret;\n  struct Dll *e, *original, *modified, *before;\n  VFS_LOGF(\"VfsMmap(%p, %zu, %d, %d, %d, %ld)\", addr, len, prot, flags, fd,\n           offset);\n  LOCK(&g_vfs.mapslock);\n  info = NULL;\n  original = modified = NULL;\n  newmap = NULL;\n  if (VfsMapListExtractAffectedRange(&g_vfs.maps, addr, len, &original,\n                                     &modified, &before) == -1) {\n    goto cleananddie;\n  }\n#ifdef MAP_ANONYMOUS\n  if (flags & MAP_ANONYMOUS) {\n    if ((ret = mmap(addr, len, prot, flags, -1, 0)) == MAP_FAILED) {\n      goto cleananddie;\n    }\n  } else {\n#else\n  {\n#endif\n    if (VfsGetFd(fd, &info) == -1) {\n      goto cleananddie;\n    }\n    newmap = (struct VfsMap *)malloc(sizeof(*newmap));\n    if (!newmap) {\n      goto cleananddie;\n    }\n    newmap->len = len;\n    newmap->offset = offset;\n    newmap->prot = prot;\n    newmap->flags = flags;\n    unassert(!VfsAcquireInfo(info, &newmap->data));\n    dll_init(&newmap->elem);\n    if (info->device->ops->Mmap) {\n      if ((ret = info->device->ops->Mmap(info, addr, len, prot, flags,\n                                         offset)) == MAP_FAILED) {\n        goto cleananddie;\n      }\n      newmap->addr = ret;\n    } else {\n      enodev();\n      goto cleananddie;\n    }\n  }\n  if (flags & MAP_FIXED) {\n    // Successful MAP_FIXED means that the old mappings were unmapped\n    for (e = dll_first(modified); e;) {\n      map = VFS_MAP_CONTAINER(e);\n      if (!VfsMemoryRangeContains(addr, len, map->addr, map->len)) {\n        unassert(!VfsMemoryRangeOverlap(addr, len, map->addr, map->len));\n        e = dll_next(modified, e);\n        continue;\n      }\n      if (map->data->device->ops->Munmap) {\n        unassert(\n            !map->data->device->ops->Munmap(map->data, map->addr, map->len));\n      }\n      e = dll_next(modified, e);\n      dll_remove(&modified, &map->elem);\n      unassert(!VfsMapFree(map));\n    }\n  }\n  if (newmap) {\n    e = dll_last(modified);\n    while (e && (map = VFS_MAP_CONTAINER(e)) &&\n           (uintptr_t)map->addr + map->len > (uintptr_t)newmap->addr) {\n      unassert(!VfsMemoryRangeOverlap(map->addr, map->len, newmap->addr,\n                                      newmap->len));\n      e = dll_prev(modified, e);\n    }\n    if (e) {\n      dll_splice_after(e, &newmap->elem);\n    } else {\n      dll_make_first(&modified, &newmap->elem);\n    }\n  }\n  VfsMapListFree(&original);\n  VfsMapListJoin(&g_vfs.maps, &modified, before);\n  VfsFreeInfo(info);\n  UNLOCK(&g_vfs.mapslock);\n  return ret;\ncleananddie:\n  VfsMapListJoin(&g_vfs.maps, &original, before);\n  VfsMapListFree(&modified);\n  VfsFreeInfo(info);\n  UNLOCK(&g_vfs.mapslock);\n  unassert(!VfsMapFree(newmap));\n  return MAP_FAILED;\n}\n\nint VfsMunmap(void *addr, size_t len) {\n  struct Dll *e;\n  struct VfsMap *map;\n  struct Dll *original, *modified, *before;\n  VFS_LOGF(\"VfsMunmap(%p, %zu)\", addr, len);\n  original = modified = NULL;\n  LOCK(&g_vfs.mapslock);\n  if (VfsMapListExtractAffectedRange(&g_vfs.maps, addr, len, &original,\n                                     &modified, &before) == -1) {\n    goto cleananddie;\n  }\n  if (munmap(addr, len) == -1) {\n    goto cleananddie;\n  }\n  for (e = dll_first(modified); e;) {\n    map = VFS_MAP_CONTAINER(e);\n    if (!VfsMemoryRangeContains(addr, len, map->addr, map->len)) {\n      unassert(!VfsMemoryRangeOverlap(addr, len, map->addr, map->len));\n      e = dll_next(modified, e);\n      continue;\n    }\n    if (map->data->device->ops->Munmap) {\n      unassert(!map->data->device->ops->Munmap(map->data, map->addr, map->len));\n    }\n    e = dll_next(modified, e);\n    dll_remove(&modified, &map->elem);\n    unassert(!VfsMapFree(map));\n  }\n  VfsMapListFree(&original);\n  VfsMapListJoin(&g_vfs.maps, &modified, before);\n  UNLOCK(&g_vfs.mapslock);\n  return 0;\ncleananddie:\n  VfsMapListJoin(&g_vfs.maps, &original, before);\n  VfsMapListFree(&modified);\n  UNLOCK(&g_vfs.mapslock);\n  return -1;\n}\n\nint VfsMprotect(void *addr, size_t len, int prot) {\n  struct Dll *e;\n  struct VfsMap *map;\n  struct Dll *original, *modified, *before;\n  VFS_LOGF(\"VfsMprotect(%p, %zu, %d)\", addr, len, prot);\n  original = modified = NULL;\n  LOCK(&g_vfs.mapslock);\n  if (VfsMapListExtractAffectedRange(&g_vfs.maps, addr, len, &original,\n                                     &modified, &before) == -1) {\n    goto cleananddie;\n  }\n  for (e = dll_first(modified); e; e = dll_next(modified, e)) {\n    map = VFS_MAP_CONTAINER(e);\n    if (!VfsMemoryRangeContains(addr, len, map->addr, map->len)) {\n      unassert(!VfsMemoryRangeOverlap(addr, len, map->addr, map->len));\n      continue;\n    }\n    if (map->data->device->ops->Mprotect) {\n      if (map->data->device->ops->Mprotect(map->data, map->addr, map->len,\n                                           prot) == -1) {\n        goto cleananddie;\n      }\n      map->prot = prot;\n    }\n  }\n  if (mprotect(addr, len, prot) == -1) {\n    goto cleananddie;\n  }\n  VfsMapListFree(&original);\n  VfsMapListJoin(&g_vfs.maps, &modified, before);\n  UNLOCK(&g_vfs.mapslock);\n  return 0;\ncleananddie:\n  if (original != NULL) {\n    for (e = dll_first(original); e; e = dll_next(original, e)) {\n      map = VFS_MAP_CONTAINER(e);\n      if (map->data->device->ops->Mprotect) {\n        unassert(!map->data->device->ops->Mprotect(map->data, map->addr,\n                                                   map->len, map->prot));\n      }\n    }\n  }\n  VfsMapListJoin(&g_vfs.maps, &original, before);\n  VfsMapListFree(&modified);\n  UNLOCK(&g_vfs.mapslock);\n  return -1;\n}\n\nint VfsMsync(void *addr, size_t len, int flags) {\n  struct Dll *e;\n  struct VfsMap *map;\n  void *currentaddr;\n  size_t currentlen;\n  VFS_LOGF(\"VfsMsync(%p, %zu, %d)\", addr, len, flags);\n  if (msync(addr, len, flags) == -1) {\n    return -1;\n  }\n  LOCK(&g_vfs.mapslock);\n  for (e = dll_first(g_vfs.maps); e; e = dll_next(g_vfs.maps, e)) {\n    map = VFS_MAP_CONTAINER(e);\n    if ((uintptr_t)map->addr + map->len <= (uintptr_t)addr ||\n        (uintptr_t)map->addr >= (uintptr_t)addr + len) {\n      continue;\n    }\n    if (!map->data->device->ops->Msync) {\n      UNLOCK(&g_vfs.mapslock);\n      return enodev();\n    }\n    currentaddr = map->addr;\n    currentlen = map->len;\n    if (currentaddr < addr) {\n      currentlen -= (uintptr_t)addr - (uintptr_t)currentaddr;\n      currentaddr = addr;\n    }\n    if ((uintptr_t)currentaddr + currentlen > (uintptr_t)addr + len) {\n      currentlen = (uintptr_t)addr + len - (uintptr_t)currentaddr;\n    }\n    if (map->data->device->ops->Msync(map->data, currentaddr, currentlen,\n                                      flags) == -1) {\n      UNLOCK(&g_vfs.mapslock);\n      return -1;\n    }\n  }\n  UNLOCK(&g_vfs.mapslock);\n  return 0;\n}\n\nint VfsTcgetattr(int fd, struct termios *termios_p) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsTcgetattr(%d, %p)\", fd, termios_p);\n  if (termios_p == NULL) {\n    return efault();\n  }\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Tcgetattr) {\n    ret = info->device->ops->Tcgetattr(info, termios_p);\n  } else {\n    errno = ENOTTY;\n    ret = -1;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsTcsetattr(int fd, int optional_actions,\n                 const struct termios *termios_p) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsTcsetattr(%d, %d, %p)\", fd, optional_actions, termios_p);\n  if (termios_p == NULL) {\n    return efault();\n  }\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Tcsetattr) {\n    ret = info->device->ops->Tcsetattr(info, optional_actions, termios_p);\n  } else {\n    errno = ENOTTY;\n    ret = -1;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsTcflush(int fd, int queue_selector) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsTcflush(%d, %d)\", fd, queue_selector);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Tcflush) {\n    ret = info->device->ops->Tcflush(info, queue_selector);\n  } else {\n    errno = ENOTTY;\n    ret = -1;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsTcdrain(int fd) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsTcdrain(%d)\", fd);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Tcdrain) {\n    ret = info->device->ops->Tcdrain(info);\n  } else {\n    errno = ENOTTY;\n    ret = -1;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsTcsendbreak(int fd, int duration) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsTcsendbreak(%d, %d)\", fd, duration);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Tcsendbreak) {\n    ret = info->device->ops->Tcsendbreak(info, duration);\n  } else {\n    errno = ENOTTY;\n    ret = -1;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsTcflow(int fd, int action) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsTcflow(%d, %d)\", fd, action);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Tcflow) {\n    ret = info->device->ops->Tcflow(info, action);\n  } else {\n    errno = ENOTTY;\n    ret = -1;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\npid_t VfsTcgetsid(int fd) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsTcgetsid(%d)\", fd);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Tcgetsid) {\n    ret = info->device->ops->Tcgetsid(info);\n  } else {\n    errno = ENOTTY;\n    ret = -1;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\npid_t VfsTcgetpgrp(int fd) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsTcgetpgrp(%d)\", fd);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Tcgetpgrp) {\n    ret = info->device->ops->Tcgetpgrp(info);\n  } else {\n    errno = ENOTTY;\n    ret = -1;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\nint VfsTcsetpgrp(int fd, pid_t pgrp_id) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsTcsetpgrp(%d, %d)\", fd, pgrp_id);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Tcsetpgrp) {\n    ret = info->device->ops->Tcsetpgrp(info, pgrp_id);\n  } else {\n    errno = ENOTTY;\n    ret = -1;\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\n#ifdef HAVE_SOCKATMARK\nint VfsSockatmark(int fd) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsSockatmark(%d)\", fd);\n  if (VfsGetFd(fd, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Sockatmark) {\n    ret = info->device->ops->Sockatmark(info);\n  } else {\n    ret = eopnotsupp();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n#endif\n\nint VfsExecve(const char *pathname, char *const *argv, char *const *envp) {\n  struct VfsInfo *info;\n  int ret;\n  VFS_LOGF(\"VfsExecve(\\\"%s\\\", %p, %p)\", pathname, argv, envp);\n  info = NULL;\n  if ((ret = VfsOpen(AT_FDCWD, pathname, O_RDONLY | O_CLOEXEC, 0)) == -1) {\n    return -1;\n  }\n  if (VfsFreeFd(ret, &info) == -1) {\n    return -1;\n  }\n  if (info->device->ops->Fexecve) {\n    ret = info->device->ops->Fexecve(info, argv, envp);\n  } else {\n    ret = eperm();\n  }\n  unassert(!VfsFreeInfo(info));\n  return ret;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nint VfsPipe(int fds[2]) {\n  struct VfsInfo *infos[2];\n  VFS_LOGF(\"VfsPipe(%p)\", fds);\n  if (fds == NULL) {\n    return efault();\n  }\n  if (HostfsPipe(infos) == -1) {\n    return -1;\n  }\n  if ((fds[0] = VfsAddFd(infos[0])) == -1) {\n    VfsFreeInfo(infos[0]);\n    VfsFreeInfo(infos[1]);\n    return -1;\n  }\n  if ((fds[1] = VfsAddFd(infos[1])) == -1) {\n    VfsFreeFd(fds[0], &infos[0]);\n    VfsFreeInfo(infos[0]);\n    VfsFreeInfo(infos[1]);\n    return -1;\n  }\n  return 0;\n}\n\n// TODO(trungnt): pipe2() should be polyfilled not partially disabled\n#ifdef HAVE_PIPE2\nint VfsPipe2(int fds[2], int flags) {\n  struct VfsInfo *infos[2];\n  VFS_LOGF(\"VfsPipe2(%p, %d)\", fds, flags);\n  if (fds == NULL) {\n    return efault();\n  }\n  if (HostfsPipe2(infos, flags) == -1) {\n    return -1;\n  }\n  if ((fds[0] = VfsAddFd(infos[0])) == -1) {\n    VfsFreeInfo(infos[0]);\n    VfsFreeInfo(infos[1]);\n    return -1;\n  }\n  if ((fds[1] = VfsAddFd(infos[1])) == -1) {\n    VfsFreeFd(fds[0], &infos[0]);\n    VfsFreeInfo(infos[0]);\n    VfsFreeInfo(infos[1]);\n    return -1;\n  }\n  return 0;\n}\n#endif\n\nint VfsSocket(int domain, int type, int protocol) {\n  struct VfsInfo *info;\n  int fd;\n  VFS_LOGF(\"VfsSocket(%d, %d, %d)\", domain, type, protocol);\n  if (HostfsSocket(domain, type, protocol, &info) == -1) {\n    return -1;\n  }\n  if ((fd = VfsAddFd(info)) == -1) {\n    unassert(!VfsFreeInfo(info));\n    return -1;\n  }\n  return fd;\n}\n\nint VfsSocketpair(int domain, int type, int protocol, int fds[2]) {\n  struct VfsInfo *infos[2];\n  VFS_LOGF(\"VfsSocketPair(%d, %d, %d, %p)\", domain, type, protocol, fds);\n  if (fds == NULL) {\n    return efault();\n  }\n  if (HostfsSocketpair(domain, type, protocol, infos) == -1) {\n    return -1;\n  }\n  if ((fds[0] = VfsAddFd(infos[0])) == -1) {\n    VfsFreeInfo(infos[0]);\n    VfsFreeInfo(infos[1]);\n    return -1;\n  }\n  if ((fds[1] = VfsAddFd(infos[1])) == -1) {\n    VfsFreeFd(fds[0], &infos[0]);\n    VfsFreeInfo(infos[0]);\n    VfsFreeInfo(infos[1]);\n    return -1;\n  }\n  return 0;\n}\n\n#endif /* DISABLE_VFS */\n"
  },
  {
    "path": "blink/vfs.h",
    "content": "#ifndef BLINK_VFS_H_\n#define BLINK_VFS_H_\n#include <dirent.h>\n#include <poll.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <sys/select.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <sys/uio.h>\n#include <sys/un.h>\n#include <termios.h>\n#include <unistd.h>\n\n#include \"blink/dll.h\"\n#include \"blink/macros.h\"\n#include \"blink/overlays.h\"\n#include \"blink/preadv.h\"\n#include \"blink/thread.h\"\n#include \"blink/tsan.h\"\n#include \"blink/types.h\"\n\n#define VFS_SYSTEM_ROOT_MOUNT \"/SystemRoot\"\n#define VFS_PATH_MAX          MAX(PATH_MAX, 4096)\n#define VFS_NAME_MAX          256\n\nstruct VfsDevice;\nstruct VfsMount;\nstruct VfsInfo;\nstruct VfsSystem;\nstruct VfsFd;\nstruct VfsMap;\n\nstruct Vfs {\n  struct Dll *devices GUARDED_BY(lock);\n  struct Dll *systems GUARDED_BY(lock);\n  struct Dll *fds GUARDED_BY(lock);\n  struct Dll *maps GUARDED_BY(mapslock);\n  pthread_mutex_t_ lock;\n  pthread_mutex_t_ mapslock;\n};\n\nstruct VfsOps {\n  int (*Init)(const char *, u64, const void *, struct VfsDevice **,\n              struct VfsMount **);\n  int (*Freeinfo)(void *);\n  int (*Freedevice)(void *);\n  int (*Readmountentry)(struct VfsDevice *, char **, char **, char **);\n  int (*Finddir)(struct VfsInfo *, const char *, struct VfsInfo **);\n  int (*Traverse)(struct VfsInfo **, const char **, struct VfsInfo *);\n  ssize_t (*Readlink)(struct VfsInfo *, char **);\n  int (*Mkdir)(struct VfsInfo *, const char *, mode_t);\n  int (*Mkfifo)(struct VfsInfo *, const char *, mode_t);\n  int (*Open)(struct VfsInfo *, const char *, int, int, struct VfsInfo **);\n  int (*Access)(struct VfsInfo *, const char *, mode_t, int);\n  int (*Stat)(struct VfsInfo *, const char *, struct stat *, int);\n  int (*Fstat)(struct VfsInfo *, struct stat *);\n  int (*Chmod)(struct VfsInfo *, const char *, mode_t, int);\n  int (*Fchmod)(struct VfsInfo *, mode_t);\n  int (*Chown)(struct VfsInfo *, const char *, uid_t, gid_t, int);\n  int (*Fchown)(struct VfsInfo *, uid_t, gid_t);\n  int (*Ftruncate)(struct VfsInfo *, off_t);\n  int (*Close)(struct VfsInfo *);\n  int (*Link)(struct VfsInfo *, const char *, struct VfsInfo *, const char *,\n              int);\n  int (*Unlink)(struct VfsInfo *, const char *, int);\n  ssize_t (*Read)(struct VfsInfo *, void *, size_t);\n  ssize_t (*Write)(struct VfsInfo *, const void *, size_t);\n  ssize_t (*Pread)(struct VfsInfo *, void *, size_t, off_t);\n  ssize_t (*Pwrite)(struct VfsInfo *, const void *, size_t, off_t);\n  ssize_t (*Readv)(struct VfsInfo *, const struct iovec *, int);\n  ssize_t (*Writev)(struct VfsInfo *, const struct iovec *, int);\n  ssize_t (*Preadv)(struct VfsInfo *, const struct iovec *, int, off_t);\n  ssize_t (*Pwritev)(struct VfsInfo *, const struct iovec *, int, off_t);\n  off_t (*Seek)(struct VfsInfo *, off_t, int);\n  int (*Fsync)(struct VfsInfo *);\n  int (*Fdatasync)(struct VfsInfo *);\n  int (*Flock)(struct VfsInfo *, int);\n  int (*Fcntl)(struct VfsInfo *, int, va_list);\n  int (*Ioctl)(struct VfsInfo *, unsigned long, const void *);\n  int (*Dup)(struct VfsInfo *, struct VfsInfo **);\n#ifdef HAVE_DUP3\n  int (*Dup3)(struct VfsInfo *, struct VfsInfo **, int);\n#endif\n  int (*Poll)(struct VfsInfo **, struct pollfd *, nfds_t, int);\n  int (*Opendir)(struct VfsInfo *, struct VfsInfo **);\n#ifdef HAVE_SEEKDIR\n  void (*Seekdir)(struct VfsInfo *, long);\n  long (*Telldir)(struct VfsInfo *);\n#endif\n  struct dirent *(*Readdir)(struct VfsInfo *);\n  void (*Rewinddir)(struct VfsInfo *);\n  int (*Closedir)(struct VfsInfo *);\n  int (*Bind)(struct VfsInfo *, const struct sockaddr *, socklen_t);\n  int (*Connect)(struct VfsInfo *, const struct sockaddr *, socklen_t);\n  int (*Connectunix)(struct VfsInfo *, struct VfsInfo *,\n                     const struct sockaddr_un *, socklen_t);\n  int (*Accept)(struct VfsInfo *, struct sockaddr *, socklen_t *,\n                struct VfsInfo **);\n  int (*Listen)(struct VfsInfo *, int);\n  int (*Shutdown)(struct VfsInfo *, int);\n  ssize_t (*Recvmsg)(struct VfsInfo *, struct msghdr *, int);\n  ssize_t (*Sendmsg)(struct VfsInfo *, const struct msghdr *, int);\n  ssize_t (*Recvmsgunix)(struct VfsInfo *, struct VfsInfo *, struct msghdr *,\n                         int);\n  ssize_t (*Sendmsgunix)(struct VfsInfo *, struct VfsInfo *,\n                         const struct msghdr *, int);\n  int (*Getsockopt)(struct VfsInfo *, int, int, void *, socklen_t *);\n  int (*Setsockopt)(struct VfsInfo *, int, int, const void *, socklen_t);\n  int (*Getsockname)(struct VfsInfo *, struct sockaddr *, socklen_t *);\n  int (*Getpeername)(struct VfsInfo *, struct sockaddr *, socklen_t *);\n  int (*Rename)(struct VfsInfo *, const char *, struct VfsInfo *, const char *);\n  int (*Utime)(struct VfsInfo *, const char *, const struct timespec[2], int);\n  int (*Futime)(struct VfsInfo *, const struct timespec[2]);\n  int (*Symlink)(const char *, struct VfsInfo *, const char *);\n  void *(*Mmap)(struct VfsInfo *, void *, size_t, int, int, off_t);\n  int (*Munmap)(struct VfsInfo *, void *, size_t);\n  int (*Mprotect)(struct VfsInfo *, void *, size_t, int);\n  int (*Msync)(struct VfsInfo *, void *, size_t, int);\n  int (*Pipe)(struct VfsInfo *[2]);\n#ifdef HAVE_PIPE2\n  int (*Pipe2)(struct VfsInfo *[2], int);\n#endif\n  int (*Socket)(int, int, int, struct VfsInfo **);\n  int (*Socketpair)(int, int, int, struct VfsInfo *[2]);\n  int (*Tcgetattr)(struct VfsInfo *, struct termios *);\n  int (*Tcsetattr)(struct VfsInfo *, int, const struct termios *);\n  int (*Tcflush)(struct VfsInfo *, int);\n  int (*Tcdrain)(struct VfsInfo *);\n  int (*Tcsendbreak)(struct VfsInfo *, int);\n  int (*Tcflow)(struct VfsInfo *, int);\n  pid_t (*Tcgetsid)(struct VfsInfo *);\n  pid_t (*Tcgetpgrp)(struct VfsInfo *);\n  int (*Tcsetpgrp)(struct VfsInfo *, pid_t);\n#ifdef HAVE_SOCKATMARK\n  int (*Sockatmark)(struct VfsInfo *);\n#endif\n  int (*Fexecve)(struct VfsInfo *, char *const *, char *const *);\n};\n\n#define VFS_SYSTEM_NAME_MAX 8\n\nstruct VfsSystem {\n  struct Dll elem;\n  struct VfsOps ops;\n  char name[VFS_SYSTEM_NAME_MAX];\n  bool nodev;\n};\n\nstruct VfsMount {\n  u64 baseino;\n  struct VfsInfo *root;\n  struct Dll elem;\n};\n\nstruct VfsDevice {\n  pthread_mutex_t_ lock;\n  struct Dll *mounts;\n  struct VfsOps *ops;\n  struct VfsInfo *root;\n  void *data;\n  struct Dll elem;\n  u64 flags;\n  u32 dev;\n  _Atomic(u32) refcount;\n};\n\nstruct VfsInfo {\n  struct VfsDevice *device;\n  struct VfsInfo *parent;\n  const char *name;\n  size_t namelen;\n  void *data;\n  u64 ino;\n  u32 dev;\n  u32 mode;\n  _Atomic(u32) refcount;\n};\n\nextern struct Vfs g_vfs;\nextern struct VfsInfo *g_cwdinfo;\nextern struct VfsInfo *g_rootinfo;\nextern struct VfsInfo *g_actualrootinfo;\n\n#define VFS_SYSTEM_CONTAINER(e) DLL_CONTAINER(struct VfsSystem, elem, (e))\n#define VFS_MOUNT_CONTAINER(e)  DLL_CONTAINER(struct VfsMount, elem, (e))\n#define VFS_DEVICE_CONTAINER(e) DLL_CONTAINER(struct VfsDevice, elem, (e))\n\n#if !defined(DISABLE_VFS)\nint VfsChdir(const char *);\nchar *VfsGetcwd(char *, size_t);\nint VfsChroot(const char *);\nint VfsMount(const char *, const char *, const char *, u64, const void *);\nint VfsUnlink(int, const char *, int);\nint VfsMkdir(int, const char *, mode_t);\nint VfsMkfifo(int, const char *, mode_t);\nint VfsOpen(int, const char *, int, int);\nint VfsChmod(int, const char *, mode_t, int);\nint VfsAccess(int, const char *, mode_t, int);\nint VfsSymlink(const char *, int, const char *);\nint VfsStat(int, const char *, struct stat *, int);\nint VfsChown(int, const char *, uid_t, gid_t, int);\nint VfsRename(int, const char *, int, const char *);\nssize_t VfsReadlink(int, const char *, char *, size_t);\nint VfsLink(int, const char *, int, const char *, int);\nint VfsUtime(int, const char *, const struct timespec[2], int);\nint VfsFutime(int, const struct timespec[2]);\nint VfsFchown(int, uid_t, gid_t);\nint VfsFstat(int, struct stat *);\nint VfsFtruncate(int, off_t);\nint VfsClose(int);\nssize_t VfsRead(int, void *, size_t);\nssize_t VfsWrite(int, const void *, size_t);\nssize_t VfsPread(int, void *, size_t, off_t);\nssize_t VfsPwrite(int, const void *, size_t, off_t);\nssize_t VfsReadv(int, const struct iovec *, int);\nssize_t VfsWritev(int, const struct iovec *, int);\nssize_t VfsPreadv(int, const struct iovec *, int, off_t);\nssize_t VfsPwritev(int, const struct iovec *, int, off_t);\noff_t VfsSeek(int, off_t, int);\nint VfsFchmod(int, mode_t);\nint VfsFchdir(int);\nint VfsFsync(int);\nint VfsFdatasync(int);\nint VfsFlock(int, int);\nint VfsFcntl(int, int, ...);\nint VfsIoctl(int, unsigned long, void *);\nint VfsDup(int);\nint VfsDup2(int, int);\n#ifdef HAVE_DUP3\nint VfsDup3(int, int, int);\n#endif\nint VfsPoll(struct pollfd *, nfds_t, int);\nint VfsSelect(int, fd_set *, fd_set *, fd_set *, struct timespec *, sigset_t *);\nDIR *VfsOpendir(int);\n#ifdef HAVE_SEEKDIR\nvoid VfsSeekdir(DIR *, long);\nlong VfsTelldir(DIR *);\n#endif\nstruct dirent *VfsReaddir(DIR *);\nvoid VfsRewinddir(DIR *);\nint VfsClosedir(DIR *);\nint VfsBind(int, const struct sockaddr *, socklen_t);\nint VfsConnect(int, const struct sockaddr *, socklen_t);\nint VfsAccept(int, struct sockaddr *, socklen_t *);\nint VfsListen(int, int);\nint VfsShutdown(int, int);\nssize_t VfsRecvmsg(int, struct msghdr *, int);\nssize_t VfsSendmsg(int, const struct msghdr *, int);\nint VfsGetsockopt(int, int, int, void *, socklen_t *);\nint VfsSetsockopt(int, int, int, const void *, socklen_t);\nint VfsGetsockname(int, struct sockaddr *, socklen_t *);\nint VfsGetpeername(int, struct sockaddr *, socklen_t *);\nint VfsPipe(int[2]);\n#ifdef HAVE_PIPE2\nint VfsPipe2(int[2], int);\n#endif\nint VfsSocket(int, int, int);\nint VfsSocketpair(int, int, int, int[2]);\n\nint VfsTcgetattr(int, struct termios *);\nint VfsTcsetattr(int, int, const struct termios *);\npid_t VfsTcgetpgrp(int);\nint VfsTcsetpgrp(int, pid_t);\nint VfsTcdrain(int);\nint VfsTcsendbreak(int, int);\nint VfsTcflow(int, int);\npid_t VfsTcgetsid(int);\nint VfsTcflush(int, int);\nint VfsSockatmark(int);\nint VfsExecve(const char *, char *const *, char *const *);\n\nvoid *VfsMmap(void *, size_t, int, int, int, off_t);\nint VfsMunmap(void *, size_t);\nint VfsMprotect(void *, size_t, int);\nint VfsMsync(void *, size_t, int);\n\nint VfsInit(const char *);\nint VfsRegister(struct VfsSystem *);\nint VfsTraverse(const char *, struct VfsInfo **, bool);\nint VfsCreateInfo(struct VfsInfo **);\nint VfsAcquireInfo(struct VfsInfo *, struct VfsInfo **);\nint VfsCreateDevice(struct VfsDevice **output);\nint VfsAcquireDevice(struct VfsDevice *, struct VfsDevice **);\nint VfsFreeDevice(struct VfsDevice *);\nint VfsFreeInfo(struct VfsInfo *);\nint VfsAddFd(struct VfsInfo *);\nint VfsFreeFd(int, struct VfsInfo **);\nint VfsSetFd(int, struct VfsInfo *);\nssize_t VfsPathBuildFull(struct VfsInfo *, struct VfsInfo *, char **);\nssize_t VfsPathBuild(struct VfsInfo *, struct VfsInfo *, bool,\n                     char[VFS_PATH_MAX]);\n#elif !defined(DISABLE_OVERLAYS)\n#define VfsChown       OverlaysChown\n#define VfsAccess      OverlaysAccess\n#define VfsStat        OverlaysStat\n#define VfsChdir       OverlaysChdir\n#define VfsGetcwd      OverlaysGetcwd\n#define VfsMkdir       OverlaysMkdir\n#define VfsChmod       OverlaysChmod\n#define VfsReadlink    OverlaysReadlink\n#define VfsOpen        OverlaysOpen\n#define VfsSymlink     OverlaysSymlink\n#define VfsMkfifo      OverlaysMkfifo\n#define VfsUnlink      OverlaysUnlink\n#define VfsRename      OverlaysRename\n#define VfsLink        OverlaysLink\n#define VfsUtime       OverlaysUtime\n#define VfsFchown      fchown\n#define VfsFchdir      fchdir\n#define VfsFchmod      fchmod\n#define VfsFutime      futimens\n#define VfsFstat       fstat\n#define VfsFtruncate   ftruncate\n#define VfsClose       close\n#define VfsRead        read\n#define VfsWrite       write\n#define VfsPread       pread\n#define VfsPwrite      pwrite\n#define VfsReadv       readv\n#define VfsWritev      writev\n#define VfsPreadv      preadv\n#define VfsPwritev     pwritev\n#define VfsSeek        lseek\n#define VfsFsync       fsync\n#define VfsFdatasync   fdatasync\n#define VfsFlock       flock\n#define VfsFcntl       fcntl\n#define VfsDup         dup\n#define VfsDup2        dup2\n#define VfsDup3        dup3\n#define VfsPoll        poll\n#define VfsSelect      pselect\n#define VfsOpendir     fdopendir\n#define VfsSeekdir     seekdir\n#define VfsTelldir     telldir\n#define VfsReaddir     readdir\n#define VfsRewinddir   rewinddir\n#define VfsClosedir    closedir\n#define VfsPipe        pipe\n#define VfsPipe2       pipe2\n#define VfsSocket      socket\n#define VfsSocketpair  socketpair\n#define VfsBind        bind\n#define VfsConnect     connect\n#define VfsAccept      accept\n#define VfsListen      listen\n#define VfsShutdown    shutdown\n#define VfsRecvmsg     recvmsg\n#define VfsSendmsg     sendmsg\n#define VfsGetsockopt  getsockopt\n#define VfsSetsockopt  setsockopt\n#define VfsGetsockname getsockname\n#define VfsGetpeername getpeername\n#define VfsIoctl       ioctl\n#define VfsTcgetattr   tcgetattr\n#define VfsTcsetattr   tcsetattr\n#define VfsTcgetpgrp   tcgetpgrp\n#define VfsTcsetpgrp   tcsetpgrp\n#define VfsTcgetsid    tcgetsid\n#define VfsTcsendbreak tcsendbreak\n#define VfsTcflow      tcflow\n#define VfsTcflush     tcflush\n#define VfsTcdrain     tcdrain\n#define VfsSockatmark  sockatmark\n#define VfsExecve      execve\n#define VfsMmap        mmap\n#define VfsMunmap      munmap\n#define VfsMprotect    mprotect\n#define VfsMsync       msync\n#else\n#define VfsChown       fchownat\n#define VfsAccess      faccessat\n#define VfsStat        fstatat\n#define VfsChdir       chdir\n#define VfsGetcwd      getcwd\n#define VfsMkdir       mkdirat\n#define VfsChmod       fchmodat\n#define VfsReadlink    readlinkat\n#define VfsOpen        openat\n#define VfsSymlink     symlinkat\n#define VfsMkfifo      mkfifoat\n#define VfsUnlink      unlinkat\n#define VfsRename      renameat\n#define VfsLink        linkat\n#define VfsUtime       utimensat\n#define VfsFchown      fchown\n#define VfsFchdir      fchdir\n#define VfsFchmod      fchmod\n#define VfsFutime      futimens\n#define VfsFstat       fstat\n#define VfsFtruncate   ftruncate\n#define VfsClose       close\n#define VfsRead        read\n#define VfsWrite       write\n#define VfsPread       pread\n#define VfsPwrite      pwrite\n#define VfsReadv       readv\n#define VfsWritev      writev\n#define VfsPreadv      preadv\n#define VfsPwritev     pwritev\n#define VfsSeek        lseek\n#define VfsFsync       fsync\n#define VfsFdatasync   fdatasync\n#define VfsFlock       flock\n#define VfsFcntl       fcntl\n#define VfsDup         dup\n#define VfsDup2        dup2\n#define VfsDup3        dup3\n#define VfsPoll        poll\n#define VfsSelect      pselect\n#define VfsOpendir     fdopendir\n#define VfsSeekdir     seekdir\n#define VfsTelldir     telldir\n#define VfsReaddir     readdir\n#define VfsRewinddir   rewinddir\n#define VfsClosedir    closedir\n#define VfsPipe        pipe\n#define VfsPipe2       pipe2\n#define VfsSocket      socket\n#define VfsSocketpair  socketpair\n#define VfsBind        bind\n#define VfsConnect     connect\n#define VfsAccept      accept\n#define VfsListen      listen\n#define VfsShutdown    shutdown\n#define VfsRecvmsg     recvmsg\n#define VfsSendmsg     sendmsg\n#define VfsGetsockopt  getsockopt\n#define VfsSetsockopt  setsockopt\n#define VfsGetsockname getsockname\n#define VfsGetpeername getpeername\n#define VfsIoctl       ioctl\n#define VfsTcgetattr   tcgetattr\n#define VfsTcsetattr   tcsetattr\n#define VfsTcgetpgrp   tcgetpgrp\n#define VfsTcsetpgrp   tcsetpgrp\n#define VfsTcgetsid    tcgetsid\n#define VfsTcsendbreak tcsendbreak\n#define VfsTcflow      tcflow\n#define VfsTcflush     tcflush\n#define VfsTcdrain     tcdrain\n#define VfsSockatmark  sockatmark\n#define VfsExecve      execve\n#define VfsMmap        mmap\n#define VfsMunmap      munmap\n#define VfsMprotect    mprotect\n#define VfsMsync       msync\n#endif\n\n#endif /* BLINK_VFS_H_ */\n"
  },
  {
    "path": "blink/vigna.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/util.h\"\n\nu64 Vigna(u64 s[1]) {\n  u64 z = (s[0] += 0x9e3779b97f4a7c15);\n  z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;\n  z = (z ^ (z >> 27)) * 0x94d049bb133111eb;\n  return z ^ (z >> 31);\n}\n"
  },
  {
    "path": "blink/watch.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/watch.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"blink/debug.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n#include \"blink/x86.h\"\n\nvoid PopWatchpoint(struct Watchpoints *wps) {\n  if (wps->i) {\n    --wps->i;\n  }\n}\n\nssize_t PushWatchpoint(struct Watchpoints *wps, struct Watchpoint *b) {\n  int i;\n  for (i = 0; i < wps->i; ++i) {\n    if (wps->p[i].disable) {\n      memcpy(&wps->p[i], b, sizeof(*b));\n      return i;\n    }\n  }\n  if (wps->i++ == wps->n) {\n    wps->n = wps->i + (wps->i >> 1);\n    wps->p = (struct Watchpoint *)realloc(wps->p, wps->n * sizeof(*wps->p));\n  }\n  wps->p[wps->i - 1] = *b;\n  return wps->i - 1;\n}\n\nssize_t IsAtWatchpoint(struct Watchpoints *wps, struct Machine *m) {\n  u8 *r;\n  int i;\n  u64 w;\n  i64 oldip;\n  bool hasop;\n  struct XedDecodedInst x;\n  if (!wps->i) return -1;\n  hasop = !GetInstruction(m, GetPc(m), &x) && x.op.has_modrm;\n  for (i = wps->i; i--;) {\n    if (wps->p[i].disable) continue;\n    oldip = m->ip;\n    m->ip += Oplength(x.op.rde);\n    if ((hasop && !IsModrmRegister(x.op.rde) &&\n         ComputeAddress(m, x.op.rde, x.op.disp, x.op.uimm0) ==\n             wps->p[i].addr) ||\n        Get64(m->ax) == wps->p[i].addr ||   //\n        Get64(m->cx) == wps->p[i].addr ||   //\n        Get64(m->dx) == wps->p[i].addr ||   //\n        Get64(m->bx) == wps->p[i].addr ||   //\n        Get64(m->sp) == wps->p[i].addr ||   //\n        Get64(m->bp) == wps->p[i].addr ||   //\n        Get64(m->si) == wps->p[i].addr ||   //\n        Get64(m->di) == wps->p[i].addr ||   //\n        Get64(m->r8) == wps->p[i].addr ||   //\n        Get64(m->r9) == wps->p[i].addr ||   //\n        Get64(m->r10) == wps->p[i].addr ||  //\n        Get64(m->r11) == wps->p[i].addr ||  //\n        Get64(m->r12) == wps->p[i].addr ||  //\n        Get64(m->r13) == wps->p[i].addr ||  //\n        Get64(m->r14) == wps->p[i].addr ||  //\n        Get64(m->r15) == wps->p[i].addr) {  //\n      return i;\n    }\n    m->ip = oldip;\n    // TODO(jart): Handle case of overlapping page boundary.\n    // TODO(jart): Possibly track munmap() type cases.\n    if ((r = SpyAddress(m, wps->p[i].addr))) {\n      w = Read64(r);\n      if (!wps->p[i].initialized) {\n        wps->p[i].oldvalue = w;\n        wps->p[i].initialized = true;\n      } else if (w != wps->p[i].oldvalue) {\n        wps->p[i].oldvalue = w;\n        return i;\n      }\n    }\n  }\n  return -1;\n}\n"
  },
  {
    "path": "blink/watch.h",
    "content": "#ifndef BLINK_WATCH_H_\n#define BLINK_WATCH_H_\n#include <sys/types.h>\n\n#include \"blink/machine.h\"\n#include \"blink/types.h\"\n\nstruct Watchpoint {\n  i64 addr;\n  const char *symbol;\n  u64 oldvalue;\n  bool initialized;\n  bool disable;\n};\n\nstruct Watchpoints {\n  int i, n;\n  struct Watchpoint *p;\n};\n\nssize_t IsAtWatchpoint(struct Watchpoints *, struct Machine *);\nssize_t PushWatchpoint(struct Watchpoints *, struct Watchpoint *);\nvoid PopWatchpoint(struct Watchpoints *);\n\n#endif /* BLINK_WATCH_H_ */\n"
  },
  {
    "path": "blink/wcwidth.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <wctype.h>\n\n#include \"blink/util.h\"\n\nint wcwidth_(wchar_t c) {\n  if (!c) return 0;\n  if (c < 0 || iswcntrl(c)) return -1;\n  return 1 +\n         (c >= 0x1100 &&\n          (c <= 0x115f || c == 0x2329 || c == 0x232a ||\n           (c >= 0x2e80 && c <= 0xa4cf && c != 0x303f) ||\n           (c >= 0xac00 && c <= 0xd7a3) || (c >= 0xf900 && c <= 0xfaff) ||\n           (c >= 0xfe10 && c <= 0xfe19) || (c >= 0xfe30 && c <= 0xfe6f) ||\n           (c >= 0xff00 && c <= 0xff60) || (c >= 0xffe0 && c <= 0xffe6) ||\n           (c >= 0x20000 && c <= 0x2fffd) || (c >= 0x30000 && c <= 0x3fffd)));\n}\n"
  },
  {
    "path": "blink/web.h",
    "content": "#ifndef BLINK_WEB_H_\n#define BLINK_WEB_H_\n#include \"blink/builtin.h\"\n#ifdef __EMSCRIPTEN__\n#include <emscripten.h>\n\nstatic void SetupWeb(void) {\n  // EM_ASM({FS.mkdir(\"/cwd\"); FS.mount(NODEFS, {root : \".\"}, \"/cwd\");});\n}\n\n#else\nstatic void SetupWeb(void) {\n}\n#endif /* __EMSCRIPTEN__ */\n#endif /* BLINK_WEB_H_ */\n"
  },
  {
    "path": "blink/x86.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2018 Intel Corporation                                             │\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Licensed under the Apache License, Version 2.0 (the \"License\");              │\n│ you may not use this file except in compliance with the License.             │\n│ You may obtain a copy of the License at                                      │\n│                                                                              │\n│     http://www.apache.org/licenses/LICENSE-2.0                               │\n│                                                                              │\n│ Unless required by applicable law or agreed to in writing, software          │\n│ distributed under the License is distributed on an \"AS IS\" BASIS,            │\n│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.     │\n│ See the License for the specific language governing permissions and          │\n│ limitations under the License.                                               │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/x86.h\"\n\n#include <stdbool.h>\n#include <string.h>\n\n#include \"blink/assert.h\"\n#include \"blink/bitscan.h\"\n#include \"blink/builtin.h\"\n#include \"blink/endian.h\"\n#include \"blink/macros.h\"\n#include \"blink/modrm.h\"\n#include \"blink/rde.h\"\n#include \"blink/types.h\"\n\nconst char kXedCopyright[] = \"\\\nXed (Apache 2.0)\\n\\\nCopyright 2018 Intel Corporation\\n\\\nCopyright 2022 Justine Alexandra Roberts Tunney\\n\\\nModifications: Removed as much code and functionality as possible\";\n\n#define XED_ILD_HASMODRM_IGNORE_MOD 2\n\nstatic const u32 xed_prefix_table_bit[8] = {\n    0x00000000, 0x40404040, 0x0000ffff, 0x000000f0,\n    0x00000000, 0x00000000, 0x00000000, 0x000d0000,\n};\n\nstatic const struct XedDenseMagnums {\n  u8 eamode[2][3];\n  u8 has_sib_table[3][4][8];\n  u8 has_disp_regular[3][4][8];\n  u8 imm_bits_2d[2][256];\n  u8 has_modrm_2d[XED_ILD_MAP2][256];\n  u8 disp_bits_2d[XED_ILD_MAP2][256];\n  u8 BRDISPz_BRDISP_WIDTH[4];\n  u8 MEMDISPv_DISP_WIDTH[4];\n  u8 SIMMz_IMM_WIDTH[4];\n  u8 UIMMv_IMM_WIDTH[4];\n  u8 ASZ_NONTERM_EASZ[2][3];\n  u8 OSZ_NONTERM_DF64_EOSZ[2][2][3];\n  u8 OSZ_NONTERM_EOSZ[2][2][3];\n} kXed = {\n    .eamode = {{XED_MODE_REAL, XED_MODE_LEGACY, XED_MODE_LONG},\n               {XED_MODE_LEGACY, XED_MODE_REAL, XED_MODE_LEGACY}},\n    .has_sib_table = {{{0, 0, 0, 0, 0, 0, 0, 0},\n                       {0, 0, 0, 0, 0, 0, 0, 0},\n                       {0, 0, 0, 0, 0, 0, 0, 0},\n                       {0, 0, 0, 0, 0, 0, 0, 0}},\n                      {{0, 0, 0, 0, 1, 0, 0, 0},\n                       {0, 0, 0, 0, 1, 0, 0, 0},\n                       {0, 0, 0, 0, 1, 0, 0, 0},\n                       {0, 0, 0, 0, 0, 0, 0, 0}},\n                      {{0, 0, 0, 0, 1, 0, 0, 0},\n                       {0, 0, 0, 0, 1, 0, 0, 0},\n                       {0, 0, 0, 0, 1, 0, 0, 0},\n                       {0, 0, 0, 0, 0, 0, 0, 0}}},\n    .has_disp_regular = {{{0, 0, 0, 0, 0, 0, 2, 0},\n                          {1, 1, 1, 1, 1, 1, 1, 1},\n                          {2, 2, 2, 2, 2, 2, 2, 2},\n                          {0, 0, 0, 0, 0, 0, 0, 0}},\n                         {{0, 0, 0, 0, 0, 4, 0, 0},\n                          {1, 1, 1, 1, 1, 1, 1, 1},\n                          {4, 4, 4, 4, 4, 4, 4, 4},\n                          {0, 0, 0, 0, 0, 0, 0, 0}},\n                         {{0, 0, 0, 0, 0, 4, 0, 0},\n                          {1, 1, 1, 1, 1, 1, 1, 1},\n                          {4, 4, 4, 4, 4, 4, 4, 4},\n                          {0, 0, 0, 0, 0, 0, 0, 0}}},\n    .imm_bits_2d =\n        {{1,  1, 1, 1, 5,  7,  1,  1,  1,  1,  1,  1,  9, 7, 1, 0, 1, 1, 1, 1,\n          5,  7, 1, 1, 1,  1,  1,  1,  5,  7,  1,  1,  1, 1, 1, 1, 5, 7, 0, 1,\n          1,  1, 1, 1, 5,  7,  0,  1,  1,  1,  1,  1,  9, 7, 0, 1, 1, 1, 1, 1,\n          5,  7, 0, 1, 1,  1,  1,  1,  1,  1,  1,  1,  1, 1, 1, 1, 1, 1, 1, 1,\n          1,  1, 1, 1, 1,  1,  1,  1,  1,  1,  1,  1,  1, 1, 1, 1, 1, 1, 1, 1,\n          0,  0, 0, 0, 6,  7,  5,  5,  1,  1,  1,  1,  1, 1, 1, 1, 1, 1, 1, 1,\n          1,  1, 1, 1, 1,  1,  1,  1,  5,  7,  5,  5,  1, 1, 1, 1, 1, 1, 1, 1,\n          1,  1, 1, 1, 1,  1,  1,  1,  1,  1,  1,  1,  1, 1, 8, 1, 1, 1, 1, 1,\n          1,  1, 1, 1, 1,  1,  1,  1,  5,  7,  1,  1,  1, 1, 1, 1, 9, 9, 9, 9,\n          9,  9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 8, 1, 1, 1, 9, 2,\n          11, 1, 8, 1, 1,  9,  1,  1,  1,  1,  1,  1,  9, 9, 1, 1, 1, 1, 1, 1,\n          1,  1, 1, 1, 1,  1,  1,  1,  9,  9,  9,  9,  1, 1, 8, 1, 1, 1, 1, 1,\n          0,  1, 0, 0, 1,  1,  3,  4,  1,  1,  1,  1,  1, 1, 1, 1},\n         {1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,  1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,  1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 9, 9, 9, 9, 1, 1, 1, 1, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9,  1, 0, 0, 1, 1, 1, 1, 9, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9,  1, 1, 1, 1, 1, 1, 1, 9, 1, 9, 9,\n          9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1}},\n    .has_modrm_2d =\n        {{1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 3, 1, 1, 1, 1, 0, 0,\n          0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 3, 0, 1, 1, 1, 1,\n          0, 0, 3, 0, 1, 1, 1, 1, 0, 0, 3, 0, 1, 1, 1, 1, 0, 0, 3, 0, 0, 0,\n          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 3, 3, 3, 3, 0, 1, 0, 1, 0, 0,\n          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,\n          1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,\n          1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,\n          3, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1},\n         {1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 3, 0, 3, 1, 0, 3, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1,\n          1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,\n          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 3, 3, 0, 0, 0, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}},\n    .disp_bits_2d =\n        {{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4,\n          4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4,\n          4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n          2, 4, 4, 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n          4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 1, 1, 1, 1, 4, 4, 4, 4, 3, 3, 2, 1, 4, 4, 4, 4, 0, 4,\n          0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},\n         {4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 0, 4, 0, 4, 4, 0, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3,\n          3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}},\n    .BRDISPz_BRDISP_WIDTH = {0, 16, 32, 32},\n    .MEMDISPv_DISP_WIDTH = {0, 16, 32, 64},\n    .SIMMz_IMM_WIDTH = {0x00, 0x10, 0x20, 0x20},\n    .UIMMv_IMM_WIDTH = {0x00, 0x10, 0x20, 0x40},\n    .ASZ_NONTERM_EASZ = {{1, 2, 3}, {2, 1, 2}},\n    .OSZ_NONTERM_DF64_EOSZ = {{{1, 2, 3}, {2, 1, 1}}, {{1, 2, 3}, {2, 1, 3}}},\n    .OSZ_NONTERM_EOSZ = {{{1, 2, 2}, {2, 1, 1}}, {{1, 2, 3}, {2, 1, 3}}},\n};\n\nstatic size_t xed_bits2bytes(unsigned bits) {\n  return bits >> 3;\n}\n\nstatic size_t xed_bytes2bits(unsigned bytes) {\n  return bytes << 3;\n}\n\nstatic u8 xed_get_prefix_table_bit(u8 a) {\n  return (xed_prefix_table_bit[a >> 5] >> (a & 0x1F)) & 1;\n}\n\nstatic void xed_set_mopcode(struct XedDecodedInst *x, u64 mopcode) {\n  x->op.rde |= mopcode << 40;\n}\n\nstatic int xed_too_short(struct XedDecodedInst *x) {\n  if (x->op.max_bytes >= 15) {\n    return XED_ERROR_INSTR_TOO_LONG;\n  } else {\n    return XED_ERROR_BUFFER_TOO_SHORT;\n  }\n}\n\nstatic void xed_set_simmz_imm_width_eosz(struct XedDecodedInst *x,\n                                         const u8 eosz[2][2][3], int *imm_width,\n                                         u8 *imm_signed) {\n  *imm_width = kXed.SIMMz_IMM_WIDTH[eosz[Rexw(x->op.rde)][Osz(x->op.rde)]\n                                        [Mode(x->op.rde)]];\n  *imm_signed = 1;\n}\n\nstatic int xed_set_imm_bytes(struct XedDecodedInst *x, int *imm_width,\n                             u8 *imm_signed) {\n  if (!*imm_width && Opmap(x->op.rde) < XED_ILD_MAP2) {\n    switch (kXed.imm_bits_2d[Opmap(x->op.rde)][Opcode(x->op.rde)]) {\n      case 0:\n        return XED_ERROR_GENERAL_ERROR;\n      case 1:\n        *imm_width = 0;\n        return XED_ERROR_NONE;\n      case 2:\n        switch (ModrmReg(x->op.rde)) {\n          case 0:\n            xed_set_simmz_imm_width_eosz(x, kXed.OSZ_NONTERM_EOSZ, imm_width,\n                                         imm_signed);\n            return XED_ERROR_NONE;\n          case 7:\n            *imm_width = 0;\n            return XED_ERROR_NONE;\n          default:\n            return XED_ERROR_NONE;\n        }\n      case 3:\n        if (ModrmReg(x->op.rde) <= 1) {\n          *imm_width = 8;\n          *imm_signed = 1;\n        } else if (2 <= ModrmReg(x->op.rde) && ModrmReg(x->op.rde) <= 7) {\n          *imm_width = 0;\n        }\n        return XED_ERROR_NONE;\n      case 4:\n        if (ModrmReg(x->op.rde) <= 1) {\n          xed_set_simmz_imm_width_eosz(x, kXed.OSZ_NONTERM_EOSZ, imm_width,\n                                       imm_signed);\n        } else if (2 <= ModrmReg(x->op.rde) && ModrmReg(x->op.rde) <= 7) {\n          *imm_width = 0;\n        }\n        return XED_ERROR_NONE;\n      case 5:\n        *imm_width = 8;\n        *imm_signed = 1;\n        return XED_ERROR_NONE;\n      case 6:\n        xed_set_simmz_imm_width_eosz(x, kXed.OSZ_NONTERM_DF64_EOSZ, imm_width,\n                                     imm_signed);\n        return XED_ERROR_NONE;\n      case 7:\n        xed_set_simmz_imm_width_eosz(x, kXed.OSZ_NONTERM_EOSZ, imm_width,\n                                     imm_signed);\n        return XED_ERROR_NONE;\n      case 8:\n        *imm_width = 16;\n        return XED_ERROR_NONE;\n      case 9:\n        *imm_width = 8;\n        return XED_ERROR_NONE;\n      case 10:\n        *imm_width = kXed.UIMMv_IMM_WIDTH[kXed.OSZ_NONTERM_EOSZ[Rexw(\n            x->op.rde)][Osz(x->op.rde)][Mode(x->op.rde)]];\n        return XED_ERROR_NONE;\n      case 11:\n        // actually 2 bytes for uimm0 & 1 byte for uimm1\n        *imm_width = xed_bytes2bits(3);\n        return XED_ERROR_NONE;\n      case 12:\n        if (Osz(x->op.rde) || Rep(x->op.rde) == 2) {\n          *imm_width = xed_bytes2bits(1);\n        }\n        return XED_ERROR_NONE;\n      default:\n        __builtin_unreachable();\n    }\n  } else {\n    return XED_ERROR_NONE;\n  }\n}\n\nstatic bool xed_is_bound_instruction(struct XedDecodedInst *x) {\n  return Mode(x->op.rde) != XED_MODE_LONG &&  //\n         x->length + 1 < x->op.max_bytes &&   //\n         (x->bytes[x->length + 1] & 0xC0) != 0xC0;\n}\n\nstatic int xed_prefix_scanner(struct XedDecodedInst *x) {\n  u32 rde;\n  u8 b, rep, max_bytes, length, islong;\n  u8 asz, osz, rex, rexw, rexr, rexx, rexb;\n  rex = 0;\n  rep = 0;\n  length = 0;\n  rde = x->op.rde;\n  max_bytes = x->op.max_bytes;\n  islong = Mode(rde) == XED_MODE_LONG;\n  while (length < max_bytes) {\n    b = x->bytes[length];\n    if (xed_get_prefix_table_bit(b) == 0) goto out;\n    switch (b) {\n      case 0x66:  // osz\n        rex = 0;\n        osz = 1;\n        rde |= osz << 5;\n        break;\n      case 0x67:  // asz\n        rex = 0;\n        asz = 1;\n        rde |= asz << 21;\n        break;\n      case 0x2E:  // cs\n        if (1 || !islong) {\n          rde &= 037770777777;\n          rde |= 000002000000;\n        }\n        rex = 0;\n        break;\n      case 0x3E:  // ds\n        if (1 || !islong) {\n          rde &= 037770777777;\n          rde |= 000004000000;\n        }\n        rex = 0;\n        break;\n      case 0x26:  // es\n        if (1 || !islong) {\n          rde &= 037770777777;\n          rde |= 000001000000;\n        }\n        rex = 0;\n        break;\n      case 0x36:  // ss\n        if (1 || !islong) {\n          rde &= 037770777777;\n          rde |= 000003000000;\n        }\n        rex = 0;\n        break;\n      case 0x64:  // fs\n        rde &= 037770777777;\n        rde |= 000005000000;\n        rex = 0;\n        break;\n      case 0x65:  // gs\n        rde &= 037770777777;\n        rde |= 000006000000;\n        rex = 0;\n        break;\n      case 0xF0:  // lock\n        rde |= 020000000000;\n        rex = 0;\n        break;\n      case 0xF2:  // rep\n      case 0xF3:\n        rep = b & 3;\n        rex = 0;\n        break;\n      default:\n        if (islong && (b & 0xf0) == 0x40) {\n          rex = b;\n          break;\n        } else {\n          goto out;\n        }\n    }\n    length++;\n  }\nout:\n  x->length = length;\n  if (rex) {\n    rexw = (rex >> 3) & 1;\n    rexr = (rex >> 2) & 1;\n    rexx = (rex >> 1) & 1;\n    rexb = rex & 1;\n    rex = 1;\n    rde |= rexx << 17 | rex << 16 | rexb << 15 | rex << 11 | rexb << 10 |\n           rexw << 6 | rex << 4 | rexr << 3;\n  }\n  x->op.rde = (u64)rep << 51 | rde;\n  if (length < max_bytes) {\n    return XED_ERROR_NONE;\n  } else {\n    return xed_too_short(x);\n  }\n}\n\nstatic void xed_set_vex_prefix(struct XedDecodedInst *x, unsigned prefix) {\n  switch (prefix) {\n    case 0:\n      break;\n    case 1:  // osz\n      x->op.rde &= ~(1 << 5);\n      x->op.rde |= 1 << 5;\n      break;\n    case 2:  // rep3\n    case 3:  // rep2\n      x->op.rde &= ~((u64)3 << 51);\n      x->op.rde |= (u64)(prefix ^ 1) << 51;\n      break;\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic int xed_vex_opcode_scanner(struct XedDecodedInst *x, int map) {\n  xed_set_mopcode(x, map << 8 | x->bytes[x->length]);\n  x->op.pos_opcode = x->length++;\n#ifndef TINY\n  if (Mode(x->op.rde) == XED_MODE_LONG && Rex(x->op.rde)) {\n    return XED_ERROR_BAD_REX_PREFIX;\n  }\n  if (Mode(x->op.rde) == XED_MODE_REAL) {\n    return XED_ERROR_INVALID_MODE;\n  }\n#endif\n  return 0;\n}\n\nstatic int xed_vex_c4_scanner(struct XedDecodedInst *x, int *imm_width,\n                              int *vexvalid) {\n  unsigned length, b1, b2;\n  int map, rexr, rexx, rexb, rexw, ymm, vrex, vexdest210;\n  if (xed_is_bound_instruction(x)) return 0;\n  length = x->length;\n  length++;\n  if (length + 2 < x->op.max_bytes) {\n    // map:   5-bit\n    // rex.b: 1-bit (expands r/m or srm register operand)\n    // rex.x: 1-bit (expands sib register operands)\n    // rex.r: 1-bit (expands reg register operand)\n    b1 = x->bytes[length];\n    rexr = !(b1 & 128);\n    rexx = !(b1 & 64);\n    rexb = (Mode(x->op.rde) == XED_MODE_LONG) & !(b1 & 32);\n    // prefix:        2-bit → {none, osz, rep3, rep2}\n    // vector_length: 1-bit → {xmm, ymm} aka VEX.L\n    // vexdest210:    3-bit (second reg operand, inverted)\n    // vrex:          1-bit a.k.a. vexdest3\n    // rex.w:         1-bit (for 64-bit registers) aka VEX.W1\n    b2 = x->bytes[length + 1];\n    rexw = !!(b2 & 128);\n    vrex = !(b2 & 64);\n    vexdest210 = (~b2 >> 3) & 7;\n    ymm = !!(b2 & 4);\n    xed_set_vex_prefix(x, b2 & 3);\n    map = b1 & 31;\n    if ((b1 & 3) == XED_ILD_MAP3) {\n      *imm_width = xed_bytes2bits(1);\n    }\n    x->op.rde |= (u64)vrex << 63 | rexx << 17 | rexb << 15 | rexb << 10 |\n                 rexw << 6 | rexr << 3;\n    x->op.rde |= ymm << 30;\n    x->op.rde |= (u64)vexdest210 << 60;\n    *vexvalid = 1;\n    length += 2;\n    x->length = length;\n    return xed_vex_opcode_scanner(x, map);\n  } else {\n    x->length = length;\n    return xed_too_short(x);\n  }\n}\n\nstatic int xed_vex_c5_scanner(struct XedDecodedInst *x, int *vexvalid) {\n  unsigned length, b;\n  int rexr, ymm, vrex, vexdest210;\n  length = x->length;\n  if (xed_is_bound_instruction(x)) return 0;\n  length++;\n  if (length + 1 < x->op.max_bytes) {\n    // prefix:        2-bit → {none, osz, rep3, rep2}\n    // vector_length: 1-bit → {xmm, ymm}\n    // vexdest210:    3-bit\n    // vrex:          1-bit\n    // rex.r:         1-bit\n    b = x->bytes[length];\n    rexr = !(b & 128);\n    vrex = !!(b & 64);\n    vexdest210 = (~b >> 3) & 7;\n    ymm = (b >> 2) & 1;\n    xed_set_vex_prefix(x, b & 3);\n    x->op.rde |= (u64)vrex << 63 | rexr << 3;\n    x->op.rde |= ymm << 30;\n    x->op.rde |= (u64)vexdest210 << 60;\n    *vexvalid = 1;\n    length++;\n    x->length = length;\n    return xed_vex_opcode_scanner(x, XED_ILD_MAP1);\n  } else {\n    x->length = length;\n    return xed_too_short(x);\n  }\n}\n\nstatic int xed_vex_scanner(struct XedDecodedInst *x, int *imm_width,\n                           int *vexvalid) {\n  if (Mode(x->op.rde) != XED_MODE_LONG) return 0;\n  switch (x->bytes[x->length]) {\n    case 0xC5:\n      return xed_vex_c5_scanner(x, vexvalid);\n    case 0xC4:\n      return xed_vex_c4_scanner(x, imm_width, vexvalid);\n    default:\n      return 0;\n  }\n}\n\nstatic int xed_get_next_as_opcode(struct XedDecodedInst *x, int map) {\n  u8 length;\n  length = x->length;\n  if (length < x->op.max_bytes) {\n    xed_set_mopcode(x, map << 8 | x->bytes[length]);\n    x->length++;\n    return XED_ERROR_NONE;\n  } else {\n    return xed_too_short(x);\n  }\n}\n\nstatic int xed_opcode_scanner(struct XedDecodedInst *x, int *imm_width) {\n  u8 b, length;\n  length = x->length;\n  if ((b = x->bytes[length]) != 0x0F) {\n    xed_set_mopcode(x, XED_ILD_MAP0 << 8 | b);\n    x->op.pos_opcode = length;\n    x->length++;\n    return XED_ERROR_NONE;\n  } else {\n    length++;\n    x->op.pos_opcode = length;\n    if (length < x->op.max_bytes) {\n      switch ((b = x->bytes[length])) {\n        case 0x38:\n          x->length = ++length;\n          return xed_get_next_as_opcode(x, XED_ILD_MAP2);\n        case 0x3A:\n          x->length = ++length;\n          *imm_width = xed_bytes2bits(1);\n          return xed_get_next_as_opcode(x, XED_ILD_MAP3);\n        case 0x3B:\n        case 0x39:\n        case 0x3C:\n        case 0x3D:\n        case 0x3E:\n        case 0x3F:\n        case 0x0F:\n          length++;\n          x->length = length;\n          xed_get_next_as_opcode(x, XED_ILD_BAD_MAP);\n          return XED_ERROR_BAD_MAP;\n        default:\n          xed_set_mopcode(x, XED_ILD_MAP1 << 8 | b);\n          x->length = ++length;\n          return XED_ERROR_NONE;\n      }\n    } else {\n      return xed_too_short(x);\n    }\n  }\n}\n\nstatic u64 xed_read_number(u8 *p, size_t n, unsigned s) {\n  switch (s << 2 | bsr(n)) {\n    case 0:\n      return Read8(p);\n    case 1:\n      return Read16(p);\n    case 2:\n      return Read32(p);\n    case 3:\n      return Read64(p);\n    case 4:\n      return (i8)Read8(p);\n    case 5:\n      return (i16)Read16(p);\n    case 6:\n      return (i32)Read32(p);\n    case 7:\n      return (i64)Read64(p);\n    default:\n      __builtin_unreachable();\n  }\n}\n\nstatic void xed_set_has_modrm(struct XedDecodedInst *x) {\n  if (Opmap(x->op.rde) < ARRAYLEN(kXed.has_modrm_2d)) {\n    x->op.has_modrm = kXed.has_modrm_2d[Opmap(x->op.rde)][Opcode(x->op.rde)];\n  } else {\n    x->op.has_modrm = 1;\n  }\n}\n\nstatic int xed_modrm_scanner(struct XedDecodedInst *x, int *disp_width,\n                             int *has_sib) {\n  u8 b, rm, reg, mod, eamode, length, has_modrm;\n  xed_set_has_modrm(x);\n  has_modrm = x->op.has_modrm;\n  if (has_modrm) {\n    length = x->length;\n    if (length < x->op.max_bytes) {\n      b = x->bytes[length];\n      x->length++;\n      rm = b & 0007;\n      reg = (b & 0070) >> 3;\n      mod = (b & 0300) >> 6;\n      x->op.rde &= ~1;\n      x->op.rde |= mod << 22 | rm << 7 | reg;\n      if (has_modrm != XED_ILD_HASMODRM_IGNORE_MOD) {\n        eamode = kXed.eamode[Asz(x->op.rde)][Mode(x->op.rde)];\n        *disp_width = xed_bytes2bits(kXed.has_disp_regular[eamode][mod][rm]);\n        *has_sib = kXed.has_sib_table[eamode][mod][rm];\n      }\n      return XED_ERROR_NONE;\n    } else {\n      return xed_too_short(x);\n    }\n  } else {\n    return XED_ERROR_NONE;\n  }\n}\n\nstatic int xed_sib_scanner(struct XedDecodedInst *x, int *disp_width) {\n  u8 b, length;\n  length = x->length;\n  if (length < x->op.max_bytes) {\n    b = x->bytes[length];\n    x->op.rde |= (u64)b << 32;  // set sib byte\n    x->length++;\n    if ((b & 7) == 5) {\n      if (!ModrmMod(x->op.rde)) {\n        *disp_width = xed_bytes2bits(4);\n      }\n    }\n    return XED_ERROR_NONE;\n  } else {\n    return xed_too_short(x);\n  }\n}\n\nstatic u8 XED_LF_BRDISPz_BRDISP_WIDTH_OSZ_NONTERM_EOSZ_l2(\n    struct XedDecodedInst *x) {\n  return kXed.BRDISPz_BRDISP_WIDTH[kXed.OSZ_NONTERM_EOSZ[Rexw(x->op.rde)][Osz(\n      x->op.rde)][Mode(x->op.rde)]];\n}\n\nstatic int xed_disp_scanner(struct XedDecodedInst *x, int disp_width) {\n  u8 disp_unsigned = 0;\n  u8 length, disp_bytes;\n  length = x->length;\n  if (Opmap(x->op.rde) < XED_ILD_MAP2) {\n    switch (kXed.disp_bits_2d[Opmap(x->op.rde)][Opcode(x->op.rde)]) {\n      case 0:\n        return XED_ERROR_GENERAL_ERROR;\n      case 1:\n        disp_width = 8;\n        break;\n      case 2:\n        disp_width = XED_LF_BRDISPz_BRDISP_WIDTH_OSZ_NONTERM_EOSZ_l2(x);\n        disp_unsigned = 1;\n        break;\n      case 3:\n        if (Mode(x->op.rde) <= XED_MODE_LEGACY) {\n          disp_width = XED_LF_BRDISPz_BRDISP_WIDTH_OSZ_NONTERM_EOSZ_l2(x);\n        } else if (Mode(x->op.rde) == XED_MODE_LONG) {\n          disp_width = 0x20;\n        }\n        break;\n      case 4:\n        break;\n      case 5:\n        disp_width =\n            kXed.MEMDISPv_DISP_WIDTH[kXed.ASZ_NONTERM_EASZ[Asz(x->op.rde)]\n                                                          [Mode(x->op.rde)]];\n        disp_unsigned = 1;\n        break;\n      case 6:\n        switch (ModrmReg(x->op.rde)) {\n          case 0:\n            break;\n          case 7:\n            disp_width = XED_LF_BRDISPz_BRDISP_WIDTH_OSZ_NONTERM_EOSZ_l2(x);\n            disp_unsigned = 1;\n            break;\n          default:\n            break;\n        }\n        break;\n      default:\n        __builtin_unreachable();\n    }\n  }\n  disp_bytes = xed_bits2bytes(disp_width);\n  if (!disp_bytes) {\n    return XED_ERROR_NONE;\n  } else if (length + disp_bytes <= x->op.max_bytes) {\n    x->op.disp = xed_read_number(x->bytes + length, disp_bytes, !disp_unsigned);\n    x->length = length + disp_bytes;\n    return XED_ERROR_NONE;\n  } else {\n    return xed_too_short(x);\n  }\n}\n\nstatic int xed_imm_scanner(struct XedDecodedInst *x, int imm_width) {\n  u8 *p;\n  int e;\n  u8 imm_signed = 0;\n  u8 i, length, imm_bytes;\n  p = x->bytes;\n  if ((e = xed_set_imm_bytes(x, &imm_width, &imm_signed))) return e;\n  i = length = x->length;\n  imm_bytes = xed_bits2bytes(imm_width);\n  if (!imm_bytes) {\n    return XED_ERROR_NONE;\n  } else if (length + imm_bytes <= x->op.max_bytes) {\n    length += imm_bytes;\n    x->length = length;\n    x->op.uimm0 = xed_read_number(p + i, imm_bytes, imm_signed);\n    return XED_ERROR_NONE;\n  } else {\n    return xed_too_short(x);\n  }\n}\n\nstatic int xed_decode_instruction_length(struct XedDecodedInst *x) {\n  int e;\n  int has_sib = 0;\n  int vexvalid = 0;\n  int imm_width = 0;\n  int disp_width = 0;\n  if ((e = xed_prefix_scanner(x))) return e;\n#ifndef DISABLE_BMI2\n  if ((e = xed_vex_scanner(x, &imm_width, &vexvalid))) return e;\n#endif\n  if (!vexvalid && (e = xed_opcode_scanner(x, &imm_width))) return e;\n  if ((e = xed_modrm_scanner(x, &disp_width, &has_sib))) return e;\n  if (has_sib && (e = xed_sib_scanner(x, &disp_width))) return e;\n  if ((e = xed_disp_scanner(x, disp_width))) return e;\n  return xed_imm_scanner(x, imm_width);\n}\n\n/**\n * Decodes machine instruction.\n *\n * This function also decodes other useful attributes, such as the\n * offsets of displacement, immediates, etc. It works for all ISAs from\n * 1977 to 2020.\n *\n * @note binary footprint increases ~4kb if this is used\n * @see biggest code in gdb/clang/tensorflow binaries\n */\nint DecodeInstruction(struct XedDecodedInst *x, const void *itext, size_t bytes,\n                      u64 mode) {\n  int rc;\n  u64 rde;\n  u8 kLog2[2][2][2] = {{{2, 3}, {1, 3}}};\n  unassert(mode == XED_MODE_LONG ||    //\n           mode == XED_MODE_LEGACY ||  //\n           mode == XED_MODE_REAL);\n  x->op.rde = mode << 26;\n  x->op.disp = 0;\n  x->op.uimm0 = 0;\n  x->op.has_modrm = 0;\n  x->op.pos_opcode = 0;\n  if (bytes >= 15) {\n    x->op.max_bytes = 15;\n    memcpy(x->bytes, itext, 15);\n  } else {\n    x->op.max_bytes = bytes;\n    memcpy(x->bytes, itext, bytes);\n  }\n  rc = xed_decode_instruction_length(x);\n  rde = x->op.rde;\n  rde |= (Opcode(rde) & 7) << 12;  // srm\n  if (Mode(rde) == XED_MODE_REAL) {\n    // in 16-bit mode, flip osz, except for SIMD instructions & cmpxchg8b;\n    // for SIMD instructions, 0x66 always refers to instructions with larger\n    // operands, & lack of 0x66 to instructions with smaller operands\n    u16 mop = Mopcode(rde);\n    if ((mop >= 0x150 && mop <= 0x176) || (mop >= 0x17C && mop <= 0x17F) ||\n        mop == 0x1C2 || (mop >= 0x1C4 && mop <= 0x1C7) ||\n        (mop >= 0x1D0 && mop <= 0x1FE)) {\n      (void)rde;\n    } else {\n      rde ^= 1 << 5;\n    }\n  }\n  rde |= (u32)kLog2[IsByteOp(rde)][Osz(rde)][Rexw(rde)] << 28;\n  rde |= (u64)kLog2[0][Osz(rde)][Rexw(rde)] << 57;  // wordlog2\n  rde |= (u32)kXed.eamode[Asz(rde)][Mode(rde)] << 24;\n  rde |= (u64)x->length << 53;\n  x->op.rde = rde;\n  return rc;\n}\n"
  },
  {
    "path": "blink/x86.h",
    "content": "#ifndef BLINK_X86_H_\n#define BLINK_X86_H_\n#include <stddef.h>\n#include <stdint.h>\n/*           ▓▓▓▓▓▓▓▓▓▓▓▓▓                      ▄▄▄▄\n             ▓▓▓▓▓▓▓▓▓▓▓▓▓     ▄▓▓▓▓▓▓▄      ▄▓▓▓▓▓▓▓▓            ▄▓▓▓▀\n             ▓▓▓▓    ▓▓▓▓▓    ▓     ▓▓▓▓    ▓▓       ▓▓▓      ▄▓▓▓▓\n▬▬▬▬▬▬▬▬▬▬▬▬▬▓▓▓▓▓▓▓▓▓▓▓▓▓▬▬▬▬▬▬▬▬▬▬▬▓▓▓▬▬▬▓▓▓▬▬▬▬▬▬▬▬▓▓▬▬▬▬▓▓▓▓▓▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n        │    ▓▓▓▓    ▓▓▓▓▓          ▓▓▓     ▓▓▓▄     ▓▓▓   ▓▓▓▓             │\n▬▬▬▬▬▬▬▬▬▬▬▬▬▓▓▓▓    ▓▓▓▓▓▬▬▬▬▬▬▬▬▓▓▓▓▓▓▓▬▬▬▀▓▓▓▓▄▄▄▓▓▓▬▬▓▓▓▓▓▓▓▓▓▓▓▓▓▬▬▬▬▬▬▬▬▬▬\n        │    ▓▓▓▓    ▓▓▓▓▓          ▓▓▓▓▓▄   ▄▄▓▓▓▓▓▓▓▓▓  ▓▓▓▓      ▓▓▓▄    │\n▬▬▬▬▬▬▬▬▬▬▬▬▬▓▓▓▓    ▓▓▓▓▓▬▬▬▬▬▬▬▬▬▬▬▓▓▓▓▓▄▄▓▓▀  ▀▀▓▓▓▓▓▓▓▓▓▓▬▬▬▬▬▬▬▬▓▓▓▬▬▬▬▬▬▬▬\n▬▬▬▬▬▬▬▬║▬▬▬▬▓▓▓▓    ▓▓▓▓▓▬▬▬▬▬▬▬▬▬▬▬▬▓▓▓▓▓▓▓▬▬▬▬▬▬▬▬▬▓▓▓ ▓▓▓▬▬▬▬▬▬▬▬▓▓▓▬▬▬▬║▬▬▬\n▬▬▬▬▬▬▬▬▬▬▬▬▬▓▓▓▓    ▓▓▓▓▓▬▬▬▬▬▬▬▬▬▬▬▓▓▓▓▬▬▓▓▓▬▬▬▬▬▬▬▬▓▓▓▬▓▓▓▓▬▬▬▬▬▬▬▓▓▓▬▬▬▬▬▬▬▬\n■■■■■■■■║■■■■▓▓▓▓    ▓▓▓▓▓■■■▓▓▓▄▄▄▓▓▓▓■■■■▬▓▓▓▓▄▄▄▄▓▓▓■■■■▬▓▓▓▓▄▄▄▓▓▓▓▀■■■■║■■■\n■■■■■■■■■■■■■▓▓▓▓▓▓▓▓▓▓▓▓▓■■■■■▀▓▓▓■■■■■■■■■■■■■■▀▀■■■■■■■■■■■■▀▓▓▀■■■■■■■■■■■■■\n        ║▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓║ */\n\n#define XED_MODE_REAL   0\n#define XED_MODE_LEGACY 1\n#define XED_MODE_LONG   2\n\n#define XED_ILD_MAP0    0  // 8086+  ...\n#define XED_ILD_MAP1    1  // 286+   0x0F,...\n#define XED_ILD_MAP2    2  // Core2+ 0x0F,0x38,...\n#define XED_ILD_MAP3    3  // Core2+ 0x0F,0x3A,...\n#define XED_ILD_MAP4    4\n#define XED_ILD_MAP5    5\n#define XED_ILD_MAP6    6\n#define XED_ILD_BAD_MAP 7\n\n#define XED_GEN_MODE_REAL      0\n#define XED_GEN_MODE_PROTECTED 1\n#define XED_GEN_MODE_V86       2  // unimplemented\n\nstruct XedMachineMode {\n  uint8_t omode : 2,  // bitness of operands, for instruction decoding\n                      // - 16-bit if XED_MODE_REAL\n                      // - 32-bit if XED_MODE_LEGACY\n                      // - 64-bit if XED_MODE_LONG\n      genmode : 6;    // general machine mode\n                      // - real address mode if XED_GEN_MODE_REAL\n                      // - protected/long mode, with GDT & all that, if\n                      //   XED_GEN_MODE_PROTECTED\n};\n\n#define XED_MACHINE_MODE_REAL \\\n  ((struct XedMachineMode){XED_MODE_REAL, XED_GEN_MODE_REAL})\n#define XED_MACHINE_MODE_LEGACY_16 \\\n  ((struct XedMachineMode){XED_MODE_REAL, XED_GEN_MODE_PROTECTED})\n#define XED_MACHINE_MODE_LEGACY_32 \\\n  ((struct XedMachineMode){XED_MODE_LEGACY, XED_GEN_MODE_PROTECTED})\n#define XED_MACHINE_MODE_LONG \\\n  ((struct XedMachineMode){XED_MODE_LONG, XED_GEN_MODE_PROTECTED})\n\n#define XED_MAX_INSTRUCTION_BYTES 15\n\n#define XED_ERROR_NONE              0\n#define XED_ERROR_BUFFER_TOO_SHORT  1\n#define XED_ERROR_GENERAL_ERROR     2\n#define XED_ERROR_BAD_LEGACY_PREFIX 7\n#define XED_ERROR_BAD_REX_PREFIX    8\n#define XED_ERROR_BAD_MAP           10\n#define XED_ERROR_INSTR_TOO_LONG    18\n#define XED_ERROR_INVALID_MODE      19\n#define XED_ERROR_LAST              22\n\nstruct XedOperands { /*\n    ┌vreg\n    │    ┌log₂𝑏 (-/16/32/64)\n    │    │ ┌length\n    │    │ │   ┌rep\n    │    │ │   │ ┌map\n    │    │ │   │ │  ┌opcode\n    │    │ │   │ │  │       ┌sib scale\n    │    │ │   │ │  │       │ ┌sib index\n    │    │ │   │ │  │       │ │  ┌sib base\n    │    │ │   │ │  │       │ │  │  ┌lock\n    │    │ │   │ │  │       │ │  │  │┌ymm\n    │    │ │   │ │  │       │ │  │  ││┌log₂𝑏 (8/16/32/64)\n    │    │ │   │ │  │       │ │  │  │││ ┌mode\n    │    │ │   │ │  │       │ │  │  │││ │ ┌eamode\n    │    │ │   │ │  │       │ │  │  │││ │ │ ┌mod\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ┌asz\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ │┌sego\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  ┌rexx\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  │┌rex         REGISTER\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  ││┌rexb       DISPATCH\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  │││┌srm       ENCODING\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  ││││  ┌rex\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  ││││  │┌rexb\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  ││││  ││┌rm\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  ││││  │││  ┌rexw\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  ││││  │││  │┌osz\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  ││││  │││  ││┌rex\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  ││││  │││  │││┌rexr\n    │    │ │   │ │  │       │ │  │  │││ │ │ │ ││  ││││  │││  ││││┌reg\n    │6   │5│5  │5│4 │4      │3│3 │3 │││2│2│2│2││  ││││  │││  │││││\n    │0   │7│3  │1│8 │0      │8│5 │2 │││8│6│4│2││18││││12│││ 7│││││ 0\n    ├──┐ ├┐├──┐├┐├─┐├──────┐├┐├─┐├─┐││├┐├┐├┐├┐│├─┐│││├─┐││├─┐││││├─┐\n  0b0000000000000000000000000000000000000000000000000000000000000000*/\n  uint64_t rde;\n  uint64_t uimm0;  // $immediate mostly sign-extended\n  int64_t disp;    // displacement(%xxx) mostly sign-extended\n  uint8_t has_modrm;\n  uint8_t pos_opcode;\n  uint8_t max_bytes;\n};\n\nstruct XedDecodedInst {\n  unsigned char length;\n  uint8_t bytes[15];\n  struct XedOperands op;\n};\n\nextern const char kXedCopyright[];\nextern const char kXedErrorNames[];\n\nint DecodeInstruction(struct XedDecodedInst *, const void *, size_t, uint64_t);\n\n#endif /* BLINK_X86_H_ */\n"
  },
  {
    "path": "blink/x86error.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/x86.h\"\n\nconst char kXedErrorNames[] = \"\\\nnone\\0\\\nbuffer too short\\0\\\ngeneral error\\0\\\ninvalid for chip\\0\\\nbad register\\0\\\nbad lock prefix\\0\\\nbad rep prefix\\0\\\nbad legacy prefix\\0\\\nbad rex prefix\\0\\\nbad evex ubit\\0\\\nbad map\\0\\\nbad evex v prime\\0\\\nbad evex z no masking\\0\\\nno output pointer\\0\\\nno agen call back registered\\0\\\nbad memop index\\0\\\ncallback problem\\0\\\ngather regs\\0\\\ninstr too long\\0\\\ninvalid mode\\0\\\nbad evex ll\\0\\\nunimplemented\\0\\\n\";\n"
  },
  {
    "path": "blink/xadd.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <limits.h>\n\n#include \"blink/alu.h\"\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/log.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/swap.h\"\n#include \"blink/thread.h\"\n\nvoid OpXaddEbGb(P) {\n  u8 x, y, z, *p, *q;\n  p = GetModrmRegisterBytePointerWrite1(A);\n  q = ByteRexrReg(m, rde);\n  if (Lock(rde)) {\n    x = atomic_load_explicit((_Atomic(u8) *)p, memory_order_acquire);\n    y = atomic_load_explicit((_Atomic(u8) *)q, memory_order_relaxed);\n    y = Little8(y);\n    do {\n      atomic_store_explicit((_Atomic(u8) *)q, x, memory_order_relaxed);\n      z = Little8(Add8(m, Little8(x), y));\n    } while (!atomic_compare_exchange_weak_explicit(\n        (_Atomic(u8) *)p, &x, z, memory_order_release, memory_order_acquire));\n  } else {\n    x = Load8(p);\n    y = Get8(q);\n    z = Add8(m, x, y);\n    Put8(q, x);\n    Store8(p, z);\n  }\n}\n\nvoid OpXaddEvqpGvqp(P) {\n  u8 *p, *q;\n  q = RegRexrReg(m, rde);\n  p = GetModrmRegisterWordPointerWriteOszRexw(A);\n  if (Rexw(rde)) {\n    u64 x, y, z;\n#if CAN_64BIT\n    if (Lock(rde) && !((uintptr_t)p & 7)) {\n      x = atomic_load_explicit((_Atomic(u64) *)p, memory_order_acquire);\n      y = atomic_load_explicit((_Atomic(u64) *)q, memory_order_relaxed);\n      y = Little64(y);\n      do {\n        atomic_store_explicit((_Atomic(u64) *)q, x, memory_order_relaxed);\n        z = Little64(Add64(m, Little64(x), y));\n      } while (!atomic_compare_exchange_weak_explicit((_Atomic(u64) *)p, &x, z,\n                                                      memory_order_release,\n                                                      memory_order_acquire));\n      return;\n    }\n#endif\n    if (Lock(rde)) {\n      LockBus(p);\n      x = Load64Unlocked(p);\n      y = Get64(q);\n      z = Add64(m, x, y);\n      Put64(q, x);\n      Store64Unlocked(p, z);\n      UnlockBus(p);\n    } else {\n      x = Load64(p);\n      y = Get64(q);\n      z = Add64(m, x, y);\n      Put64(q, x);\n      Store64(p, z);\n    }\n  } else if (!Osz(rde)) {\n    u32 x, y, z;\n    if (Lock(rde) && !((uintptr_t)p & 3)) {\n      x = atomic_load_explicit((_Atomic(u32) *)p, memory_order_acquire);\n      y = atomic_load_explicit((_Atomic(u32) *)q, memory_order_relaxed);\n      y = Little32(y);\n      do {\n        atomic_store_explicit((_Atomic(u32) *)q, x, memory_order_relaxed);\n        z = Little32(Add32(m, Little32(x), y));\n      } while (!atomic_compare_exchange_weak_explicit((_Atomic(u32) *)p, &x, z,\n                                                      memory_order_release,\n                                                      memory_order_acquire));\n    } else {\n      if (Lock(rde)) LockBus(p);\n      x = Load32(p);\n      y = Get32(q);\n      z = Add32(m, x, y);\n      Put32(q, x);\n      Store32(p, z);\n      if (Lock(rde)) UnlockBus(p);\n    }\n    Put32(q + 4, 0);\n    if (IsModrmRegister(rde)) {\n      Put32(p + 4, 0);\n    }\n  } else {\n    u16 x, y, z;\n    if (Lock(rde) && !((uintptr_t)p & 1)) {\n      x = atomic_load_explicit((_Atomic(u16) *)p, memory_order_acquire);\n      y = atomic_load_explicit((_Atomic(u16) *)q, memory_order_relaxed);\n      y = Little16(y);\n      do {\n        atomic_store_explicit((_Atomic(u16) *)q, x, memory_order_relaxed);\n        z = Little16(Add16(m, Little16(x), y));\n      } while (!atomic_compare_exchange_weak_explicit((_Atomic(u16) *)p, &x, z,\n                                                      memory_order_release,\n                                                      memory_order_acquire));\n    } else {\n      if (Lock(rde)) LockBus(p);\n      x = Load16(p);\n      y = Get16(q);\n      z = Add16(m, x, y);\n      Put16(q, x);\n      Store16(p, z);\n      if (Lock(rde)) UnlockBus(p);\n    }\n  }\n}\n"
  },
  {
    "path": "blink/xchg.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <limits.h>\n\n#include \"blink/assert.h\"\n#include \"blink/atomic.h\"\n#include \"blink/builtin.h\"\n#include \"blink/bus.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n#include \"blink/modrm.h\"\n#include \"blink/thread.h\"\n\nvoid OpXchgGbEb(P) {\n  u8 *p, *q, x, y;\n  q = ByteRexrReg(m, rde);\n  /* When a memory operand is used with the XCHG instruction, the\n     processor's LOCK signal is automatically asserted. ──Intel V.1\n     §7.3.1.2 */\n  if (!IsModrmRegister(rde)) {\n    p = ComputeReserveAddressWrite1(A);\n    *q = atomic_exchange_explicit((_Atomic(u8) *)p, *q, memory_order_acq_rel);\n  } else {\n    p = ByteRexbRm(m, rde);\n    x = Get8(q);\n    y = Get8(p);\n    Put8(q, y);\n    Put8(p, x);\n  }\n}\n\nvoid OpXchgGvqpEvqp(P) {\n  u8 *q = RegRexrReg(m, rde);\n  u8 *p = GetModrmRegisterWordPointerWriteOszRexw(A);\n  if (Rexw(rde)) {\n#if CAN_64BIT\n    if (!IsModrmRegister(rde) && !((uintptr_t)p & 7)) {\n      atomic_store_explicit(\n          (_Atomic(u64) *)q,\n          atomic_exchange_explicit(\n              (_Atomic(u64) *)p,\n              atomic_load_explicit((_Atomic(u64) *)q, memory_order_relaxed),\n              memory_order_acq_rel),\n          memory_order_relaxed);\n      return;\n    }\n#endif\n    u64 x, y;\n    if (IsModrmRegister(rde)) {\n      x = Get64(q);\n      y = Get64(p);\n      Put64(q, y);\n      Put64(p, x);\n    } else {\n      LockBus(p);\n      y = Load64Unlocked(p);\n      x = Get64(q);\n      Put64(q, y);\n      Store64Unlocked(p, x);\n      UnlockBus(p);\n    }\n  } else if (!Osz(rde)) {\n    if (!IsModrmRegister(rde) && !((uintptr_t)p & 3)) {\n      atomic_store_explicit(\n          (_Atomic(u32) *)q,\n          atomic_exchange_explicit(\n              (_Atomic(u32) *)p,\n              atomic_load_explicit((_Atomic(u32) *)q, memory_order_relaxed),\n              memory_order_acq_rel),\n          memory_order_relaxed);\n    } else {\n      u32 x, y;\n      if (!IsModrmRegister(rde)) LockBus(p);\n      y = Load32(p);\n      x = Read32(q);\n      Write32(q, y);\n      Store32(p, x);\n      if (!IsModrmRegister(rde)) UnlockBus(p);\n    }\n    Write32(q + 4, 0);\n    if (IsModrmRegister(rde)) {\n      Write32(p + 4, 0);\n    }\n  } else {\n    if (!IsModrmRegister(rde) && !((uintptr_t)p & 1)) {\n      atomic_store_explicit(\n          (_Atomic(u16) *)q,\n          atomic_exchange_explicit(\n              (_Atomic(u16) *)p,\n              atomic_load_explicit((_Atomic(u16) *)q, memory_order_relaxed),\n              memory_order_acq_rel),\n          memory_order_relaxed);\n    } else {\n      u16 x, y;\n      if (!IsModrmRegister(rde)) LockBus(p);\n      y = Load16(p);\n      x = Read16(q);\n      Write16(q, y);\n      Store16(p, x);\n      if (!IsModrmRegister(rde)) UnlockBus(p);\n    }\n  }\n}\n"
  },
  {
    "path": "blink/xlat.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/xlat.h\"\n\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <netinet/tcp.h>\n#include <netinet/udp.h>\n#include <signal.h>\n#include <stddef.h>\n#include <string.h>\n#include <sys/file.h>\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#include <sys/socket.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <sys/un.h>\n#include <sys/wait.h>\n#include <time.h>\n#include <unistd.h>\n\n#include \"blink/builtin.h\"\n#include \"blink/case.h\"\n#include \"blink/endian.h\"\n#include \"blink/errno.h\"\n#include \"blink/linux.h\"\n#include \"blink/log.h\"\n#include \"blink/macros.h\"\n#include \"blink/map.h\"\n#include \"blink/ndelay.h\"\n#include \"blink/sigwinch.h\"\n#include \"blink/util.h\"\n\n#if defined(__APPLE__) || defined(__NetBSD__)\n#define st_atim st_atimespec\n#define st_ctim st_ctimespec\n#define st_mtim st_mtimespec\n#endif\n\n// NSIG isn't POSIX but it's more common than SIGRTMAX which is.\n// Note: OpenBSD defines NSIG as 33, even though it only has 32.\n#ifdef NSIG\n#define TOPSIG NSIG\n#elif defined(SIGRTMAX)\n#define TOPSIG SIGRTMAX\n#else\n#define TOPSIG 32\n#endif\n\nint XlatErrno(int x) {\n  if (x == EPERM) return EPERM_LINUX;\n  if (x == ENOENT) return ENOENT_LINUX;\n  if (x == ESRCH) return ESRCH_LINUX;\n  if (x == EINTR) return EINTR_LINUX;\n  if (x == EIO) return EIO_LINUX;\n  if (x == ENXIO) return ENXIO_LINUX;\n  if (x == E2BIG) return E2BIG_LINUX;\n  if (x == ENOEXEC) return ENOEXEC_LINUX;\n  if (x == EBADF) return EBADF_LINUX;\n  if (x == ECHILD) return ECHILD_LINUX;\n  if (x == EAGAIN) return EAGAIN_LINUX;\n#if EWOULDBLOCK != EAGAIN\n  if (x == EWOULDBLOCK) return EWOULDBLOCK_LINUX;\n#endif\n  if (x == ENOMEM) return ENOMEM_LINUX;\n  if (x == EACCES) return EACCES_LINUX;\n  if (x == EFAULT) return EFAULT_LINUX;\n#ifdef ENOTBLK\n  if (x == ENOTBLK) return ENOTBLK_LINUX;\n#endif\n  if (x == EBUSY) return EBUSY_LINUX;\n  if (x == EEXIST) return EEXIST_LINUX;\n  if (x == EXDEV) return EXDEV_LINUX;\n  if (x == ENODEV) return ENODEV_LINUX;\n  if (x == ENOTDIR) return ENOTDIR_LINUX;\n  if (x == EISDIR) return EISDIR_LINUX;\n  if (x == EINVAL) return EINVAL_LINUX;\n  if (x == ENFILE) return ENFILE_LINUX;\n  if (x == EMFILE) return EMFILE_LINUX;\n  if (x == ENOTTY) return ENOTTY_LINUX;\n  if (x == ETXTBSY) return ETXTBSY_LINUX;\n  if (x == EFBIG) return EFBIG_LINUX;\n  if (x == ENOSPC) return ENOSPC_LINUX;\n  if (x == ESPIPE) return ESPIPE_LINUX;\n  if (x == EROFS) return EROFS_LINUX;\n  if (x == EMLINK) return EMLINK_LINUX;\n  if (x == EPIPE) return EPIPE_LINUX;\n  if (x == EDOM) return EDOM_LINUX;\n  if (x == ERANGE) return ERANGE_LINUX;\n  if (x == EDEADLK) return EDEADLK_LINUX;\n  if (x == ENAMETOOLONG) return ENAMETOOLONG_LINUX;\n  if (x == ENOLCK) return ENOLCK_LINUX;\n  if (x == ENOSYS) return ENOSYS_LINUX;\n  if (x == ENOTEMPTY) return ENOTEMPTY_LINUX;\n  if (x == ELOOP) return ELOOP_LINUX;\n  if (x == ENOMSG) return ENOMSG_LINUX;\n  if (x == EIDRM) return EIDRM_LINUX;\n#ifdef EREMOTE\n  if (x == EREMOTE) return EREMOTE_LINUX;\n#endif\n  if (x == EPROTO) return EPROTO_LINUX;\n  if (x == EBADMSG) return EBADMSG_LINUX;\n  if (x == EOVERFLOW) return EOVERFLOW_LINUX;\n  if (x == EILSEQ) return EILSEQ_LINUX;\n#ifdef EUSERS\n  if (x == EUSERS) return EUSERS_LINUX;\n#endif\n  if (x == ENOTSOCK) return ENOTSOCK_LINUX;\n  if (x == EDESTADDRREQ) return EDESTADDRREQ_LINUX;\n  if (x == EMSGSIZE) return EMSGSIZE_LINUX;\n  if (x == EPROTOTYPE) return EPROTOTYPE_LINUX;\n  if (x == ENOPROTOOPT) return ENOPROTOOPT_LINUX;\n  if (x == EPROTONOSUPPORT) return EPROTONOSUPPORT_LINUX;\n#ifdef ESOCKTNOSUPPORT\n  if (x == ESOCKTNOSUPPORT) return ESOCKTNOSUPPORT_LINUX;\n#endif\n  if (x == ENOTSUP) return ENOTSUP_LINUX;\n#if EOPNOTSUPP != ENOTSUP\n  if (x == EOPNOTSUPP) return EOPNOTSUPP_LINUX;\n#endif\n#ifdef EPFNOSUPPORT\n  if (x == EPFNOSUPPORT) return EPFNOSUPPORT_LINUX;\n#endif\n  if (x == EAFNOSUPPORT) return EAFNOSUPPORT_LINUX;\n  if (x == EADDRINUSE) return EADDRINUSE_LINUX;\n  if (x == EADDRNOTAVAIL) return EADDRNOTAVAIL_LINUX;\n  if (x == ENETDOWN) return ENETDOWN_LINUX;\n  if (x == ENETUNREACH) return ENETUNREACH_LINUX;\n  if (x == ENETRESET) return ENETRESET_LINUX;\n  if (x == ECONNABORTED) return ECONNABORTED_LINUX;\n  if (x == ECONNRESET) return ECONNRESET_LINUX;\n  if (x == ENOBUFS) return ENOBUFS_LINUX;\n  if (x == EISCONN) return EISCONN_LINUX;\n  if (x == ENOTCONN) return ENOTCONN_LINUX;\n#ifdef ESHUTDOWN\n  if (x == ESHUTDOWN) return ESHUTDOWN_LINUX;\n#endif\n#ifdef ETOOMANYREFS\n  if (x == ETOOMANYREFS) return ETOOMANYREFS_LINUX;\n#endif\n  if (x == ETIMEDOUT) return ETIMEDOUT_LINUX;\n  if (x == ECONNREFUSED) return ECONNREFUSED_LINUX;\n#ifdef EHOSTDOWN\n  if (x == EHOSTDOWN) return EHOSTDOWN_LINUX;\n#endif\n  if (x == EHOSTUNREACH) return EHOSTUNREACH_LINUX;\n  if (x == EALREADY) return EALREADY_LINUX;\n  if (x == EINPROGRESS) return EINPROGRESS_LINUX;\n  if (x == ESTALE) return ESTALE_LINUX;\n  if (x == EDQUOT) return EDQUOT_LINUX;\n  if (x == ECANCELED) return ECANCELED_LINUX;\n#ifdef EOWNERDEAD\n  if (x == EOWNERDEAD) return EOWNERDEAD_LINUX;\n#endif\n#ifdef ENOTRECOVERABLE\n  if (x == ENOTRECOVERABLE) return ENOTRECOVERABLE_LINUX;\n#endif\n#ifdef ETIME\n  if (x == ETIME) return ETIME_LINUX;\n#endif\n#ifdef ENONET\n  if (x == ENONET) return ENONET_LINUX;\n#endif\n#ifdef ERESTART\n  if (x == ERESTART) return ERESTART_LINUX;\n#endif\n#ifdef ENOSR\n  if (x == ENOSR) return ENOSR_LINUX;\n#endif\n#ifdef ENOSTR\n  if (x == ENOSTR) return ENOSTR_LINUX;\n#endif\n#ifdef ENODATA\n  if (x == ENODATA) return ENODATA_LINUX;\n#endif\n#ifdef EMULTIHOP\n  if (x == EMULTIHOP) return EMULTIHOP_LINUX;\n#endif\n#ifdef ENOLINK\n  if (x == ENOLINK) return ENOLINK_LINUX;\n#endif\n#ifdef ENOMEDIUM\n  if (x == ENOMEDIUM) return ENOMEDIUM_LINUX;\n#endif\n#ifdef EMEDIUMTYPE\n  if (x == EMEDIUMTYPE) return EMEDIUMTYPE_LINUX;\n#endif\n  return x;\n}\n\nint XlatSignal(int x) {\n  switch (x) {\n    XLAT(SIGHUP_LINUX, SIGHUP);\n    XLAT(SIGINT_LINUX, SIGINT);\n    XLAT(SIGQUIT_LINUX, SIGQUIT);\n    XLAT(SIGILL_LINUX, SIGILL);\n    XLAT(SIGTRAP_LINUX, SIGTRAP);\n    XLAT(SIGABRT_LINUX, SIGABRT);\n    XLAT(SIGBUS_LINUX, SIGBUS);\n    XLAT(SIGFPE_LINUX, SIGFPE);\n    XLAT(SIGKILL_LINUX, SIGKILL);\n    XLAT(SIGUSR1_LINUX, SIGUSR1);\n    XLAT(SIGSEGV_LINUX, SIGSEGV);\n    XLAT(SIGUSR2_LINUX, SIGUSR2);\n    XLAT(SIGPIPE_LINUX, SIGPIPE);\n    XLAT(SIGALRM_LINUX, SIGALRM);\n    XLAT(SIGTERM_LINUX, SIGTERM);\n#ifdef SIGSTKFLT\n    XLAT(SIGSTKFLT_LINUX, SIGSTKFLT);\n#endif\n    XLAT(SIGCHLD_LINUX, SIGCHLD);\n    XLAT(SIGCONT_LINUX, SIGCONT);\n    XLAT(SIGSTOP_LINUX, SIGSTOP);\n    XLAT(SIGTSTP_LINUX, SIGTSTP);\n    XLAT(SIGTTIN_LINUX, SIGTTIN);\n    XLAT(SIGTTOU_LINUX, SIGTTOU);\n    XLAT(SIGURG_LINUX, SIGURG);\n    XLAT(SIGXCPU_LINUX, SIGXCPU);\n    XLAT(SIGXFSZ_LINUX, SIGXFSZ);\n    XLAT(SIGVTALRM_LINUX, SIGVTALRM);\n    XLAT(SIGPROF_LINUX, SIGPROF);\n    XLAT(SIGWINCH_LINUX, SIGWINCH);\n#ifdef SIGIO\n    XLAT(SIGIO_LINUX, SIGIO);\n#endif\n#ifdef SIGPWR\n    XLAT(SIGPWR_LINUX, SIGPWR);\n#endif\n    XLAT(SIGSYS_LINUX, SIGSYS);\n    default:\n      break;\n  }\n#ifdef SIGRTMIN\n  if ((SIGRTMIN_LINUX <= x && x <= SIGRTMAX_LINUX) &&\n      SIGRTMIN + (x - SIGRTMIN_LINUX) <= SIGRTMAX) {\n    return SIGRTMIN + (x - SIGRTMIN_LINUX);\n  }\n#endif\n  return einval();\n}\n\nint XlatResource(int x) {\n  switch (x) {\n    XLAT(RLIMIT_CPU_LINUX, RLIMIT_CPU);\n    XLAT(RLIMIT_FSIZE_LINUX, RLIMIT_FSIZE);\n    XLAT(RLIMIT_DATA_LINUX, RLIMIT_DATA);\n    XLAT(RLIMIT_STACK_LINUX, RLIMIT_STACK);\n    XLAT(RLIMIT_CORE_LINUX, RLIMIT_CORE);\n#ifdef RLIMIT_AS\n    XLAT(RLIMIT_AS_LINUX, RLIMIT_AS);\n#endif\n#ifndef DISABLE_NONPOSIX\n#ifdef RLIMIT_RSS\n    XLAT(RLIMIT_RSS_LINUX, RLIMIT_RSS);\n#endif\n#ifdef RLIMIT_NPROC\n    XLAT(RLIMIT_NPROC_LINUX, RLIMIT_NPROC);\n#endif\n    XLAT(RLIMIT_NOFILE_LINUX, RLIMIT_NOFILE);\n#ifdef RLIMIT_MEMLOCK\n    XLAT(RLIMIT_MEMLOCK_LINUX, RLIMIT_MEMLOCK);\n#endif\n#ifdef RLIMIT_LOCKS\n    XLAT(RLIMIT_LOCKS_LINUX, RLIMIT_LOCKS);\n#endif\n#ifdef RLIMIT_SIGPENDING\n    XLAT(RLIMIT_SIGPENDING_LINUX, RLIMIT_SIGPENDING);\n#endif\n#ifdef RLIMIT_MSGQUEUE\n    XLAT(RLIMIT_MSGQUEUE_LINUX, RLIMIT_MSGQUEUE);\n#endif\n#ifdef RLIMIT_NICE\n    XLAT(RLIMIT_NICE_LINUX, RLIMIT_NICE);\n#endif\n#ifdef RLIMIT_RTPRIO\n    XLAT(RLIMIT_RTPRIO_LINUX, RLIMIT_RTPRIO);\n#endif\n#ifdef RLIMIT_RTTIME\n    XLAT(RLIMIT_RTTIME_LINUX, RLIMIT_RTTIME);\n#endif\n#endif /* DISABLE_NONPOSIX */\n    default:\n      LOGF(\"rlimit %d not supported yet\", x);\n      return einval();\n  }\n}\n\nint UnXlatSignal(int x) {\n  if (x == SIGHUP) return SIGHUP_LINUX;\n  if (x == SIGINT) return SIGINT_LINUX;\n  if (x == SIGQUIT) return SIGQUIT_LINUX;\n  if (x == SIGILL) return SIGILL_LINUX;\n  if (x == SIGTRAP) return SIGTRAP_LINUX;\n  if (x == SIGABRT) return SIGABRT_LINUX;\n  if (x == SIGBUS) return SIGBUS_LINUX;\n  if (x == SIGFPE) return SIGFPE_LINUX;\n  if (x == SIGKILL) return SIGKILL_LINUX;\n  if (x == SIGUSR1) return SIGUSR1_LINUX;\n  if (x == SIGSEGV) return SIGSEGV_LINUX;\n  if (x == SIGUSR2) return SIGUSR2_LINUX;\n  if (x == SIGPIPE) return SIGPIPE_LINUX;\n  if (x == SIGALRM) return SIGALRM_LINUX;\n  if (x == SIGTERM) return SIGTERM_LINUX;\n  if (x == SIGCHLD) return SIGCHLD_LINUX;\n  if (x == SIGCONT) return SIGCONT_LINUX;\n  if (x == SIGTTIN) return SIGTTIN_LINUX;\n  if (x == SIGTTOU) return SIGTTOU_LINUX;\n  if (x == SIGXCPU) return SIGXCPU_LINUX;\n  if (x == SIGXFSZ) return SIGXFSZ_LINUX;\n  if (x == SIGVTALRM) return SIGVTALRM_LINUX;\n  if (x == SIGPROF) return SIGPROF_LINUX;\n  if (x == SIGWINCH) return SIGWINCH_LINUX;\n#ifdef SIGIO\n  if (x == SIGIO) return SIGIO_LINUX;\n#endif\n#ifdef SIGPWR\n  if (x == SIGPWR) return SIGPWR_LINUX;\n#endif\n#ifdef SIGSTKFLT\n  if (x == SIGSTKFLT) return SIGSTKFLT_LINUX;\n#endif\n  if (x == SIGSTOP) return SIGSTOP_LINUX;\n  if (x == SIGSYS) return SIGSYS_LINUX;\n  if (x == SIGTSTP) return SIGTSTP_LINUX;\n  if (x == SIGURG) return SIGURG_LINUX;\n#ifdef SIGRTMIN\n  if ((SIGRTMIN <= x && x <= SIGRTMAX) &&\n      SIGRTMIN_LINUX + (x - SIGRTMIN) <= SIGRTMAX_LINUX) {\n    return SIGRTMIN_LINUX + (x - SIGRTMIN);\n  }\n#endif\n  return einval();\n}\n\nint UnXlatSiCode(int sig, int code) {\n#ifdef SI_USER\n  if (code == SI_USER) return SI_USER_LINUX;\n#endif\n#ifdef SI_QUEUE\n  if (code == SI_QUEUE) return SI_QUEUE_LINUX;\n#endif\n#ifdef SI_TIMER\n  if (code == SI_TIMER) return SI_TIMER_LINUX;\n#endif\n#ifdef SI_TKILL\n  if (code == SI_TKILL) return SI_TKILL_LINUX;\n#endif\n#ifdef SI_MESGQ\n  if (code == SI_MESGQ) return SI_MESGQ_LINUX;\n#endif\n#ifdef SI_ASYNCIO\n  if (code == SI_ASYNCIO) return SI_ASYNCIO_LINUX;\n#endif\n#ifdef SI_ASYNCNL\n  if (code == SI_ASYNCNL) return SI_ASYNCNL_LINUX;\n#endif\n#ifdef SI_KERNEL\n  if (code == SI_KERNEL) return SI_KERNEL_LINUX;\n#endif\n#ifdef SI_NOINFO\n  if (code == SI_NOINFO) return SI_NOINFO_LINUX;\n#endif\n  switch (sig) {\n    case SIGCHLD_LINUX:\n#ifdef CLD_EXITED\n      if (code == CLD_EXITED) return CLD_EXITED_LINUX;\n#endif\n#ifdef CLD_KILLED\n      if (code == CLD_KILLED) return CLD_KILLED_LINUX;\n#endif\n#ifdef CLD_DUMPED\n      if (code == CLD_DUMPED) return CLD_DUMPED_LINUX;\n#endif\n#ifdef CLD_TRAPPED\n      if (code == CLD_TRAPPED) return CLD_TRAPPED_LINUX;\n#endif\n#ifdef CLD_STOPPED\n      if (code == CLD_STOPPED) return CLD_STOPPED_LINUX;\n#endif\n#ifdef CLD_CONTINUED\n      if (code == CLD_CONTINUED) return CLD_CONTINUED_LINUX;\n#endif\n      break;\n    case SIGTRAP_LINUX:\n#ifdef TRAP_BRKPT\n      if (code == TRAP_BRKPT) return TRAP_BRKPT_LINUX;\n#endif\n#ifdef TRAP_TRACE\n      if (code == TRAP_TRACE) return TRAP_TRACE_LINUX;\n#endif\n      break;\n    case SIGSEGV_LINUX:\n#ifdef SEGV_MAPERR\n      if (code == SEGV_MAPERR) return SEGV_MAPERR_LINUX;\n#endif\n#ifdef SEGV_ACCERR\n      if (code == SEGV_ACCERR) return SEGV_ACCERR_LINUX;\n#endif\n#ifdef SEGV_PKUERR\n      if (code == SEGV_PKUERR) return SEGV_PKUERR_LINUX;\n#endif\n      break;\n    case SIGFPE_LINUX:\n#ifdef FPE_INTDIV\n      if (code == FPE_INTDIV) return FPE_INTDIV_LINUX;\n#endif\n#ifdef FPE_INTOVF\n      if (code == FPE_INTOVF) return FPE_INTOVF_LINUX;\n#endif\n#ifdef FPE_FLTDIV\n      if (code == FPE_FLTDIV) return FPE_FLTDIV_LINUX;\n#endif\n#ifdef FPE_FLTOVF\n      if (code == FPE_FLTOVF) return FPE_FLTOVF_LINUX;\n#endif\n#ifdef FPE_FLTUND\n      if (code == FPE_FLTUND) return FPE_FLTUND_LINUX;\n#endif\n#ifdef FPE_FLTRES\n      if (code == FPE_FLTRES) return FPE_FLTRES_LINUX;\n#endif\n#ifdef FPE_FLTINV\n      if (code == FPE_FLTINV) return FPE_FLTINV_LINUX;\n#endif\n#ifdef FPE_FLTSUB\n      if (code == FPE_FLTSUB) return FPE_FLTSUB_LINUX;\n#endif\n      break;\n    case SIGILL_LINUX:\n#ifdef ILL_ILLOPC\n      if (code == ILL_ILLOPC) return ILL_ILLOPC_LINUX;\n#endif\n#ifdef ILL_ILLOPN\n      if (code == ILL_ILLOPN) return ILL_ILLOPN_LINUX;\n#endif\n#ifdef ILL_ILLADR\n      if (code == ILL_ILLADR) return ILL_ILLADR_LINUX;\n#endif\n#ifdef ILL_ILLTRP\n      if (code == ILL_ILLTRP) return ILL_ILLTRP_LINUX;\n#endif\n#ifdef ILL_PRVOPC\n      if (code == ILL_PRVOPC) return ILL_PRVOPC_LINUX;\n#endif\n#ifdef ILL_PRVREG\n      if (code == ILL_PRVREG) return ILL_PRVREG_LINUX;\n#endif\n#ifdef ILL_COPROC\n      if (code == ILL_COPROC) return ILL_COPROC_LINUX;\n#endif\n#ifdef ILL_BADSTK\n      if (code == ILL_BADSTK) return ILL_BADSTK_LINUX;\n#endif\n      break;\n    case SIGBUS_LINUX:\n#ifdef BUS_ADRALN\n      if (code == BUS_ADRALN) return BUS_ADRALN_LINUX;\n#endif\n#ifdef BUS_ADRERR\n      if (code == BUS_ADRERR) return BUS_ADRERR_LINUX;\n#endif\n#ifdef BUS_OBJERR\n      if (code == BUS_OBJERR) return BUS_OBJERR_LINUX;\n#endif\n#ifdef BUS_OOMERR\n      if (code == BUS_OOMERR) return BUS_OOMERR_LINUX;\n#endif\n#ifdef BUS_MCEERR_AR\n      if (code == BUS_MCEERR_AR) return BUS_MCEERR_AR_LINUX;\n#endif\n#ifdef BUS_MCEERR_AO\n      if (code == BUS_MCEERR_AO) return BUS_MCEERR_AO_LINUX;\n#endif\n      break;\n    case SIGIO_LINUX:\n#ifdef POLL_IN\n      if (code == POLL_IN) return POLL_IN_LINUX;\n#endif\n#ifdef POLL_OUT\n      if (code == POLL_OUT) return POLL_OUT_LINUX;\n#endif\n#ifdef POLL_MSG\n      if (code == POLL_MSG) return POLL_MSG_LINUX;\n#endif\n#ifdef POLL_ERR\n      if (code == POLL_ERR) return POLL_ERR_LINUX;\n#endif\n#ifdef POLL_PRI\n      if (code == POLL_PRI) return POLL_PRI_LINUX;\n#endif\n#ifdef POLL_HUP\n      if (code == POLL_HUP) return POLL_HUP_LINUX;\n#endif\n      break;\n    default:\n      break;\n  }\n  return code;\n}\n\nint XlatRusage(int x) {\n  switch (x) {\n    XLAT(0, RUSAGE_SELF);\n    XLAT(-1, RUSAGE_CHILDREN);\n    default:\n      LOGF(\"%s %d not supported yet\", \"rusage\", x);\n      return einval();\n  }\n}\n\nint XlatSocketFamily(int x) {\n  switch (x) {\n    XLAT(AF_UNSPEC_LINUX, AF_UNSPEC);\n    XLAT(AF_UNIX_LINUX, AF_UNIX);\n    XLAT(AF_INET_LINUX, AF_INET);\n    XLAT(AF_INET6_LINUX, AF_INET6);\n    default:\n      LOGF(\"%s %d not supported yet\", \"socket family\", x);\n      errno = ENOPROTOOPT;\n      return -1;\n  }\n}\n\nint UnXlatSocketFamily(int x) {\n  if (x == AF_UNSPEC) return AF_UNSPEC_LINUX;\n  if (x == AF_UNIX) return AF_UNIX_LINUX;\n  if (x == AF_INET) return AF_INET_LINUX;\n  if (x == AF_INET6) return AF_INET6_LINUX;\n  LOGF(\"don't know how to translate %s %d\", \"socket family\", x);\n  return x;\n}\n\nint XlatSocketType(int x) {\n  switch (x) {\n    XLAT(SOCK_STREAM_LINUX, SOCK_STREAM);\n    XLAT(SOCK_DGRAM_LINUX, SOCK_DGRAM);\n    XLAT(SOCK_RAW_LINUX, SOCK_RAW);\n    default:\n      LOGF(\"%s %d not supported yet\", \"socket type\", x);\n      return einval();\n  }\n}\n\nint XlatSocketProtocol(int x) {\n  switch (x) {\n    XLAT(0, 0);\n    XLAT(IPPROTO_RAW_LINUX, IPPROTO_RAW);\n    XLAT(IPPROTO_TCP_LINUX, IPPROTO_TCP);\n    XLAT(IPPROTO_UDP_LINUX, IPPROTO_UDP);\n    XLAT(IPPROTO_ICMP_LINUX, IPPROTO_ICMP);\n#ifdef IPPROTO_ICMPV6\n    XLAT(IPPROTO_ICMPV6_LINUX, IPPROTO_ICMPV6);\n#endif\n    default:\n      LOGF(\"%s %d not supported yet\", \"socket protocol\", x);\n      return einval();\n  }\n}\n\nint XlatSocketLevel(int x, int *level) {\n  // Haiku defines SOL_SOCKET as -1\n  int res;\n  switch (x) {\n    CASE(SOL_SOCKET_LINUX, res = SOL_SOCKET);\n    CASE(SOL_IP_LINUX, res = IPPROTO_IP);\n    CASE(SOL_IPV6_LINUX, res = IPPROTO_IPV6);\n    CASE(SOL_TCP_LINUX, res = IPPROTO_TCP);\n    CASE(SOL_UDP_LINUX, res = IPPROTO_UDP);\n    default:\n      LOGF(\"%s %d not supported yet\", \"socket level\", x);\n      return einval();\n  }\n  *level = res;\n  return 0;\n}\n\nint XlatSocketOptname(int level, int optname) {\n  switch (level) {\n    case SOL_SOCKET_LINUX:\n      switch (optname) {\n        XLAT(SO_TYPE_LINUX, SO_TYPE);\n        XLAT(SO_ERROR_LINUX, SO_ERROR);\n        XLAT(SO_DEBUG_LINUX, SO_DEBUG);\n        XLAT(SO_REUSEADDR_LINUX, SO_REUSEADDR);\n        XLAT(SO_DONTROUTE_LINUX, SO_DONTROUTE);\n        XLAT(SO_SNDBUF_LINUX, SO_SNDBUF);\n        XLAT(SO_RCVBUF_LINUX, SO_RCVBUF);\n        XLAT(SO_BROADCAST_LINUX, SO_BROADCAST);\n        XLAT(SO_KEEPALIVE_LINUX, SO_KEEPALIVE);\n        XLAT(SO_RCVTIMEO_LINUX, SO_RCVTIMEO);\n        XLAT(SO_SNDTIMEO_LINUX, SO_SNDTIMEO);\n        XLAT(SO_RCVLOWAT_LINUX, SO_RCVLOWAT);\n        XLAT(SO_SNDLOWAT_LINUX, SO_SNDLOWAT);\n#ifndef DISABLE_NONPOSIX\n#ifdef SO_REUSEPORT\n        XLAT(SO_REUSEPORT_LINUX, SO_REUSEPORT);\n#endif\n#endif\n        default:\n          break;\n      }\n      break;\n#ifndef DISABLE_NONPOSIX\n    case SOL_IP_LINUX:\n      switch (optname) {\n#ifdef IP_TOS\n        XLAT(IP_TOS_LINUX, IP_TOS);\n#endif\n#ifdef IP_TTL\n        XLAT(IP_TTL_LINUX, IP_TTL);\n#endif\n#ifdef IP_HDRINCL\n        XLAT(IP_HDRINCL_LINUX, IP_HDRINCL);\n#endif\n#ifdef IP_OPTIONS\n        XLAT(IP_OPTIONS_LINUX, IP_OPTIONS);\n#endif\n#ifdef IP_RECVTTL\n        XLAT(IP_RECVTTL_LINUX, IP_RECVTTL);\n#endif\n#ifdef IP_RECVERR\n        XLAT(IP_RECVERR_LINUX, IP_RECVERR);\n#endif\n#ifdef IP_RETOPTS\n        XLAT(IP_RETOPTS_LINUX, IP_RETOPTS);\n#endif\n        default:\n          break;\n      }\n      break;\n    case SOL_IPV6_LINUX:\n      switch (optname) {\n#ifdef IPV6_RECVERR\n        XLAT(IPV6_RECVERR_LINUX, IPV6_RECVERR);\n#endif\n        default:\n          break;\n      }\n      break;\n#endif /* DISABLE_NONPOSIX */\n    case SOL_TCP_LINUX:\n      switch (optname) {\n        XLAT(TCP_NODELAY_LINUX, TCP_NODELAY);\n#ifndef DISABLE_NONPOSIX\n#ifdef TCP_MAXSEG\n        XLAT(TCP_MAXSEG_LINUX, TCP_MAXSEG);\n#endif\n#if defined(TCP_CORK)\n        XLAT(TCP_CORK_LINUX, TCP_CORK);\n#elif defined(TCP_NOPUSH)\n        XLAT(TCP_NOPUSH_LINUX, TCP_NOPUSH);\n#endif\n#ifdef TCP_KEEPIDLE\n        XLAT(TCP_KEEPIDLE_LINUX, TCP_KEEPIDLE);\n#endif\n#ifdef TCP_KEEPINTVL\n        XLAT(TCP_KEEPINTVL_LINUX, TCP_KEEPINTVL);\n#endif\n#ifdef TCP_KEEPCNT\n        XLAT(TCP_KEEPCNT_LINUX, TCP_KEEPCNT);\n#endif\n#ifdef TCP_SYNCNT\n        XLAT(TCP_SYNCNT_LINUX, TCP_SYNCNT);\n#endif\n#ifdef TCP_DEFER_ACCEPT\n        XLAT(TCP_DEFER_ACCEPT_LINUX, TCP_DEFER_ACCEPT);\n#endif\n#ifdef TCP_WINDOW_CLAMP\n        XLAT(TCP_WINDOW_CLAMP_LINUX, TCP_WINDOW_CLAMP);\n#endif\n#ifdef TCP_FASTOPEN\n        XLAT(TCP_FASTOPEN_LINUX, TCP_FASTOPEN);\n#endif\n#ifdef TCP_NOTSENT_LOWAT\n        XLAT(TCP_NOTSENT_LOWAT_LINUX, TCP_NOTSENT_LOWAT);\n#endif\n#ifdef TCP_FASTOPEN_CONNECT\n        XLAT(TCP_FASTOPEN_CONNECT_LINUX, TCP_FASTOPEN_CONNECT);\n#endif\n#ifdef TCP_QUICKACK\n        XLAT(TCP_QUICKACK_LINUX, TCP_QUICKACK);\n#endif\n#ifdef TCP_SAVE_SYN\n        XLAT(TCP_SAVE_SYN_LINUX, TCP_SAVE_SYN);\n#endif\n#endif /* DISABLE_NONPOSIX */\n        default:\n          break;\n      }\n      break;\n    default:\n      break;\n  }\n  LOGF(\"socket level %d optname %d not supported yet\", level, optname);\n  return einval();\n}\n\nint XlatAccess(int x) {\n  int r = 0;\n  if (x == F_OK_LINUX) return F_OK;\n  if (x & X_OK_LINUX) r |= X_OK, x &= ~X_OK_LINUX;\n  if (x & W_OK_LINUX) r |= W_OK, x &= ~W_OK_LINUX;\n  if (x & R_OK_LINUX) r |= R_OK, x &= ~R_OK_LINUX;\n  if (x) return einval();\n  return r;\n}\n\nint XlatShutdown(int x) {\n  if (x == SHUT_RD_LINUX) return SHUT_RD;\n  if (x == SHUT_WR_LINUX) return SHUT_WR;\n  if (x == SHUT_RDWR_LINUX) return SHUT_RDWR;\n  return einval();\n}\n\nint XlatWait(int x) {\n  int r = 0;\n  if (x & WNOHANG_LINUX) {\n    r |= WNOHANG;\n    x &= ~WNOHANG_LINUX;\n  }\n  if (x & WUNTRACED_LINUX) {\n    r |= WUNTRACED;\n    x &= ~WUNTRACED_LINUX;\n  }\n#ifdef WCONTINUED\n  if (x & WCONTINUED_LINUX) {\n    r |= WCONTINUED;\n    x &= ~WCONTINUED_LINUX;\n  }\n#endif\n  if (x) {\n    LOGF(\"%s %d not supported yet\", \"wait\", x);\n    return einval();\n  }\n  return r;\n}\n\nint XlatClock(int x, clock_t *clock) {\n  // Haiku defines CLOCK_REALTIME as -1\n  clock_t res;\n  switch (x) {\n    CASE(CLOCK_REALTIME_LINUX, res = CLOCK_REALTIME);\n    CASE(CLOCK_MONOTONIC_LINUX, res = CLOCK_MONOTONIC);\n    CASE(CLOCK_PROCESS_CPUTIME_ID_LINUX, res = CLOCK_PROCESS_CPUTIME_ID);\n    CASE(CLOCK_THREAD_CPUTIME_ID_LINUX, res = CLOCK_THREAD_CPUTIME_ID);\n#ifndef DISABLE_NONPOSIX\n#ifdef CLOCK_REALTIME_COARSE\n    CASE(CLOCK_REALTIME_COARSE_LINUX, res = CLOCK_REALTIME_COARSE);\n#elif defined(CLOCK_REALTIME_FAST)\n    CASE(CLOCK_REALTIME_FAST_LINUX, res = CLOCK_REALTIME_FAST);\n#endif\n#ifdef CLOCK_MONOTONIC_COARSE\n    CASE(CLOCK_MONOTONIC_COARSE_LINUX, res = CLOCK_MONOTONIC_COARSE);\n#elif defined(CLOCK_REALTIME_FAST)\n    CASE(CLOCK_MONOTONIC_FAST_LINUX, res = CLOCK_MONOTONIC_FAST);\n#endif\n#ifdef CLOCK_MONOTONIC_RAW\n    CASE(CLOCK_MONOTONIC_RAW_LINUX, res = CLOCK_MONOTONIC_RAW);\n#endif\n#ifdef CLOCK_BOOTTIME\n    CASE(CLOCK_BOOTTIME_LINUX, res = CLOCK_BOOTTIME);\n#endif\n#ifdef CLOCK_TAI\n    CASE(CLOCK_TAI_LINUX, res = CLOCK_TAI);\n#endif\n#endif /* DISABLE_NONPOSIX */\n    default:\n      LOGF(\"%s %d not supported yet\", \"clock\", x);\n      return einval();\n  }\n  *clock = res;\n  return 0;\n}\n\nint XlatAccMode(int x) {\n  switch (x & O_ACCMODE_LINUX) {\n    case O_RDONLY_LINUX:\n      return O_RDONLY;\n    case O_WRONLY_LINUX:\n      return O_WRONLY;\n    case O_RDWR_LINUX:\n      return O_RDWR;\n    default:\n      return einval();\n  }\n}\n\nint UnXlatAccMode(int flags) {\n  switch (flags & O_ACCMODE) {\n    case O_RDONLY:\n      return O_RDONLY_LINUX;\n    case O_WRONLY:\n      return O_WRONLY_LINUX;\n    case O_RDWR:\n      return O_RDWR_LINUX;\n    default:\n      return einval();\n  }\n}\n\nint XlatOpenFlags(int x) {\n  int res;\n  res = XlatAccMode(x);\n  x &= ~O_ACCMODE_LINUX;\n  if (x & O_APPEND_LINUX) res |= O_APPEND, x &= ~O_APPEND_LINUX;\n  if (x & O_CREAT_LINUX) res |= O_CREAT, x &= ~O_CREAT_LINUX;\n  if (x & O_EXCL_LINUX) res |= O_EXCL, x &= ~O_EXCL_LINUX;\n  if (x & O_TRUNC_LINUX) res |= O_TRUNC, x &= ~O_TRUNC_LINUX;\n#ifdef O_PATH\n  if (x & O_PATH_LINUX) res |= O_PATH, x &= ~O_PATH_LINUX;\n#elif defined(O_EXEC)\n  if (x & O_PATH_LINUX) res |= O_EXEC, x &= ~O_PATH_LINUX;\n#else\n  x &= ~O_PATH_LINUX;\n#endif\n#ifdef O_LARGEFILE\n  if (x & O_LARGEFILE_LINUX) res |= O_LARGEFILE, x &= ~O_LARGEFILE_LINUX;\n#else\n  x &= ~O_LARGEFILE_LINUX;\n#endif\n#ifdef O_NDELAY\n  if (x & O_NDELAY_LINUX) res |= O_NDELAY, x &= ~O_NDELAY_LINUX;\n#endif\n#ifdef O_DIRECT\n  if (x & O_DIRECT_LINUX) res |= O_DIRECT, x &= ~O_DIRECT_LINUX;\n#endif\n#ifdef O_SYNC\n  if ((x & O_SYNC_LINUX) == O_SYNC_LINUX) {\n    res |= O_SYNC;\n    x &= ~O_SYNC_LINUX;\n  }\n  // order matters: O_DSYNC ⊂ O_SYNC\n#endif\n#ifdef O_DSYNC\n  if (x & O_DSYNC_LINUX) {\n    res |= O_DSYNC;\n    x &= ~O_DSYNC_LINUX;\n  }\n#endif\n#ifndef DISABLE_NONPOSIX\n#ifdef O_TMPFILE\n  if ((x & O_TMPFILE_LINUX) == O_TMPFILE_LINUX) {\n    res |= O_TMPFILE;\n    x &= ~O_TMPFILE_LINUX;\n  }\n  // order matters: O_DIRECTORY ⊂ O_TMPFILE\n#endif\n#endif\n  if (x & O_DIRECTORY_LINUX) {\n    res |= O_DIRECTORY;\n    x &= ~O_DIRECTORY_LINUX;\n  }\n#ifdef O_NOFOLLOW\n  if (x & O_NOFOLLOW_LINUX) res |= O_NOFOLLOW, x &= ~O_NOFOLLOW_LINUX;\n#endif\n  if (x & O_CLOEXEC_LINUX) res |= O_CLOEXEC, x &= ~O_CLOEXEC_LINUX;\n  if (x & O_NOCTTY_LINUX) res |= O_NOCTTY, x &= ~O_NOCTTY_LINUX;\n#ifndef DISABLE_NONPOSIX\n#ifdef O_ASYNC\n  if (x & O_ASYNC_LINUX) res |= O_ASYNC, x &= ~O_ASYNC_LINUX;\n#endif\n#endif\n#ifndef DISABLE_NONPOSIX\n#ifdef O_NOATIME\n  if (x & O_NOATIME_LINUX) res |= O_NOATIME, x &= ~O_NOATIME_LINUX;\n#endif\n#endif\n  if (x) {\n    LOGF(\"%s %#x not supported\", \"open flags\", x);\n    return einval();\n  }\n  return res;\n}\n\nint UnXlatOpenFlags(int x) {\n  int res;\n  res = UnXlatAccMode(x);\n  if ((x & O_APPEND) == O_APPEND) {\n    res |= O_APPEND_LINUX;\n    x &= ~O_APPEND;\n  }\n  if ((x & O_CREAT) == O_CREAT) {\n    res |= O_CREAT_LINUX;\n    x &= ~O_CREAT;\n  }\n  if ((x & O_EXCL) == O_EXCL) {\n    res |= O_EXCL_LINUX;\n    x &= ~O_EXCL;\n  }\n  if ((x & O_TRUNC) == O_TRUNC) {\n    res |= O_TRUNC_LINUX;\n    x &= ~O_TRUNC;\n  }\n#ifdef O_PATH\n  if ((x & O_PATH) == O_PATH) {\n    res |= O_PATH_LINUX;\n    x &= ~O_PATH;\n  }\n#elif defined(O_EXEC)\n  if ((x & O_EXEC) == O_EXEC) {\n    res |= O_PATH_LINUX;\n    x &= ~O_EXEC;\n  }\n#endif\n#ifdef O_LARGEFILE\n  if ((x & O_LARGEFILE) == O_LARGEFILE) {\n    res |= O_LARGEFILE_LINUX;\n    x &= ~O_LARGEFILE;\n  }\n#endif\n#ifdef O_NDELAY\n  if ((x & O_NDELAY) == O_NDELAY) {\n    res |= O_NDELAY_LINUX;\n    x &= ~O_NDELAY;\n  }\n#endif\n#ifdef O_DIRECT\n  if ((x & O_DIRECT) == O_DIRECT) {\n    res |= O_DIRECT_LINUX;\n    x &= ~O_DIRECT;\n  }\n#endif\n#ifndef DISABLE_NONPOSIX\n#ifdef O_TMPFILE\n  if ((x & O_TMPFILE) == O_TMPFILE) {\n    res |= O_TMPFILE_LINUX;\n    x &= ~O_TMPFILE;\n  }\n#endif\n#endif\n  if ((x & O_DIRECTORY) == O_DIRECTORY) {\n    res |= O_DIRECTORY_LINUX;\n    x &= ~O_DIRECTORY;\n  }\n#ifdef O_SYNC\n  if ((x & O_SYNC) == O_SYNC) {\n    res |= O_SYNC_LINUX;\n    x &= ~O_SYNC;\n  }\n#endif\n#ifdef O_NOFOLLOW\n  if ((x & O_NOFOLLOW) == O_NOFOLLOW) {\n    res |= O_NOFOLLOW_LINUX;\n    x &= ~O_NOFOLLOW;\n  }\n#endif\n  if ((x & O_CLOEXEC) == O_CLOEXEC) {\n    res |= O_CLOEXEC_LINUX;\n    x &= ~O_CLOEXEC;\n  }\n  if ((x & O_NOCTTY) == O_NOCTTY) {\n    res |= O_NOCTTY_LINUX;\n    x &= ~O_NOCTTY;\n  }\n#ifndef DISABLE_NONPOSIX\n#ifdef O_ASYNC\n  if ((x & O_ASYNC) == O_ASYNC) {\n    res |= O_ASYNC_LINUX;\n    x &= ~O_ASYNC;\n  }\n#endif\n#endif\n#ifndef DISABLE_NONPOSIX\n#ifdef O_NOATIME\n  if ((x & O_NOATIME) == O_NOATIME) {\n    res |= O_NOATIME_LINUX;\n    x &= ~O_NOATIME;\n  }\n#endif\n#endif\n#ifdef O_DSYNC\n  if ((x & O_DSYNC) == O_DSYNC) {\n    res |= O_DSYNC_LINUX;\n    x &= ~O_DSYNC;\n  }\n#endif\n  return res;\n}\n\nint UnXlatItimer(int x) {\n  switch (x) {\n    case ITIMER_REAL_LINUX:\n      return ITIMER_REAL;\n    case ITIMER_VIRTUAL_LINUX:\n      return ITIMER_VIRTUAL;\n    case ITIMER_PROF_LINUX:\n      return ITIMER_PROF;\n    default:\n      LOGF(\"%s %#x not supported\", \"itimer\", x);\n      return einval();\n  }\n}\n\nint XlatSockaddrToHost(struct sockaddr_storage *dst,\n                       const struct sockaddr_linux *src, u32 srclen) {\n  if (srclen < 2) {\n    LOGF(\"sockaddr size %d too small for %s\", (int)srclen, \"family\");\n    return einval();\n  }\n  switch (Read16(src->family)) {\n    case AF_UNSPEC_LINUX:\n      memset(dst, 0, sizeof(*dst));\n      dst->ss_family = AF_UNSPEC;\n      return sizeof(*dst);\n    case AF_UNIX_LINUX: {\n      size_t n;\n      struct sockaddr_un *dst_un;\n      const struct sockaddr_un_linux *src_un;\n      if (srclen < offsetof(struct sockaddr_un_linux, path)) {\n        LOGF(\"sockaddr size too small for %s\", \"sockaddr_un_linux\");\n        return einval();\n      }\n      dst_un = (struct sockaddr_un *)dst;\n      src_un = (const struct sockaddr_un_linux *)src;\n      n = strnlen(src_un->path,\n                  MIN(srclen - offsetof(struct sockaddr_un_linux, path),\n                      sizeof(src_un->path)));\n      if (n >= sizeof(dst_un->sun_path)) {\n        LOGF(\"sockaddr_un path too long for host\");\n        return einval();\n      }\n      memset(dst_un, 0, sizeof(*dst_un));\n      dst_un->sun_family = AF_UNIX;\n      if (n) memcpy(dst_un->sun_path, src_un->path, n);\n      dst_un->sun_path[n] = 0;\n      return sizeof(struct sockaddr_un);\n    }\n    case AF_INET_LINUX: {\n      struct sockaddr_in *dst_in;\n      const struct sockaddr_in_linux *src_in;\n      if (srclen < sizeof(struct sockaddr_in_linux)) {\n        LOGF(\"sockaddr size too small for %s\", \"sockaddr_in_linux\");\n        return einval();\n      }\n      dst_in = (struct sockaddr_in *)dst;\n      src_in = (const struct sockaddr_in_linux *)src;\n      memset(dst_in, 0, sizeof(*dst_in));\n      dst_in->sin_family = AF_INET;\n      dst_in->sin_port = src_in->port;\n      dst_in->sin_addr.s_addr = src_in->addr;\n      return sizeof(struct sockaddr_in);\n    }\n    case AF_INET6_LINUX: {\n      struct sockaddr_in6 *dst_in;\n      const struct sockaddr_in6_linux *src_in;\n      _Static_assert(sizeof(dst_in->sin6_addr) == 16, \"\");\n      _Static_assert(sizeof(src_in->addr) == 16, \"\");\n      if (srclen < sizeof(struct sockaddr_in6_linux)) {\n        LOGF(\"sockaddr size too small for %s\", \"sockaddr_in6_linux\");\n        return einval();\n      }\n      dst_in = (struct sockaddr_in6 *)dst;\n      src_in = (const struct sockaddr_in6_linux *)src;\n      memset(dst_in, 0, sizeof(*dst_in));\n      dst_in->sin6_family = AF_INET6;\n      dst_in->sin6_port = src_in->port;\n      memcpy(&dst_in->sin6_addr, src_in->addr, 16);\n      return sizeof(struct sockaddr_in6);\n    }\n    default:\n      LOGF(\"%s %d not supported yet\", \"socket family\", Read16(src->family));\n      errno = EAFNOSUPPORT;\n      return -1;\n  }\n}\n\nint XlatSockaddrToLinux(struct sockaddr_storage_linux *dst,\n                        const struct sockaddr *src, socklen_t srclen) {\n  if (srclen < 2) {\n    LOGF(\"sockaddr size %d too small for %s\", (int)srclen, \"family\");\n    return einval();\n  }\n  if (src->sa_family == AF_UNIX) {\n    size_t n;\n    struct sockaddr_un_linux *dst_un;\n    const struct sockaddr_un *src_un;\n    if (srclen < offsetof(struct sockaddr_un, sun_path)) {\n      LOGF(\"sockaddr size %d too small for %s\", (int)srclen, \"sockaddr_un\");\n      return einval();\n    }\n    dst_un = (struct sockaddr_un_linux *)dst;\n    src_un = (const struct sockaddr_un *)src;\n    n = strnlen(src_un->sun_path,\n                MIN(srclen - offsetof(struct sockaddr_un, sun_path),\n                    sizeof(src_un->sun_path)));\n    if (n >= sizeof(dst_un->path)) {\n      LOGF(\"sockaddr_un path too long for linux\");\n      return einval();\n    }\n    memset(dst_un, 0, sizeof(*dst_un));\n    Write16(dst_un->family, AF_UNIX_LINUX);\n    if (n) memcpy(dst_un->path, src_un->sun_path, n);\n    dst_un->path[n] = 0;\n    return offsetof(struct sockaddr_un, sun_path) + n + 1;\n  } else if (src->sa_family == AF_INET) {\n    struct sockaddr_in_linux *dst_in;\n    const struct sockaddr_in *src_in;\n    if (srclen < sizeof(struct sockaddr_in)) {\n      LOGF(\"sockaddr size %d too small for %s\", (int)srclen, \"sockaddr_in\");\n      return einval();\n    }\n    dst_in = (struct sockaddr_in_linux *)dst;\n    src_in = (const struct sockaddr_in *)src;\n    memset(dst_in, 0, sizeof(*dst_in));\n    Write16(dst_in->family, AF_INET_LINUX);\n    dst_in->port = src_in->sin_port;\n    dst_in->addr = src_in->sin_addr.s_addr;\n    return sizeof(struct sockaddr_in_linux);\n  } else if (src->sa_family == AF_INET6) {\n    struct sockaddr_in6_linux *dst_in;\n    const struct sockaddr_in6 *src_in;\n    if (srclen < sizeof(struct sockaddr_in6)) {\n      LOGF(\"sockaddr size %d too small for %s\", (int)srclen, \"sockaddr_in6\");\n      return einval();\n    }\n    dst_in = (struct sockaddr_in6_linux *)dst;\n    src_in = (const struct sockaddr_in6 *)src;\n    memset(dst_in, 0, sizeof(*dst_in));\n    Write16(dst_in->family, AF_INET6_LINUX);\n    dst_in->port = src_in->sin6_port;\n    memcpy(dst_in->addr, &src_in->sin6_addr, 16);\n    return sizeof(struct sockaddr_in6_linux);\n  } else {\n    LOGF(\"%s %d not supported yet\", \"socket family\", src->sa_family);\n    errno = EAFNOSUPPORT;\n    return -1;\n  }\n}\n\nvoid XlatStatToLinux(struct stat_linux *dst, const struct stat *src) {\n  Write64(dst->dev, src->st_dev);\n  Write64(dst->ino, src->st_ino);\n  Write64(dst->nlink, src->st_nlink);\n  Write32(dst->mode, src->st_mode);\n  Write32(dst->uid, src->st_uid);\n  Write32(dst->gid, src->st_gid);\n  Write32(dst->pad_, 0);\n  Write64(dst->rdev, src->st_rdev);\n  Write64(dst->size, src->st_size);\n  Write64(dst->blksize, src->st_blksize);\n  Write64(dst->blocks, src->st_blocks);\n  Write64(dst->dev, src->st_dev);\n  Write64(dst->atim.sec, src->st_atim.tv_sec);\n  Write64(dst->atim.nsec, src->st_atim.tv_nsec);\n  Write64(dst->mtim.sec, src->st_mtim.tv_sec);\n  Write64(dst->mtim.nsec, src->st_mtim.tv_nsec);\n  Write64(dst->ctim.sec, src->st_ctim.tv_sec);\n  Write64(dst->ctim.nsec, src->st_ctim.tv_nsec);\n}\n\nvoid XlatRusageToLinux(struct rusage_linux *dst, const struct rusage *src) {\n  Write64(dst->utime.sec, src->ru_utime.tv_sec);\n  Write64(dst->utime.usec, src->ru_utime.tv_usec);\n  Write64(dst->stime.sec, src->ru_stime.tv_sec);\n  Write64(dst->stime.usec, src->ru_stime.tv_usec);\n  Write64(dst->maxrss, src->ru_maxrss);\n  Write64(dst->ixrss, src->ru_ixrss);\n  Write64(dst->idrss, src->ru_idrss);\n  Write64(dst->isrss, src->ru_isrss);\n  Write64(dst->minflt, src->ru_minflt);\n  Write64(dst->majflt, src->ru_majflt);\n  Write64(dst->nswap, src->ru_nswap);\n  Write64(dst->inblock, src->ru_inblock);\n  Write64(dst->oublock, src->ru_oublock);\n  Write64(dst->msgsnd, src->ru_msgsnd);\n  Write64(dst->msgrcv, src->ru_msgrcv);\n  Write64(dst->nsignals, src->ru_nsignals);\n  Write64(dst->nvcsw, src->ru_nvcsw);\n  Write64(dst->nivcsw, src->ru_nivcsw);\n}\n\nstatic u64 XlatRlimitToLinuxScalar(u64 x) {\n  if (x == RLIM_INFINITY) x = RLIM_INFINITY_LINUX;\n  return x;\n}\n\nvoid XlatRlimitToLinux(struct rlimit_linux *dst, const struct rlimit *src) {\n  Write64(dst->cur, XlatRlimitToLinuxScalar(src->rlim_cur));\n  Write64(dst->max, XlatRlimitToLinuxScalar(src->rlim_max));\n}\n\nstatic u64 XlatLinuxToRlimitScalar(int r, u64 x) {\n  if (x == RLIM_INFINITY_LINUX) {\n    x = RLIM_INFINITY;\n  } else if (r == RLIMIT_NOFILE) {\n    x += 4;\n  } else if (r == RLIMIT_CPU ||   //\n             r == RLIMIT_DATA ||  //\n#ifdef RLIMIT_RSS\n             r == RLIMIT_RSS ||  //\n#endif\n#ifdef RLIMIT_AS\n             r == RLIMIT_AS ||  //\n#endif\n             0) {\n    x *= 10;\n  }\n  return x;\n}\n\nvoid XlatLinuxToRlimit(int sysresource, struct rlimit *dst,\n                       const struct rlimit_linux *src) {\n  dst->rlim_cur = XlatLinuxToRlimitScalar(sysresource, Read64(src->cur));\n  dst->rlim_max = XlatLinuxToRlimitScalar(sysresource, Read64(src->max));\n}\n\nvoid XlatItimervalToLinux(struct itimerval_linux *dst,\n                          const struct itimerval *src) {\n  Write64(dst->interval.sec, src->it_interval.tv_sec);\n  Write64(dst->interval.usec, src->it_interval.tv_usec);\n  Write64(dst->value.sec, src->it_value.tv_sec);\n  Write64(dst->value.usec, src->it_value.tv_usec);\n}\n\nvoid XlatLinuxToItimerval(struct itimerval *dst,\n                          const struct itimerval_linux *src) {\n  dst->it_interval.tv_sec = Read64(src->interval.sec);\n  dst->it_interval.tv_usec = Read64(src->interval.usec);\n  dst->it_value.tv_sec = Read64(src->value.sec);\n  dst->it_value.tv_usec = Read64(src->value.usec);\n}\n\nvoid XlatWinsizeToLinux(struct winsize_linux *dst, const struct winsize *src) {\n  memset(dst, 0, sizeof(*dst));\n  Write16(dst->row, src->ws_row);\n  Write16(dst->col, src->ws_col);\n}\n\nvoid XlatWinsizeToHost(struct winsize *dst, const struct winsize_linux *src) {\n  memset(dst, 0, sizeof(*dst));\n  dst->ws_row = Read16(src->row);\n  dst->ws_col = Read16(src->col);\n}\n\nvoid XlatSigsetToLinux(u8 dst[8], const sigset_t *src) {\n  u64 set = 0;\n  int syssig, linuxsig;\n  for (syssig = 1; syssig <= MIN(64, TOPSIG); ++syssig) {\n    if (sigismember(src, syssig) == 1 &&\n        (linuxsig = UnXlatSignal(syssig)) != -1) {\n      set |= (u64)1 << (linuxsig - 1);\n    }\n  }\n  Write64(dst, set);\n}\n\nvoid XlatLinuxToSigset(sigset_t *dst, u64 set) {\n  int syssig, linuxsig;\n  sigemptyset(dst);\n  for (linuxsig = 1; linuxsig <= MIN(64, TOPSIG); ++linuxsig) {\n    if ((((u64)1 << (linuxsig - 1)) & set) &&\n        (syssig = XlatSignal(linuxsig)) != -1) {\n      sigaddset(dst, syssig);\n    }\n  }\n}\n\nstatic int XlatTermiosCflag(int x) {\n  int r = 0;\n  if (x & CSTOPB_LINUX) r |= CSTOPB;\n  if (x & CREAD_LINUX) r |= CREAD;\n  if (x & PARENB_LINUX) r |= PARENB;\n  if (x & PARODD_LINUX) r |= PARODD;\n  if (x & HUPCL_LINUX) r |= HUPCL;\n  if (x & CLOCAL_LINUX) r |= CLOCAL;\n  if ((x & CSIZE_LINUX) == CS5_LINUX) {\n    r |= CS5;\n  } else if ((x & CSIZE_LINUX) == CS6_LINUX) {\n    r |= CS6;\n  } else if ((x & CSIZE_LINUX) == CS7_LINUX) {\n    r |= CS7;\n  } else if ((x & CSIZE_LINUX) == CS8_LINUX) {\n    r |= CS8;\n  }\n  return r;\n}\n\nstatic int UnXlatTermiosCflag(int x) {\n  int r = 0;\n  if (x & CSTOPB) r |= CSTOPB_LINUX;\n  if (x & CREAD) r |= CREAD_LINUX;\n  if (x & PARENB) r |= PARENB_LINUX;\n  if (x & PARODD) r |= PARODD_LINUX;\n  if (x & HUPCL) r |= HUPCL_LINUX;\n  if (x & CLOCAL) r |= CLOCAL_LINUX;\n  if ((x & CSIZE) == CS5) {\n    r |= CS5_LINUX;\n  } else if ((x & CSIZE) == CS6) {\n    r |= CS6_LINUX;\n  } else if ((x & CSIZE) == CS7) {\n    r |= CS7_LINUX;\n  } else if ((x & CSIZE) == CS8) {\n    r |= CS8_LINUX;\n  }\n  return r;\n}\n\nstatic int XlatTermiosLflag(int x) {\n  int r = 0;\n  if (x & ISIG_LINUX) r |= ISIG;\n  if (x & ICANON_LINUX) r |= ICANON;\n  if (x & ECHO_LINUX) r |= ECHO;\n  if (x & ECHOE_LINUX) r |= ECHOE;\n  if (x & ECHOK_LINUX) r |= ECHOK;\n  if (x & ECHONL_LINUX) r |= ECHONL;\n  if (x & NOFLSH_LINUX) r |= NOFLSH;\n  if (x & TOSTOP_LINUX) r |= TOSTOP;\n  if (x & IEXTEN_LINUX) r |= IEXTEN;\n#ifdef ECHOCTL\n  if (x & ECHOCTL_LINUX) r |= ECHOCTL;\n#endif\n#ifdef ECHOPRT\n  if (x & ECHOPRT_LINUX) r |= ECHOPRT;\n#endif\n#ifdef ECHOKE\n  if (x & ECHOKE_LINUX) r |= ECHOKE;\n#endif\n#ifdef FLUSHO\n  if (x & FLUSHO_LINUX) r |= FLUSHO;\n#endif\n#ifdef PENDIN\n  if (x & PENDIN_LINUX) r |= PENDIN;\n#endif\n#ifdef XCASE\n  if (x & XCASE_LINUX) r |= XCASE;\n#endif\n  return r;\n}\n\nstatic int UnXlatTermiosLflag(int x) {\n  int r = 0;\n  if (x & ISIG) r |= ISIG_LINUX;\n  if (x & ICANON) r |= ICANON_LINUX;\n  if (x & ECHO) r |= ECHO_LINUX;\n  if (x & ECHOE) r |= ECHOE_LINUX;\n  if (x & ECHOK) r |= ECHOK_LINUX;\n  if (x & ECHONL) r |= ECHONL_LINUX;\n  if (x & NOFLSH) r |= NOFLSH_LINUX;\n  if (x & TOSTOP) r |= TOSTOP_LINUX;\n  if (x & IEXTEN) r |= IEXTEN_LINUX;\n#ifdef ECHOCTL\n  if (x & ECHOCTL) r |= ECHOCTL_LINUX;\n#endif\n#ifdef ECHOPRT\n  if (x & ECHOPRT) r |= ECHOPRT_LINUX;\n#endif\n#ifdef ECHOKE\n  if (x & ECHOKE) r |= ECHOKE_LINUX;\n#endif\n#ifdef FLUSHO\n  if (x & FLUSHO) r |= FLUSHO_LINUX;\n#endif\n#ifdef PENDIN\n  if (x & PENDIN) r |= PENDIN_LINUX;\n#endif\n#ifdef XCASE\n  if (x & XCASE) r |= XCASE_LINUX;\n#endif\n  return r;\n}\n\nstatic int XlatTermiosIflag(int x) {\n  int r = 0;\n  if (x & IGNBRK_LINUX) r |= IGNBRK;\n  if (x & BRKINT_LINUX) r |= BRKINT;\n  if (x & IGNPAR_LINUX) r |= IGNPAR;\n  if (x & PARMRK_LINUX) r |= PARMRK;\n  if (x & INPCK_LINUX) r |= INPCK;\n  if (x & ISTRIP_LINUX) r |= ISTRIP;\n  if (x & INLCR_LINUX) r |= INLCR;\n  if (x & IGNCR_LINUX) r |= IGNCR;\n  if (x & ICRNL_LINUX) r |= ICRNL;\n  if (x & IXON_LINUX) r |= IXON;\n#ifdef IXANY\n  if (x & IXANY_LINUX) r |= IXANY;\n#endif\n  if (x & IXOFF_LINUX) r |= IXOFF;\n#ifdef IMAXBEL\n  if (x & IMAXBEL_LINUX) r |= IMAXBEL;\n#endif\n#ifdef IUTF8\n  if (x & IUTF8_LINUX) r |= IUTF8;\n#endif\n#ifdef IUCLC\n  if (x & IUCLC_LINUX) r |= IUCLC;\n#endif\n  return r;\n}\n\nstatic int UnXlatTermiosIflag(int x) {\n  int r = 0;\n  if (x & IGNBRK) r |= IGNBRK_LINUX;\n  if (x & BRKINT) r |= BRKINT_LINUX;\n  if (x & IGNPAR) r |= IGNPAR_LINUX;\n  if (x & PARMRK) r |= PARMRK_LINUX;\n  if (x & INPCK) r |= INPCK_LINUX;\n  if (x & ISTRIP) r |= ISTRIP_LINUX;\n  if (x & INLCR) r |= INLCR_LINUX;\n  if (x & IGNCR) r |= IGNCR_LINUX;\n  if (x & ICRNL) r |= ICRNL_LINUX;\n  if (x & IXON) r |= IXON_LINUX;\n#ifdef IXANY\n  if (x & IXANY) r |= IXANY_LINUX;\n#endif\n  if (x & IXOFF) r |= IXOFF_LINUX;\n#ifdef IMAXBEL\n  if (x & IMAXBEL) r |= IMAXBEL_LINUX;\n#endif\n#ifdef IUTF8\n  if (x & IUTF8) r |= IUTF8_LINUX;\n#endif\n#ifdef IUCLC\n  if (x & IUCLC) r |= IUCLC_LINUX;\n#endif\n  return r;\n}\n\nstatic int XlatTermiosOflag(int x) {\n  int r = 0;\n  if (x & OPOST_LINUX) r |= OPOST;\n#ifdef ONLCR\n  if (x & ONLCR_LINUX) r |= ONLCR;\n#endif\n#ifdef OCRNL\n  if (x & OCRNL_LINUX) r |= OCRNL;\n#endif\n#ifdef ONOCR\n  if (x & ONOCR_LINUX) r |= ONOCR;\n#endif\n#ifdef ONLRET\n  if (x & ONLRET_LINUX) r |= ONLRET;\n#endif\n#ifdef OFILL\n  if (x & OFILL_LINUX) r |= OFILL;\n#endif\n#ifdef OFDEL\n  if (x & OFDEL_LINUX) r |= OFDEL;\n#endif\n#ifdef NLDLY\n  if ((x & NLDLY_LINUX) == NL0_LINUX) {\n    r |= NL0;\n  } else if ((x & NLDLY_LINUX) == NL1_LINUX) {\n    r |= NL1;\n  }\n#endif\n#ifdef CRDLY\n  if ((x & CRDLY_LINUX) == CR0_LINUX) {\n    r |= CR0;\n  } else if ((x & CRDLY_LINUX) == CR1_LINUX) {\n    r |= CR1;\n  } else if ((x & CRDLY_LINUX) == CR2_LINUX) {\n    r |= CR2;\n  } else if ((x & CRDLY_LINUX) == CR3_LINUX) {\n    r |= CR3;\n  }\n#endif\n#ifdef TABDLY\n  if ((x & TABDLY_LINUX) == TAB0_LINUX) {\n    r |= TAB0;\n#ifdef TAB1\n  } else if ((x & TABDLY_LINUX) == TAB1_LINUX) {\n    r |= TAB1;\n#endif\n#ifdef TAB1\n  } else if ((x & TABDLY_LINUX) == TAB2_LINUX) {\n    r |= TAB2;\n#endif\n  } else if ((x & TABDLY_LINUX) == TAB3_LINUX) {\n    r |= TAB3;\n  }\n#endif\n#ifdef BSDLY\n  if ((x & BSDLY_LINUX) == BS0_LINUX) {\n    r |= BS0;\n  } else if ((x & BSDLY_LINUX) == BS1_LINUX) {\n    r |= BS1;\n  }\n#endif\n#ifdef VTBDLY\n  if ((x & VTDLY_LINUX) == VT0_LINUX) {\n    r |= VT0;\n  } else if ((x & VTDLY_LINUX) == VT1_LINUX) {\n    r |= VT1;\n  }\n#endif\n#ifdef FFBDLY\n  if ((x & FFDLY_LINUX) == FF0_LINUX) {\n    r |= FF0;\n  } else if ((x & FFDLY_LINUX) == FF1_LINUX) {\n    r |= FF1;\n  }\n#endif\n#ifdef OLCUC\n  if (x & 0x0002) r |= OLCUC;\n#endif\n  return r;\n}\n\nstatic int UnXlatTermiosOflag(int x) {\n  int r = 0;\n  if (x & OPOST) r |= OPOST_LINUX;\n#ifdef ONLCR\n  if (x & ONLCR) r |= ONLCR_LINUX;\n#endif\n#ifdef OCRNL\n  if (x & OCRNL) r |= OCRNL_LINUX;\n#endif\n#ifdef ONOCR\n  if (x & ONOCR) r |= ONOCR_LINUX;\n#endif\n#ifdef ONLRET\n  if (x & ONLRET) r |= ONLRET_LINUX;\n#endif\n#ifdef OFILL\n  if (x & OFILL) r |= OFILL_LINUX;\n#endif\n#ifdef OFDEL\n  if (x & OFDEL) r |= OFDEL_LINUX;\n#endif\n#ifdef NLDLY\n  if ((x & NLDLY) == NL0) {\n    r |= NL0_LINUX;\n  } else if ((x & NLDLY) == NL1) {\n    r |= NL1_LINUX;\n#ifdef NL2\n  } else if ((x & NLDLY) == NL2) {\n    r |= 0x0000;  // ???\n#endif\n#ifdef NL3\n  } else if ((x & NLDLY) == NL3) {\n    r |= 0x0000;  // ???\n#endif\n  }\n#endif\n#ifdef CRDLY\n  if ((x & CRDLY) == CR0) {\n    r |= CR0_LINUX;\n  } else if ((x & CRDLY) == CR1) {\n    r |= CR1_LINUX;\n  } else if ((x & CRDLY) == CR2) {\n    r |= CR2_LINUX;\n  } else if ((x & CRDLY) == CR3) {\n    r |= CR3_LINUX;\n  }\n#endif\n#ifdef TABDLY\n  if ((x & TABDLY) == TAB0) {\n    r |= TAB0_LINUX;\n#ifdef TAB1\n  } else if ((x & TABDLY) == TAB1) {\n    r |= TAB1_LINUX;\n#endif\n#ifdef TAB2\n  } else if ((x & TABDLY) == TAB2) {\n    r |= TAB2_LINUX;\n#endif\n  } else if ((x & TABDLY) == TAB3) {\n    r |= TAB3_LINUX;\n  }\n#endif\n#ifdef BSDLY\n  if ((x & BSDLY) == BS0) {\n    r |= BS0_LINUX;\n  } else if ((x & BSDLY) == BS1) {\n    r |= BS1_LINUX;\n  }\n#endif\n#ifdef VTDLY\n  if ((x & VTDLY) == VT0) {\n    r |= VT0_LINUX;\n  } else if ((x & VTDLY) == VT1) {\n    r |= VT1_LINUX;\n  }\n#endif\n#ifdef FFDLY\n  if ((x & FFDLY) == FF0) {\n    r |= FF0_LINUX;\n  } else if ((x & FFDLY) == FF1) {\n    r |= FF1_LINUX;\n  }\n#endif\n#ifdef OLCUC\n  if (x & OLCUC) r |= OLCUC_LINUX;\n#endif\n  return r;\n}\n\nstatic void XlatTermiosCc(struct termios *dst,\n                          const struct termios_linux *src) {\n  dst->c_cc[VINTR] = src->cc[VINTR_LINUX];\n  dst->c_cc[VQUIT] = src->cc[VQUIT_LINUX];\n  dst->c_cc[VERASE] = src->cc[VERASE_LINUX];\n  dst->c_cc[VKILL] = src->cc[VKILL_LINUX];\n  dst->c_cc[VEOF] = src->cc[VEOF_LINUX];\n  dst->c_cc[VTIME] = src->cc[VTIME_LINUX];\n  dst->c_cc[VMIN] = src->cc[VMIN_LINUX];\n  dst->c_cc[VSTART] = src->cc[VSTART_LINUX];\n  dst->c_cc[VSTOP] = src->cc[VSTOP_LINUX];\n  dst->c_cc[VSUSP] = src->cc[VSUSP_LINUX];\n  dst->c_cc[VEOL] = src->cc[VEOL_LINUX];\n#ifdef VSWTC\n  dst->c_cc[VSWTC] = src->cc[VSWTC_LINUX];\n#endif\n#ifdef VREPRINT\n  dst->c_cc[VREPRINT] = src->cc[VREPRINT_LINUX];\n#endif\n#ifdef VDISCARD\n  dst->c_cc[VDISCARD] = src->cc[VDISCARD_LINUX];\n#endif\n#ifdef VWERASE\n  dst->c_cc[VWERASE] = src->cc[VWERASE_LINUX];\n#endif\n#ifdef VLNEXT\n  dst->c_cc[VLNEXT] = src->cc[VLNEXT_LINUX];\n#endif\n#ifdef VEOL2\n  dst->c_cc[VEOL2] = src->cc[VEOL2_LINUX];\n#endif\n}\n\nstatic void UnXlatTermiosCc(struct termios_linux *dst,\n                            const struct termios *src) {\n  dst->cc[VINTR_LINUX] = src->c_cc[VINTR];\n  dst->cc[VQUIT_LINUX] = src->c_cc[VQUIT];\n  dst->cc[VERASE_LINUX] = src->c_cc[VERASE];\n  dst->cc[VKILL_LINUX] = src->c_cc[VKILL];\n  dst->cc[VEOF_LINUX] = src->c_cc[VEOF];\n  dst->cc[VTIME_LINUX] = src->c_cc[VTIME];\n  dst->cc[VMIN_LINUX] = src->c_cc[VMIN];\n  dst->cc[VSTART_LINUX] = src->c_cc[VSTART];\n  dst->cc[VSTOP_LINUX] = src->c_cc[VSTOP];\n  dst->cc[VSUSP_LINUX] = src->c_cc[VSUSP];\n  dst->cc[VEOL_LINUX] = src->c_cc[VEOL];\n#ifdef VSWTC\n  dst->cc[VSWTC_LINUX] = src->c_cc[VSWTC];\n#endif\n#ifdef VREPRINT\n  dst->cc[VREPRINT_LINUX] = src->c_cc[VREPRINT];\n#endif\n#ifdef VDISCARD\n  dst->cc[VDISCARD_LINUX] = src->c_cc[VDISCARD];\n#endif\n#ifdef VWERASE\n  dst->cc[VWERASE_LINUX] = src->c_cc[VWERASE];\n#endif\n#ifdef VLNEXT\n  dst->cc[VLNEXT_LINUX] = src->c_cc[VLNEXT];\n#endif\n#ifdef VEOL2\n  dst->cc[VEOL2_LINUX] = src->c_cc[VEOL2];\n#endif\n}\n\nvoid XlatLinuxToTermios(struct termios *dst, const struct termios_linux *src) {\n  speed_t speed;\n  memset(dst, 0, sizeof(*dst));\n  dst->c_iflag = XlatTermiosIflag(Read32(src->iflag));\n  dst->c_oflag = XlatTermiosOflag(Read32(src->oflag));\n  dst->c_cflag = XlatTermiosCflag(Read32(src->cflag));\n  dst->c_lflag = XlatTermiosLflag(Read32(src->lflag));\n  switch (Read32(src->cflag) & CBAUD_LINUX) {\n    case B0_LINUX:\n      speed = B0;\n      break;\n    case B50_LINUX:\n      speed = B50;\n      break;\n    case B75_LINUX:\n      speed = B75;\n      break;\n    case B110_LINUX:\n      speed = B110;\n      break;\n    case B134_LINUX:\n      speed = B134;\n      break;\n    case B150_LINUX:\n      speed = B150;\n      break;\n    case B200_LINUX:\n      speed = B200;\n      break;\n    case B300_LINUX:\n      speed = B300;\n      break;\n    case B600_LINUX:\n      speed = B600;\n      break;\n    case B1200_LINUX:\n      speed = B1200;\n      break;\n    case B1800_LINUX:\n      speed = B1800;\n      break;\n    case B2400_LINUX:\n      speed = B2400;\n      break;\n    case B4800_LINUX:\n      speed = B4800;\n      break;\n    case B9600_LINUX:\n      speed = B9600;\n      break;\n    case B19200_LINUX:\n      speed = B19200;\n      break;\n    case B38400_LINUX:\n      speed = B38400;\n      break;\n#ifdef B57600\n    case B57600_LINUX:\n      speed = B57600;\n      break;\n#endif\n#ifdef B115200\n    case B115200_LINUX:\n      speed = B115200;\n      break;\n#endif\n#ifdef B230400\n    case B230400_LINUX:\n      speed = B230400;\n      break;\n#endif\n#ifdef B460800\n    case B460800_LINUX:\n      speed = B460800;\n      break;\n#endif\n#ifdef B500000\n    case B500000_LINUX:\n      speed = B500000;\n      break;\n#endif\n#ifdef B576000\n    case B576000_LINUX:\n      speed = B576000;\n      break;\n#endif\n#ifdef B921600\n    case B921600_LINUX:\n      speed = B921600;\n      break;\n#endif\n#ifdef B1000000\n    case B1000000_LINUX:\n      speed = B1000000;\n      break;\n#endif\n#ifdef B1152000\n    case B1152000_LINUX:\n      speed = B1152000;\n      break;\n#endif\n#ifdef B1500000\n    case B1500000_LINUX:\n      speed = B1500000;\n      break;\n#endif\n#ifdef B2000000\n    case B2000000_LINUX:\n      speed = B2000000;\n      break;\n#endif\n#ifdef B2500000\n    case B2500000_LINUX:\n      speed = B2500000;\n      break;\n#endif\n#ifdef B3000000\n    case B3000000_LINUX:\n      speed = B3000000;\n      break;\n#endif\n#ifdef B3500000\n    case B3500000_LINUX:\n      speed = B3500000;\n      break;\n#endif\n#ifdef B4000000\n    case B4000000_LINUX:\n      speed = B4000000;\n      break;\n#endif\n    default:\n      LOGF(\"unknown baud rate: %#x\", Read32(src->cflag) & CBAUD_LINUX);\n      speed = B38400;\n      break;\n  }\n  cfsetispeed(dst, speed);\n  cfsetospeed(dst, speed);\n  XlatTermiosCc(dst, src);\n}\n\nvoid XlatTermiosToLinux(struct termios_linux *dst, const struct termios *src) {\n  int speed;\n  speed_t srcspeed;\n  memset(dst, 0, sizeof(*dst));\n  Write32(dst->iflag, UnXlatTermiosIflag(src->c_iflag));\n  Write32(dst->oflag, UnXlatTermiosOflag(src->c_oflag));\n  Write32(dst->cflag, UnXlatTermiosCflag(src->c_cflag));\n  Write32(dst->lflag, UnXlatTermiosLflag(src->c_lflag));\n  if ((srcspeed = cfgetospeed(src)) != (speed_t)-1) {\n    if (srcspeed == B0) {\n      speed = B0_LINUX;\n    } else if (srcspeed == B50) {\n      speed = B50_LINUX;\n    } else if (srcspeed == B75) {\n      speed = B75_LINUX;\n    } else if (srcspeed == B110) {\n      speed = B110_LINUX;\n    } else if (srcspeed == B134) {\n      speed = B134_LINUX;\n    } else if (srcspeed == B150) {\n      speed = B150_LINUX;\n    } else if (srcspeed == B200) {\n      speed = B200_LINUX;\n    } else if (srcspeed == B300) {\n      speed = B300_LINUX;\n    } else if (srcspeed == B600) {\n      speed = B600_LINUX;\n    } else if (srcspeed == B1200) {\n      speed = B1200_LINUX;\n    } else if (srcspeed == B1800) {\n      speed = B1800_LINUX;\n    } else if (srcspeed == B2400) {\n      speed = B2400_LINUX;\n    } else if (srcspeed == B4800) {\n      speed = B4800_LINUX;\n    } else if (srcspeed == B9600) {\n      speed = B9600_LINUX;\n    } else if (srcspeed == B19200) {\n      speed = B19200_LINUX;\n    } else if (srcspeed == B38400) {\n      speed = B38400_LINUX;\n#ifdef B57600\n    } else if (srcspeed == B57600) {\n      speed = B57600_LINUX;\n#endif\n#ifdef B115200\n    } else if (srcspeed == B115200) {\n      speed = B115200_LINUX;\n#endif\n#ifdef B230400\n    } else if (srcspeed == B230400) {\n      speed = B230400_LINUX;\n#endif\n#ifdef B460800\n    } else if (srcspeed == B460800) {\n      speed = B460800_LINUX;\n#endif\n#ifdef B500000\n    } else if (srcspeed == B500000) {\n      speed = B500000_LINUX;\n#endif\n#ifdef B576000\n    } else if (srcspeed == B576000) {\n      speed = B576000_LINUX;\n#endif\n#ifdef B921600\n    } else if (srcspeed == B921600) {\n      speed = B921600_LINUX;\n#endif\n#ifdef B1000000\n    } else if (srcspeed == B1000000) {\n      speed = B1000000_LINUX;\n#endif\n#ifdef B1152000\n    } else if (srcspeed == B1152000) {\n      speed = B1152000_LINUX;\n#endif\n#ifdef B1500000\n    } else if (srcspeed == B1500000) {\n      speed = B1500000_LINUX;\n#endif\n#ifdef B2000000\n    } else if (srcspeed == B2000000) {\n      speed = B2000000_LINUX;\n#endif\n#ifdef B2500000\n    } else if (srcspeed == B2500000) {\n      speed = B2500000_LINUX;\n#endif\n#ifdef B3000000\n    } else if (srcspeed == B3000000) {\n      speed = B3000000_LINUX;\n#endif\n#ifdef B3500000\n    } else if (srcspeed == B3500000) {\n      speed = B3500000_LINUX;\n#endif\n#ifdef B4000000\n    } else if (srcspeed == B4000000) {\n      speed = B4000000_LINUX;\n#endif\n    } else {\n      LOGF(\"unrecognized baud rate: %ld\", (long)srcspeed);\n      speed = B38400;\n    }\n  } else {\n    LOGF(\"failed to get baud rate: %s\", DescribeHostErrno(errno));\n    speed = B38400;\n  }\n  Write32(dst->cflag, (Read32(dst->cflag) & ~CBAUD_LINUX) | speed);\n  UnXlatTermiosCc(dst, src);\n}\n\nint XlatWhence(int x) {\n  switch (x) {\n    XLAT(SEEK_SET_LINUX, SEEK_SET);\n    XLAT(SEEK_CUR_LINUX, SEEK_CUR);\n    XLAT(SEEK_END_LINUX, SEEK_END);\n    default:\n      LOGF(\"unrecognized whence: %d\", x);\n      return einval();\n  }\n}\n"
  },
  {
    "path": "blink/xlat.h",
    "content": "#ifndef BLINK_XLAT_H_\n#define BLINK_XLAT_H_\n#include <netinet/in.h>\n#include <signal.h>\n#include <sys/ioctl.h>\n#include <sys/resource.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/statvfs.h>\n#include <sys/time.h>\n#include <termios.h>\n\n#include \"blink/linux.h\"\n\nint UnXlatSiCode(int, int);\nint UnXlatOpenFlags(int);\nint UnXlatAccMode(int);\nint UnXlatSignal(int);\nint UnXlatItimer(int);\nint XlatAccess(int);\nint XlatClock(int, clock_t *);\nint XlatErrno(int);\nint XlatOpenFlags(int);\nint XlatAccMode(int);\nint XlatResource(int);\nint XlatRusage(int);\nint XlatShutdown(int);\nint XlatSignal(int);\nint XlatSocketFamily(int);\nint XlatSocketLevel(int, int *);\nint XlatSocketOptname(int, int);\nint XlatSocketProtocol(int);\nint XlatSocketType(int);\nint XlatWait(int);\nint XlatWhence(int);\n\nint XlatSockaddrToHost(struct sockaddr_storage *, const struct sockaddr_linux *,\n                       u32);\nint XlatSockaddrToLinux(struct sockaddr_storage_linux *,\n                        const struct sockaddr *, socklen_t);\nvoid XlatStatToLinux(struct stat_linux *, const struct stat *);\nvoid XlatRusageToLinux(struct rusage_linux *, const struct rusage *);\nvoid XlatItimervalToLinux(struct itimerval_linux *, const struct itimerval *);\nvoid XlatLinuxToItimerval(struct itimerval *, const struct itimerval_linux *);\nvoid XlatLinuxToTermios(struct termios *, const struct termios_linux *);\nvoid XlatTermiosToLinux(struct termios_linux *, const struct termios *);\nvoid XlatWinsizeToLinux(struct winsize_linux *, const struct winsize *);\nvoid XlatWinsizeToHost(struct winsize *, const struct winsize_linux *);\nvoid XlatSigsetToLinux(u8[8], const sigset_t *);\nvoid XlatLinuxToSigset(sigset_t *, u64);\nvoid XlatRlimitToLinux(struct rlimit_linux *, const struct rlimit *);\nvoid XlatLinuxToRlimit(int, struct rlimit *, const struct rlimit_linux *);\n\n#endif /* BLINK_XLAT_H_ */\n"
  },
  {
    "path": "blink/xmm.h",
    "content": "#ifndef BLINK_XMM_H_\n#define BLINK_XMM_H_\n#include \"blink/builtin.h\"\n#include \"blink/types.h\"\n\n#ifdef __CYGWIN__\n#define XMM_TYPE           void\n#define RETURN_XMM(ax, dx) asm volatile(\"\" : : \"a\"(ax), \"d\"(dx))\n#else\nstruct Xmm {\n  u64 lo;\n  u64 hi;\n};\n#define XMM_TYPE struct Xmm\n#define RETURN_XMM(ax, dx) \\\n  return (struct Xmm) {    \\\n    ax, dx                 \\\n  }\n#endif\n\n#endif /* BLINK_XMM_H_ */\n"
  },
  {
    "path": "blink/xmmtype.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/xmmtype.h\"\n\n#include \"blink/rde.h\"\n\nstatic void UpdateXmmTypes(u64 rde, struct XmmType *xt, int regtype,\n                           int rmtype) {\n  xt->type[RexrReg(rde)] = regtype;\n  if (IsModrmRegister(rde)) {\n    xt->type[RexbRm(rde)] = rmtype;\n  }\n}\n\nstatic void UpdateXmmSizes(u64 rde, struct XmmType *xt, int regsize,\n                           int rmsize) {\n  xt->size[RexrReg(rde)] = regsize;\n  if (IsModrmRegister(rde)) {\n    xt->size[RexbRm(rde)] = rmsize;\n  }\n}\n\nvoid UpdateXmmType(u64 rde, struct XmmType *xt) {\n  switch (Mopcode(rde)) {\n    case 0x110:\n    case 0x111: /* MOVSS,MOVSD */\n      if (Rep(rde) == 3) {\n        UpdateXmmTypes(rde, xt, kXmmFloat, kXmmFloat);\n      } else if (Rep(rde) == 2) {\n        UpdateXmmTypes(rde, xt, kXmmDouble, kXmmDouble);\n      }\n      break;\n    case 0x12E: /* UCOMIS */\n    case 0x12F: /* COMIS */\n    case 0x151: /* SQRT */\n    case 0x152: /* RSQRT */\n    case 0x153: /* RCP */\n    case 0x158: /* ADD */\n    case 0x159: /* MUL */\n    case 0x15C: /* SUB */\n    case 0x15D: /* MIN */\n    case 0x15E: /* DIV */\n    case 0x15F: /* MAX */\n    case 0x1C2: /* CMP */\n      if (Osz(rde) || Rep(rde) == 2) {\n        UpdateXmmTypes(rde, xt, kXmmDouble, kXmmDouble);\n      } else {\n        UpdateXmmTypes(rde, xt, kXmmFloat, kXmmFloat);\n      }\n      break;\n    case 0x12A: /* CVTPI2PS,CVTSI2SS,CVTPI2PD,CVTSI2SD */\n      if (Osz(rde) || Rep(rde) == 2) {\n        UpdateXmmSizes(rde, xt, 8, 4);\n        UpdateXmmTypes(rde, xt, kXmmDouble, kXmmIntegral);\n      } else {\n        UpdateXmmSizes(rde, xt, 4, 4);\n        UpdateXmmTypes(rde, xt, kXmmFloat, kXmmIntegral);\n      }\n      break;\n    case 0x15A: /* CVT{P,S}{S,D}2{P,S}{S,D} */\n      if (Osz(rde) || Rep(rde) == 2) {\n        UpdateXmmTypes(rde, xt, kXmmFloat, kXmmDouble);\n      } else {\n        UpdateXmmTypes(rde, xt, kXmmDouble, kXmmFloat);\n      }\n      break;\n    case 0x15B: /* CVT{,T}{DQ,PS}2{PS,DQ} */\n      UpdateXmmSizes(rde, xt, 4, 4);\n      if (Osz(rde) || Rep(rde) == 3) {\n        UpdateXmmTypes(rde, xt, kXmmIntegral, kXmmFloat);\n      } else {\n        UpdateXmmTypes(rde, xt, kXmmFloat, kXmmIntegral);\n      }\n      break;\n    case 0x17C: /* HADD */\n    case 0x17D: /* HSUB */\n    case 0x1D0: /* ADDSUB */\n      if (Osz(rde)) {\n        UpdateXmmTypes(rde, xt, kXmmDouble, kXmmDouble);\n      } else {\n        UpdateXmmTypes(rde, xt, kXmmFloat, kXmmFloat);\n      }\n      break;\n    case 0x164: /* PCMPGTB */\n    case 0x174: /* PCMPEQB */\n    case 0x1D8: /* PSUBUSB */\n    case 0x1DA: /* PMINUB */\n    case 0x1DC: /* PADDUSB */\n    case 0x1DE: /* PMAXUB */\n    case 0x1E0: /* PAVGB */\n    case 0x1E8: /* PSUBSB */\n    case 0x1EC: /* PADDSB */\n    case 0x1F8: /* PSUBB */\n    case 0x1FC: /* PADDB */\n      UpdateXmmSizes(rde, xt, 1, 1);\n      UpdateXmmTypes(rde, xt, kXmmIntegral, kXmmIntegral);\n      break;\n    case 0x165: /* PCMPGTW */\n    case 0x175: /* PCMPEQW */\n    case 0x171: /* PSRLW,PSRAW,PSLLW */\n    case 0x1D1: /* PSRLW */\n    case 0x1D5: /* PMULLW */\n    case 0x1D9: /* PSUBUSW */\n    case 0x1DD: /* PADDUSW */\n    case 0x1E1: /* PSRAW */\n    case 0x1E3: /* PAVGW */\n    case 0x1E4: /* PMULHUW */\n    case 0x1E5: /* PMULHW */\n    case 0x1E9: /* PSUBSW */\n    case 0x1EA: /* PMINSW */\n    case 0x1ED: /* PADDSW */\n    case 0x1EE: /* PMAXSW */\n    case 0x1F1: /* PSLLW */\n    case 0x1F6: /* PSADBW */\n    case 0x1F9: /* PSUBW */\n    case 0x1FD: /* PADDW */\n      UpdateXmmSizes(rde, xt, 2, 2);\n      UpdateXmmTypes(rde, xt, kXmmIntegral, kXmmIntegral);\n      break;\n    case 0x166: /* PCMPGTD */\n    case 0x176: /* PCMPEQD */\n    case 0x172: /* PSRLD,PSRAD,PSLLD */\n    case 0x1D2: /* PSRLD */\n    case 0x1E2: /* PSRAD */\n    case 0x1F2: /* PSLLD */\n    case 0x1FA: /* PSUBD */\n    case 0x1FE: /* PADDD */\n      UpdateXmmSizes(rde, xt, 4, 4);\n      UpdateXmmTypes(rde, xt, kXmmIntegral, kXmmIntegral);\n      break;\n    case 0x173: /* PSRLQ,PSRLQ,PSRLDQ,PSLLQ,PSLLDQ */\n    case 0x1D3: /* PSRLQ */\n    case 0x1D4: /* PADDQ */\n    case 0x1F3: /* PSLLQ */\n    case 0x1F4: /* PMULUDQ */\n    case 0x1FB: /* PSUBQ */\n      UpdateXmmSizes(rde, xt, 8, 8);\n      UpdateXmmTypes(rde, xt, kXmmIntegral, kXmmIntegral);\n      break;\n    case 0x16B: /* PACKSSDW */\n    case 0x1F5: /* PMADDWD */\n      UpdateXmmSizes(rde, xt, 4, 2);\n      UpdateXmmTypes(rde, xt, kXmmIntegral, kXmmIntegral);\n      break;\n    case 0x163: /* PACKSSWB */\n    case 0x167: /* PACKUSWB */\n      UpdateXmmSizes(rde, xt, 1, 2);\n      UpdateXmmTypes(rde, xt, kXmmIntegral, kXmmIntegral);\n      break;\n    case 0x128: /* MOVAPS Vps Wps */\n      if (IsModrmRegister(rde)) {\n        xt->type[RexrReg(rde)] = xt->type[RexbRm(rde)];\n        xt->size[RexrReg(rde)] = xt->size[RexbRm(rde)];\n      }\n      break;\n    case 0x129: /* MOVAPS Wps Vps */\n      if (IsModrmRegister(rde)) {\n        xt->type[RexbRm(rde)] = xt->type[RexrReg(rde)];\n        xt->size[RexbRm(rde)] = xt->size[RexrReg(rde)];\n      }\n      break;\n    case 0x16F: /* MOVDQA Vdq Wdq */\n      if (Osz(rde) && IsModrmRegister(rde)) {\n        xt->type[RexrReg(rde)] = xt->type[RexbRm(rde)];\n        xt->size[RexrReg(rde)] = xt->size[RexbRm(rde)];\n      }\n      break;\n    default:\n      return;\n  }\n}\n"
  },
  {
    "path": "blink/xmmtype.h",
    "content": "#ifndef BLINK_XMMTYPE_H_\n#define BLINK_XMMTYPE_H_\n#include \"blink/machine.h\"\n\n#define kXmmIntegral 0\n#define kXmmDouble   1\n#define kXmmFloat    2\n\nstruct XmmType {\n  u8 type[16];\n  u8 size[16];\n};\n\nvoid UpdateXmmType(u64, struct XmmType *);\n\n#endif /* BLINK_XMMTYPE_H_ */\n"
  },
  {
    "path": "blink/xnu.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/machine.h\"\n\n// @asyncsignalsafe\nint FixXnuSignal(struct Machine *m, int sig, siginfo_t *si) {\n  u64 pte;\n  // The fruit platform will raise SIGBUS on writes to anon mappings\n  // which don't have the PROT_WRITE protection, even when aligned!!\n  // We only create this kind of memory for getting notifications if\n  // RWX memory is modified. The XNU codebase implements a hack that\n  // prevents this from happening for stack memory, but for anything\n  // else we're on our own.\n  if (HasLinearMapping() && sig == SIGBUS && si->si_code == BUS_ADRALN) {\n    ConvertHostToGuestAddress(m->system, si->si_addr, &pte);\n    // check that fault address mapped to an actual guest address, and\n    // that either (1) the page doesn't have read+write permission, or\n    // (2) it's an RWX page and therefore likely to be sneak protected\n    if ((pte & PAGE_V) &&\n        ((pte & (PAGE_U | PAGE_RW)) != (PAGE_U | PAGE_RW) ||\n         (pte & (PAGE_U | PAGE_RW | PAGE_XD)) == (PAGE_U | PAGE_RW))) {\n      // we're now quite certain this is actually a segmentation fault\n      sig = SIGSEGV;\n      si->si_signo = SIGSEGV;\n      si->si_code = SEGV_ACCERR;\n    }\n  }\n  return sig;\n}\n"
  },
  {
    "path": "build/config.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nTAGS ?= /usr/bin/ctags\n\nIMAGE_BASE_VIRTUAL = 0x23000000\n\nifeq ($(HOST_SYSTEM), Haiku)\nCFLAGS += -fpic\nendif\n\nCPPFLAGS += -iquote.\n\nifeq ($(HOST_SYSTEM), Haiku)\nLDLIBS += -lroot -lnetwork -lbsd\nendif\n\nifeq ($(HOST_OS), Cygwin)\nLDLIBS += -lntdll\nendif\n\nifeq ($(HOST_SYSTEM), OpenBSD)\nCFLAGS += -gdwarf-2\nendif\n\n# FreeBSD loads executables to 0x200000 by default which is likely to\n# overlap the static Linux guest binary, we usually load to 0x400000.\nifeq ($(HOST_SYSTEM), FreeBSD)\nLDFLAGS += -Wl,--image-base=$(IMAGE_BASE_VIRTUAL)\nendif\n\n# Tune the build when using our prebuilt musl-cross-make toolchains.\nCPPFLAGS_STATIC =\t\t\t\\\n\t-DMUSL_CROSS_MAKE\nLDFLAGS_STATIC =\t\t\t\\\n\t-static\t\t\t\t\\\n\t-fno-exceptions\t\t\t\\\n\t-fno-unwind-tables\t\t\\\n\t-fno-asynchronous-unwind-tables\t\\\n\t-Wl,-z,max-page-size=4096\t\\\n\t-Wl,-z,common-page-size=4096\t\\\n\t-Wl,-z,norelro\t\t\t\\\n\t-Wl,-Ttext-segment=$(IMAGE_BASE_VIRTUAL)\n\nTAGSFLAGS =\t\t\t\t\\\n\t-e\t\t\t\t\\\n\t-a\t\t\t\t\\\n\t--if0=no\t\t\t\\\n\t--langmap=c:.c.h.i\t\t\\\n\t--line-directives=yes\n\n# some distros like alpine have a file /usr/include/fortify/string.h\n# which wraps functions like memcpy() with inline branch traps which\n# check for things like overlapping parameters and buffer overrun in\n# situations where the array size is known. memcpy() is important in\n# avoiding aliasing memory and proving no aliases exist so that code\n# goes faster and is more portable. for example, here we use it when\n# moving values to/from the cpu register file therefore the size and\n# boundaries are always known, and as such, fortification needlessly\n# causes an explosive growth in object code size in files like sse.c\nCFLAGS += -U_FORTIFY_SOURCE\n\n# ifeq ($(USER), jart)\n# CFLAGS := -Wall -Werror $(CFLAGS)\n# endif\n\nifeq ($(MODE), zero)\nCFLAGS += -O0 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer\nendif\n\nifeq ($(MODE), dbg)\nCFLAGS += -O0 -g -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer\nCPPFLAGS += -DDEBUG\nendif\n\nifeq ($(MODE), rel)\nCPPFLAGS += -DNDEBUG\nCFLAGS += -O2 -mtune=generic -fno-align-functions -fno-align-jumps -fno-align-labels -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables\nendif\n\nifeq ($(MODE), rel-llvm)\nCC = clang\nCPPFLAGS += -DNDEBUG\nCFLAGS += -O2 -mtune=generic\nendif\n\nifeq ($(MODE), tiny)\nCPPFLAGS += -DNDEBUG -DTINY\nCFLAGS += -Os -fomit-frame-pointer -mtune=generic -fno-align-functions -fno-align-jumps -fno-align-labels -fno-align-loops -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables\nLDFLAGS += #-Wl,--cref,-Map=$@.map\nendif\n\nifeq ($(MODE), tiny-llvm)\nCC = clang\nCPPFLAGS += -DNDEBUG -DTINY\nCFLAGS += -Oz\nendif\n\nifeq ($(MODE), opt)\nCPPFLAGS += -DNDEBUG\nCFLAGS += -O3 -march=native\nendif\n\nifeq ($(MODE), opt-llvm)\nCC = clang\nCPPFLAGS += -DNDEBUG\nCFLAGS += -O2\nTARGET_ARCH = -march=native\nendif\n\n# ./configure MODE=prof\n# make -j8\n# o/prof/blink/blink third_party/cosmo/2/mu_test.com\n# gprof o/prof/blink/blink gmon.out | less\nifeq ($(MODE), prof)\nCFLAGS += -pg -O0\nLDFLAGS += -pg -O0\nendif\n\n# make m=cov check\n# gcov -ukqjo o/cov/blink blink/*.c\n# less alu.c.gcov\nifeq ($(MODE), cov)\nCPPFLAGS += -DNOJIT\nCFLAGS += -fprofile-arcs -ftest-coverage\nLDFLAGS += -fprofile-arcs -ftest-coverage\nendif\n\nifeq ($(MODE), asan)\nCFLAGS += -O0\nCPPFLAGS += -DDEBUG\nCPPFLAGS += -fsanitize=address\nLDLIBS += -fsanitize=address\nendif\n\nifeq ($(MODE), ubsan)\nCPPFLAGS += -DDEBUG -DNOJIT -DUBSAN\nCFLAGS += -Werror -Wno-unused-parameter -Wno-missing-field-initializers\nCFLAGS += -fsanitize=undefined\nLDLIBS += -fsanitize=undefined\nendif\n\nifeq ($(MODE), tsan)\nCC = clang++\nCPPFLAGS += -DTSAN\nCFLAGS += -xc++ -Werror -Wno-unused-parameter -Wno-missing-field-initializers\nCFLAGS += -fsanitize=thread\nLDLIBS += -fsanitize=thread\nendif\n\nifeq ($(MODE), msan)\nCC = clang\nCPPFLAGS += -DDEBUG\nCFLAGS += -Werror -Wno-unused-parameter -Wno-missing-field-initializers\nCFLAGS += -fsanitize=memory\nLDLIBS += -fsanitize=memory\nendif\n\nifeq ($(MODE), llvm)\nCC = clang\nCPPFLAGS += -DDEBUG\nCFLAGS += -Werror -Wno-unused-parameter -Wno-unused-function -Wno-missing-field-initializers\nLDFLAGS += --rtlib=compiler-rt\nendif\n\nifeq ($(MODE), llvm++)\nCC = clang++\nCPPFLAGS += -DDEBUG\nCFLAGS += -xc++ -Werror -Wno-unused-function -Wno-unused-parameter -Wno-missing-field-initializers\nLDFLAGS += --rtlib=compiler-rt\nendif\n"
  },
  {
    "path": "build/htags",
    "content": "#!/bin/sh\n#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐\n#── vi: set et ft=sh ts=2 sts=2 fenc=utf-8 :vi ─────────────┘\n#\n# OVERVIEW\n#\n#   Header Symbol Index Generator\n#\n# DESCRIPTION\n#\n#   This is a static source analyzer that lets us configure Emacs\n#   keybindings to insert #include lines.\n#\n# EXAMPLES\n#\n#   build/htags -o HTAGS $(find . -name \\*.h)\n#\n#   (defun jart-add-include ()\n#     (interactive)\n#     (let* ((tag-file \"HTAGS\")\n#            (case-fold-search nil)\n#            (search (thing-at-point 'symbol))\n#            (buffer (find-file-noselect (format \"%s/%s\"\n#                                                (locate-dominating-file\n#                                                 (buffer-name) tag-file)\n#                                                tag-file)))\n#            (header (with-current-buffer buffer\n#                      (save-excursion\n#                        (goto-char 0)\n#                        (when (re-search-forward\n#                               (concat \"\\177\" search \"\\001\") nil t)\n#                          (when (re-search-backward \"\\f\\n\\\\([^,]*\\\\),\" nil t)\n#                            (match-string 1)))))))\n#       (when header\n#         (save-excursion\n#           (goto-char 0)\n#           (re-search-forward \"#include\")\n#           (re-search-forward \"^$\")\n#           (insert (concat \"#include \\\"\" header \"\\\"\\n\"))))))\n#   (defun jart-c-mode-common-hook ()\n#     (define-key c-mode-base-map (kbd \"C-c C-h\") 'jart-add-include))\n#   (eval-after-load 'markdown-mode\n#     '(progn\n#        (add-hook 'c-mode-common-hook 'jart-c-mode-common-hook)))\n\n# ctags doesn't understand atomics, e.g.\n#   extern char **environ;\nset -- --regex-c='/_Atomic(\\([^)]*\\))/\\1/b' \"$@\"\n\n# ctags doesn't understand variable prototypes, e.g.\n#   extern char **environ;\nset -- --regex-c='/^\\(\\(hidden\\|extern\\|const\\) \\)*[_[:alpha:]][_[:alnum:]]*[ *][ *]*\\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\\)*\\([_[:alpha:]][_$[:alnum:]]*\\)/\\4/b' \"$@\"\n\n# ctags doesn't understand function prototypes, e.g.\n#   bool isheap(void *p) dontthrow nocallback;\nset -- --regex-c='/^[_[:alpha:]][_[:alnum:]]*[ *][ *]*\\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\\)*\\([_[:alpha:]][_$[:alnum:]]*\\)(.*/\\2/b' \"$@\"\n\n# ctags doesn't understand function pointers, e.g.\n#   extern int32_t (*const SetEvent)(int64_t hEvent) wincall;\nset -- --regex-c='/^extern [^(]*(\\*const \\([^)]*\\))(/\\1/b' \"$@\"\n\n# ctags doesn't understand forward declarations, e.g.\n#   struct WorstSoftwareEver;\nset -- --regex-c='/^struct.*;$/uehocruehcroue/b' \"$@\"\n\nexec ${TAGS:-ctags}                                               \\\n     -e                                                           \\\n     --langmap=c:.c.h                                             \\\n     --exclude=libc/nt/struct/imagefileheader.internal.h          \\\n     --exclude=libc/nt/struct/imageseparatedebugheader.internal.h \\\n     --exclude=libc/nt/struct/importobjectheader.h                \\\n     --exclude=libc/nt/struct/nonpageddebuginfo.h                 \\\n     --exclude=libc/nt/struct/ansistring.h                        \\\n     --exclude=libc/nt/struct/filesegmentelement.h                \\\n     \"$@\"\n"
  },
  {
    "path": "build/objdump",
    "content": "#!/bin/sh\nexec objdump \"$@\"\n"
  },
  {
    "path": "build/rules.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\no/$(MODE)/%.o: %.s\n\t@mkdir -p $(@D)\n\t$(AS) -o $@ $<\n\no/$(MODE)/%.o: %.S\n\t@mkdir -p $(@D)\n\t$(CC) $(CPPFLAGS) -c -o $@ $<\n\no/$(MODE)/%.o: %.c\n\t@mkdir -p $(@D)\n\t$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/%.h.ok: %.h\n\t@mkdir -p $(@D)\n\t$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -x c -g0 -o $@ $<\n\no/$(MODE)/%.a:\n\trm -f $@\n\t$(AR) rcs $@ $^\no/$(MODE)/i486/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/i486/bin/i486-linux-musl-ar rcsD $@ $^\no/$(MODE)/m68k/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/m68k/bin/m68k-linux-musl-ar rcsD $@ $^\no/$(MODE)/x86_64/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/x86_64/bin/x86_64-linux-musl-ar rcsD $@ $^\no/$(MODE)/x86_64-gcc49/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-ar rcsD $@ $^\no/$(MODE)/arm/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/arm/bin/arm-linux-musleabi-ar rcsD $@ $^\no/$(MODE)/aarch64/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/aarch64/bin/aarch64-linux-musl-ar rcsD $@ $^\no/$(MODE)/riscv64/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/riscv64/bin/riscv64-linux-musl-ar rcsD $@ $^\no/$(MODE)/mips/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/mips/bin/mips-linux-musl-ar rcsD $@ $^\no/$(MODE)/mipsel/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/mipsel/bin/mipsel-linux-musl-ar rcsD $@ $^\no/$(MODE)/mips64/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/mips64/bin/mips64-linux-musl-ar rcsD $@ $^\no/$(MODE)/mips64el/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/mips64el/bin/mips64el-linux-musl-ar rcsD $@ $^\no/$(MODE)/s390x/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/s390x/bin/s390x-linux-musl-ar rcsD $@ $^\no/$(MODE)/microblaze/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/microblaze/bin/microblaze-linux-musl-ar rcsD $@ $^\no/$(MODE)/powerpc/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/powerpc/bin/powerpc-linux-musl-ar rcsD $@ $^\no/$(MODE)/powerpc64le/%.a:\n\trm -f $@\n\t$(VM) o/third_party/gcc/powerpc64le/bin/powerpc64le-linux-musl-ar rcsD $@ $^\n\no/$(MODE)/%-gcc.asm: %.c\n\t@mkdir -p $(@D)\n\t$(CC) $(CFLAGS) -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-stack-protector -iquote. $(CPPFLAGS) $(TARGET_ARCH) -S -g0 $(OUTPUT_OPTION) $<\no/$(MODE)/%-clang.asm: %.c\n\t@mkdir -p $(@D)\n\t$(CC) $(CFLAGS) -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-stack-protector -iquote. $(CPPFLAGS) $(TARGET_ARCH) -S -g0 $(OUTPUT_OPTION) $<\n"
  },
  {
    "path": "config.h.in",
    "content": "#ifndef BLINK_CONFIG_H_\n#define BLINK_CONFIG_H_\n\n// #define DISABLE_JIT\n// #define DISABLE_X87\n// #define DISABLE_THREADS\n// #define DISABLE_SOCKETS\n// #define DISABLE_OVERLAYS\n#define DISABLE_VFS\n// #define DISABLE_NONPOSIX\n// #define DISABLE_ANCILLARY\n// #define DISABLE_DISASSEMBLER\n// #define DISABLE_BACKTRACE\n// #define DISABLE_STRACE\n// #define DISABLE_METAL\n// #define DISABLE_MMX\n// #define DISABLE_BCD\n// #define DISABLE_ROM\n// #define DISABLE_BMI2\n\n// #define HAVE_FORK\n// #define HAVE_SYNC\n// #define HAVE_DUP3\n// #define HAVE_PIPE2\n// #define HAVE_WAIT4\n// #define HAVE_SYSCTL\n// #define HAVE_INT128\n// #define HAVE_SA_LEN\n// #define HAVE_PREADV\n// #define HAVE_MKFIFO\n// #define HAVE_WCWIDTH\n// #define HAVE_SYSINFO\n// #define HAVE_FEXECVE\n// #define HAVE_SCHED_H\n// #define HAVE_MEMCCPY\n// #define HAVE_SEEKDIR\n// #define HAVE_MKFIFOAT\n// #define HAVE_REALPATH\n// #define HAVE_SETREUID\n// #define HAVE_FDATASYNC\n// #define HAVE_STRCHRNUL\n// #define HAVE_VASPRINTF\n// #define HAVE_SETRESUID\n// #define HAVE_KERN_ARND\n// #define HAVE_GETRANDOM\n// #define HAVE_SETGROUPS\n// #define HAVE_LIBUNWIND\n// #define HAVE_GETENTROPY\n// #define HAVE_MAP_SHARED\n// #define HAVE_SENDTO_ZERO\n// #define HAVE_SIOCGIFCONF\n// #define HAVE_F_GETOWN_EX\n// #define HAVE_DEV_URANDOM\n// #define HAVE_SCHED_YIELD\n// #define HAVE_RTLGENRANDOM\n// #define HAVE_EPOLL_PWAIT1\n// #define HAVE_EPOLL_PWAIT2\n// #define HAVE_GETDOMAINNAME\n// #define HAVE_MAP_ANONYMOUS\n// #define HAVE_CLOCK_SETTIME\n// #define HAVE_SYS_GETRANDOM\n// #define HAVE_SYS_GETENTROPY\n// #define HAVE_SCM_CREDENTIALS\n// #define HAVE_STRUCT_TIMEZONE\n// #define HAVE_SCHED_GETAFFINITY\n// #define HAVE_PTHREAD_PROCESS_SHARED\n// #define HAVE_SYS_MOUNT_H\n// #define HAVE_PTHREAD_SETCANCELSTATE\n// #define HAVE_SOCKATMARK\n\n#endif /* BLINK_CONFIG_H_ */\n"
  },
  {
    "path": "configure",
    "content": "#!/bin/sh\n# Blinkenlights Configuration Script\n# Run ./configure --help for usage\n\nCONFIG_COMMAND=\"$0 $*\"\n\n# Evaluate FOO=bar environment variables passed as arguments (carefully\n# ignoring --foo=bar flags) and then remove MODE=foo from the arguments\ncleared=\nfor x; do\n  test \"$cleared\" || set -- ; cleared=1\n  if [ x\"${x%%=*}\" != x\"$x\" ] && [ x\"${x#--}\" = x\"$x\" ]; then\n    eval \"${x%%=*}='${x#*=}'\"\n  fi\n  if [ x\"${x%%=*}\" != x\"MODE\" ]; then\n    set -- \"$@\" \"$x\"\n  fi\ndone\n\nCC=\"${CC:-cc}\"\nAR=\"${AR:-ar}\"\nPREFIX=\"/usr/local\"\nMODE=\"${MODE:-${m}}\"\nTMPDIR=\"${TMPDIR:-o/tmp}\"\nCFLAGS=\"${CFLAGS:--g -O2}\"\nUOPFLAGS=\"${UOPFLAGS:--O2}\"\nCPPFLAGS=\"${CPPFLAGS:--D_FILE_OFFSET_BITS=64 -D_DARWIN_C_SOURCE -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_GNU_SOURCE}\"\n\nHOST_ARCH=$(uname -m)\nHOST_SYSTEM=$(uname -s)\nHOST_OS=$(uname -o 2>/dev/null)\n\nif [ \"${HOST_ARCH}\" = \"amd64\" ] ||\n   [ \"${HOST_ARCH}\" = \"x86_64\" ] ||\n   [ \"${HOST_ARCH}\" = \"arm64\" ] ||\n   [ \"${HOST_ARCH}\" = \"aarch64\" ]; then\n  JIT_POSSIBLE=1\nelse\n  JIT_POSSIBLE=\nfi\n\nif [ \"$1\" = \"--help\" ]; then\n  echo \"usage: ./configure [OPTION]... [VARIABLE=VAL]...\"\n  echo\n  echo \"options\"\n  echo\n  echo \"  --help\"\n  echo \"    shows this help\"\n  echo\n  echo \"  --static\"\n  echo \"    compile blink as a statically-linked binary\"\n  echo\n  echo \"  --prefix=PATH\"\n  echo \"    configures system install path (defaults to /usr/local)\"\n  echo\n  echo \"  --enable-vfs\"\n  echo \"    enables true filesystem emulation support (overlays alternative)\"\n  echo\n  echo \"  --disable-jit\"\n  echo \"    forces jit compilation to be disabled (shaves ~26kb off MODE=tiny)\"\n  echo\n  echo \"  --disable-x87\"\n  echo \"    disables x87 fpu and long double support (shaves ~23kb off MODE=tiny)\"\n  echo\n  echo \"  --disable-threads\"\n  echo \"    disables clone() and removes locks / barriers (shaves ~12kb off MODE=tiny)\"\n  echo\n  echo \"  --disable-sockets\"\n  echo \"    disables socket() and related system calls (shaves ~5kb off MODE=tiny)\"\n  echo\n  if [ \"${MODE%%-*}\" != \"tiny\" ] && [ \"${MODE%%-*}\" != \"rel\" ] && [ \"${MODE%%-*}\" != \"opt\" ]; then\n    echo \"  --disable-disassembler\"\n    echo \"    disables printing disassembled opcodes on crash (shaves ~48kb off MODE='')\"\n    echo\n    echo \"  --disable-strace\"\n    echo \"    disables system call logging functionality (shaves ~40kb off MODE='')\"\n    echo\n    echo \"  --disable-backtrace\"\n    echo \"    disables printing guest backtrace on crash (shaves ~5kb off MODE='')\"\n    echo\n  fi\n  echo \"  --disable-metal\"\n  echo \"    disables i8086, i386, and ring-0 instructions (shaves ~3kb off MODE=tiny)\"\n  echo\n  echo \"  --disable-mmx\"\n  echo \"    disables rarely used intel mmx legacy instructions (shaves ~3kb off MODE=tiny)\"\n  echo\n  echo \"  --disable-fork\"\n  echo \"    disables fork() and interprocess communication (shaves ~3kb off MODE=tiny)\"\n  echo\n  echo \"  --disable-overlays\"\n  echo \"    disables filesystem overlays and chroot() support (shaves ~3kb off MODE=tiny)\"\n  echo\n  echo \"  --disable-nonposix\"\n  echo \"    disables linux apis that aren't part of posix (shaves ~6kb off MODE=tiny)\"\n  echo \"    intended for testing compliance of guest programs\"\n  echo\n  echo \"  --disable-bmi2\"\n  echo \"    disables bmi2 and adx instruction sets (shaves ~3kb off MODE=tiny)\"\n  echo\n  echo \"  --disable-ancillary\"\n  echo \"    disables sendmsg/recvmsg control data support (shaves ~2kb off MODE=tiny)\"\n  echo\n  echo \"  --disable-bcd\"\n  echo \"    disables i8086 binary coded decimal support (shaves ~1kb off MODE=tiny)\"\n  echo\n  echo \"  --disable-rom\"\n  echo \"    disables write protection of metal bios (shaves ~600 bytes off MODE=tiny)\"\n  echo\n  echo \"  --disable-all\"\n  echo \"    disable all optional features (shaves ~81kb off MODE=tiny)\"\n  echo \"    you may use --enable-FOO to turn features back on\"\n  echo\n  echo \"  --posix\"\n  echo \"    strictly conform to POSIX.1-2008 XSI and C11 standards (clobbers \\$CPPFLAGS)\"\n  echo \"    linux-specific apis are still provided by blink when they can be polyfilled\"\n  echo \"    intended for testing compliance of blink's codebase\"\n  echo\n  echo \"variables\"\n  echo\n  echo \"  MODE\"\n  echo \"    tunes makefile by choosing a preset configuration. defaults\"\n  echo \"    to empty string which is recommended. may alternatively be\"\n  echo \"    set to: tiny, opt, rel, dbg, cosmo, prof, cov, asan, ubsan,\"\n  echo \"    tsan, msan, llvm, llvm++, rel-llvm, or tiny-llvm.\"\n  echo\n  echo \"  CC\"\n  echo \"    used to compile and link code [currently: $CC]\"\n  echo\n  echo \"  CFLAGS\"\n  echo \"    shall be passed to \\$CC when compiling c sources [currently: $CFLAGS]\"\n  echo\n  echo \"  CPPFLAGS\"\n  echo \"    shall be passed to \\$CC when using the c preprocessor [currently: $CPPFLAGS]\"\n  echo\n  echo \"  LDFLAGS\"\n  echo \"    shall be passed to \\$CC when linking binaries [currently: $LDFLAGS]\"\n  echo\n  echo \"  TARGET_ARCH\"\n  echo \"    shall be passed to \\$CC when compiling objects [currently: $TARGET_ARCH]\"\n  echo\n  echo \"  LOADLIBES\"\n  echo \"    may supply additional libraries to link earlier [currently: $LOADLIBES]\"\n  echo\n  echo \"  LDLIBS\"\n  echo \"    may supply additional libraries to link [currently: $LDLIBS]\"\n  echo\n  echo \"  TMPDIR\"\n  echo \"    used to store temporary files [currently: $TMPDIR]\"\n  echo\n  echo \"  AR\"\n  echo \"    used to create static archives [currently: $AR]\"\n  echo\n  exit 0\nfi\n\nif ! [ -f blink/blink.c ]; then\n  echo \"error: not in blink project root directory\" >&2\n  echo \"please change the current directory\" >&2\n  exit 1\nfi\n\n# POSIX compliant realpath solution for Darwin\n# https://stackoverflow.com/a/18443300/1653720\nrealpath() (\n  OURPWD=$PWD\n  cd \"$(dirname \"$1\")\"\n  LINK=$(readlink \"$(basename \"$1\")\")\n  while [ \"$LINK\" ]; do\n    cd \"$(dirname \"$LINK\")\"\n    LINK=$(readlink \"$(basename \"$1\")\")\n  done\n  REALPATH=\"$PWD/$(basename \"$1\")\"\n  cd \"$OURPWD\"\n  echo \"$REALPATH\"\n)\n\nmkdir -p \"${TMPDIR}\" || exit\nmkdir -p o/tool/config || exit\nexport TMPDIR=$(realpath \"$TMPDIR\")\n\nprintf \"checking for flock... \" >&2\nif command -v flock >/dev/null; then\n  echo yes >&2\n  FLOCK=flock\nelif [ -x o/tool/flock ]; then\n  echo o/tool/flock >&2\n  FLOCK=o/tool/flock\nelse\n  echo no >&2\n  printf \"building tool/flock.c... \" >&2\n  f=$(mktemp \"${TMPDIR}/flock.XXXXXX\")\n  if ${CC} -o \"${f}\" tool/flock.c; then\n    echo ok >&2\n    mv -f \"${f}\" o/tool/flock || exit\n    FLOCK=o/tool/flock\n  else\n    echo \"error: need the flock command\" >&2\n    exit 1\n  fi\nfi\n\nCONFIG=$(mktemp \"${TMPDIR}/blink-config.h.XXXXXX\")\nBUILD=$(mktemp \"${TMPDIR}/blink-config.mk.XXXXXX\")\nLOCK=$(mktemp \"${TMPDIR}/blink-config.lock.XXXXXX\")\n\ncp config.h.in \"${CONFIG}\" || exit\nrm -f config.log\n\nrun() {\n  (\n    printf '%s\\n' \"$*\"\n    if nice \"$@\"; then\n      exit 0\n    else\n      rc=$?\n      echo \"exit code $rc\"\n      exit $rc\n    fi\n  ) >&6 2>&6\n}\n\ncompile() {\n  run ${CC:-cc} \\\n      ${EXTRA_CFLAGS} \\\n      ${CFLAGS} \\\n      ${EXTRA_CPPFLAGS} \\\n      ${CPPFLAGS} \\\n      ${EXTRA_LDFLAGS} \\\n      ${LDFLAGS} \\\n      ${TARGET_ARCH} \\\n      \"$@\" \\\n      ${LOADLIBES} \\\n      ${EXTRA_LDLIBS} \\\n      ${LDLIBS}\n}\n\nconfig() {\n  PROGRAM=\"$1\"\n  # If running on cygwin, msys2 or wsl then enable testing mingw-w64 produced binaries\n  if test \"${CC#*w64-mingw}\" != \"${CC}\"; then\n    RUNPROGRAM=\"$1.exe\"\n  elif [ \"${HOST_OS}\" = \"Cygwin\" ]; then\n    RUNPROGRAM=\"$1.exe\"\n  else\n    RUNPROGRAM=\"$1\"\n  fi\n  MESSAGE=\"$2\"\n  shift 2\n  LOG=$(mktemp \"${TMPDIR}/blink-config.log.XXXXXX\")\n  exec 6<>\"${LOG}\"\n  echo >&6\n  echo ======================================================================== >&6\n  echo \"${MESSAGE}\" >&6\n  echo ======================================================================== >&6\n  echo >&6\n  if [ ! -f \"tool/config/${PROGRAM}.c\" ]; then\n    echo \"tool/config/${PROGRAM}.c: not found\" >&2\n    exit 1\n  fi\n  if compile -Werror -o \"o/tool/config/${PROGRAM}\" \"tool/config/${PROGRAM}.c\" &&\n     run \"o/tool/config/${RUNPROGRAM}\"; then\n    printf '%s\\n' \"${MESSAGE} yes\" >&2\n    if [ $# -gt 0 ]; then\n      \"$@\"\n    fi\n    rc=0\n  else\n    printf '%s\\n' \"${MESSAGE} no\" >&2\n    rc=1\n  fi\n  cat <\"${LOG}\" >>config.log\n  rm -f \"${LOG}\"\n  exec 6<&-\n  EXTRA_CFLAGS=\n  EXTRA_CPPFLAGS=\n  EXTRA_LDFLAGS=\n  EXTRA_LDLIBS=\n  return $rc\n}\n\nhassstr() {\n  if ! grep \"$1\" <\"${CONFIG}\" >/dev/null 2>&1; then\n    echo \"config.h.in didn't contain $1\" >&2\n  fi\n}\n\nreplace() {\n  exec 7<>\"${LOCK}\"\n  \"${FLOCK}\" -x 7\n  sed \"s@$1@$2@\" <\"${CONFIG}\" >\"${CONFIG}.tmp\" &&\n  mv -f \"${CONFIG}.tmp\" \"${CONFIG}\"\n  exec 7<&-\n}\n\ncomment() {\n  hassstr \"$1\"\n  replace \"$1\" \"// $1\"\n}\n\nuncomment() {\n  hassstr \"$1\"\n  replace \"// $1\" \"$1\"\n}\n\nfor x; do\n  if [ x\"${x%=*}\" != x\"$x\" ] && [ x\"${x#--}\" = x\"$x\" ]; then\n    continue\n  fi\n\n  if [ x\"$x\" = x\"--disable-all\" ]; then\n    uncomment \"#define DISABLE\"\n    DISABLE_NONPOSIX=1\n    DISABLE_THREADS=1\n    DISABLE_SOCKETS=1\n    DISABLE_FORK=1\n    DISABLE_X87=1\n    DISABLE_JIT=1\n\n  elif [ x\"${x%%=*}\" = x\"--prefix\" ]; then\n    PREFIX=\"${x#*=}\"\n\n  elif [ x\"$x\" = x\"--static\" ]; then\n    STATIC=1\n\n  elif [ x\"$x\" = x\"--enable-fork\" ]; then\n    unset DISABLE_FORK\n  elif [ x\"$x\" = x\"--disable-fork\" ]; then\n    DISABLE_FORK=1\n\n  elif [ x\"$x\" = x\"--enable-jit\" ]; then\n    comment \"#define DISABLE_JIT\"\n    unset DISABLE_JIT\n  elif [ x\"$x\" = x\"--disable-jit\" ]; then\n    uncomment \"#define DISABLE_JIT\"\n    DISABLE_JIT=1\n\n  elif [ x\"$x\" = x\"--enable-x87\" ]; then\n    comment \"#define DISABLE_X87\"\n    unset DISABLE_X87\n  elif [ x\"$x\" = x\"--disable-x87\" ]; then\n    uncomment \"#define DISABLE_X87\"\n    DISABLE_X87=1\n\n  elif [ x\"$x\" = x\"--enable-mmx\" ]; then\n    comment \"#define DISABLE_MMX\"\n  elif [ x\"$x\" = x\"--disable-mmx\" ]; then\n    uncomment \"#define DISABLE_MMX\"\n\n  elif [ x\"$x\" = x\"--enable-metal\" ]; then\n    comment \"#define DISABLE_METAL\"\n  elif [ x\"$x\" = x\"--disable-metal\" ]; then\n    uncomment \"#define DISABLE_METAL\"\n\n  elif [ x\"$x\" = x\"--enable-strace\" ]; then\n    comment \"#define DISABLE_STRACE\"\n  elif [ x\"$x\" = x\"--disable-strace\" ]; then\n    uncomment \"#define DISABLE_STRACE\"\n\n  elif [ x\"$x\" = x\"--enable-threads\" ]; then\n    comment \"#define DISABLE_THREADS\"\n    unset DISABLE_THREADS\n  elif [ x\"$x\" = x\"--disable-threads\" ]; then\n    uncomment \"#define DISABLE_THREADS\"\n    DISABLE_THREADS=1\n\n  elif [ x\"$x\" = x\"--enable-sockets\" ]; then\n    comment \"#define DISABLE_SOCKETS\"\n    unset DISABLE_SOCKETS\n  elif [ x\"$x\" = x\"--disable-sockets\" ]; then\n    uncomment \"#define DISABLE_SOCKETS\"\n    DISABLE_SOCKETS=1\n\n  elif [ x\"$x\" = x\"--enable-overlays\" ]; then\n    comment \"#define DISABLE_OVERLAYS\"\n    uncomment \"#define DISABLE_VFS\"\n  elif [ x\"$x\" = x\"--disable-overlays\" ]; then\n    uncomment \"#define DISABLE_OVERLAYS\"\n\n  elif [ x\"$x\" = x\"--enable-vfs\" ]; then\n    comment \"#define DISABLE_VFS\"\n    uncomment \"#define DISABLE_OVERLAYS\"\n  elif [ x\"$x\" = x\"--disable-vfs\" ]; then\n    uncomment \"#define DISABLE_VFS\"\n\n  elif [ x\"$x\" = x\"--enable-ancillary\" ]; then\n    comment \"#define DISABLE_ANCILLARY\"\n  elif [ x\"$x\" = x\"--disable-ancillary\" ]; then\n    uncomment \"#define DISABLE_ANCILLARY\"\n\n  elif [ x\"$x\" = x\"--enable-disassembler\" ]; then\n    comment \"#define DISABLE_DISASSEMBLER\"\n  elif [ x\"$x\" = x\"--disable-disassembler\" ]; then\n    uncomment \"#define DISABLE_DISASSEMBLER\"\n\n  elif [ x\"$x\" = x\"--enable-backtrace\" ]; then\n    comment \"#define DISABLE_BACKTRACE\"\n  elif [ x\"$x\" = x\"--disable-backtrace\" ]; then\n    uncomment \"#define DISABLE_BACKTRACE\"\n\n  elif [ x\"$x\" = x\"--enable-nonposix\" ]; then\n    comment \"#define DISABLE_NONPOSIX\"\n    unset DISABLE_NONPOSIX\n  elif [ x\"$x\" = x\"--disable-nonposix\" ]; then\n    uncomment \"#define DISABLE_NONPOSIX\"\n    DISABLE_NONPOSIX=1\n\n  elif [ x\"$x\" = x\"--enable-bmi2\" ]; then\n    comment \"#define DISABLE_BMI2\"\n  elif [ x\"$x\" = x\"--disable-bmi2\" ]; then\n    uncomment \"#define DISABLE_BMI2\"\n\n  elif [ x\"$x\" = x\"--enable-bcd\" ]; then\n    comment \"#define DISABLE_BCD\"\n  elif [ x\"$x\" = x\"--disable-bcd\" ]; then\n    uncomment \"#define DISABLE_BCD\"\n\n  elif [ x\"$x\" = x\"--enable-rom\" ]; then\n    comment \"#define DISABLE_ROM\"\n  elif [ x\"$x\" = x\"--disable-rom\" ]; then\n    uncomment \"#define DISABLE_ROM\"\n\n  elif [ x\"$x\" = x\"--posix\" ]; then\n    CPPFLAGS=\"-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -std=c11\"\n    POSIX=1\n\n  elif [ x\"$x\" = x\"--pedantic\" ]; then\n    CFLAGS=\"$CFLAGS -std=c11 -pedantic -Wall -Werror\"\n\n  else\n    echo \"error: unrecognized flag: $x\" >&2\n    echo \"use $0 --help for help\" >&2\n    exit 1\n  fi\ndone\n\nif [ \"${STATIC}\" ]; then\n  LDFLAGS=\"-static ${LDFLAGS}\"\n  EXTRA_CFLAGS=-fno-pie\n  EXTRA_LDFLAGS=-no-pie\n  if config noop \"checking for no-pie... \"; then\n    CFLAGS=\"-fno-pie ${CFLAGS}\"\n    LDFLAGS=\"-no-pie ${LDFLAGS}\"\n  fi\nfi\n\n# position independent executables\n# 1. help ensure blink won't overlap static binaries in memory\n# 2. gcc and clang generates tinier code for switch statements\nEXTRA_CFLAGS=-fpie\nEXTRA_LDFLAGS=-pie\nif [ -z \"${STATIC}\" ] && config noop \"checking for pie... \"; then\n  CFLAGS=\"-fpie ${CFLAGS}\"\n  LDFLAGS=\"-pie ${LDFLAGS}\"\nelse\n  # otherwise relocate blink somewhere irregular\n  BASE=-Wl,--image-base=0x23000000\n  EXTRA_LDFLAGS=\"${BASE}\"\n  if config noop \"checking for ${BASE}... \"; then\n    LDFLAGS=\"${BASE} ${LDFLAGS}\"\n  else\n    BASE=-Wl,-Ttext-segment=0x23000000\n    EXTRA_LDFLAGS=\"${BASE}\"\n    if config noop \"checking for ${BASE}... \"; then\n      LDFLAGS=\"${BASE} ${LDFLAGS}\"\n    fi\n  fi\nfi\n\n# ensure binaries will run on apple m1, cygwin, etc.\n# blink can't map a program into memory without this\nGOODELF=-Wl,-z,common-page-size=65536,-z,max-page-size=65536\nEXTRA_LDFLAGS=\"${GOODELF}\"\nif config noop \"checking for ${GOODELF}...\"; then\n  LDFLAGS=\"${GOODELF} ${LDFLAGS}\"\n  # with 64kb pages these two security blankets would otherwise cause\n  # blink's minimum binary size to increase from 120kb to 250kb. yuck\n  NORELRO=-Wl,-z,norelro\n  EXTRA_LDFLAGS=\"${NORELRO}\"\n  if config noop \"checking for ${NORELRO}... \"; then\n    LDFLAGS=\"${NORELRO} ${LDFLAGS}\"\n  fi\n  NORODATAPHDR=-Wl,-z,noseparate-code\n  EXTRA_LDFLAGS=\"${NORODATAPHDR}\"\n  if config noop \"checking for ${NORODATAPHDR}... \"; then\n    LDFLAGS=\"${NORODATAPHDR} ${LDFLAGS}\"\n  fi\nfi\n\n# check for the math library\nEXTRA_LDLIBS=-lm\nif config lm \"checking for -lm... \"; then\n  LDLIBS=\"-lm ${LDLIBS}\"\nfi\n\n# check for the posix threads library\nif [ -z \"${DISABLE_THREADS}\" ]; then\n  EXTRA_CFLAGS=-pthread\n  EXTRA_LDFLAGS=-pthread\n  if config pthread \"checking for -pthread... \"; then\n    CFLAGS=\"-pthread ${CFLAGS}\"\n    LDFLAGS=\"-pthread ${LDFLAGS}\"\n  else\n    EXTRA_LDLIBS=-lpthread\n    if config pthread \"checking for -lpthread... \"; then\n      LDLIBS=\"-lpthread ${LDLIBS}\"\n    else\n      if config pthread \"checking for pthreads... \"; then\n        LDLIBS=\"-lpthread ${LDLIBS}\"\n      else\n        uncomment \"#define DISABLE_THREADS\"\n      fi\n    fi\n  fi\nfi\n\n# check for the posix.1b realtime extensions library\n# note: librt depends on pthreads, on rhel5 at least\nEXTRA_LDLIBS=-lrt\nif config lrt \"checking for -lrt... \"; then\n  LDLIBS=\"-lrt ${LDLIBS}\"\nfi\n\n# should be the default and macos build fails without it\nEXTRA_CFLAGS=-fno-common\nif config noop \"checking for -fno-common... \"; then\n  CFLAGS=\"-fno-common ${CFLAGS}\"\nfi\n\n# make sure sanitizers aren't enabled on micro-op functions\nEXTRA_CFLAGS=-fno-sanitize=all\nif config noop \"checking for -fno-sanitize=all... \"; then\n  UOPFLAGS=\"-fno-sanitize=all ${UOPFLAGS}\"\nfi\n\n# blink's jit will align the functions that matter\nif [ -n \"${JIT_POSSIBLE}\" ] && [ -z \"${DISABLE_JIT}\" ]; then\n  EXTRA_CFLAGS=-fno-align-functions\n  if config noop \"checking for -fno-align-functions... \"; then\n    CFLAGS=\"-fno-align-functions ${CFLAGS}\"\n  fi\nfi\n\n# blink's jit can't extract and relocate micro-op function bodies if the\n# compiler inserts things like static memory references into them.\nEXTRA_CFLAGS=-fno-stack-protector\nif config noop \"checking for -fno-stack-protector... \"; then\n  UOPFLAGS=\"-fno-stack-protector ${UOPFLAGS}\"\nfi\n\n# avoid cosmo libc function call tracing messing up micro-ops\nEXTRA_CFLAGS=-fpatchable-function-entry=0,0\nif config noop \"checking for -fpatchable-function-entry=0,0... \"; then\n  UOPFLAGS=\"-fpatchable-function-entry=0,0 ${UOPFLAGS}\"\nfi\n\n# avoid creating stack frames in micro-op functions\nif [ \"${MODE}\" != \"prof\" ]; then\n  EXTRA_CFLAGS=-fomit-frame-pointer\n  if config noop \"checking for -fomit-frame-pointer... \"; then\n    UOPFLAGS=\"${UOPFLAGS} -fomit-frame-pointer\"\n  fi\nfi\n\n# for everything else, stack frames are extremely important\nif [ \"${MODE}\" != \"tiny\" ]; then\n  EXTRA_CFLAGS=-fno-omit-frame-pointer\n  if config noop \"checking for -fno-omit-frame-pointer... \"; then\n    CFLAGS=\"${CFLAGS} -fno-omit-frame-pointer\"\n  fi\nfi\n\n# c11 atomics are no-op'd when both fork and threads are disabled\n# this causes code to break modern compiler strict aliasing rules\n# TODO(jart) is it safe to quash warning w/o -fno-strict-aliasing\nif [ -n \"${DISABLE_THREADS}\" ] && [ -n \"${DISABLE_FORK}\" ]; then\n  EXTRA_CFLAGS=-Wno-strict-aliasing\n  if config noop \"checking for -Wno-strict-aliasing... \"; then\n    CFLAGS=\"${CFLAGS} -Wno-strict-aliasing\"\n  fi\nfi\n\n# this optimization harms our ability to backtrace binaries\n# blink doesn't rely on tail call optimization so we don't need it\nif [ -z \"${MODE}\" ] && [ -n \"${JIT_POSSIBLE}\" ] && [ -z \"${DISABLE_JIT}\" ]; then\n  EXTRA_CFLAGS=-fno-optimize-sibling-calls\n  if config noop \"checking for -fno-optimize-sibling-calls... \"; then\n    CFLAGS=\"${CFLAGS} -fno-optimize-sibling-calls\"\n  fi\nfi\n\n# the new intel cet instructions may interfere with jit, and only\n# offer improved security if the os and cpu both know about them;\n# we can revisit cet later when it becomes more mainstream\nif [ -n \"${JIT_POSSIBLE}\" ] && [ -z \"${DISABLE_JIT}\" ]; then\n  EXTRA_CFLAGS=-fcf-protection=none\n  if config noop \"checking for -fcf-protection=none... \"; then\n    CFLAGS=\"${CFLAGS} -fcf-protection=none\"\n  fi\nfi\n\n# use the system zlib if available\n# otherwise, use our vendored copy\nZLIB_CFLAGS=\"$(pkg-config --cflags zlib 2>/dev/null)\"\nif ! ZLIB_LDLIBS=\"$(pkg-config --libs zlib 2>/dev/null)\"; then\n  ZLIB_LDLIBS=\"-lz\"\nfi\nEXTRA_CFLAGS=\"${ZLIB_CFLAGS}\"\nEXTRA_LDLIBS=\"${ZLIB_LDLIBS}\"\nif config zlib \"checking for zlib... \"; then\n  CFLAGS=\"${ZLIB_CFLAGS} ${CFLAGS}\"\n  LDLIBS=\"${ZLIB_LDLIBS} ${LDLIBS}\"\n  ZLIB=\nelse\n  ZLIB='o/$(MODE)/third_party/libz/zlib.a'\nfi\n\n# try to get blink backtraces if possible\nif [ \"${MODE}\" != \"tiny\" ] && [ \"${MODE}\" != \"rel\" ]; then\n  UNWIND_CFLAGS=\"$(pkg-config --cflags libunwind 2>/dev/null)\"\n  if ! UNWIND_LDLIBS=\"$(pkg-config --libs libunwind 2>/dev/null)\"; then\n    UNWIND_LDLIBS=\"-lunwind -llzma\"\n  fi\n  EXTRA_CFLAGS=\"${UNWIND_CFLAGS}\"\n  EXTRA_LDLIBS=\"${UNWIND_LDLIBS}\"\n  if config libunwind \"checking for libunwind... \"; then\n    CFLAGS=\"${UNWIND_CFLAGS} ${CFLAGS}\"\n    LDLIBS=\"${UNWIND_LDLIBS} ${LDLIBS}\"\n    uncomment \"#define HAVE_LIBUNWIND\"\n  fi\nfi\n\n# attempt to polyfill c11 atomics if it's not available\nif ! config stdatomic \"checking for stdatomic.h... \"; then\n  CPPFLAGS=\"-isystem tool/stdatomic ${CPPFLAGS}\"\nfi\n\nif [ -z \"${DISABLE_FORK}\" ]; then\n  ( config fork \"checking for fork()... \" uncomment \"#define HAVE_FORK\" ) &\nelse\n  echo \"checking for fork()... disabled\"\nfi\n\nif [ -z \"${POSIX}\" ]; then\n  ( config dup3 \"checking for dup3()... \" uncomment \"#define HAVE_DUP3\" ) &\n  ( config pipe2 \"checking for pipe2()... \" uncomment \"#define HAVE_PIPE2\" ) &\n  ( config getrandom \"checking for getrandom()... \" uncomment \"#define HAVE_GETRANDOM\" ) &\n  ( config getentropy \"checking for getentropy() in unistd.h... \" uncomment \"#define HAVE_GETENTROPY\" ) &\n  ( config dev_urandom \"checking for /dev/urandom... \" uncomment \"#define HAVE_DEV_URANDOM\" ) &\n  ( config rtlgenrandom \"checking for RtlGenRandom()... \" uncomment \"#define HAVE_RTLGENRANDOM\" ) &\n  ( config sys_getrandom \"checking for syscall(SYS_getrandom)... \" uncomment \"#define HAVE_SYS_GETRANDOM\" ) &\n  ( config sys_getentropy \"checking for getentropy() in sys/random.h... \" uncomment \"#define HAVE_SYS_GETENTROPY\" ) &\n  ( config getdomainname \"checking for getdomainname()... \" uncomment \"#define HAVE_GETDOMAINNAME\" ) &\n  ( config kern_arnd \"checking for sysctl(KERN_ARND)... \" uncomment \"#define HAVE_KERN_ARND\" ) &\n  ( config siocgifconf \"checking for SIOCGIFCONF... \" uncomment \"#define HAVE_SIOCGIFCONF\" ) &\n  ( config epoll_pwait1 \"checking for epoll_pwait()... \" uncomment \"#define HAVE_EPOLL_PWAIT1\" ) &\n  wait\n  ( config epoll_pwait2 \"checking for epoll_pwait2()... \" uncomment \"#define HAVE_EPOLL_PWAIT2\" ) &\n  ( config map_anonymous \"checking for mmap(MAP_ANONYMOUS)... \" uncomment \"#define HAVE_MAP_ANONYMOUS\" ) &\n  ( config sched_getaffinity \"checking for sched_getaffinity()... \" uncomment \"#define HAVE_SCHED_GETAFFINITY\" ) &\n  ( config scm_credentials \"checking for SCM_CREDENTIALS... \" uncomment \"#define HAVE_SCM_CREDENTIALS\" ) &\n  ( config f_getown_ex \"checking for F_GETOWN_EX... \" uncomment \"#define HAVE_F_GETOWN_EX\" ) &\n  ( config setgroups \"checking for setgroups()... \" uncomment \"#define HAVE_SETGROUPS\" ) &\n  ( config vasprintf \"checking for vasprintf()... \" uncomment \"#define HAVE_VASPRINTF\" ) &\n  ( config strchrnul \"checking for strchrnul()... \" uncomment \"#define HAVE_STRCHRNUL\" ) &\n  ( config mkfifo \"checking for mkfifo()... \" uncomment \"#define HAVE_MKFIFO\" ) &\n  ( config mkfifoat \"checking for mkfifoat()... \" uncomment \"#define HAVE_MKFIFOAT\" ) &\n  ( config preadv \"checking for preadv() and pwritev()... \" uncomment \"#define HAVE_PREADV\" ) &\n  ( config wait4 \"checking for wait4()... \" uncomment \"#define HAVE_WAIT4\" ) &\n  ( config setresuid \"checking for setresuid()... \" uncomment \"#define HAVE_SETRESUID\" ) &\n  ( config sys_mount_h \"checking for sys/mount.h... \" uncomment \"#define HAVE_SYS_MOUNT_H\" ) &\nfi\n\n( config sync \"checking for sync()... \" uncomment \"#define HAVE_SYNC\" ) &\n( config sysctl \"checking for sysctl()... \" uncomment \"#define HAVE_SYSCTL\" ) &\n( config sysinfo \"checking for sysinfo()... \" uncomment \"#define HAVE_SYSINFO\" ) &\n( config fexecve \"checking for fexecve()... \" uncomment \"#define HAVE_FEXECVE\" ) &\n( config wcwidth \"checking for wcwidth()... \" uncomment \"#define HAVE_WCWIDTH\" ) &\n( config memccpy \"checking for memccpy()... \" uncomment \"#define HAVE_MEMCCPY\" ) &\n( config seekdir \"checking for seekdir()... \" uncomment \"#define HAVE_SEEKDIR\" ) &\n( config realpath \"checking for realpath()... \" uncomment \"#define HAVE_REALPATH\" ) &\n( config setreuid \"checking for setreuid()... \" uncomment \"#define HAVE_SETREUID\" ) &\n( config fdatasync \"checking for fdatasync()... \" uncomment \"#define HAVE_FDATASYNC\" ) &\n( config sendto_zero \"checking for sendto(0.0.0.0)... \" uncomment \"#define HAVE_SENDTO_ZERO\" ) &\nwait\n( config struct_timezone \"checking for struct timezone... \" uncomment \"#define HAVE_STRUCT_TIMEZONE\" ) &\n( config sa_len \"checking for sockaddr::sa_len... \" uncomment \"#define HAVE_SA_LEN\" ) &\n( config map_shared \"checking for mmap(MAP_SHARED)... \" uncomment \"#define HAVE_MAP_SHARED\" ) &\n( config sched_yield \"checking for sched_yield()... \" uncomment \"#define HAVE_SCHED_YIELD\" ) &\n( config clock_settime \"checking for clock_settime()... \" uncomment \"#define HAVE_CLOCK_SETTIME\" ) &\n( config sched_h \"checking for sched.h... \" uncomment \"#define HAVE_SCHED_H\" ) &\n( config pthread_process_shared \"checking for PTHREAD_PROCESS_SHARED... \" uncomment \"#define HAVE_PTHREAD_PROCESS_SHARED\" ) &\n( config pthread_setcancelstate \"checking for pthread_setcancelstate()... \" uncomment \"#define HAVE_PTHREAD_SETCANCELSTATE\" ) &\n( config sockatmark \"checking for sockatmark()... \" uncomment \"#define HAVE_SOCKATMARK\" ) &\n\nwait\nrm -f \"${LOCK}\"\n\nBLINK_UNAME_V=\nif test \"${DISABLE_NONPOSIX}\"; then\n  BLINK_UNAME_V=\"${BLINK_UNAME_V} POSIX\"\nfi\nif test \"${DISABLE_JIT}\" || test -z \"${JIT_POSSIBLE}\"; then\n  BLINK_UNAME_V=\"${BLINK_UNAME_V} NOJIT\"\nfi\nif test \"${DISABLE_SOCKETS}\"; then\n  BLINK_UNAME_V=\"${BLINK_UNAME_V} NOSOCK\"\nfi\nif test -z \"${BLINK_UNAME_V}\"; then\n  if test -z \"$*\"; then\n    BLINK_UNAME_V=\"${BLINK_UNAME_V:-DEFAULT}\"\n  else\n    BLINK_UNAME_V=\"${BLINK_UNAME_V:-CUSTOM}\"\n  fi\nfi\n\nfor x; do\n  if [ x\"${x%=*}\" != x\"$x\" ] && [ x\"${x#--}\" = x\"$x\" ]; then\n    printf '%s\\n' \"$x\" >>\"${BUILD}\"\n  fi\ndone\n\ncat >>\"${BUILD}\" <<EOF || exit\nCC = ${CC}\nAR = ${AR}\nMODE ?= ${MODE}\nTMPDIR = ${TMPDIR}\nPREFIX = ${PREFIX}\nCFLAGS = ${CFLAGS}\nCPPFLAGS = ${CPPFLAGS}\nUOPFLAGS = ${UOPFLAGS}\nTARGET_ARCH = ${TARGET_ARCH}\nLDFLAGS = ${LDFLAGS}\nLDLIBS = ${LDLIBS}\nHOST_OS = ${HOST_OS}\nHOST_ARCH = ${HOST_ARCH}\nHOST_SYSTEM = ${HOST_SYSTEM}\nCONFIG_HOSTNAME = $(hostname)\nCONFIG_COMMAND = ${CONFIG_COMMAND}\nCONFIG_ARGUMENTS = -DCONFIG_ARGUMENTS=\"\\\"$(echo $* | sed s/\\ / /g)\\\"\"\nBLINK_UNAME_V = -DBLINK_UNAME_V=\"\\\"$(echo ${BLINK_UNAME_V})\\\"\"\nZLIB = ${ZLIB}\nEOF\n\necho \"creating config.log\" >&2\n\necho \"creating config.mk\" >&2\nmv \"${BUILD}\" config.mk || exit\n\necho \"creating config.h\" >&2\nmv \"${CONFIG}\" config.h || exit\n"
  },
  {
    "path": "test/asm/README.md",
    "content": "# Blink's Assembly Tests\n\nBlink's \"assembly tests\" are tests written in pure assembly that we run\nboth in Blink and on bare metal.\n\nCompilers only utilize a subset of what the instruction set architecture\nis capable of doing. For example, `CMPXCHG` is able to set the overflow\nflag under certain conditions, but that would never matter to any C code\nthat's compiled by GCC. Another example is the clearing of the upper\nhalf of registers on 32-bit operations. We need to ensure that Blink\nwill always do that when appropriate, just as the host hardware would.\nHowever C code may be unlikely to catch when this happening.\n\nIn host environments that aren't AMD64 Linux, bare metal testing will be\nstubbed out using `$(VM)`. Therefore this test suite will still pass,\nbut it'll only be 100% useful when it's run on an `x86_64-linux` system.\n"
  },
  {
    "path": "test/asm/add.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/asm/add.elf\n//\to//blink/blinkenlights o//test/asm/add.elf\n\n\t.test\t\"add64\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x0000000000000001,%rbx\n\tmov\t$0x1234567812345679,%rcx\n\tadd\t%rbx,%rax\n\t.nz\n\t.nc\n\t.ns\n\t.no\n\t.np\n\tcmp\t%rcx,%rax\n\t.e\n\n\t.test\t\"add32\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x0001000100000001,%rbx\n\tmov\t$0x0000000012345679,%rcx\n\tmov\t$0x0001000100000001,%rdx\n\tadd\t%ebx,%eax\n\t.nz\n\t.nc\n\t.ns\n\t.no\n\t.np\n\tcmp\t%rcx,%rax\n\t.e\n\tcmp\t%rdx,%rbx\n\t.e\n\n\t.test\t\"add16\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x0001000100010001,%rbx\n\tmov\t$0x1234567812345679,%rcx\n\tmov\t$0x0001000100010001,%rdx\n\tadd\t%bx,%ax\n\t.nz\n\t.nc\n\t.ns\n\t.no\n\t.np\n\tcmp\t%rcx,%rax\n\t.e\n\tcmp\t%rdx,%rbx\n\t.e\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/adx.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$10,%r15\n\"test jit too\":\n\n//\tunsigned addition with special flags\n//\tmake -j8 o//blink o//test/asm/adx.elf\n//\to//blink/blinkenlights o//test/asm/adx.elf\n\n\tmov\t$7,%eax\t\t\t# extended features\n\txor\t%ecx,%ecx\n\tcpuid\n\tbt\t$19,%ebx\t\t# adx\n\tjnc\t\"test not possible\"\n\n\t.test\t\"adcx\"\n\tmov\t$0xF0000000,%eax\n\tmov\t$0x10000000,%ebx\n\tstc\n\tadcx\t%ebx,%eax\n\t.c\n\tcmp\t$0x00000001,%eax\n\t.e\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n\"test not possible\":\n\t.exit\n"
  },
  {
    "path": "test/asm/asm.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nTEST_ASM_FILES := $(wildcard test/asm/*)\nTEST_ASM_SRCS = $(filter %.S,$(TEST_ASM_FILES))\nTEST_ASM_OBJS = $(TEST_ASM_SRCS:%.S=o/$(MODE)/x86_64-gcc49/%.o)\nTEST_ASM_BINS = $(TEST_ASM_SRCS:%.S=o/$(MODE)/%.elf)\nTEST_ASM_COMS = $(TEST_ASM_SRCS:%.S=o/$(MODE)/%.com)\nTEST_ASM_CHECKS = $(TEST_ASM_SRCS:%.S=o/$(MODE)/%.com.ok)\nTEST_ASM_EMULATES = $(foreach ARCH,$(ARCHITECTURES),$(foreach SRC,$(TEST_ASM_SRCS),$(SRC:%.S=o/$(MODE)/$(ARCH)/%.elf.emulates)))\n\nTEST_ASM_LINK =\t$(VM)\t\t\t\t\t\t\t\t\\\n\t\to/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-ld.bfd\t\\\n\t\t-static\t\t\t\t\t\t\t\t\\\n\t\t--omagic\t\t\t\t\t\t\t\\\n\t\t-z noexecstack\t\t\t\t\t\t\t\\\n\t\t-z max-page-size=65536\t\t\t\t\t\t\\\n\t\t-z common-page-size=65536\t\t\t\t\t\\\n\t\t$<\t\t\t\t\t\t\t\t\\\n\t\t-o $@\n\no/$(MODE)/test/asm/%.com.ok:\t\t\t\t\t\t\t\\\n\t\to/$(MODE)/test/asm/%.com\n\t$<\n\t@touch $@\n\n.PRECIOUS: o/$(MODE)/test/asm/%.elf\no/$(MODE)/test/asm/%.elf:\t\t\t\t\t\t\t\\\n\t\to/$(MODE)/x86_64-gcc49/test/asm/%.o\t\t\t\t\\\n\t\to/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc\t\\\n\t\t$(VM)\n\t@mkdir -p $(@D)\n\t$(TEST_ASM_LINK)\n\n$(TEST_ASM_OBJS): test/asm/asm.mk test/asm/mac.inc\n\n# the .com extension is for cosmo/tool/emacs/ integration\n.PRECIOUS: o/$(MODE)/test/asm/%.com\no/$(MODE)/test/asm/%.com:\t\t\t\t\t\t\\\n\t\to/$(MODE)/test/asm/%.elf\t\t\t\t\\\n\t\to/$(MODE)/blink/blink\t\t\t\t\t\\\n\t\to/third_party/qemu/4/qemu-x86_64\t\t\t\\\n\t\t$(VM)\n\t@mkdir -p $(@D)\n\t@echo \"#!/bin/sh\" >$@\n\t@echo \"echo [test] $(VM) $< >&2\" >>$@\n\t@echo \"$(VM) $< || exit\" >>$@\n\t@echo \"echo [test] o/$(MODE)/blink/blink $< >&2\" >>$@\n\t@echo \"o/$(MODE)/blink/blink $< || exit\" >>$@\n\t@echo \"echo [test] o/$(MODE)/blink/blink -m $< >&2\" >>$@\n\t@echo \"o/$(MODE)/blink/blink -m $< || exit\" >>$@\n\t@echo \"echo [test] o/$(MODE)/blink/blink -jm $< >&2\" >>$@\n\t@echo \"o/$(MODE)/blink/blink -jm $< || exit\" >>$@\n\t@echo \"echo [test] o/third_party/qemu/4/qemu-x86_64 -cpu core2duo $< >&2\" >>$@\n\t@echo \"$(VM) o/third_party/qemu/4/qemu-x86_64 -cpu core2duo $< || exit\" >>$@\n\t@chmod +x $@\n\n.PHONY: o/$(MODE)/test/asm\no/$(MODE)/test/asm:\t\t\t\t\t\t\t\\\n\t$(TEST_ASM_CHECKS)\n\n.PHONY: o/$(MODE)/test/asm/emulates\no/$(MODE)/test/asm/emulates:\t\t\t\t\t\t\\\n\t$(TEST_ASM_EMULATES)\n"
  },
  {
    "path": "test/asm/bzhi.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$10,%r15\n\"test jit too\":\n\n//\tclear high bits\n//\tmake -j8 o//blink o//test/asm/bzhi.elf\n//\to//blink/blinkenlights o//test/asm/bzhi.elf\n\n\tmov\t$7,%eax\t\t\t# extended features\n\txor\t%ecx,%ecx\n\tcpuid\n\tbt\t$8,%ebx\t\t\t# bmi2\n\tjnc\t\"test not possible\"\n\n\t.test\t\"bzhi 1\"\n\tmov\t$0xffffffff,%eax\t# input value\n\tmov\t$0x31337133,%ebx\t# random data\n\tmov\t$0xffffff08,%ecx\t# clear bit 8 and above\n\tbzhi\t%ecx,%eax,%ebx\n\tcmp\t$0xffffffff,%eax\t# unchanged\n\t.e\n\tcmp\t$0x000000ff,%ebx\t# output value\n\t.e\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n\"test not possible\":\n\t.exit\n"
  },
  {
    "path": "test/asm/cmc.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tcomplement carry flag tests\n//\tmake -j8 o//blink o//test/asm/page.elf\n//\to//blink/blinkenlights o//test/asm/page.elf\n\n\t.test\t\"carry flag manipulation\"\n\tstc\n\t.c\n\tclc\n\t.nc\n\tcmc\n\t.c\n\tcmc\n\t.nc\n\tstc\n\t.c\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/cmov.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/asm/cmov.elf\n//\to//blink/blinkenlights o//test/asm/cmov.elf\n\n\t.test\t\"cmovq taken\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t$0x5555555155555550,%rcx\n\tmov\t$0x5555555155555550,%rdx\n\tstc\n\tcmovc\t%rbx,%rax\n\tcmp\t%rcx,%rax\n\t.e\n\tcmp\t%rdx,%rbx\n\t.e\n\n\t.test\t\"cmovl taken\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t$0x0000000055555550,%rcx\n\tmov\t$0x5555555155555550,%rdx\n\tstc\n\tcmovc\t%ebx,%eax\n\tcmp\t%rcx,%rax\n\t.e\n\tcmp\t%rdx,%rbx\n\t.e\n\n\t.test\t\"cmovl not taken clears upper half\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555555555555,%rbx\n\tmov\t$0x0000000012345678,%rcx\n\tmov\t$0x5555555555555555,%rdx\n\tclc\n\tcmovc\t%ebx,%eax\n\tcmp\t%rcx,%rax\n\t.e\n\tcmp\t%rdx,%rbx\n\t.e\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/cmp.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$10,%r15\n\"test jit too\":\n\n//\tcmp compares registers and memory\n//\tmake -j8 o//blink o//test/asm/cmp.elf\n//\to//blink/blinkenlights -j o//test/asm/cmp.elf\n\n\t.test\t\"cmp hi reg\"\n\tmov\t$3,%bh\n\tmovb\t$3,(%rsp)\n\tcmp\t%bh,(%rsp)\n\t.e\n\n\t.test\t\"cmp jit test\"\n\tmov\t$3,%ecx\n1:\tmov\t$1,%eax\n\tmov\t$1,%ebx\n\tcmp\t%eax,%ebx\n\t.e\n\tloop\t1b\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/cmpxchg.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tcompare and exchange tests\n//\tmake -j8 o//blink o//test/asm/cmpxchg.elf\n//\to//blink/blinkenlights o//test/asm/cmpxchg.elf\n\n\txor\t%ebp,%ebp\n\tand\t$-16,%rsp\n\tpush\t%rbp\n\tmov\t%rsp,%rbp\n\tsub\t$16,%rsp\n\n////////////////////////////////////////////////////////////////////////////////\n//\tlocked\n\n\t.test\t\"lock cmpxchg 64 taken\"\n\tmov\t$0x7fffffff,%eax\n\tadd\t$1,%eax\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rax,-8(%rbp)\n\tlock cmpxchg %rbx,-8(%rbp)\n\t.z\n\t.no\n\t.ns\n\t.nc\n\t.p\n\tmov\t$0x1234567812345678,%rcx\n\tmov\t$0x5555555155555550,%rdx\n\tcmp\t%rcx,%rax\t\t\t# rax stays the same\n\t.e\n\tcmp\t%rdx,%rbx\t\t\t# reg stays the same\n\t.e\n\tcmp\t%rdx,-8(%rbp)\t\t\t# memory got swapped\n\t.e\n\n\t.test\t\"lock cmpxchg 64 not taken\"\n\tmov\t$0x7fffffff,%eax\n\tadd\t$1,%eax\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rbx,-8(%rbp)\n\tlock cmpxchg %rbx,-8(%rbp)\n\t.nz\n\t.no\n\t.s\n\t.c\n\t.p\n\tmov\t$0x5555555155555550,%rdx\n\tcmp\t%rdx,%rax\t\t\t# mem is put in rax\n\t.e\n\tcmp\t%rdx,%rbx\t\t\t# reg stays the same\n\t.e\n\tcmp\t%rdx,-8(%rbp)\t\t\t# memory is the same\n\t.e\n\n\t.test\t\"lock cmpxchg 64 unaligned taken\"\n\tmov\t$0x7fffffff,%eax\n\tadd\t$1,%eax\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rax,-9(%rbp)\n\tlock cmpxchg %rbx,-9(%rbp)\n\t.z\n\t.no\n\t.ns\n\t.nc\n\t.p\n\tmov\t$0x1234567812345678,%rcx\n\tmov\t$0x5555555155555550,%rdx\n\tcmp\t%rcx,%rax\t\t\t# rax stays the same\n\t.e\n\tcmp\t%rdx,%rbx\t\t\t# reg stays the same\n\t.e\n\tcmp\t%rdx,-9(%rbp)\t\t\t# memory got swapped\n\t.e\n\n\"are we running in qemu\":\n\tmov\t$0x40000001,%eax\n\tcpuid\n\tcmp\t%ebx,qemu\n\tje\t\"qemu cmpxchg 32 broken\"\n\t.exit\n\n\t.test\t\"lock cmpxchg 32 taken\"\n\tmov\t$0x7fffffff,%eax\n\tadd\t$1,%eax\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rax,-8(%rbp)\n\tlock cmpxchg %ebx,-8(%rbp)\n\t.z\n\t.p\n\t.ns\n\t.nc\n\t.no\n\tmov\t$0x1234567812345678,%rcx\n\tmov\t$0x5555555155555550,%rdx\n\tmov\t$0x1234567855555550,%r8\n\tcmp\t%rcx,%rax\t\t\t# rax stays the same\n\t.e\t\t\t\t\t# is NOT upper zerod\n\tcmp\t%rdx,%rbx\t\t\t# reg stays the same\n\t.e\t\t\t\t\t# is NOT upper zerod\n\tcmp\t%r8,-8(%rbp)\t\t\t# memory got swapped\n\t.e\n\n\"qemu cmpxchg 32 broken\":\n\n\t.test\t\"lock cmpxchg 32 not taken\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rbx,-8(%rbp)\n\tlock cmpxchg %ebx,-8(%rbp)\n\t.nz\n\t.p\n\t.s\n\t.c\n\t.no\n\tmov\t$0x0000000055555550,%rdx\t# mem is put in rax\n\tcmp\t%rdx,%rax\n\t.e\n\tmov\t$0x5555555155555550,%rdx\t# reg stays the same\n\tcmp\t%rdx,%rbx\n\t.e\n\tcmp\t%rdx,-8(%rbp)\t\t\t# memory is the same\n\t.e\n\n\t.test\t\"lock cmpxchg 8 taken\"\n\tmov\t$0x7fffffff,%eax\n\tadd\t$1,%eax\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rax,-8(%rbp)\n\tlock cmpxchg %bl,-8(%rbp)\n\t.z\n\t.p\n\t.ns\n\t.nc\n\t.no\n\tmov\t$0x1234567812345678,%rcx\n\tmov\t$0x5555555155555550,%rdx\n\tmov\t$0x1234567812345650,%r8\n\tcmp\t%rcx,%rax\t\t\t# rax stays the same\n\t.e\t\t\t\t\t# is NOT upper zerod\n\tcmp\t%rdx,%rbx\t\t\t# reg stays the same\n\t.e\t\t\t\t\t# is NOT upper zerod\n\tcmp\t%r8,-8(%rbp)\t\t\t# memory got swapped\n\t.e\n\n\t.test\t\"lock cmpxchg 8 not taken\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rbx,-8(%rbp)\n\tlock cmpxchg %bl,-8(%rbp)\n\t.nz\n\t.p\n\t.ns\n\t.nc\n\t.no\n\tmov\t$0x1234567812345650,%rdx\t# mem is put in rax\n\tcmp\t%rdx,%rax\n\t.e\n\tmov\t$0x5555555155555550,%rdx\t# reg stays the same\n\tcmp\t%rdx,%rbx\n\t.e\n\tcmp\t%rdx,-8(%rbp)\t\t\t# memory is the same\n\t.e\n\n////////////////////////////////////////////////////////////////////////////////\n//\tunlocked\n\n\t.test\t\"cmpxchg 64 taken\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rax,-8(%rbp)\n\tcmpxchg\t%rbx,-8(%rbp)\n\t.z\n\tmov\t$0x1234567812345678,%rcx\n\tmov\t$0x5555555155555550,%rdx\n\tcmp\t%rcx,%rax\t\t\t# rax stays the same\n\t.e\n\tcmp\t%rdx,%rbx\t\t\t# reg stays the same\n\t.e\n\tcmp\t%rdx,-8(%rbp)\t\t\t# memory got swapped\n\t.e\n\n\t.test\t\"cmpxchg 64 not taken\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rbx,-8(%rbp)\n\tcmpxchg\t%rbx,-8(%rbp)\n\t.nz\n\tmov\t$0x5555555155555550,%rdx\n\tcmp\t%rdx,%rax\t\t\t# mem is put in rax\n\t.e\n\tcmp\t%rdx,%rbx\t\t\t# reg stays the same\n\t.e\n\tcmp\t%rdx,-8(%rbp)\t\t\t# memory is the same\n\t.e\n\n\t.test\t\"cmpxchg 32 taken\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rax,-8(%rbp)\n\tcmpxchg\t%ebx,-8(%rbp)\n\t.z\n\tmov\t$0x1234567812345678,%rcx\n\tmov\t$0x5555555155555550,%rdx\n\tmov\t$0x1234567855555550,%r8\n\tcmp\t%rcx,%rax\t\t\t# rax stays the same\n\t.e\t\t\t\t\t# is NOT upper zerod\n\tcmp\t%rdx,%rbx\t\t\t# reg stays the same\n\t.e\t\t\t\t\t# is NOT upper zerod\n\tcmp\t%r8,-8(%rbp)\t\t\t# memory got swapped\n\t.e\n\n\t.test\t\"cmpxchg 32 not taken\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rbx,-8(%rbp)\n\tcmpxchg\t%ebx,-8(%rbp)\n\t.nz\n\tmov\t$0x0000000055555550,%rdx\t# mem is put in rax\n\tcmp\t%rdx,%rax\n\t.e\n\tmov\t$0x5555555155555550,%rdx\t# reg stays the same\n\tcmp\t%rdx,%rbx\n\t.e\n\tcmp\t%rdx,-8(%rbp)\t\t\t# memory is the same\n\t.e\n\n\"test succeeded\":\n\t.exit\n\nqemu:\t.ascii\t\"TCGTCGTCGTCG\"\n"
  },
  {
    "path": "test/asm/cmpxchg16b.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tcompare and exchange tests\n//\tmake -j8 o//blink o//test/asm/cmpxchg16b.elf\n//\to//blink/blinkenlights o//test/asm/cmpxchg16b.elf\n\n\tmov\t$0,%rax\n\tmov\t%rax,-16(%rsp)\n\tmov\t%rax,-8(%rsp)\n\n\t.test\t\"lock cmpxchg16b 64 not taken\"\n//\tif memory is equal to me\n\tmov\t$0x5555555155555550,%rdx\n\tmov\t$0x1234567812345678,%rax\n//\treplace it with me\n\tmov\t$0x5500005155550050,%rcx\n\tmov\t$0x1200067810000078,%rbx\n\tlock cmpxchg16b -16(%rsp)\n\t.nz\n\tcmp\t$0,%rdx\n\t.z\n\tcmp\t$0,%rax\n\t.z\n\n\t.test\t\"lock cmpxchg16b 64 taken\"\n//\tif memory is equal to me\n\tmov\t$0x5555555155555550,%rdx\n\tmov\t$0x1234567812345678,%rax\n\tmov\t%rax,-16(%rsp)\n\tmov\t%rdx,-8(%rsp)\n//\treplace it with me\n\tmov\t$0x5500005155550050,%rcx\n\tmov\t$0x1200067810000078,%rbx\n\tlock cmpxchg16b -16(%rsp)\n\t.z\n\tcmp\t%rbx,-16(%rsp)\n\t.z\n\tcmp\t%rcx,-8(%rsp)\n\t.z\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/enter.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/asm/enter.elf\n//\to//blink/blinkenlights o//test/asm/enter.elf\n\n#define MAGIC1\t\t0x2b8cfa3db6a78c9a\n#define MAGIC2\t\t0x58b8\n#define MAGIC3\t\t0x225e\n#define MAGIC4\t\t0x4ea0\n\n\t.test\t\"enterq stores frame pointer of size 8\"\n\tmovabs\t$MAGIC1,%rbx\n\tlea\t-8-MAGIC2(%rsp),%rax\n\tlea\t-8(%rsp),%rcx\n\tmov\t%rsp,%rdx\n\n\tmov\t%rbx,%rbp\n\tenterq\t$MAGIC2,$0\n\tcmp\t%rsp,%rax\n\t.e\n\tcmp\t%rbp,%rcx\n\t.e\n\tcmp\t(%rbp),%rbx\n\t.e\n\n\t.test\t\"leaveq restores frame pointer of size 8\"\n\tleaveq\n\tcmp\t%rdx,%rsp\n\t.e\n\tcmp\t%rbx,%rbp\n\t.e\n\n\t.test\t\"enterw stores frame pointer of size 2\"\n\txor\t%sp,%sp\t\t\t// make sure %sp does not wrap\n\tsub\t$8,%rsp\t\t\t// around 64 KiB boundary\n\n\tmov\t%rsp,%rbx\n\tmov\t$MAGIC3,%bx\n\tlea\t-2-MAGIC4(%rsp),%rax\n\tlea\t-2(%rsp),%rcx\n\tmov\t%rsp,%rdx\n\n\tmov\t%rbx,%rbp\n\tenterw\t$MAGIC4,$0\n\tcmp\t%rsp,%rax\n\t.e\n\tcmp\t%rbp,%rcx\n\t.e\n\tcmp\t(%rbp),%bx\n\t.e\n\n\t.test\t\"leavew restores frame pointer of size 2\"\n\tleavew\n\tcmp\t%rdx,%rsp\n\t.e\n\tmov\t%bx,%dx\n\tcmp\t%rdx,%rbp\n\t.e\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/exit.S",
    "content": "//\texit(0) example\n//\tmake -j8 o//blink o//test/asm/exit.elf\n//\to//blink/blinkenlights o//test/asm/exit.elf\n\n\t.globl\t_start\n_start:\tmov\t$0,%edi\n\tmov\t$231,%eax\n\tsyscall\n"
  },
  {
    "path": "test/asm/lahf.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/asm/lahf.elf\n//\to//blink/blinkenlights o//test/asm/lahf.elf\n\n\t.test\t\"LAHF stores flags into AH\"\n\tmov\t$0x7fffffff,%eax\n\tadd\t$4,%eax\n\t.sop\n\tmov\t$-1,%eax\n\tlahf\n\n//\twe need to remove AF from the result to be\n//\tconsistent with the actual hardware result\n//\n//\t                              cf ──┐\n//\t                              1 ──┐│\n//\t                            pf ──┐││\n//\t                            0 ──┐│││\n//\t                          af ──┐││││\n//\t                          0 ──┐│││││\n//\t                        zf ──┐││││││\n//\t                       sf ──┐│││││││\n//\t                            ││││││││\n\tand\t$0b11111111111111111111011111111111,%eax\n\tcmp\t$0b11111111111111111001011011111111,%eax\n\t.e\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/lock.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/asm/lock.elf\n//\to//blink/blinkenlights o//test/asm/lock.elf\n\n\t.test\t\"lock aligned\"\n\tmovl\t$0,(%rsp)\n\tlock incl (%rsp)\n\tlock incl (%rsp)\n\tcmpl\t$2,(%rsp)\n\t.e\n\n\t.test\t\"lock misaligned\"\n\tmovl\t$0,1(%rsp)\n\tlock incl 1(%rsp)\n\tlock incl 1(%rsp)\n\tcmpl\t$2,1(%rsp)\n\t.e\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/mac.inc",
    "content": "// -*- mode: unix-assembly; indent-tabs-mode: t; tab-width: 8; coding: utf-8 -*-\n\n\t.macro\t.exit\n\tmov\t$0,%edi\n\tmov\t$231,%eax\n\tsyscall\n\t.endm\n\n\t.macro\t.test name:req\nprologue\\@:\n\tjmp\t101f\n100:\tint3\n101:\tnop\n\"\\name\":\n\t.endm\n\n\t.macro\t.c\n\tjnc\t100b\n\t.endm\n\t.macro\t.nc\n\tjc\t100b\n\t.endm\n\n\t.macro\t.e\n\tjne\t100b\n\t.endm\n\t.macro\t.ne\n\tje\t100b\n\t.endm\n\n\t.macro\t.z\n\tjnz\t100b\n\t.endm\n\t.macro\t.nz\n\tjz\t100b\n\t.endm\n\n\t.macro\t.s\n\tjns\t100b\n\t.endm\n\t.macro\t.ns\n\tjs\t100b\n\t.endm\n\n\t.macro\t.o\n\tjno\t100b\n\t.endm\n\t.macro\t.no\n\tjo\t100b\n\t.endm\n\n\t.macro\t.p\n\tjnp\t100b\n\t.endm\n\t.macro\t.np\n\tjp\t100b\n\t.endm\n\n\t.macro\t.sop\n\t.nz\n\t.s\n\t.nc\n\t.o\n\t.p\n\t.endm\n"
  },
  {
    "path": "test/asm/movi.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$3,%r15\n\"test jit too\":\n\n//\timmediate moves\n//\tmake -j8 o//blink o//test/asm/movi.elf\n//\to//blink/blinkenlights o//test/asm/movi.elf\n\n\t.test\t\"mov imm reg 32\"\n\tmov\t$0x3133731337,%rax\n\tmov\t$0x3133731337,%rdx\n\tmov\t$0x31337,%eax\n\tmov\t$0x31337,%edx\n\tpush\t$0x31337\n\tpop\t%r8\n\tcmp\t%r8,%rax\n\t.e\n\tcmp\t%r8,%rdx\n\t.e\n\n\t.test\t\"mov imm reg 16\"\n\tmov\t$0x3133731337,%rax\n\tmov\t$0x3133731337,%rdx\n\tmov\t$0xdead,%ax\n\tmov\t$0xdead,%dx\n\tmov\t$0x313373dead,%r8\n\tcmp\t%r8,%rax\n\t.e\n\tcmp\t%r8,%rdx\n\t.e\n\n\t.test\t\"mov imm reg 8\"\n\tmov\t$0x3133731337,%rax\n\tmov\t$0x3133731337,%rdx\n\tmov\t$0xbb,%al\n\tmov\t$0xcc,%dh\n\tmov\t$0x31337313bb,%r8\n\tcmp\t%r8,%rax\n\t.e\n\tmov\t$0x313373cc37,%r8\n\tcmp\t%r8,%rdx\n\t.e\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/movmskpd.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$3,%r15\n\"test jit too\":\n\n//\textract floating point sign mask\n//\tmake -j8 o//blink o//test/asm/movmskpd.elf\n//\to//blink/blinkenlights o//test/asm/movmskpd.elf\n\n\t.test\t\"movmskpd neg neg\"\n\tmovaps\tnegneg(%rip),%xmm0\n\tmovmskpd %xmm0,%eax\n\tcmp\t$0b11,%eax\n\t.e\n\n\t.test\t\"movmskpd neg pos\"\n\tmovaps\tnegpos(%rip),%xmm0\n\tmovmskpd %xmm0,%eax\n\tcmp\t$0b01,%eax\n\t.e\n\n\t.test\t\"movmskpd pos pos\"\n\tmovaps\tpospos(%rip),%xmm0\n\tmovmskpd %xmm0,%eax\n\tcmp\t$0b00,%eax\n\t.e\n\n\t.test\t\"movmskps neg neg neg neg\"\n\tmovaps\tnnnn(%rip),%xmm0\n\tmovmskps %xmm0,%eax\n\tcmp\t$0b1111,%eax\n\t.e\n\n\t.test\t\"movmskps neg pos neg pos\"\n\tmovaps\tnpnp(%rip),%xmm0\n\tmovmskps %xmm0,%eax\n\tcmp\t$0b0101,%eax\n\t.e\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n\n\t.section .rodata\n\t.align\t16\nnegneg:\t.double\t-1.1, -2.2\nnegpos:\t.double\t-1.1, +2.2\npospos:\t.double\t+1.1, +2.2\nnnnn:\t.float\t-1.1, -2.2, -2.2, -4.2\nnpnp:\t.float\t-1.1, +2.2, -2.2, +4.2\n"
  },
  {
    "path": "test/asm/movntdq.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$10,%r15\n\"test jit too\":\n\n//\tnon-temporal move\n//\tmake -j8 o//blink o//test/asm/movntdq.elf\n//\to//blink/blinkenlights o//test/asm/movntdq.elf\n\n\t.test\t\"movntdq\"\n\tmovdqa\tdata,%xmm12\n\tmovntdq\t%xmm12,(%rsp)\n\tcmpq\t$123,(%rsp)\n\t.e\n\tcmpq\t$456,8(%rsp)\n\t.e\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n\n\t.align\t16\ndata:\t.quad\t123\n\t.quad\t456\n"
  },
  {
    "path": "test/asm/movsreg.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$3,%r15\n\"test jit too\":\n\n//\tmake -j8 o//blink o//test/asm/movsreg.elf\n//\to//blink/blinkenlights -j o//test/asm/movsreg.elf\n\n\t.test\t\"mov cs\"\n\tmov\t%cs,%eax\n\tmov\t%al,%dl\n\tand\t$3,%dl\n\tcmp\t$3,%dl\t\t\t// default cs should have RPL 3\n\t.e\n\n\tshr\t$2,%ax\t\t\t// default cs should not be null\n\t.ne\n\n\t.test\t\"mov ss\"\n\tmov\t%ss,%eax\n\tmov\t%al,%dl\n\tand\t$3,%dl\n\tcmp\t$3,%dl\t\t\t// default ss should have RPL 3\n\t.e\n\n\tshr\t$2,%ax\n\t.ne\t\t\t\t// default ss should not be null\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/movsxd.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$5,%r15\n\"test jit too\":\n\n//\tsign extending moves\n//\tmake -j8 o//blink o//test/asm/movsxd.elf\n//\to//blink/blinkenlights o//test/asm/movsxd.elf\n\n\t.test\t\"sign extend 32-bit to 32-bit\"\n\tpush\t$-2147483648\n\t.byte\t0x63,0x04,0x24\t\t\t# movsll (%rsp),%eax\n\tmovabs\t$0x0000000080000000,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\n\t.test\t\"sign extend 32-bit to 64-bit\"\n\tpush\t$-2147483648\n\tmovslq\t(%rsp),%rax\n\tmov\t$0xffffffff80000000,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\n\tsub\t$1,%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/movz.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$3,%r15\n\"test jit too\":\n\n//\tzero-extending moves\n//\tmake -j8 o//blink o//test/asm/cmp.elf\n//\to//blink/blinkenlights -j o//test/asm/cmp.elf\n\n\t.test\t\"movzbl reg\"\n\tmov\t$0x0102030405060708,%rax\n\tmovzbl\t%al,%eax\n\tmov\t$0x0000000000000008,%rbx\n\tcmp\t%rbx,%rax\n\t.e\n\n\t.test\t\"movzwl reg\"\n\tmov\t$0x0102030405060708,%rax\n\tmovzwl\t%ax,%eax\n\tmov\t$0x0000000000000708,%rbx\n\tcmp\t%rbx,%rax\n\t.e\n\n\t.test\t\"movzwl mem\"\n\tmov\t$0x0102030405060708,%rax\n\tmov\t%rax,(%rsp)\n\tor\t$-1,%rax\n\tmovzwl\t(%rsp),%eax\n\tmov\t$0x0000000000000708,%rbx\n\tcmp\t%rbx,%rax\n\t.e\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/mulx.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$10,%r15\n\"test jit too\":\n\n//\tunsigned multiply w/o affecting flags\n//\tmake -j8 o//blink o//test/asm/mulx.elf\n//\to//blink/blinkenlights o//test/asm/mulx.elf\n\n\tmov\t$7,%eax\t\t\t# extended features\n\txor\t%ecx,%ecx\n\tcpuid\n\tbt\t$8,%ebx\t\t\t# bmi2\n\tjnc\t\"test not possible\"\n\n\t.test\t\"mulx 1\"\n\tmov\t$2,%eax\n\tmov\t$3,%ebx\n\tmov\t$4,%ecx\n\tmov\t$5,%edx\n\tmulx\t%eax,%ebx,%ecx\n\tcmp\t$2,%eax\t\t# unchanged\n\t.e\n\tcmp\t$5,%edx\t\t# unchanged\n\t.e\n\tcmp\t$10,%ebx\t# (2 * 5) & 0xffffffff\n\t.e\n\tcmp\t$0,%ecx\t\t# (2 * 5) >> 32\n\t.e\n\n\t.test\t\"mulx 2\"\n\tmov\t$2,%r10d\n\tmov\t$3,%ebx\n\tmov\t$4,%ecx\n\tmov\t$5,%edx\n\tmulx\t%r10d,%ebx,%ecx\n\tcmp\t$2,%r10d\t# unchanged\n\t.e\n\tcmp\t$5,%edx\t\t# unchanged\n\t.e\n\tcmp\t$10,%ebx\t# (2 * 5) & 0xffffffff\n\t.e\n\tcmp\t$0,%ecx\t\t# (2 * 5) >> 32\n\t.e\n\n\t.test\t\"mulx 3\"\n\tmov\t$2,%eax\n\tmov\t$3,%r10d\n\tmov\t$4,%ecx\n\tmov\t$5,%edx\n\tmulx\t%eax,%r10d,%ecx\n\tcmp\t$2,%eax\t\t# unchanged\n\t.e\n\tcmp\t$5,%edx\t\t# unchanged\n\t.e\n\tcmp\t$10,%r10d\t# (2 * 5) & 0xffffffff\n\t.e\n\tcmp\t$0,%ecx\t\t# (2 * 5) >> 32\n\t.e\n\n\t.test\t\"mulx 4\"\n\tmov\t$2,%eax\n\tmov\t$3,%ebx\n\tmov\t$4,%r10d\n\tmov\t$5,%edx\n\tmulx\t%eax,%ebx,%r10d\n\tcmp\t$2,%eax\t\t# unchanged\n\t.e\n\tcmp\t$5,%edx\t\t# unchanged\n\t.e\n\tcmp\t$10,%ebx\t# (2 * 5) & 0xffffffff\n\t.e\n\tcmp\t$0,%r10d\t# (2 * 5) >> 32\n\t.e\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n\"test not possible\":\n\t.exit\n"
  },
  {
    "path": "test/asm/nop.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/asm/nop.elf\n//\to//blink/blinkenlights o//test/asm/nop.elf\n\n\tnop\n\tnopl\t(%rax)\n\tnop\n\tnop\n\tnopl\t(%rax)\n\tnop\n\tnopl\t(%rax)\n\tnop\n\tnop\n\n\tpush\t$0\n\tmov\t%rsp,%rdi\n\txchg\t(%rdi),%r12\n\n\t.test\t\"nop doesn't clear high bits of %rax\"\n\tmov\t$0x0102030405060708,%rax\n\tmov\t%rax,%rbx\n\tnop\n\tcmp\t%rbx,%rax\n\t.e\n\n\t.test\t\"rexb nop clears high bits and swaps with %r8d\"\n\tmov\t$0x7172737475767778,%r8\n\trex.b\n\tnop\n\tmov\t$0x0000000075767778,%rbx\n\tcmp\t%rbx,%rax\n\t.e\n\tmov\t$0x0000000005060708,%rbx\n\tcmp\t%rbx,%r8\n\t.e\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/overflow.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$3,%r15\n\"test jit too\":\n\n//\tmake -j8 o//blink o//test/asm/overflow.elf\n//\to//blink/blinkenlights o//test/asm/overflow.elf\n\n////////////////////////////////////////////////////////////////////////////////\n// ADD INSTRUCTION\n\n\t.test\t\"overflow add 64\"\n\txor\t%eax,%eax\n\tmov\t$0x7ffffffffffffffe,%rax\n\tadd\t$1,%rax\n\t.no\n\tadd\t$1,%rax\n\t.o\n\n\t.test\t\"overflow add 32\"\n\txor\t%eax,%eax\n\tmov\t$0x7ffffffe,%eax\n\tadd\t$1,%eax\n\t.no\n\tadd\t$1,%eax\n\t.o\n\n\t.test\t\"overflow add 16\"\n\txor\t%ax,%ax\n\tmov\t$0x7ffe,%ax\n\tadd\t$1,%ax\n\t.no\n\tadd\t$1,%ax\n\t.o\n\n\t.test\t\"overflow add lo\"\n\txor\t%al,%al\n\tmov\t$0x7e,%al\n\tadd\t$1,%al\n\t.no\n\tadd\t$1,%al\n\t.o\n\n\t.test\t\"overflow add hi\"\n\txor\t%ah,%ah\n\tmov\t$0x7e,%ah\n\tadd\t$1,%ah\n\t.no\n\tadd\t$1,%ah\n\t.o\n\n////////////////////////////////////////////////////////////////////////////////\n// SUB INSTRUCTION\n\n\t.test\t\"overflow sub 64\"\n\txor\t%eax,%eax\n\tmov\t$0x7ffffffffffffffe,%rax\n\tsub\t$-1,%rax\n\t.no\n\tsub\t$-1,%rax\n\t.o\n\n\t.test\t\"overflow sub 32\"\n\txor\t%eax,%eax\n\tmov\t$0x7ffffffe,%eax\n\tsub\t$-1,%eax\n\t.no\n\tsub\t$-1,%eax\n\t.o\n\n\t.test\t\"overflow sub 16\"\n\txor\t%ax,%ax\n\tmov\t$0x7ffe,%ax\n\tsub\t$-1,%ax\n\t.no\n\tsub\t$-1,%ax\n\t.o\n\n\t.test\t\"overflow sub lo\"\n\txor\t%al,%al\n\tmov\t$0x7e,%al\n\tsub\t$-1,%al\n\t.no\n\tsub\t$-1,%al\n\t.o\n\n\t.test\t\"overflow sub hi\"\n\txor\t%ah,%ah\n\tmov\t$0x7e,%ah\n\tsub\t$-1,%ah\n\t.no\n\tsub\t$-1,%ah\n\t.o\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/page.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tmemory page tests\n//\tmake -j8 o//blink o//test/asm/page.elf\n//\to//blink/blinkenlights o//test/asm/page.elf\n\n\tsub\t$8,%rsp\n\tand\t$-4096,%rsp\n\n\t.test\t\"read/write page overlap\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t%rax,-1(%rsp)\n\tmov\t-1(%rsp),%rbx\n\tcmp\t%rbx,%rax\n\t.e\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/push.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/asm/push.elf\n//\to//blink/blinkenlights o//test/asm/push.elf\n\n\tsub\t$1,%rsp\n\n\t.test\t\"push moves stack by 8\"\n\tmov\t%rsp,%rax\n\tpush\t%rax\n\tmov\t%rsp,%rbx\n\tsub\t%rbx,%rax\n\tcmp\t$8,%rax\n\t.e\n\n\t.test   \"asz does not affect stack pointer size for push\"\n\tmov\t%rsp,%rax\n\torq\t$-1,-8(%rsp)\n\taddr32 push %rax\n\tmov\t%rsp,%rbx\n\tcmp\t%rax,(%rbx)\n\t.e\n\tsub\t%rbx,%rax\n\tcmp\t$8,%rax\n\t.e\n\n\t.test\t\"osz push moves stack by 2\"\n\tmov\t%rsp,%rax\n\tpushw\t$0x439d\n\tmov\t%rsp,%rbx\n\tsub\t%rbx,%rax\n\tcmp\t$2,%rax\n\t.e\n\n\t.test\t\"osz push changes two bytes\"\n\txor\t%eax,%eax\n\tmov\t%rsp,%rbp\n\tmovl\t$0xffffffff,-4(%rbp)\n\tpush\t%ax\n\tcmpl\t$0x0000ffff,-4(%rbp)\n\t.e\n\n\t.test\t\"osz pop changes low two bytes only\"\n\tor\t$-1,%rax\n\tpop\t%ax\n\tmov\t$0xffffffffffff0000,%rbx\n\tcmp\t%rbx,%rax\n\t.e\n\n\t.test   \"asz does not affect stack pointer size for pop\"\n\taddr32 pop %ax\n\tmov\t$0xffffffffffff439d,%rbx\n\tcmp\t%rbx,%rax\n\t.e\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/repmovsb.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\trep movsb\n//\tmake -j8 o//blink o//test/asm/repmovsb.elf\n//\to//blink/blinkenlights o//test/asm/repmovsb.elf\n\n\t.test\t\"rep movsb\"\n\tor\t$0,A1\n\tlea\tA1+4,%rdi\n\tlea\tA1,%rsi\n\tmov\t$A2-A1-4,%rcx\n\trep movsb\n\tlea\tA1-1,%rdi\n\tlea\tB1-1,%rsi\n\tmov\t$A2-A1+2,%rcx\n\trepz cmpsb\n\t.e\n\n\t.test\t\"reverse rep movsb\"\n\tor\t$0,C1\n\tlea\tC1+(C2-C1-4),%rdi\n\tlea\tC1+(C2-C1-1),%rsi\n\tmov\t$C2-C1-3,%rcx\n\tstd\n\trep movsb\n\tcld\n\tlea\tC1-1,%rdi\n\tlea\tD1-1,%rsi\n\tmov\t$C2-C1+2,%rcx\n\trepz cmpsb\n\t.e\n\n\"test succeeded\":\n\t.exit\n\n\t.data\n\n//\ttest case 1\n\t.align\t64\n\t.byte\t0\n\t.align\t64\nA1:\t.ascii\t\"hello world!\"\nA2:\n\t.align\t64\nB1:\t.ascii\t\"hellhellhell\"\nB2:\t.byte\t0\n\t.align\t64\n\n//\ttest case 2\n\t.align\t64\n\t.byte\t0\n\t.align\t64\nC1:\t.ascii\t\"hello world!\"\nC2:\n\t.align\t64\nD1:\t.ascii\t\"ld!ld!ld!ld!\"\nD2:\t.byte\t0\n\t.align\t64\n"
  },
  {
    "path": "test/asm/rol.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\tleft rotate (rol) example\n//\tmake -j8 o//blink o//test/asm/rol.elf\n//\to//blink/blinkenlights o//test/asm/rol.elf\n\n\t.test\t\"rol1\"\n\tstc\n\tmov\t$1,%eax\n\trol\t$0,%eax\n\t.c\n\tcmp\t$1,%eax\n\t.e\n\n\t.test\t\"rol2\"\n\tclc\n\tmov\t$1,%eax\n\trol\t$0,%eax\n\t.nc\n\t.no\n\tcmp\t$1,%eax\n\t.e\n\n\t.test\t\"rol3\"\n\tclc\n\tmov\t$0x0000000080000000,%rax\n\tmov\t$1,%cl\n\trol\t%cl,%rax\n\t.nc\n\t.no\n\tmov\t$0x0000000100000000,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\n\t.test\t\"rol4\"\n\tclc\n\tmov\t$0x0000000080000000,%rax\n\trol\t%rax\n\t.nc\n\t.no\n\tmov\t$0x0000000100000000,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\n\t.test\t\"rol5\"\n\tmov\t$1,%eax\n\trol\t$1,%eax\n\t.nc\n\t.no\n\tcmp\t$2,%eax\n\t.e\n\n\t.test\t\"rol 32-bit by 1\"\n\tmov\t$0x8000000080000000,%rax\n\trol\t%eax\n\t.c\n\t.o\n\tmov\t$0x0000000000000001,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\n\t.test\t\"rol 16-bit doesn't zero extend\"\n\tmov\t$0x8000000000008000,%rax\n\trol\t%ax\n\t.c\n\t.o\n\tmov\t$0x8000000000000001,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\n\t.test\t\"rol 8-bit doesn't zero extend\"\n\tmov\t$0x8000000000000080,%rax\n\trol\t%al\n\t.c\n\t.o\n\tmov\t$0x8000000000000001,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\n\t.test\t\"rol 8-bit hi register\"\n\tmov\t$0x8000000000008007,%rax\n\trol\t%ah\n\t.c\n\t.o\n\tmov\t$0x8000000000000107,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\n\t.test\t\"rol 8-bit rex register\"\n\tmov\t$0x8000000000000080,%rdi\n\trol\t%dil\n\t.c\n\t.o\n\tmov\t$0x8000000000000001,%rcx\n\tcmp\t%rcx,%rdi\n\t.e\n\n\t.test\t\"rolq by 2\"\n\tmov\t$0b1000000000000000000000000000000000000000000000001000000000000111,%rax\n\trol\t$2,%rax\n\t.nc\n\tmov\t$0b0000000000000000000000000000000000000000000000100000000000011110,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\n\t.test\t\"rolq by 2 carry\"\n\tmov\t$0b0100000000000000000000000000000000000000000000001000000000000111,%rax\n\trol\t$2,%rax\n\t.c\n\tmov\t$0b0000000000000000000000000000000000000000000000100000000000011101,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\n\t.test\t\"rol64imm(1,1) == 2\"\n\tmov\t$1,%rax\n\trol\t$1,%rax\n\tcmp\t$2,%rax\n\t.e\n\n\t.test\t\"rol32imm(0x1234ul<<32|(u32)INT_MIN,1) == 1\"\n\tmov\t$0x123480000000,%rax\n\trol\t$1,%eax\n\tcmp\t$1,%rax\n\t.e\n\n\t.test\t\"rol32(0x1234ul<<32|(u32)INT_MIN,0x1234ul<<32|(u32)1) == 1\"\n\tmov\t$0x123480000000,%rax\n\tmov\t$0x123400000001,%rcx\n\trol\t%cl,%eax\n\tcmp\t$1,%rax\n\t.e\n\tmov\t$0x123400000001,%rax\n\tcmp\t%rax,%rcx\n\t.e\n\n\t.test\t\"prepare for rol flags test\"\n\tmov\t$0x7fffffff,%eax\n\tadd\t$4,%eax\n\t.sop\n\t.test\t\"rol32 doesn't change flags if count is zero (imm)\"\n\trol\t$0,%eax\n\t.sop\n\t.test\t\"If the masked count is 0, the flags are not affected (32-bit imm)\"\n\trol\t$0xffffffe0,%eax\n\t.sop\n\t.test\t\"If the masked count is 0, the flags are not affected (16-bit imm)\"\n\trol\t$0xffffffe0,%ax\n\t.sop\n\t.test\t\"If the masked count is 0, the flags are not affected (8-bit imm)\"\n\trol\t$0xffffffe0,%ax\n\t.sop\n\t.test\t\"rol32 doesn't change flags if count is zero (cl)\"\n\tmov\t$0,%cl\n\trol\t%cl,%eax\n\t.sop\n\t.test\t\"rol16 doesn't change flags if count is zero (imm)\"\n\trol\t$0,%ax\n\t.sop\n\t.test\t\"rol16 doesn't change flags if count is zero (cl)\"\n\tmov\t$0,%cl\n\trol\t%cl,%ax\n\t.sop\n\t.test\t\"rol8 doesn't change flags if count is zero (imm)\"\n\trol\t$0,%al\n\t.sop\n\t.test\t\"rol8 doesn't change flags if count is zero (cl)\"\n\tmov\t$0,%cl\n\trol\t%cl,%al\n\t.sop\n\t.test\t\"rolb doesn't change flags if count is zero (mem imm)\"\n\trolb\t$0,(%rsp)\n\t.sop\n\t.test\t\"rolw doesn't change flags if count is zero (mem imm)\"\n\trolw\t$0,(%rsp)\n\t.sop\n\t.test\t\"roll doesn't change flags if count is zero (mem imm)\"\n\troll\t$0,(%rsp)\n\t.sop\n\t.test\t\"rolq doesn't change flags if count is zero (mem imm)\"\n\trolq\t$0,(%rsp)\n\t.sop\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/rorx.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$10,%r15\n\"test jit too\":\n\n//\trol w/o flags\n//\tmake -j8 o//blink o//test/asm/rorx.elf\n//\to//blink/blinkenlights o//test/asm/rorx.elf\n\n\tmov\t$7,%eax\t\t\t# extended features\n\txor\t%ecx,%ecx\n\tcpuid\n\tbt\t$8,%ebx\t\t\t# bmi2\n\tjnc\t\"test not possible\"\n\n\t.test\t\"rorx 1\"\n\tstc\n\tmov\t$0xf0000fff,%eax\t# input value\n\tmov\t$0x31337133,%ebx\t# random data\n\trorx\t$4*2,%eax,%ebx\n\t.c\n\tcmp\t$0xf0000fff,%eax\t# unchanged\n\t.e\n\tcmp\t$0xfff0000f,%ebx\t# output value\n\t.e\n\n\t.test\t\"rorx $0 does nothing\"\n\tstc\n\tmov\t$0xf0000fff,%eax\t# input value\n\tmov\t$0x31337133,%ebx\t# random data\n\trorx\t$0,%eax,%ebx\n\t.c\n\tcmp\t$0xf0000fff,%eax\t# unchanged\n\t.e\n\tcmp\t$0xf0000fff,%ebx\t# output value\n\t.e\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n\"test not possible\":\n\t.exit\n"
  },
  {
    "path": "test/asm/setcc.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$5,%r15\n\"test jit too\":\n\n//\tcondition code moves\n//\tmake -j8 o//blink o//test/asm/setcc.elf\n//\to//blink/blinkenlights o//test/asm/setcc.elf\n\n\t.test\t\"set carry reg true\"\n\tor\t$-1,%eax\n\tstc\n\tsetc\t%al\n\tcmp\t$1,%al\n\t.e\n\n\t.test\t\"set carry reg false\"\n\tor\t$-1,%eax\n\tclc\n\tsetc\t%ah\n\tcmp\t$0,%ah\n\t.e\n\n\t.test\t\"set carry reg doesn't extend\"\n\tor\t$-1,%eax\n\tstc\n\tsetc\t%al\n\tcmp\t$0xffffff01,%eax\n\t.e\n\n\t.test\t\"set carry mem\"\n\tmovl\t$-1,(%rsp)\n\tstc\n\tsetc\t(%rsp)\n\tcmpl\t$0xffffff01,(%rsp)\n\t.e\n\n\t.test\t\"set carry reg true r14\"\n\tstc\n\tsetc\t%r14b\n\tcmp\t$1,%r14b\n\t.e\n\n\tsub\t$1,%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/asm/shufpd.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$3,%r15\n\"test jit too\":\n\n//\tpacked interleave shuffle of pairs of double floats\n//\tmake -j8 o//blink o//test/asm/shufpd.elf\n//\to//blink/blinkenlights o//test/asm/shufpd.elf\n\n\t.test\t\"shufpd $1 A==B\"\n\tmovaps\tA,%xmm0\n\tshufpd\t$1,%xmm0,%xmm0\n\tmovq\t%xmm0,%rax\t\t\t# test lower half\n\tcmp\t%rax,B+0\n\t.e\n\tpunpckhqdq %xmm0,%xmm0\t\t\t# test upper half\n\tmovq\t%xmm0,%rax\n\tcmp\t%rax,B+8\n\t.e\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n\n\t.section .rodata\n\t.align\t16\nA:\t.quad\t1,2\nB:\t.quad\t2,1\n"
  },
  {
    "path": "test/asm/shx.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$10,%r15\n\"test jit too\":\n\n//\tsarx/shlx/shrx -- shift w/o flags\n//\tmake -j8 o//blink o//test/asm/shx.elf\n//\to//blink/blinkenlights o//test/asm/shx.elf\n\n\tmov\t$7,%eax\t\t\t# extended features\n\txor\t%ecx,%ecx\n\tcpuid\n\tbt\t$8,%ebx\t\t\t# bmi2\n\tjnc\t\"test not possible\"\n\n\t.test\t\"shlx 1\"\n\tstc\n\tmov\t$0xf0000fff,%eax\t# input value\n\tmov\t$0x31337133,%ebx\t# random data\n\tmov\t$4,%ecx\n\tshlx\t%ecx,%eax,%ebx\n\t.c\n\tcmp\t$0xf0000fff,%eax\t# unchanged\n\t.e\n\tcmp\t$0x0000fff0,%ebx\t# output value\n\t.e\n\n\t.test\t\"shrx 1\"\n\tstc\n\tmov\t$0xf0000fff,%eax\t# input value\n\tmov\t$0x31337133,%ebx\t# random data\n\tmov\t$4,%ecx\n\tshrx\t%ecx,%eax,%ebx\n\t.c\n\tcmp\t$0xf0000fff,%eax\t# unchanged\n\t.e\n\tcmp\t$0x0f0000ff,%ebx\t# output value\n\t.e\n\n\t.test\t\"sarx 1\"\n\tstc\n\tmov\t$0xf0000fff,%eax\t# input value\n\tmov\t$0x31337133,%ebx\t# random data\n\tmov\t$4,%ecx\n\tsarx\t%ecx,%eax,%ebx\n\t.c\n\tcmp\t$0xf0000fff,%eax\t# unchanged\n\t.e\n\tcmp\t$0xff0000ff,%ebx\t# output value\n\t.e\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n\"test not possible\":\n\t.exit\n"
  },
  {
    "path": "test/asm/ssemov.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$5,%r15\n\"test jit too\":\n\n//\tsse moves\n//\tmake -j8 o//blink o//test/asm/ssemov.elf\n//\to//blink/blinkenlights o//test/asm/ssemov.elf\n\n\t.test\t\"sse mov unaligned\"\n\tand\t$-16,%rsp\n\tsub\t$17,%rsp\n\tmovdqu\tonetwo(%rip),%xmm0\n\tmovdqu\t%xmm0,%xmm0\n\tmovdqu\t%xmm0,(%rsp)\n\tmov\t(%rsp),%rax\n\tmov\t8(%rsp),%rdx\n\tmov\t$0x1111111111111111,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\tmov\t$0x2222222222222222,%rcx\n\tcmp\t%rcx,%rdx\n\t.e\n\n\t.test\t\"sse mov aligned\"\n\tand\t$-16,%rsp\n\tsub\t$16,%rsp\n\tmovdqa\tonetwo(%rip),%xmm9\n\tmovdqa\t%xmm9,%xmm6\n\tmovdqa\t%xmm6,(%rsp)\n\tmov\t(%rsp),%rax\n\tmov\t8(%rsp),%rdx\n\tmov\t$0x1111111111111111,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\tmov\t$0x2222222222222222,%rcx\n\tcmp\t%rcx,%rdx\n\t.e\n\n\t.test\t\"sse mov unaligned #2\"\n\tand\t$-16,%rsp\n\tsub\t$16,%rsp\n\tmovups\tonetwo(%rip),%xmm9\n\tmovups\t%xmm9,%xmm6\n\tmovups\t%xmm6,(%rsp)\n\tmov\t(%rsp),%rax\n\tmov\t8(%rsp),%rdx\n\tmov\t$0x1111111111111111,%rcx\n\tcmp\t%rcx,%rax\n\t.e\n\tmov\t$0x2222222222222222,%rcx\n\tcmp\t%rcx,%rdx\n\t.e\n\n\tsub\t$1,%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n\n\t.section .rodata\n\t.align\t16\nonetwo:\t.quad\t0x1111111111111111,0x2222222222222222\n"
  },
  {
    "path": "test/asm/write.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\n\n//\texit(0) example\n//\tmake -j8 o//blink o//test/asm/exit.elf\n//\to//blink/blinkenlights o//test/asm/exit.elf\n\n#define SYS_write 1\n#define SYS_exit  231\n#define EBADF     9\n\n\t.test\t\"call write(1, msg, len)\"\n\tmov\t$1,%edi\n\tlea\t1f(%rip),%rsi\n\tmov\t$2f-1f,%edx\n\tmov\t$SYS_write,%eax\n\tsyscall\n\tcmp\t$2f-1f,%rax\n\t.e\n\n\t.test\t\"write(-1, 0, 0) -> EBADF\"\n\tmov\t$-1,%edi\n\tmov\t$0,%esi\n\tmov\t$0,%edx\n\tmov\t$SYS_write,%eax\n\tsyscall\n\tcmp\t$-EBADF,%rax\n\t.e\n\n\t.test\t\"call exit(0)\"\n\tmov\t$0,%edi\n\tmov\t$SYS_exit,%eax\n\tsyscall\n\n1:\t.ascii\t\"hello world\\n\"\n2:\n"
  },
  {
    "path": "test/asm/xchg.S",
    "content": "#include \"test/asm/mac.inc\"\n.globl\t_start\n_start:\tmov\t$3,%r15\n\"test jit too\":\n\n//\tequivalent exchange\n//\tmake -j8 o//blink o//test/asm/xchg.elf\n//\to//blink/blinkenlights o//test/asm/xchg.elf\n\n\t.test\t\"xchgl reg/reg zero-extends\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\txchg\t%eax,%ebx\n\tmov\t$0x0000000012345678,%rcx\n\tmov\t$0x0000000055555550,%rdx\n\tcmp\t%rdx,%rax\n\t.e\n\tcmp\t%rcx,%rbx\n\t.e\n\n\t.test\t\"xchgl mem/reg zero-extends\"\n\tmov\t$0x1234567812345678,%rax\n\tmov\t$0x5555555155555550,%rbx\n\tmov\t%rbx,(%rsp)\n\txchg\t%eax,(%rsp)\n\tmov\t$0x5555555112345678,%rcx\n\tmov\t$0x0000000055555550,%rdx\n\tcmp\t%rdx,%rax\n\t.e\n\tcmp\t%rcx,(%rsp)\n\t.e\n\n\tdec\t%r15\n\tjnz\t\"test jit too\"\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/blink/disinst_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2020 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/dis.h\"\n#include \"blink/high.h\"\n#include \"blink/modrm.h\"\n#include \"test/test.h\"\n\n#define ILD(OP, MODE) \\\n  ASSERT_EQ(0, DecodeInstruction(d->xedd, OP, sizeof(OP), MODE))\n\nchar b1[64];\nchar b2[64];\nstruct Dis d[1];\n\nvoid SetUp(void) {\n  d->notab = true;\n  g_high.enabled = false;\n}\n\nvoid TearDown(void) {\n}\n\nTEST(DisInst, testInt3) {\n  u8 op[] = {0xcc};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"int3 \", b1);\n}\n\nTEST(DisInst, testImmMem_needsSuffix) {\n  u8 op[] = {0x80, 0x3c, 0x07, 0x00};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"cmpb $0,(%rdi,%rax)\", b1);\n}\n\nTEST(DisInst, testImmReg_doesntNeedSuffix) {\n  u8 op[] = {0xb8, 0x08, 0x70, 0x40, 0x00};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"mov $0x407008,%eax\", b1);\n}\n\nTEST(DisInst, testPuttingOnTheRiz) {\n  static u8 ops[][15] = {\n      {0x8d, 0b00110100, 0b00100110},\n      {0x67, 0x8d, 0b00110100, 0b11100110},\n      {0x67, 0x8d, 0b10110100, 0b11100101, 0, 0, 0, 0},\n      {0x8d, 0b00110100, 0b11100101, 0x37, 0x13, 0x03, 0},\n      {0x8d, 0b10110100, 0b11100101, 0, 0, 0, 0},\n  };\n  ILD(ops[0], XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"lea (%rsi),%esi\", b1);\n  ILD(ops[1], XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"lea (%esi,%eiz,8),%esi\", b1);\n  ILD(ops[2], XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"lea 0(%ebp,%eiz,8),%esi\", b1);\n  ILD(ops[3], XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"lea 0x31337,%esi\", b1);\n  ILD(ops[4], XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"lea 0(%rbp,%riz,8),%esi\", b1);\n}\n\nTEST(DisInst, testSibIndexOnly) {\n  u8 op[] = {76, 141, 4, 141, 0, 0, 0, 0};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"lea 0(,%rcx,4),%r8\", b1);\n}\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testRealMode) {\n  u8 op[] = {0x89, 0xe5};\n  ILD(op, XED_MODE_REAL);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"mov %sp,%bp\", b1);\n}\n#endif\n\nTEST(DisInst, testNop) {\n  u8 op[] = {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"nopw %cs:0(%rax,%rax)\", b1);\n}\n\nTEST(DisInst, testJne) {\n  u8 op[] = {0x75, (u8)-24};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"jne -24\", b1);\n}\n\nTEST(DisInst, testPush) {\n  u8 op[] = {0x41, 0x5c};\n  ILD(op, XED_MODE_LONG);\n  EXPECT_EQ(4, ModrmSrm(d->xedd->op.rde));\n  EXPECT_EQ(1, Rexb(d->xedd->op.rde));\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"pop %r12\", b1);\n}\n\nTEST(DisInst, testMovb) {\n  u8 op[] = {0x8a, 0x1e, 0x0c, 0x32};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"mov (%rsi),%bl\", b1);\n#ifndef DISABLE_METAL\n  ILD(op, XED_MODE_REAL);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"mov 0x320c,%bl\", b1);\n#endif\n}\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testLes) {\n  u8 op[] = {0xc4, 0x3e, 0x16, 0x32};\n  ILD(op, XED_MODE_REAL);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"les 0x3216,%di\", b1);\n}\n#endif\n\nTEST(DisInst, testStosbLong) {\n  u8 op[] = {0xAA};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"stosb %al,(%rdi)\", b1);\n}\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testStosbReal) {\n  u8 op[] = {0xAA};\n  ILD(op, XED_MODE_REAL);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"stosb %al,(%di)\", b1);\n}\n#endif\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testStosbLegacy) {\n  u8 op[] = {0xAA};\n  ILD(op, XED_MODE_LEGACY);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"stosb %al,(%edi)\", b1);\n}\n#endif\n\nTEST(DisInst, testStosbLongAsz) {\n  u8 op[] = {0x67, 0xAA};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"stosb %al,(%edi)\", b1);\n}\n\nTEST(DisInst, testAddLong) {\n  u8 op[] = {0x01, 0xff};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"add %edi,%edi\", b1);\n}\n\nTEST(DisInst, testAddLegacy) {\n  u8 op[] = {0x01, 0xff};\n  ILD(op, XED_MODE_LEGACY);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"add %edi,%edi\", b1);\n}\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testAddReal) {\n  u8 op[] = {0x01, 0xff};\n  ILD(op, XED_MODE_REAL);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"add %di,%di\", b1);\n}\n#endif\n\nTEST(DisInst, testAddLongOsz) {\n  u8 op[] = {0x66, 0x01, 0xff};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"add %di,%di\", b1);\n}\n\nTEST(DisInst, testAddLegacyOsz) {\n  u8 op[] = {0x66, 0x01, 0xff};\n  ILD(op, XED_MODE_LEGACY);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"add %di,%di\", b1);\n}\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testAddRealOsz) {\n  u8 op[] = {0x66, 0x01, 0xff};\n  ILD(op, XED_MODE_REAL);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"add %edi,%edi\", b1);\n}\n#endif\n\nTEST(DisInst, testFxam) {\n  u8 op[] = {0xd9, 0xe5};\n  ILD(op, XED_MODE_LONG);\n  ASSERT_EQ(4, ModrmReg(d->xedd->op.rde));\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"fxam \", b1);\n}\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testOrImmCode16gcc) {\n  u8 op[] = {0x67, 0x81, 0x4c, 0x24, 0x0c, 0x00, 0x0c};\n  ILD(op, XED_MODE_REAL);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"orw $0xc00,12(%esp)\", b1);\n}\n#endif\n\nTEST(DisInst, testPause) {\n  u8 op[] = {0xf3, 0x90};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"pause \", b1);\n}\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testJmpEw) {\n  u8 op[] = {0xff, 0xe0};\n  ILD(op, XED_MODE_REAL);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"jmp *%ax\", b1);\n}\n#endif\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testJmpEv16) {\n  u8 op[] = {0x66, 0xff, 0xe0};\n  ILD(op, XED_MODE_REAL);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"jmp *%eax\", b1);\n}\n#endif\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testJmpEv32) {\n  u8 op[] = {0xff, 0xe0};\n  ILD(op, XED_MODE_LEGACY);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"jmp *%eax\", b1);\n}\n#endif\n\nTEST(DisInst, testJmpEq) {\n  u8 op[] = {0x66, 0xff, 0xe0};\n  ILD(op, XED_MODE_LONG);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"jmp *%rax\", b1);\n}\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testMovswSs) {\n  u8 op[] = {0x36, 0xA5};\n  ILD(op, XED_MODE_REAL);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"movs %ss:(%si),(%di)\", b1);\n}\n#endif\n\n#ifndef DISABLE_METAL\nTEST(DisInst, testRealModrm_sibOverlap_showsNoDisplacement) {\n  u8 op[] = {0x8b, 0b00100101};\n  ILD(op, XED_MODE_REAL);\n  DisInst(d, b1, DisSpec(d->xedd, b2));\n  EXPECT_STREQ(\"mov (%di),%sp\", b1);\n}\n#endif\n"
  },
  {
    "path": "test/blink/divmul_imul64_test.inc",
    "content": "/* clang-format off */\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0x1,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0x80000000,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0x7fffffff,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0x80000001,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0x7ffffffe,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0xffffffff,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0xdeadbeef,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0xb6,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0xb504,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0xb505,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0xb504f334,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0x7fffffffffffffff,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0,0x8000000000000000,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0x1,0,0x1,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0x80000000,0,0x80000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0x7fffffff,0,0x7fffffff,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0x80000001,0,0x80000001,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0x7ffffffe,0,0x7ffffffe,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0xffffffff,0,0xffffffff,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0xdeadbeef,0,0xdeadbeef,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0xb6,0,0xb6,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0xb504,0,0xb504,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0xb505,0,0xb505,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0xb504f334,0,0xb504f334,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0x7fffffffffffffff,0,0x7fffffffffffffff,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x1,0x8000000000000000,0,0x8000000000000000,0xffffffffffffffff,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0x1,0,0x80000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0x80000000,0,0x4000000000000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0x7fffffff,0,0x3fffffff80000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0x80000001,0,0x4000000080000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0x7ffffffe,0,0x3fffffff00000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0xffffffff,0,0x7fffffff80000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0xdeadbeef,0,0x6f56df7780000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0xb6,0,0x5b00000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0xb504,0,0x5a8200000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0xb505,0,0x5a8280000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0xb504f334,0,0x5a82799a00000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0x7fffffffffffffff,0,0xffffffff80000000,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000000,0x8000000000000000,0,0,0xffffffffc0000000,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0x1,0,0x7fffffff,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0x80000000,0,0x3fffffff80000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0x7fffffff,0,0x3fffffff00000001,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0x80000001,0,0x3fffffffffffffff,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0x7ffffffe,0,0x3ffffffe80000002,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0xffffffff,0,0x7ffffffe80000001,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0xdeadbeef,0,0x6f56df76a1524111,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0xb6,0,0x5affffff4a,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0xb504,0,0x5a81ffff4afc,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0xb505,0,0x5a827fff4afb,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0xb504f334,0,0x5a8279994afb0ccc,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0x7fffffffffffffff,0,0x7fffffff80000001,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffff,0x8000000000000000,0,0x8000000000000000,0xffffffffc0000000,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0x1,0,0x80000001,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0x80000000,0,0x4000000080000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0x7fffffff,0,0x3fffffffffffffff,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0x80000001,0,0x4000000100000001,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0x7ffffffe,0,0x3fffffff7ffffffe,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0xffffffff,0,0x800000007fffffff,0,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0xdeadbeef,0,0x6f56df785eadbeef,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0xb6,0,0x5b000000b6,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0xb504,0,0x5a820000b504,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0xb505,0,0x5a828000b505,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0xb504f334,0,0x5a82799ab504f334,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0x7fffffffffffffff,0,0x7fffffff7fffffff,0x40000000,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x80000001,0x8000000000000000,0,0x8000000000000000,0xffffffffbfffffff,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0x1,0,0x7ffffffe,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0x80000000,0,0x3fffffff00000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0x7fffffff,0,0x3ffffffe80000002,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0x80000001,0,0x3fffffff7ffffffe,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0x7ffffffe,0,0x3ffffffe00000004,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0xffffffff,0,0x7ffffffd80000002,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0xdeadbeef,0,0x6f56df75c2a48222,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0xb6,0,0x5afffffe94,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0xb504,0,0x5a81fffe95f8,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0xb505,0,0x5a827ffe95f6,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0xb504f334,0,0x5a82799895f61998,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0x7fffffffffffffff,0,0xffffffff80000002,0x3ffffffe,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7ffffffe,0x8000000000000000,0,0,0xffffffffc0000001,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0x1,0,0xffffffff,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0x80000000,0,0x7fffffff80000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0x7fffffff,0,0x7ffffffe80000001,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0x80000001,0,0x800000007fffffff,0,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0x7ffffffe,0,0x7ffffffd80000002,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0xffffffff,0,0xfffffffe00000001,0,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0xdeadbeef,0,0xdeadbeee21524111,0,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0xb6,0,0xb5ffffff4a,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0xb504,0,0xb503ffff4afc,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0xb505,0,0xb504ffff4afb,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0xb504f334,0,0xb504f3334afb0ccc,0,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0x7fffffffffffffff,0,0x7fffffff00000001,0x7fffffff,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xffffffff,0x8000000000000000,0,0x8000000000000000,0xffffffff80000000,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0x1,0,0xdeadbeef,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0x80000000,0,0x6f56df7780000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0x7fffffff,0,0x6f56df76a1524111,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0x80000001,0,0x6f56df785eadbeef,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0x7ffffffe,0,0x6f56df75c2a48222,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0xffffffff,0,0xdeadbeee21524111,0,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0xdeadbeef,0,0xc1b1cd12216da321,0,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0xb6,0,0x9e4f85bdea,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0xb504,0,0x9d7452b5f6bc,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0xb505,0,0x9d753163b5ab,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0xb504f334,0,0x9d7526421e43a58c,0,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0x7fffffffffffffff,0,0x7fffffff21524111,0x6f56df77,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xdeadbeef,0x8000000000000000,0,0x8000000000000000,0xffffffff90a92088,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0x1,0,0xb6,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0x80000000,0,0x5b00000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0x7fffffff,0,0x5affffff4a,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0x80000001,0,0x5b000000b6,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0x7ffffffe,0,0x5afffffe94,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0xffffffff,0,0xb5ffffff4a,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0xdeadbeef,0,0x9e4f85bdea,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0xb6,0,0x8164,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0xb504,0,0x80b0d8,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0xb505,0,0x80b18e,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0xb504f334,0,0x80b184e6f8,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0x7fffffffffffffff,0,0xffffffffffffff4a,0x5a,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb6,0x8000000000000000,0,0,0xffffffffffffffa5,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0x1,0,0xb504,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0x80000000,0,0x5a8200000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0x7fffffff,0,0x5a81ffff4afc,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0x80000001,0,0x5a820000b504,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0x7ffffffe,0,0x5a81fffe95f8,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0xffffffff,0,0xb503ffff4afc,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0xdeadbeef,0,0x9d7452b5f6bc,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0xb6,0,0x80b0d8,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0xb504,0,0x7ffea810,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0xb505,0,0x7fff5d14,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0xb504f334,0,0x7fff540790d0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0x7fffffffffffffff,0,0xffffffffffff4afc,0x5a81,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504,0x8000000000000000,0,0,0xffffffffffffa57e,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0x1,0,0xb505,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0x80000000,0,0x5a8280000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0x7fffffff,0,0x5a827fff4afb,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0x80000001,0,0x5a828000b505,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0x7ffffffe,0,0x5a827ffe95f6,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0xffffffff,0,0xb504ffff4afb,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0xdeadbeef,0,0x9d753163b5ab,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0xb6,0,0x80b18e,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0xb504,0,0x7fff5d14,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0xb505,0,0x80001219,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0xb504f334,0,0x8000090c8404,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0x7fffffffffffffff,0,0x7fffffffffff4afb,0x5a82,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb505,0x8000000000000000,0,0x8000000000000000,0xffffffffffffa57d,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0x1,0,0xb504f334,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0x80000000,0,0x5a82799a00000000,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0x7fffffff,0,0x5a8279994afb0ccc,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0x80000001,0,0x5a82799ab504f334,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0x7ffffffe,0,0x5a82799895f61998,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0xffffffff,0,0xb504f3334afb0ccc,0,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0xdeadbeef,0,0x9d7526421e43a58c,0,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0xb6,0,0x80b184e6f8,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0xb504,0,0x7fff540790d0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0xb505,0,0x8000090c8404,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0xb504f334,0,0x8000000008abc290,0,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0x7fffffffffffffff,0,0xffffffff4afb0ccc,0x5a827999,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0xb504f334,0x8000000000000000,0,0,0xffffffffa57d8666,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0x1,0,0x7fffffffffffffff,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0x80000000,0,0xffffffff80000000,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0x7fffffff,0,0x7fffffff80000001,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0x80000001,0,0x7fffffff7fffffff,0x40000000,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0x7ffffffe,0,0xffffffff80000002,0x3ffffffe,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0xffffffff,0,0x7fffffff00000001,0x7fffffff,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0xdeadbeef,0,0x7fffffff21524111,0x6f56df77,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0xb6,0,0xffffffffffffff4a,0x5a,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0xb504,0,0xffffffffffff4afc,0x5a81,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0xb505,0,0x7fffffffffff4afb,0x5a82,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0xb504f334,0,0xffffffff4afb0ccc,0x5a827999,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0x7fffffffffffffff,0,0x1,0x3fffffffffffffff,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x7fffffffffffffff,0x8000000000000000,0,0x8000000000000000,0xc000000000000000,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0x1,0,0x8000000000000000,0xffffffffffffffff,0,0)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0x80000000,0,0,0xffffffffc0000000,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0x7fffffff,0,0x8000000000000000,0xffffffffc0000000,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0x80000001,0,0x8000000000000000,0xffffffffbfffffff,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0x7ffffffe,0,0,0xffffffffc0000001,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0xffffffff,0,0x8000000000000000,0xffffffff80000000,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0xdeadbeef,0,0x8000000000000000,0xffffffff90a92088,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0xb6,0,0,0xffffffffffffffa5,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0xb504,0,0,0xffffffffffffa57e,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0xb505,0,0x8000000000000000,0xffffffffffffa57d,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0xb504f334,0,0,0xffffffffa57d8666,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0x7fffffffffffffff,0,0x8000000000000000,0xc000000000000000,1,1)\nM(OpMulRdxRaxEvqpSigned,REXW|MOD(3)|RM(CX),0x8000000000000000,0x8000000000000000,0,0,0x4000000000000000,1,1)\n"
  },
  {
    "path": "test/blink/divmul_mul64_test.inc",
    "content": "/* clang-format off */\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0x1,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0x80000000,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0x7fffffff,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0x80000001,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0x7ffffffe,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0xffffffff,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0xb6,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0xb504,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0xb505,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0xb504f333,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0xb504f334,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0x7fffffffffffffff,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0,0x8000000000000000,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0x1,0,0x1,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0x80000000,0,0x80000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0x7fffffff,0,0x7fffffff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0x80000001,0,0x80000001,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0x7ffffffe,0,0x7ffffffe,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0xffffffff,0,0xffffffff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0xb6,0,0xb6,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0xb504,0,0xb504,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0xb505,0,0xb505,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0xb504f333,0,0xb504f333,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0xb504f334,0,0xb504f334,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0x7fffffffffffffff,0,0x7fffffffffffffff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x1,0x8000000000000000,0,0x8000000000000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0x1,0,0x80000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0x80000000,0,0x4000000000000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0x7fffffff,0,0x3fffffff80000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0x80000001,0,0x4000000080000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0x7ffffffe,0,0x3fffffff00000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0xffffffff,0,0x7fffffff80000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0xb6,0,0x5b00000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0xb504,0,0x5a8200000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0xb505,0,0x5a8280000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0xb504f333,0,0x5a82799980000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0xb504f334,0,0x5a82799a00000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0x7fffffffffffffff,0,0xffffffff80000000,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000000,0x8000000000000000,0,0,0x40000000,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0x1,0,0x7fffffff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0x80000000,0,0x3fffffff80000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0x7fffffff,0,0x3fffffff00000001,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0x80000001,0,0x3fffffffffffffff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0x7ffffffe,0,0x3ffffffe80000002,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0xffffffff,0,0x7ffffffe80000001,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0xb6,0,0x5affffff4a,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0xb504,0,0x5a81ffff4afc,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0xb505,0,0x5a827fff4afb,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0xb504f333,0,0x5a827998cafb0ccd,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0xb504f334,0,0x5a8279994afb0ccc,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0x7fffffffffffffff,0,0x7fffffff80000001,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffff,0x8000000000000000,0,0x8000000000000000,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0x1,0,0x80000001,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0x80000000,0,0x4000000080000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0x7fffffff,0,0x3fffffffffffffff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0x80000001,0,0x4000000100000001,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0x7ffffffe,0,0x3fffffff7ffffffe,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0xffffffff,0,0x800000007fffffff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0xb6,0,0x5b000000b6,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0xb504,0,0x5a820000b504,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0xb505,0,0x5a828000b505,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0xb504f333,0,0x5a82799a3504f333,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0xb504f334,0,0x5a82799ab504f334,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0x7fffffffffffffff,0,0x7fffffff7fffffff,0x40000000,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x80000001,0x8000000000000000,0,0x8000000000000000,0x40000000,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0x1,0,0x7ffffffe,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0x80000000,0,0x3fffffff00000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0x7fffffff,0,0x3ffffffe80000002,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0x80000001,0,0x3fffffff7ffffffe,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0x7ffffffe,0,0x3ffffffe00000004,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0xffffffff,0,0x7ffffffd80000002,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0xb6,0,0x5afffffe94,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0xb504,0,0x5a81fffe95f8,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0xb505,0,0x5a827ffe95f6,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0xb504f333,0,0x5a82799815f6199a,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0xb504f334,0,0x5a82799895f61998,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0x7fffffffffffffff,0,0xffffffff80000002,0x3ffffffe,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7ffffffe,0x8000000000000000,0,0,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0x1,0,0xffffffff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0x80000000,0,0x7fffffff80000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0x7fffffff,0,0x7ffffffe80000001,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0x80000001,0,0x800000007fffffff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0x7ffffffe,0,0x7ffffffd80000002,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0xffffffff,0,0xfffffffe00000001,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0xb6,0,0xb5ffffff4a,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0xb504,0,0xb503ffff4afc,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0xb505,0,0xb504ffff4afb,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0xb504f333,0,0xb504f3324afb0ccd,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0xb504f334,0,0xb504f3334afb0ccc,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0x7fffffffffffffff,0,0x7fffffff00000001,0x7fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xffffffff,0x8000000000000000,0,0x8000000000000000,0x7fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0x1,0,0xb6,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0x80000000,0,0x5b00000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0x7fffffff,0,0x5affffff4a,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0x80000001,0,0x5b000000b6,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0x7ffffffe,0,0x5afffffe94,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0xffffffff,0,0xb5ffffff4a,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0xb6,0,0x8164,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0xb504,0,0x80b0d8,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0xb505,0,0x80b18e,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0xb504f333,0,0x80b184e642,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0xb504f334,0,0x80b184e6f8,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0x7fffffffffffffff,0,0xffffffffffffff4a,0x5a,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb6,0x8000000000000000,0,0,0x5b,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0x1,0,0xb504,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0x80000000,0,0x5a8200000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0x7fffffff,0,0x5a81ffff4afc,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0x80000001,0,0x5a820000b504,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0x7ffffffe,0,0x5a81fffe95f8,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0xffffffff,0,0xb503ffff4afc,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0xb6,0,0x80b0d8,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0xb504,0,0x7ffea810,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0xb505,0,0x7fff5d14,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0xb504f333,0,0x7fff5406dbcc,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0xb504f334,0,0x7fff540790d0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0x7fffffffffffffff,0,0xffffffffffff4afc,0x5a81,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504,0x8000000000000000,0,0,0x5a82,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0x1,0,0xb505,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0x80000000,0,0x5a8280000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0x7fffffff,0,0x5a827fff4afb,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0x80000001,0,0x5a828000b505,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0x7ffffffe,0,0x5a827ffe95f6,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0xffffffff,0,0xb504ffff4afb,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0xb6,0,0x80b18e,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0xb504,0,0x7fff5d14,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0xb505,0,0x80001219,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0xb504f333,0,0x8000090bceff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0xb504f334,0,0x8000090c8404,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0x7fffffffffffffff,0,0x7fffffffffff4afb,0x5a82,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb505,0x8000000000000000,0,0x8000000000000000,0x5a82,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0x1,0,0xb504f333,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0x80000000,0,0x5a82799980000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0x7fffffff,0,0x5a827998cafb0ccd,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0x80000001,0,0x5a82799a3504f333,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0x7ffffffe,0,0x5a82799815f6199a,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0xffffffff,0,0xb504f3324afb0ccd,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0xb6,0,0x80b184e642,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0xb504,0,0x7fff5406dbcc,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0xb505,0,0x8000090bceff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0xb504f333,0,0x7ffffffe9ea1dc29,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0xb504f334,0,0x7fffffff53a6cf5c,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0x7fffffffffffffff,0,0x7fffffff4afb0ccd,0x5a827999,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f333,0x8000000000000000,0,0x8000000000000000,0x5a827999,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0x1,0,0xb504f334,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0x80000000,0,0x5a82799a00000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0x7fffffff,0,0x5a8279994afb0ccc,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0x80000001,0,0x5a82799ab504f334,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0x7ffffffe,0,0x5a82799895f61998,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0xffffffff,0,0xb504f3334afb0ccc,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0xb6,0,0x80b184e6f8,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0xb504,0,0x7fff540790d0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0xb505,0,0x8000090c8404,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0xb504f333,0,0x7fffffff53a6cf5c,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0xb504f334,0,0x8000000008abc290,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0x7fffffffffffffff,0,0xffffffff4afb0ccc,0x5a827999,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0xb504f334,0x8000000000000000,0,0,0x5a82799a,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0x1,0,0x7fffffffffffffff,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0x80000000,0,0xffffffff80000000,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0x7fffffff,0,0x7fffffff80000001,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0x80000001,0,0x7fffffff7fffffff,0x40000000,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0x7ffffffe,0,0xffffffff80000002,0x3ffffffe,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0xffffffff,0,0x7fffffff00000001,0x7fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0xb6,0,0xffffffffffffff4a,0x5a,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0xb504,0,0xffffffffffff4afc,0x5a81,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0xb505,0,0x7fffffffffff4afb,0x5a82,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0xb504f333,0,0x7fffffff4afb0ccd,0x5a827999,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0xb504f334,0,0xffffffff4afb0ccc,0x5a827999,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0x7fffffffffffffff,0,0x1,0x3fffffffffffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x7fffffffffffffff,0x8000000000000000,0,0x8000000000000000,0x3fffffffffffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0,0,0,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0x1,0,0x8000000000000000,0,0,0)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0x80000000,0,0,0x40000000,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0x7fffffff,0,0x8000000000000000,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0x80000001,0,0x8000000000000000,0x40000000,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0x7ffffffe,0,0,0x3fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0xffffffff,0,0x8000000000000000,0x7fffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0xb6,0,0,0x5b,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0xb504,0,0,0x5a82,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0xb505,0,0x8000000000000000,0x5a82,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0xb504f333,0,0x8000000000000000,0x5a827999,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0xb504f334,0,0,0x5a82799a,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0x7fffffffffffffff,0,0x8000000000000000,0x3fffffffffffffff,1,1)\nM(OpMulRdxRaxEvqpUnsigned,REXW | MOD(3) | RM(CX),0x8000000000000000,0x8000000000000000,0,0,0x4000000000000000,1,1)\n"
  },
  {
    "path": "test/blink/divmul_mul8_test.inc",
    "content": "/* clang-format off */\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0,0,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0,0x1,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0,0x80,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0,0x7f,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0,0x81,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0,0x7e,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0,0xff,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0,0xb6,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x1,0,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x1,0x1,0,0x1,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x1,0x80,0,0x80,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x1,0x7f,0,0x7f,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x1,0x81,0,0x81,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x1,0x7e,0,0x7e,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x1,0xff,0,0xff,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x1,0xb6,0,0xb6,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x80,0,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x80,0x1,0,0x80,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x80,0x80,0,0x4000,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x80,0x7f,0,0x3f80,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x80,0x81,0,0x4080,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x80,0x7e,0,0x3f00,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x80,0xff,0,0x7f80,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x80,0xb6,0,0x5b00,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7f,0,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7f,0x1,0,0x7f,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7f,0x80,0,0x3f80,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7f,0x7f,0,0x3f01,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7f,0x81,0,0x3fff,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7f,0x7e,0,0x3e82,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7f,0xff,0,0x7e81,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7f,0xb6,0,0x5a4a,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x81,0,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x81,0x1,0,0x81,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x81,0x80,0,0x4080,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x81,0x7f,0,0x3fff,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x81,0x81,0,0x4101,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x81,0x7e,0,0x3f7e,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x81,0xff,0,0x807f,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x81,0xb6,0,0x5bb6,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7e,0,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7e,0x1,0,0x7e,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7e,0x80,0,0x3f00,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7e,0x7f,0,0x3e82,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7e,0x81,0,0x3f7e,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7e,0x7e,0,0x3e04,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7e,0xff,0,0x7d82,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0x7e,0xb6,0,0x5994,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xff,0,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xff,0x1,0,0xff,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xff,0x80,0,0x7f80,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xff,0x7f,0,0x7e81,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xff,0x81,0,0x807f,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xff,0x7e,0,0x7d82,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xff,0xff,0,0xfe01,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xff,0xb6,0,0xb54a,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xb6,0,0,0,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xb6,0x1,0,0xb6,0,0,0)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xb6,0x80,0,0x5b00,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xb6,0x7f,0,0x5a4a,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xb6,0x81,0,0x5bb6,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xb6,0x7e,0,0x5994,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xb6,0xff,0,0xb54a,0,1,1)\nM(OpMulAxAlEbUnsigned,MOD(3)|RM(CX),0xb6,0xb6,0,0x8164,0,1,1)\n"
  },
  {
    "path": "test/blink/divmul_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/endian.h\"\n#include \"blink/flags.h\"\n#include \"blink/macros.h\"\n#include \"test/test.h\"\n\n#define CX     1\n#define OSZ    00000000040\n#define REXW   00000000100\n#define RM(x)  (0000001600 & ((x) << 007))\n#define MOD(x) (0060000000 & ((x) << 026))\n\nstruct Machine m[1];\n\nstruct {\n  const char *name;\n  void (*f)(P);\n  u64 rde;\n  u64 ax;\n  u64 cx;\n  u64 dx;\n  u64 out_ax;\n  u64 out_dx;\n  bool out_cf;\n  bool out_of;\n} kVector[] = {\n#define M(f, m, a, c, d, oa, od, cf, of) {#f, f, m, a, c, d, oa, od, cf, of},\n#include \"test/blink/divmul_imul64_test.inc\"\n#include \"test/blink/divmul_mul64_test.inc\"\n#include \"test/blink/divmul_mul8_test.inc\"\n};\n\nvoid SetUp(void) {\n}\n\nvoid TearDown(void) {\n}\n\nTEST(divmul, test) {\n  int i;\n  for (i = 0; i < ARRAYLEN(kVector); ++i) {\n    Write64(m->ax, kVector[i].ax);\n    Write64(m->cx, kVector[i].cx);\n    Write64(m->dx, kVector[i].dx);\n    kVector[i].f(m, kVector[i].rde, 0, 0);\n    ASSERT_EQ(kVector[i].out_ax, Read64(m->ax), \"%d: %s\", i, kVector[i].name);\n    ASSERT_EQ(kVector[i].out_dx, Read64(m->dx), \"%d: %s\", i, kVector[i].name);\n    ASSERT_EQ(kVector[i].out_cf, GetFlag(m->flags, FLAGS_CF), \"%d: %s\", i,\n              kVector[i].name);\n    ASSERT_EQ(kVector[i].out_of, GetFlag(m->flags, FLAGS_OF), \"%d: %s\", i,\n              kVector[i].name);\n  }\n}\n"
  },
  {
    "path": "test/blink/ldbl_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <float.h>\n#include <limits.h>\n#include <math.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n#include \"blink/ldbl.h\"\n#include \"test/test.h\"\n\nvoid SetUp(void) {\n}\n\nvoid TearDown(void) {\n}\n\ndouble RoundTrip(double x) {\n  uint8_t b[10];\n  return DeserializeLdbl(SerializeLdbl(b, x));\n}\n\nTEST(SerializeLdbl, testRoundTrip) {\n  EXPECT_STREQ(\"0\", Format(\"%g\", RoundTrip(0)));\n  EXPECT_STREQ(\"-0\", Format(\"%g\", RoundTrip(-0.)));\n  EXPECT_STREQ(\"nan\", Format(\"%g\", RoundTrip(NAN)));\n  EXPECT_STREQ(\"inf\", Format(\"%g\", RoundTrip(INFINITY)));\n  EXPECT_STREQ(\"-inf\", Format(\"%g\", RoundTrip(-INFINITY)));\n  EXPECT_STREQ(Format(\"%.17g\", DBL_MIN), Format(\"%.17g\", RoundTrip(DBL_MIN)));\n  EXPECT_STREQ(Format(\"%.17g\", DBL_MAX), Format(\"%.17g\", RoundTrip(DBL_MAX)));\n  // TODO(jart): What's up with Apple Silicon here?\n  // EXPECT_STREQ(\"-nan\", Format(\"%g\", RoundTrip(-NAN)));\n}\n"
  },
  {
    "path": "test/blink/modrm_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/assert.h\"\n#include \"blink/endian.h\"\n#include \"blink/machine.h\"\n#include \"blink/map.h\"\n#include \"blink/modrm.h\"\n#include \"blink/x86.h\"\n#include \"test/test.h\"\n\nstruct System *s;\nstruct Machine *m;\nstruct XedDecodedInst xedd;\n\nvoid SetUp(void) {\n  InitMap();\n  unassert((s = NewSystem(XED_MACHINE_MODE_LONG)));\n  unassert((m = NewMachine(s, 0)));\n  m->xedd = &xedd;\n  memset(&xedd, 0, sizeof(xedd));\n}\n\nvoid TearDown(void) {\n  FreeMachine(m);\n}\n\nTEST(modrm, testAddressSizeOverride_isNotPresent_keepsWholeExpression) {\n  uint8_t op[] = {0x8d, 0x04, 0x03}; /* lea (%rbx,%rax,1),%eax */\n  Write64(m->bx, 0x2);\n  Write64(m->ax, 0xffffffff);\n  ASSERT_EQ(0, DecodeInstruction(m->xedd, op, sizeof(op), XED_MODE_LONG));\n  EXPECT_EQ(0x100000001, ComputeAddress(m, m->xedd->op.rde, m->xedd->op.disp,\n                                        m->xedd->op.uimm0));\n}\n\nTEST(modrm, testAddressSizeOverride_isPresent_modulesWholeExpression) {\n  uint8_t op[] = {0x67, 0x8d, 0x04, 0x03}; /* lea (%ebx,%eax,1),%eax */\n  Write64(m->bx, 0x2);\n  Write64(m->ax, 0xffffffff);\n  ASSERT_EQ(0, DecodeInstruction(m->xedd, op, sizeof(op), XED_MODE_LONG));\n  EXPECT_EQ(0x000000001, ComputeAddress(m, m->xedd->op.rde, m->xedd->op.disp,\n                                        m->xedd->op.uimm0));\n}\n\nTEST(modrm, testOverflow_doesntTriggerTooling) {\n  uint8_t op[] = {0x8d, 0x04, 0x03}; /* lea (%rbx,%rax,1),%eax */\n  Write64(m->bx, 0x0000000000000001);\n  Write64(m->ax, 0x7fffffffffffffff);\n  ASSERT_EQ(0, DecodeInstruction(m->xedd, op, sizeof(op), XED_MODE_LONG));\n  EXPECT_EQ(0x8000000000000000ull,\n            (uint64_t)ComputeAddress(m, m->xedd->op.rde, m->xedd->op.disp,\n                                     m->xedd->op.uimm0));\n}\n\nTEST(modrm, testPuttingOnTheRiz) {\n  static uint8_t op[][15] = {\n      {0x8d, 0b00110100, 0b00100110},        // lea (%rsi),%esi\n      {0x67, 0x8d, 0b00110100, 0b11100110},  // lea (%esi,%eiz,8),%esi\n      {103, 141, 180, 229, 55, 19, 3, 0},    // lea 0x31337(%ebp,%eiz,8),%esi\n      {141, 52, 229, 55, 19, 3, 0},          // lea 0x31337,%esi\n  };\n  Write64(m->si, 0x100000001);\n  Write64(m->bp, 0x200000002);\n  ASSERT_EQ(0, DecodeInstruction(m->xedd, op[0], sizeof(op[0]), XED_MODE_LONG));\n  EXPECT_EQ(0x100000001, ComputeAddress(m, m->xedd->op.rde, m->xedd->op.disp,\n                                        m->xedd->op.uimm0));\n  ASSERT_EQ(0, DecodeInstruction(m->xedd, op[1], sizeof(op[1]), XED_MODE_LONG));\n  EXPECT_EQ(0x000000001, ComputeAddress(m, m->xedd->op.rde, m->xedd->op.disp,\n                                        m->xedd->op.uimm0));\n  ASSERT_EQ(0, DecodeInstruction(m->xedd, op[2], sizeof(op[2]), XED_MODE_LONG));\n  EXPECT_EQ(0x31339, ComputeAddress(m, m->xedd->op.rde, m->xedd->op.disp,\n                                    m->xedd->op.uimm0));\n  ASSERT_EQ(0, DecodeInstruction(m->xedd, op[3], sizeof(op[3]), XED_MODE_LONG));\n  EXPECT_EQ(0x31337, ComputeAddress(m, m->xedd->op.rde, m->xedd->op.disp,\n                                    m->xedd->op.uimm0));\n}\n\nTEST(modrm, testSibIndexOnly) {\n  // lea 0x0(,%rcx,4),%r8\n  //       mod                  = 0b00  (0)\n  //       reg                  = 0b000 (0)\n  //       rm                   = 0b100 (4)\n  //       scale                = 0b10  (2)\n  //       index                = 0b001 (1)\n  //       base                 = 0b101 (5)\n  uint8_t op[] = {0x4c, 0x8d, 0x04, 0x8d, 0, 0, 0, 0};\n  Write64(m->bp, 0x123);\n  Write64(m->cx, 0x123);\n  ASSERT_EQ(0, DecodeInstruction(m->xedd, op, sizeof(op), XED_MODE_LONG));\n  EXPECT_TRUE(Rexw(m->xedd->op.rde));\n  EXPECT_TRUE(Rexr(m->xedd->op.rde));\n  EXPECT_FALSE(Rexb(m->xedd->op.rde));\n  EXPECT_EQ(0b000, ModrmReg(m->xedd->op.rde));\n  EXPECT_EQ(0b100, ModrmRm(m->xedd->op.rde));\n  EXPECT_EQ(0x123 * 4,\n            (uint64_t)ComputeAddress(m, m->xedd->op.rde, m->xedd->op.disp,\n                                     m->xedd->op.uimm0));\n}\n"
  },
  {
    "path": "test/blink/test.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nPKGS += TEST_BLINK\nTEST_BLINK_FILES := $(wildcard test/blink/*)\nTEST_BLINK_SRCS = $(filter %.c,$(TEST_BLINK_FILES))\nTEST_BLINK_HDRS = $(filter %.h,$(TEST_BLINK_FILES))\nTEST_BLINK_OBJS = $(TEST_BLINK_SRCS:%.c=o/$(MODE)/%.o)\n\n# this file takes a minute to compile on raspi using -O2\no/$(MODE)/test/blink/x86_test.o\t\t\t\t\\\no/$(MODE)/i486/test/blink/x86_test.o\t\t\t\\\no/$(MODE)/m68k/test/blink/x86_test.o\t\t\t\\\no/$(MODE)/x86_64/test/blink/x86_test.o\t\t\t\\\no/$(MODE)/x86_64-gcc49/test/blink/x86_test.o\t\t\\\no/$(MODE)/arm/test/blink/x86_test.o\t\t\t\\\no/$(MODE)/aarch64/test/blink/x86_test.o\t\t\t\\\no/$(MODE)/riscv64/test/blink/x86_test.o\t\t\t\\\no/$(MODE)/mips/test/blink/x86_test.o\t\t\t\\\no/$(MODE)/mipsel/test/blink/x86_test.o\t\t\t\\\no/$(MODE)/mips64/test/blink/x86_test.o\t\t\t\\\no/$(MODE)/mips64el/test/blink/x86_test.o\t\t\\\no/$(MODE)/s390x/test/blink/x86_test.o\t\t\t\\\no/$(MODE)/powerpc/test/blink/x86_test.o\t\t\t\\\no/$(MODE)/powerpc64le/test/blink/x86_test.o:\t\t\\\n\t\tprivate CFLAGS += -O0\n\no/$(MODE)/test/blink/divmul_test.com: o/$(MODE)/test/blink/divmul_test.o o/$(MODE)/blink/blink.a\n\t$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/i486/test/blink/divmul_test.com: o/$(MODE)/i486/test/blink/divmul_test.o o/$(MODE)/i486/blink/blink.a\n\to/third_party/gcc/i486/bin/i486-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/m68k/test/blink/divmul_test.com: o/$(MODE)/m68k/test/blink/divmul_test.o o/$(MODE)/m68k/blink/blink.a\n\to/third_party/gcc/m68k/bin/m68k-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/x86_64/test/blink/divmul_test.com: o/$(MODE)/x86_64/test/blink/divmul_test.o o/$(MODE)/x86_64/blink/blink.a\n\to/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/x86_64-gcc49/test/blink/divmul_test.com: o/$(MODE)/x86_64-gcc49/test/blink/divmul_test.o o/$(MODE)/x86_64-gcc49/blink/blink.a\n\to/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/arm/test/blink/divmul_test.com: o/$(MODE)/arm/test/blink/divmul_test.o o/$(MODE)/arm/blink/blink.a\n\to/third_party/gcc/arm/bin/arm-linux-musleabi-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/aarch64/test/blink/divmul_test.com: o/$(MODE)/aarch64/test/blink/divmul_test.o o/$(MODE)/aarch64/blink/blink.a\n\to/third_party/gcc/aarch64/bin/aarch64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/riscv64/test/blink/divmul_test.com: o/$(MODE)/riscv64/test/blink/divmul_test.o o/$(MODE)/riscv64/blink/blink.a\n\to/third_party/gcc/riscv64/bin/riscv64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips/test/blink/divmul_test.com: o/$(MODE)/mips/test/blink/divmul_test.o o/$(MODE)/mips/blink/blink.a\n\to/third_party/gcc/mips/bin/mips-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mipsel/test/blink/divmul_test.com: o/$(MODE)/mipsel/test/blink/divmul_test.o o/$(MODE)/mipsel/blink/blink.a\n\to/third_party/gcc/mipsel/bin/mipsel-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips64/test/blink/divmul_test.com: o/$(MODE)/mips64/test/blink/divmul_test.o o/$(MODE)/mips64/blink/blink.a\n\to/third_party/gcc/mips64/bin/mips64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips64el/test/blink/divmul_test.com: o/$(MODE)/mips64el/test/blink/divmul_test.o o/$(MODE)/mips64el/blink/blink.a\n\to/third_party/gcc/mips64el/bin/mips64el-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/s390x/test/blink/divmul_test.com: o/$(MODE)/s390x/test/blink/divmul_test.o o/$(MODE)/s390x/blink/blink.a\n\to/third_party/gcc/s390x/bin/s390x-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/powerpc/test/blink/divmul_test.com: o/$(MODE)/powerpc/test/blink/divmul_test.o o/$(MODE)/powerpc/blink/blink.a\n\to/third_party/gcc/powerpc/bin/powerpc-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/powerpc64le/test/blink/divmul_test.com: o/$(MODE)/powerpc64le/test/blink/divmul_test.o o/$(MODE)/powerpc64le/blink/blink.a\n\to/third_party/gcc/powerpc64le/bin/powerpc64le-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\n\no/$(MODE)/test/blink/modrm_test.com: o/$(MODE)/test/blink/modrm_test.o o/$(MODE)/blink/blink.a\n\t$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/i486/test/blink/modrm_test.com: o/$(MODE)/i486/test/blink/modrm_test.o o/$(MODE)/i486/blink/blink.a\n\to/third_party/gcc/i486/bin/i486-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/m68k/test/blink/modrm_test.com: o/$(MODE)/m68k/test/blink/modrm_test.o o/$(MODE)/m68k/blink/blink.a\n\to/third_party/gcc/m68k/bin/m68k-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/x86_64/test/blink/modrm_test.com: o/$(MODE)/x86_64/test/blink/modrm_test.o o/$(MODE)/x86_64/blink/blink.a\n\to/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/x86_64-gcc49/test/blink/modrm_test.com: o/$(MODE)/x86_64-gcc49/test/blink/modrm_test.o o/$(MODE)/x86_64-gcc49/blink/blink.a\n\to/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/arm/test/blink/modrm_test.com: o/$(MODE)/arm/test/blink/modrm_test.o o/$(MODE)/arm/blink/blink.a\n\to/third_party/gcc/arm/bin/arm-linux-musleabi-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/aarch64/test/blink/modrm_test.com: o/$(MODE)/aarch64/test/blink/modrm_test.o o/$(MODE)/aarch64/blink/blink.a\n\to/third_party/gcc/aarch64/bin/aarch64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/riscv64/test/blink/modrm_test.com: o/$(MODE)/riscv64/test/blink/modrm_test.o o/$(MODE)/riscv64/blink/blink.a\n\to/third_party/gcc/riscv64/bin/riscv64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips/test/blink/modrm_test.com: o/$(MODE)/mips/test/blink/modrm_test.o o/$(MODE)/mips/blink/blink.a\n\to/third_party/gcc/mips/bin/mips-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mipsel/test/blink/modrm_test.com: o/$(MODE)/mipsel/test/blink/modrm_test.o o/$(MODE)/mipsel/blink/blink.a\n\to/third_party/gcc/mipsel/bin/mipsel-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips64/test/blink/modrm_test.com: o/$(MODE)/mips64/test/blink/modrm_test.o o/$(MODE)/mips64/blink/blink.a\n\to/third_party/gcc/mips64/bin/mips64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips64el/test/blink/modrm_test.com: o/$(MODE)/mips64el/test/blink/modrm_test.o o/$(MODE)/mips64el/blink/blink.a\n\to/third_party/gcc/mips64el/bin/mips64el-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/s390x/test/blink/modrm_test.com: o/$(MODE)/s390x/test/blink/modrm_test.o o/$(MODE)/s390x/blink/blink.a\n\to/third_party/gcc/s390x/bin/s390x-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/powerpc/test/blink/modrm_test.com: o/$(MODE)/powerpc/test/blink/modrm_test.o o/$(MODE)/powerpc/blink/blink.a\n\to/third_party/gcc/powerpc/bin/powerpc-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/powerpc64le/test/blink/modrm_test.com: o/$(MODE)/powerpc64le/test/blink/modrm_test.o o/$(MODE)/powerpc64le/blink/blink.a\n\to/third_party/gcc/powerpc64le/bin/powerpc64le-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\n\no/$(MODE)/test/blink/x86_test.com: o/$(MODE)/test/blink/x86_test.o o/$(MODE)/blink/blink.a\n\t$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/i486/test/blink/x86_test.com: o/$(MODE)/i486/test/blink/x86_test.o o/$(MODE)/i486/blink/blink.a\n\to/third_party/gcc/i486/bin/i486-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/m68k/test/blink/x86_test.com: o/$(MODE)/m68k/test/blink/x86_test.o o/$(MODE)/m68k/blink/blink.a\n\to/third_party/gcc/m68k/bin/m68k-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/x86_64/test/blink/x86_test.com: o/$(MODE)/x86_64/test/blink/x86_test.o o/$(MODE)/x86_64/blink/blink.a\n\to/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/x86_64-gcc49/test/blink/x86_test.com: o/$(MODE)/x86_64-gcc49/test/blink/x86_test.o o/$(MODE)/x86_64-gcc49/blink/blink.a\n\to/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/arm/test/blink/x86_test.com: o/$(MODE)/arm/test/blink/x86_test.o o/$(MODE)/arm/blink/blink.a\n\to/third_party/gcc/arm/bin/arm-linux-musleabi-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/aarch64/test/blink/x86_test.com: o/$(MODE)/aarch64/test/blink/x86_test.o o/$(MODE)/aarch64/blink/blink.a\n\to/third_party/gcc/aarch64/bin/aarch64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/riscv64/test/blink/x86_test.com: o/$(MODE)/riscv64/test/blink/x86_test.o o/$(MODE)/riscv64/blink/blink.a\n\to/third_party/gcc/riscv64/bin/riscv64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips/test/blink/x86_test.com: o/$(MODE)/mips/test/blink/x86_test.o o/$(MODE)/mips/blink/blink.a\n\to/third_party/gcc/mips/bin/mips-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mipsel/test/blink/x86_test.com: o/$(MODE)/mipsel/test/blink/x86_test.o o/$(MODE)/mipsel/blink/blink.a\n\to/third_party/gcc/mipsel/bin/mipsel-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips64/test/blink/x86_test.com: o/$(MODE)/mips64/test/blink/x86_test.o o/$(MODE)/mips64/blink/blink.a\n\to/third_party/gcc/mips64/bin/mips64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips64el/test/blink/x86_test.com: o/$(MODE)/mips64el/test/blink/x86_test.o o/$(MODE)/mips64el/blink/blink.a\n\to/third_party/gcc/mips64el/bin/mips64el-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/s390x/test/blink/x86_test.com: o/$(MODE)/s390x/test/blink/x86_test.o o/$(MODE)/s390x/blink/blink.a\n\to/third_party/gcc/s390x/bin/s390x-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/powerpc/test/blink/x86_test.com: o/$(MODE)/powerpc/test/blink/x86_test.o o/$(MODE)/powerpc/blink/blink.a\n\to/third_party/gcc/powerpc/bin/powerpc-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/powerpc64le/test/blink/x86_test.com: o/$(MODE)/powerpc64le/test/blink/x86_test.o o/$(MODE)/powerpc64le/blink/blink.a\n\to/third_party/gcc/powerpc64le/bin/powerpc64le-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\n\no/$(MODE)/test/blink/ldbl_test.com: o/$(MODE)/test/blink/ldbl_test.o o/$(MODE)/blink/blink.a\n\t$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/i486/test/blink/ldbl_test.com: o/$(MODE)/i486/test/blink/ldbl_test.o o/$(MODE)/i486/blink/blink.a\n\to/third_party/gcc/i486/bin/i486-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/m68k/test/blink/ldbl_test.com: o/$(MODE)/m68k/test/blink/ldbl_test.o o/$(MODE)/m68k/blink/blink.a\n\to/third_party/gcc/m68k/bin/m68k-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/x86_64/test/blink/ldbl_test.com: o/$(MODE)/x86_64/test/blink/ldbl_test.o o/$(MODE)/x86_64/blink/blink.a\n\to/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/x86_64-gcc49/test/blink/ldbl_test.com: o/$(MODE)/x86_64-gcc49/test/blink/ldbl_test.o o/$(MODE)/x86_64-gcc49/blink/blink.a\n\to/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/arm/test/blink/ldbl_test.com: o/$(MODE)/arm/test/blink/ldbl_test.o o/$(MODE)/arm/blink/blink.a\n\to/third_party/gcc/arm/bin/arm-linux-musleabi-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/aarch64/test/blink/ldbl_test.com: o/$(MODE)/aarch64/test/blink/ldbl_test.o o/$(MODE)/aarch64/blink/blink.a\n\to/third_party/gcc/aarch64/bin/aarch64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/riscv64/test/blink/ldbl_test.com: o/$(MODE)/riscv64/test/blink/ldbl_test.o o/$(MODE)/riscv64/blink/blink.a\n\to/third_party/gcc/riscv64/bin/riscv64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips/test/blink/ldbl_test.com: o/$(MODE)/mips/test/blink/ldbl_test.o o/$(MODE)/mips/blink/blink.a\n\to/third_party/gcc/mips/bin/mips-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mipsel/test/blink/ldbl_test.com: o/$(MODE)/mipsel/test/blink/ldbl_test.o o/$(MODE)/mipsel/blink/blink.a\n\to/third_party/gcc/mipsel/bin/mipsel-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips64/test/blink/ldbl_test.com: o/$(MODE)/mips64/test/blink/ldbl_test.o o/$(MODE)/mips64/blink/blink.a\n\to/third_party/gcc/mips64/bin/mips64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips64el/test/blink/ldbl_test.com: o/$(MODE)/mips64el/test/blink/ldbl_test.o o/$(MODE)/mips64el/blink/blink.a\n\to/third_party/gcc/mips64el/bin/mips64el-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/s390x/test/blink/ldbl_test.com: o/$(MODE)/s390x/test/blink/ldbl_test.o o/$(MODE)/s390x/blink/blink.a\n\to/third_party/gcc/s390x/bin/s390x-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/powerpc/test/blink/ldbl_test.com: o/$(MODE)/powerpc/test/blink/ldbl_test.o o/$(MODE)/powerpc/blink/blink.a\n\to/third_party/gcc/powerpc/bin/powerpc-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/powerpc64le/test/blink/ldbl_test.com: o/$(MODE)/powerpc64le/test/blink/ldbl_test.o o/$(MODE)/powerpc64le/blink/blink.a\n\to/third_party/gcc/powerpc64le/bin/powerpc64le-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\n\no/$(MODE)/test/blink/disinst_test.com: o/$(MODE)/test/blink/disinst_test.o o/$(MODE)/blink/blink.a\n\t$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/i486/test/blink/disinst_test.com: o/$(MODE)/i486/test/blink/disinst_test.o o/$(MODE)/i486/blink/blink.a\n\to/third_party/gcc/i486/bin/i486-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/m68k/test/blink/disinst_test.com: o/$(MODE)/m68k/test/blink/disinst_test.o o/$(MODE)/m68k/blink/blink.a\n\to/third_party/gcc/m68k/bin/m68k-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/x86_64/test/blink/disinst_test.com: o/$(MODE)/x86_64/test/blink/disinst_test.o o/$(MODE)/x86_64/blink/blink.a\n\to/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/x86_64-gcc49/test/blink/disinst_test.com: o/$(MODE)/x86_64-gcc49/test/blink/disinst_test.o o/$(MODE)/x86_64-gcc49/blink/blink.a\n\to/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/arm/test/blink/disinst_test.com: o/$(MODE)/arm/test/blink/disinst_test.o o/$(MODE)/arm/blink/blink.a\n\to/third_party/gcc/arm/bin/arm-linux-musleabi-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/aarch64/test/blink/disinst_test.com: o/$(MODE)/aarch64/test/blink/disinst_test.o o/$(MODE)/aarch64/blink/blink.a\n\to/third_party/gcc/aarch64/bin/aarch64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/riscv64/test/blink/disinst_test.com: o/$(MODE)/riscv64/test/blink/disinst_test.o o/$(MODE)/riscv64/blink/blink.a\n\to/third_party/gcc/riscv64/bin/riscv64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips/test/blink/disinst_test.com: o/$(MODE)/mips/test/blink/disinst_test.o o/$(MODE)/mips/blink/blink.a\n\to/third_party/gcc/mips/bin/mips-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mipsel/test/blink/disinst_test.com: o/$(MODE)/mipsel/test/blink/disinst_test.o o/$(MODE)/mipsel/blink/blink.a\n\to/third_party/gcc/mipsel/bin/mipsel-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips64/test/blink/disinst_test.com: o/$(MODE)/mips64/test/blink/disinst_test.o o/$(MODE)/mips64/blink/blink.a\n\to/third_party/gcc/mips64/bin/mips64-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/mips64el/test/blink/disinst_test.com: o/$(MODE)/mips64el/test/blink/disinst_test.o o/$(MODE)/mips64el/blink/blink.a\n\to/third_party/gcc/mips64el/bin/mips64el-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/s390x/test/blink/disinst_test.com: o/$(MODE)/s390x/test/blink/disinst_test.o o/$(MODE)/s390x/blink/blink.a\n\to/third_party/gcc/s390x/bin/s390x-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/powerpc/test/blink/disinst_test.com: o/$(MODE)/powerpc/test/blink/disinst_test.o o/$(MODE)/powerpc/blink/blink.a\n\to/third_party/gcc/powerpc/bin/powerpc-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\no/$(MODE)/powerpc64le/test/blink/disinst_test.com: o/$(MODE)/powerpc64le/test/blink/disinst_test.o o/$(MODE)/powerpc64le/blink/blink.a\n\to/third_party/gcc/powerpc64le/bin/powerpc64le-linux-musl-gcc -static $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@\n\no/$(MODE)/test/blink:\t\t\t\t\t\t\t\\\n\t\t$(TEST_BLINK_OBJS)\t\t\t\t\t\\\n\t\to/$(MODE)/test/blink/divmul_test.com.runs\t\t\\\n\t\to/$(MODE)/test/blink/modrm_test.com.runs\t\t\\\n\t\to/$(MODE)/test/blink/x86_test.com.runs\t\t\t\\\n\t\to/$(MODE)/test/blink/ldbl_test.com.runs\t\t\t\\\n\t\to/$(MODE)/test/blink/disinst_test.com.runs\n\no/$(MODE)/test/blink/emulates:\t\t\t\t\t\t\\\n\t\to/$(MODE)/blink/blink\t\t\t\t\t\\\n\t\to/$(MODE)/i486/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/m68k/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/x86_64/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/arm/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/aarch64/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/riscv64/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/mips/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/mipsel/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/mips64/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/mips64el/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/s390x/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/powerpc/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/powerpc64le/blink/blink\t\t\t\\\n\t\to/$(MODE)/blink/blink\t\t\t\t\t\\\n\t\to/$(MODE)/i486/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/m68k/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/x86_64/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/arm/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/aarch64/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/riscv64/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/mips/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/mipsel/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/mips64/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/mips64el/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/s390x/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/powerpc/blink/blink\t\t\t\t\\\n\t\to/$(MODE)/powerpc64le/blink/blink\t\t\t\\\n\t\to/$(MODE)/i486/test/blink/divmul_test.com.runs\t\t\\\n\t\to/$(MODE)/m68k/test/blink/divmul_test.com.runs\t\t\\\n\t\to/$(MODE)/x86_64/test/blink/divmul_test.com.runs\t\\\n\t\to/$(MODE)/arm/test/blink/divmul_test.com.runs\t\t\\\n\t\to/$(MODE)/aarch64/test/blink/divmul_test.com.runs\t\\\n\t\to/$(MODE)/riscv64/test/blink/divmul_test.com.runs\t\\\n\t\to/$(MODE)/mips/test/blink/divmul_test.com.runs\t\t\\\n\t\to/$(MODE)/mipsel/test/blink/divmul_test.com.runs\t\\\n\t\to/$(MODE)/mips64/test/blink/divmul_test.com.runs\t\\\n\t\to/$(MODE)/mips64el/test/blink/divmul_test.com.runs\t\\\n\t\to/$(MODE)/s390x/test/blink/divmul_test.com.runs\t\t\\\n\t\to/$(MODE)/powerpc/test/blink/divmul_test.com.runs\t\\\n\t\to/$(MODE)/powerpc64le/test/blink/divmul_test.com.runs\t\\\n\t\to/$(MODE)/i486/test/blink/modrm_test.com.runs\t\t\\\n\t\to/$(MODE)/m68k/test/blink/modrm_test.com.runs\t\t\\\n\t\to/$(MODE)/x86_64/test/blink/modrm_test.com.runs\t\t\\\n\t\to/$(MODE)/arm/test/blink/modrm_test.com.runs\t\t\\\n\t\to/$(MODE)/aarch64/test/blink/modrm_test.com.runs\t\\\n\t\to/$(MODE)/riscv64/test/blink/modrm_test.com.runs\t\\\n\t\to/$(MODE)/mips/test/blink/modrm_test.com.runs\t\t\\\n\t\to/$(MODE)/mipsel/test/blink/modrm_test.com.runs\t\t\\\n\t\to/$(MODE)/mips64/test/blink/modrm_test.com.runs\t\t\\\n\t\to/$(MODE)/mips64el/test/blink/modrm_test.com.runs\t\\\n\t\to/$(MODE)/s390x/test/blink/modrm_test.com.runs\t\t\\\n\t\to/$(MODE)/powerpc/test/blink/modrm_test.com.runs\t\\\n\t\to/$(MODE)/powerpc64le/test/blink/modrm_test.com.runs\t\\\n\t\to/$(MODE)/i486/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/m68k/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/x86_64/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/arm/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/aarch64/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/riscv64/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/mips/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/mipsel/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/mips64/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/mips64el/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/s390x/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/powerpc/test/blink/x86_test.com.runs\t\t\\\n\t\to/$(MODE)/powerpc64le/test/blink/x86_test.com.runs\t\\\n\t\to/$(MODE)/i486/test/blink/ldbl_test.com.runs\t\t\\\n\t\to/$(MODE)/m68k/test/blink/ldbl_test.com.runs\t\t\\\n\t\to/$(MODE)/x86_64/test/blink/ldbl_test.com.runs\t\t\\\n\t\to/$(MODE)/arm/test/blink/ldbl_test.com.runs\t\t\\\n\t\to/$(MODE)/aarch64/test/blink/ldbl_test.com.runs\t\t\\\n\t\to/$(MODE)/riscv64/test/blink/ldbl_test.com.runs\t\t\\\n\t\to/$(MODE)/mips/test/blink/ldbl_test.com.runs\t\t\\\n\t\to/$(MODE)/mipsel/test/blink/ldbl_test.com.runs\t\t\\\n\t\to/$(MODE)/mips64/test/blink/ldbl_test.com.runs\t\t\\\n\t\to/$(MODE)/mips64el/test/blink/ldbl_test.com.runs\t\\\n\t\to/$(MODE)/s390x/test/blink/ldbl_test.com.runs\t\t\\\n\t\to/$(MODE)/powerpc/test/blink/ldbl_test.com.runs\t\t\\\n\t\to/$(MODE)/powerpc64le/test/blink/ldbl_test.com.runs\t\\\n\t\to/$(MODE)/i486/test/blink/disinst_test.com.runs\t\t\\\n\t\to/$(MODE)/m68k/test/blink/disinst_test.com.runs\t\t\\\n\t\to/$(MODE)/x86_64/test/blink/disinst_test.com.runs\t\\\n\t\to/$(MODE)/arm/test/blink/disinst_test.com.runs\t\t\\\n\t\to/$(MODE)/aarch64/test/blink/disinst_test.com.runs\t\\\n\t\to/$(MODE)/riscv64/test/blink/disinst_test.com.runs\t\\\n\t\to/$(MODE)/mips/test/blink/disinst_test.com.runs\t\t\\\n\t\to/$(MODE)/mipsel/test/blink/disinst_test.com.runs\t\\\n\t\to/$(MODE)/mips64/test/blink/disinst_test.com.runs\t\\\n\t\to/$(MODE)/mips64el/test/blink/disinst_test.com.runs\t\\\n\t\to/$(MODE)/s390x/test/blink/disinst_test.com.runs\t\\\n\t\to/$(MODE)/powerpc/test/blink/disinst_test.com.runs\t\\\n\t\to/$(MODE)/powerpc64le/test/blink/disinst_test.com.runs\n"
  },
  {
    "path": "test/blink/x86_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include \"blink/modrm.h\"\n#include \"blink/x86.h\"\n#include \"test/test.h\"\n\nint error;\nstruct XedDecodedInst xedd;\n\nvoid SetUp(void) {\n}\n\nvoid TearDown(void) {\n}\n\nTEST(x86, testPopR10) {\n  DecodeInstruction(&xedd, \"\\115\\132\\0\\0\", 4, XED_MODE_LONG);\n  ASSERT_EQ(2, xedd.length);\n  ASSERT_EQ(0132, Opcode(xedd.op.rde));\n  ASSERT_EQ(0, Osz(xedd.op.rde));\n  ASSERT_EQ(0, Asz(xedd.op.rde));\n  ASSERT_EQ(0, Rep(xedd.op.rde));\n  ASSERT_EQ(1, Rex(xedd.op.rde));\n  ASSERT_EQ(1, Rexb(xedd.op.rde));\n  ASSERT_EQ(1, Rexw(xedd.op.rde));\n  ASSERT_EQ(1, Rexr(xedd.op.rde));\n  ASSERT_EQ(0, Rexx(xedd.op.rde));\n  ASSERT_EQ(0, Sego(xedd.op.rde));\n  ASSERT_EQ(XED_MODE_LONG, Mode(xedd.op.rde));\n  ASSERT_EQ(XED_MODE_LONG, Eamode(xedd.op.rde));\n}\n\nTEST(x86, tesRepzCmpsb) {\n  DecodeInstruction(&xedd, \"\\363\\246\\0\\0\", 4, XED_MODE_LONG);\n  ASSERT_EQ(2, xedd.length);\n  ASSERT_EQ(0246, Opcode(xedd.op.rde));\n  ASSERT_EQ(0, Osz(xedd.op.rde));\n  ASSERT_EQ(0, Asz(xedd.op.rde));\n  ASSERT_EQ(3, Rep(xedd.op.rde));\n  ASSERT_EQ(0, Rex(xedd.op.rde));\n  ASSERT_EQ(0, Rexb(xedd.op.rde));\n  ASSERT_EQ(0, Rexw(xedd.op.rde));\n  ASSERT_EQ(0, Rexr(xedd.op.rde));\n  ASSERT_EQ(0, Rexx(xedd.op.rde));\n  ASSERT_EQ(0, Sego(xedd.op.rde));\n  ASSERT_EQ(XED_MODE_LONG, Mode(xedd.op.rde));\n  ASSERT_EQ(XED_MODE_LONG, Eamode(xedd.op.rde));\n}\n\nint ild(const char *p, size_t n) {\n  error = DecodeInstruction(&xedd, p, n, XED_MODE_LONG);\n  return error == XED_ERROR_NONE ? xedd.length : -error;\n}\n\nint ildreal(const char *p, size_t n) {\n  error = DecodeInstruction(&xedd, p, n, XED_MODE_REAL);\n  return error == XED_ERROR_NONE ? xedd.length : -error;\n}\n\nint ildlegacy(const char *p, size_t n) {\n  error = DecodeInstruction(&xedd, p, n, XED_MODE_LEGACY);\n  return error == XED_ERROR_NONE ? xedd.length : -error;\n}\n\nTEST(ild, test86) {\n  EXPECT_EQ(6, ild(\"\\017\\202\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\017\\203\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\017\\204\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\017\\205\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\017\\206\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\017\\207\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\017\\210\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\017\\211\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\017\\215\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\017\\216\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(4, ild(\"@\\210k\\000\", 4));\n  EXPECT_EQ(4, ild(\"@\\210s\\000\", 4));\n  EXPECT_EQ(4, ild(\"@\\210w\\000\", 4));\n  EXPECT_EQ(4, ild(\"@\\210{\\000\", 4));\n  EXPECT_EQ(3, ild(\"@\\210\\305\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\306\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\307\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\316\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\326\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\327\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\350\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\352\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\360\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\361\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\362\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\367\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\371\", 3));\n  EXPECT_EQ(3, ild(\"@\\210\\372\", 3));\n  EXPECT_EQ(3, ild(\"@\\2120\", 3));\n  EXPECT_EQ(4, ild(\"@\\212k\\000\", 4));\n  EXPECT_EQ(4, ild(\"@\\212p\\000\", 4));\n  EXPECT_EQ(4, ild(\"@\\212s\\000\", 4));\n  EXPECT_EQ(4, ild(\"@\\212w\\000\", 4));\n  EXPECT_EQ(4, ild(\"@\\212{\\000\", 4));\n  EXPECT_EQ(4, ild(\"@\\212}\\000\", 4));\n  EXPECT_EQ(3, ild(\"@\\266\\000\", 3));\n  EXPECT_EQ(2, ild(\"AT\", 2));\n  EXPECT_EQ(2, ild(\"AU\", 2));\n  EXPECT_EQ(2, ild(\"AV\", 2));\n  EXPECT_EQ(2, ild(\"AW\", 2));\n  EXPECT_EQ(2, ild(\"AX\", 2));\n  EXPECT_EQ(2, ild(\"A\\134\", 2));\n  EXPECT_EQ(2, ild(\"A]\", 2));\n  EXPECT_EQ(2, ild(\"A^\", 2));\n  EXPECT_EQ(2, ild(\"A_\", 2));\n  EXPECT_EQ(4, ild(\"A\\210P\\000\", 4));\n  EXPECT_EQ(3, ild(\"A\\210\\300\", 3));\n  EXPECT_EQ(3, ild(\"A\\210\\301\", 3));\n  EXPECT_EQ(3, ild(\"A\\210\\302\", 3));\n  EXPECT_EQ(3, ild(\"A\\210\\303\", 3));\n  EXPECT_EQ(3, ild(\"A\\210\\316\", 3));\n  EXPECT_EQ(3, ild(\"A\\210\\362\", 3));\n  EXPECT_EQ(7, ild(\"A\\211\\210\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"A\\211\\300\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\301\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\304\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\305\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\306\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\307\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\310\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\313\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\320\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\323\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\326\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\327\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\334\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\350\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\362\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\364\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\365\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\370\", 3));\n  EXPECT_EQ(3, ild(\"A\\211\\373\", 3));\n  EXPECT_EQ(4, ild(\"A\\212\\004\\000\", 4));\n  EXPECT_EQ(4, ild(\"A\\212\\004\\004\", 4));\n  EXPECT_EQ(4, ild(\"A\\212\\014\\024\", 4));\n  EXPECT_EQ(7, ild(\"A\\213\\200\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(6, ild(\"A\\270\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"A\\271\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"A\\274\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"A\\275\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"A\\276\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"A\\277\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(4, ild(\"A\\306\\000\\000\", 4));\n  EXPECT_EQ(5, ild(\"A\\306\\004$\\000\", 5));\n  EXPECT_EQ(3, ild(\"A\\323\\340\", 3));\n  EXPECT_EQ(4, ild(\"A\\377\\024\\304\", 4));\n  EXPECT_EQ(4, ild(\"B\\210\\004\\007\", 4));\n  EXPECT_EQ(4, ild(\"B\\212\\004\\006\", 4));\n  EXPECT_EQ(4, ild(\"B\\212\\024\\000\", 4));\n  EXPECT_EQ(8, ild(\"B\\213\\024\\215\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(5, ild(\"C\\306\\004\\016\\000\", 5));\n  EXPECT_EQ(4, ild(\"D\\210@\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\210C\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\210G\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\210K\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\210S\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\210c\\000\", 4));\n  EXPECT_EQ(3, ild(\"D\\210\\300\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\302\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\305\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\306\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\310\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\311\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\312\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\315\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\316\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\320\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\322\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\331\", 3));\n  EXPECT_EQ(3, ild(\"D\\210\\350\", 3));\n  EXPECT_EQ(5, ild(\"D\\211D$\\000\", 5));\n  EXPECT_EQ(7, ild(\"D\\211\\211\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"D\\211\\300\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\301\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\302\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\310\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\316\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\331\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\340\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\341\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\342\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\346\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\347\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\350\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\351\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\352\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\357\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\362\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\367\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\372\", 3));\n  EXPECT_EQ(3, ild(\"D\\211\\377\", 3));\n  EXPECT_EQ(3, ild(\"D\\212\\001\", 3));\n  EXPECT_EQ(4, ild(\"D\\212C\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\212F\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\212G\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\212N\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\212O\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\212S\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\212W\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\213\\004$\", 4));\n  EXPECT_EQ(5, ild(\"D\\213D$\\000\", 5));\n  EXPECT_EQ(4, ild(\"D\\213E\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\213G\\000\", 4));\n  EXPECT_EQ(4, ild(\"D\\213g\\000\", 4));\n  EXPECT_EQ(5, ild(\"D\\213l$\\000\", 5));\n  EXPECT_EQ(4, ild(\"D\\213w\\000\", 4));\n  EXPECT_EQ(5, ild(\"D\\213|$\\000\", 5));\n  EXPECT_EQ(4, ild(\"D\\213}\\000\", 4));\n  EXPECT_EQ(7, ild(\"D\\213\\201\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(4, ild(\"E\\2104$\", 4));\n  EXPECT_EQ(3, ild(\"E\\210\\307\", 3));\n  EXPECT_EQ(3, ild(\"E\\210\\310\", 3));\n  EXPECT_EQ(3, ild(\"E\\210\\321\", 3));\n  EXPECT_EQ(3, ild(\"E\\210\\323\", 3));\n  EXPECT_EQ(3, ild(\"E\\210\\370\", 3));\n  EXPECT_EQ(3, ild(\"E\\211\\301\", 3));\n  EXPECT_EQ(3, ild(\"E\\211\\312\", 3));\n  EXPECT_EQ(3, ild(\"E\\211\\313\", 3));\n  EXPECT_EQ(3, ild(\"E\\211\\330\", 3));\n  EXPECT_EQ(7, ild(\"E\\213\\220\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(4, ild(\"G\\210,\\016\", 4));\n  EXPECT_EQ(3, ild(\"Hc\\022\", 3));\n  EXPECT_EQ(3, ild(\"Hc\\307\", 3));\n  EXPECT_EQ(3, ild(\"Hc\\310\", 3));\n  EXPECT_EQ(3, ild(\"Hc\\311\", 3));\n  EXPECT_EQ(3, ild(\"Hc\\320\", 3));\n  EXPECT_EQ(3, ild(\"Hc\\322\", 3));\n  EXPECT_EQ(3, ild(\"Hc\\366\", 3));\n  EXPECT_EQ(3, ild(\"Hc\\370\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\002\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\003\", 3));\n  EXPECT_EQ(7, ild(\"H\\211\\005\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"H\\211\\006\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\007\", 3));\n  EXPECT_EQ(7, ild(\"H\\211\\015\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"H\\211\\020\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\023\", 3));\n  EXPECT_EQ(7, ild(\"H\\211\\025\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"H\\211\\027\", 3));\n  EXPECT_EQ(4, ild(\"H\\2114$\", 4));\n  EXPECT_EQ(7, ild(\"H\\2115\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"H\\2117\", 3));\n  EXPECT_EQ(7, ild(\"H\\211=\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(4, ild(\"H\\211C\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\211G\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\211S\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\211W\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\211w\\000\", 4));\n  EXPECT_EQ(3, ild(\"H\\211\\301\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\302\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\303\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\305\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\306\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\307\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\310\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\312\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\315\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\316\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\320\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\321\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\323\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\325\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\326\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\327\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\331\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\336\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\337\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\345\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\347\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\351\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\356\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\357\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\360\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\361\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\363\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\365\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\367\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\370\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\372\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\373\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\375\", 3));\n  EXPECT_EQ(3, ild(\"H\\211\\376\", 3));\n  EXPECT_EQ(3, ild(\"H\\213\\000\", 3));\n  EXPECT_EQ(3, ild(\"H\\213\\003\", 3));\n  EXPECT_EQ(8, ild(\"H\\213\\004\\305\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(4, ild(\"H\\213\\004\\320\", 4));\n  EXPECT_EQ(8, ild(\"H\\213\\004\\365\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(7, ild(\"H\\213\\005\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"H\\213\\007\", 3));\n  EXPECT_EQ(3, ild(\"H\\213\\013\", 3));\n  EXPECT_EQ(7, ild(\"H\\213\\015\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"H\\213\\022\", 3));\n  EXPECT_EQ(3, ild(\"H\\213\\023\", 3));\n  EXPECT_EQ(4, ild(\"H\\213\\024\\312\", 4));\n  EXPECT_EQ(8, ild(\"H\\213\\024\\325\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"H\\213\\024\\335\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(3, ild(\"H\\213\\027\", 3));\n  EXPECT_EQ(7, ild(\"H\\213\\035\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"H\\2133\", 3));\n  EXPECT_EQ(4, ild(\"H\\2134$\", 4));\n  EXPECT_EQ(3, ild(\"H\\2137\", 3));\n  EXPECT_EQ(3, ild(\"H\\213;\", 3));\n  EXPECT_EQ(7, ild(\"H\\213=\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(4, ild(\"H\\213A\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213C\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213E\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213G\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213K\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213O\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213R\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213S\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213U\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213W\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213o\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213s\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213w\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213{\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\213\\177\\000\", 4));\n  EXPECT_EQ(7, ild(\"H\\213\\200\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"H\\213\\206\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"H\\213\\207\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"H\\213\\220\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"H\\213\\221\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"H\\213\\226\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(2, ild(\"H\\230\", 2));\n  EXPECT_EQ(10, ild(\"H\\270\\000\\000\\000\\000\\000\\000\\000\\000\", 10));\n  EXPECT_EQ(10, ild(\"H\\271\\000\\000\\000\\000\\000\\000\\000\\000\", 10));\n  EXPECT_EQ(10, ild(\"H\\272\\000\\000\\000\\000\\000\\000\\000\\000\", 10));\n  EXPECT_EQ(10, ild(\"H\\276\\000\\000\\000\\000\\000\\000\\000\\000\", 10));\n  EXPECT_EQ(10, ild(\"H\\277\\000\\000\\000\\000\\000\\000\\000\\000\", 10));\n  EXPECT_EQ(7, ild(\"H\\307\\003\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(11, ild(\"H\\307\\005\\000\\000\\000\\000\\000\\000\\000\\000\", 11));\n  EXPECT_EQ(7, ild(\"H\\307\\007\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(8, ild(\"H\\307C\\000\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"H\\307G\\000\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(7, ild(\"H\\307\\300\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"H\\323\\300\", 3));\n  EXPECT_EQ(3, ild(\"H\\323\\340\", 3));\n  EXPECT_EQ(3, ild(\"H\\323\\342\", 3));\n  EXPECT_EQ(3, ild(\"H\\323\\350\", 3));\n  EXPECT_EQ(3, ild(\"H\\323\\352\", 3));\n  EXPECT_EQ(3, ild(\"Ic\\367\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\304\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\305\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\315\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\320\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\325\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\344\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\362\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\364\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\365\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\366\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\374\", 3));\n  EXPECT_EQ(3, ild(\"I\\211\\375\", 3));\n  EXPECT_EQ(4, ild(\"I\\213U\\000\", 4));\n  EXPECT_EQ(3, ild(\"I\\323\\340\", 3));\n  EXPECT_EQ(3, ild(\"I\\323\\355\", 3));\n  EXPECT_EQ(8, ild(\"J\\2134\\305\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(4, ild(\"L\\211c\\000\", 4));\n  EXPECT_EQ(4, ild(\"L\\211s\\000\", 4));\n  EXPECT_EQ(3, ild(\"L\\211\\301\", 3));\n  EXPECT_EQ(3, ild(\"L\\211\\306\", 3));\n  EXPECT_EQ(3, ild(\"L\\211\\316\", 3));\n  EXPECT_EQ(3, ild(\"L\\211\\320\", 3));\n  EXPECT_EQ(3, ild(\"L\\211\\346\", 3));\n  EXPECT_EQ(3, ild(\"L\\211\\347\", 3));\n  EXPECT_EQ(3, ild(\"L\\211\\352\", 3));\n  EXPECT_EQ(3, ild(\"L\\211\\356\", 3));\n  EXPECT_EQ(3, ild(\"L\\211\\357\", 3));\n  EXPECT_EQ(3, ild(\"L\\211\\372\", 3));\n  EXPECT_EQ(7, ild(\"L\\213%\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(4, ild(\"L\\213C\\000\", 4));\n  EXPECT_EQ(4, ild(\"L\\213G\\000\", 4));\n  EXPECT_EQ(4, ild(\"L\\213c\\000\", 4));\n  EXPECT_EQ(4, ild(\"L\\213g\\000\", 4));\n  EXPECT_EQ(4, ild(\"L\\213m\\000\", 4));\n  EXPECT_EQ(4, ild(\"L\\213o\\000\", 4));\n  EXPECT_EQ(4, ild(\"L\\213w\\000\", 4));\n  EXPECT_EQ(3, ild(\"Mc\\300\", 3));\n  EXPECT_EQ(3, ild(\"Mc\\356\", 3));\n  EXPECT_EQ(3, ild(\"M\\211\\303\", 3));\n  EXPECT_EQ(3, ild(\"M\\211\\354\", 3));\n  EXPECT_EQ(1, ild(\"S\", 1));\n  EXPECT_EQ(1, ild(\"U\", 1));\n  EXPECT_EQ(1, ild(\"X\", 1));\n  EXPECT_EQ(1, ild(\"Y\", 1));\n  EXPECT_EQ(1, ild(\"Z\", 1));\n  EXPECT_EQ(1, ild(\"[\", 1));\n  EXPECT_EQ(1, ild(\"]\", 1));\n  EXPECT_EQ(5, ild(\"fD\\213G\\000\", 5));\n  EXPECT_EQ(5, ild(\"fD\\213o\\000\", 5));\n  EXPECT_EQ(5, ild(\"fD\\213u\\000\", 5));\n  EXPECT_EQ(3, ild(\"f\\211\\002\", 3));\n  EXPECT_EQ(3, ild(\"f\\211\\020\", 3));\n  EXPECT_EQ(4, ild(\"f\\211C\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\211G\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\211K\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\211O\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\211W\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\211s\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\211w\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\211{\\000\", 4));\n  EXPECT_EQ(7, ild(\"f\\211\\201\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"f\\211\\202\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"f\\211\\220\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(8, ild(\"f\\213\\004\\205\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"f\\213\\024\\255\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"f\\213\\024\\325\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"f\\213\\024\\355\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(4, ild(\"f\\213C\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\213G\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\213K\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\213O\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\213S\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\213W\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\213s\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\213w\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\213{\\000\", 4));\n  EXPECT_EQ(7, ild(\"f\\213\\200\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(8, ild(\"f\\213\\204\\000\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"f\\213\\224\\000\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"f\\213\\224-\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(7, ild(\"f\\213\\225\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(2, ild(\"f\\220\", 2));\n  EXPECT_EQ(9, ild(\"f\\307\\005\\000\\000\\000\\000\\000\\000\", 9));\n  EXPECT_EQ(6, ild(\"f\\307G\\000\\000\\000\", 6));\n  EXPECT_EQ(9, ild(\"f\\307\\200\\000\\000\\000\\000\\000\\000\", 9));\n  EXPECT_EQ(9, ild(\"f\\307\\202\\000\\000\\000\\000\\000\\000\", 9));\n  EXPECT_EQ(2, ild(\"r\\000\", 2));\n  EXPECT_EQ(2, ild(\"s\\000\", 2));\n  EXPECT_EQ(2, ild(\"t\\000\", 2));\n  EXPECT_EQ(2, ild(\"u\\000\", 2));\n  EXPECT_EQ(2, ild(\"v\\000\", 2));\n  EXPECT_EQ(2, ild(\"w\\000\", 2));\n  EXPECT_EQ(2, ild(\"x\\000\", 2));\n  EXPECT_EQ(2, ild(\"y\\000\", 2));\n  EXPECT_EQ(2, ild(\"|\\000\", 2));\n  EXPECT_EQ(2, ild(\"}\\000\", 2));\n  EXPECT_EQ(2, ild(\"~\\000\", 2));\n  EXPECT_EQ(2, ild(\"\\177\\000\", 2));\n  EXPECT_EQ(2, ild(\"\\210\\002\", 2));\n  EXPECT_EQ(3, ild(\"\\210\\0143\", 3));\n  EXPECT_EQ(2, ild(\"\\210\\020\", 2));\n  EXPECT_EQ(3, ild(\"\\210C\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\210D\\024\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\210D$\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\210G\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\210K\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\210O\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\210Q\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\210S\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\210T\\003\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\210T\\007\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\210W\\000\", 3));\n  EXPECT_EQ(2, ild(\"\\210\\301\", 2));\n  EXPECT_EQ(2, ild(\"\\210\\302\", 2));\n  EXPECT_EQ(2, ild(\"\\210\\310\", 2));\n  EXPECT_EQ(2, ild(\"\\210\\312\", 2));\n  EXPECT_EQ(2, ild(\"\\210\\320\", 2));\n  EXPECT_EQ(2, ild(\"\\210\\321\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\002\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\003\", 2));\n  EXPECT_EQ(3, ild(\"\\211\\004$\", 3));\n  EXPECT_EQ(2, ild(\"\\211\\020\", 2));\n  EXPECT_EQ(6, ild(\"\\211\\025\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\211=\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(3, ild(\"\\211B\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\211C\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\211D$\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\211E\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\211G\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\211K\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\211L$\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\211O\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\211P\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\211T$\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\211W\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\211X\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\211Z\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\211]\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\211j\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\211s\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\211t$\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\211w\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\211|$\\000\", 4));\n  EXPECT_EQ(6, ild(\"\\211\\202\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\211\\220\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(7, ild(\"\\211\\224$\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(6, ild(\"\\211\\232\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\211\\252\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(2, ild(\"\\211\\300\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\301\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\302\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\303\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\305\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\306\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\307\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\310\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\313\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\316\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\320\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\321\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\323\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\325\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\326\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\327\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\330\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\332\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\336\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\337\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\350\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\351\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\352\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\356\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\360\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\361\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\362\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\363\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\365\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\366\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\367\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\370\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\371\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\373\", 2));\n  EXPECT_EQ(2, ild(\"\\211\\377\", 2));\n  EXPECT_EQ(2, ild(\"\\212\\000\", 2));\n  EXPECT_EQ(3, ild(\"\\212\\004\\001\", 3));\n  EXPECT_EQ(3, ild(\"\\212\\004\\002\", 3));\n  EXPECT_EQ(3, ild(\"\\212\\004\\006\", 3));\n  EXPECT_EQ(7, ild(\"\\212\\004\\225\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\212\\004\\325\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(2, ild(\"\\212\\006\", 2));\n  EXPECT_EQ(2, ild(\"\\212\\010\", 2));\n  EXPECT_EQ(3, ild(\"\\212\\014\\001\", 3));\n  EXPECT_EQ(3, ild(\"\\212\\014\\010\", 3));\n  EXPECT_EQ(7, ild(\"\\212\\014\\325\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(2, ild(\"\\212\\020\", 2));\n  EXPECT_EQ(3, ild(\"\\212\\024\\002\", 3));\n  EXPECT_EQ(3, ild(\"\\212\\024\\012\", 3));\n  EXPECT_EQ(3, ild(\"\\212\\024\\021\", 3));\n  EXPECT_EQ(7, ild(\"\\212\\024\\225\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\212\\024\\305\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\212\\024\\325\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\212\\024\\365\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"\\212@\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212C\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212E\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212F\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212G\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212H\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212J\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212K\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212M\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212N\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212O\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212P\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\212S\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\212T$\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\212W\\000\", 3));\n  EXPECT_EQ(6, ild(\"\\212\\200\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(7, ild(\"\\212\\204\\020\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(6, ild(\"\\212\\211\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\212\\220\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\212\\222\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(2, ild(\"\\213\\000\", 2));\n  EXPECT_EQ(7, ild(\"\\213\\004\\205\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\004\\225\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\004\\265\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\004\\275\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\004\\305\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\004\\325\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\004\\375\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(2, ild(\"\\213\\006\", 2));\n  EXPECT_EQ(2, ild(\"\\213\\007\", 2));\n  EXPECT_EQ(7, ild(\"\\213\\014\\205\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\014\\215\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\014\\265\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\014\\275\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\014\\315\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\014\\325\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(2, ild(\"\\213\\020\", 2));\n  EXPECT_EQ(7, ild(\"\\213\\024\\205\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\024\\225\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\024\\255\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\024\\305\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\024\\315\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\024\\325\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\024\\355\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\213\\024\\365\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(6, ild(\"\\213\\025\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(2, ild(\"\\213\\026\", 2));\n  EXPECT_EQ(2, ild(\"\\213\\036\", 2));\n  EXPECT_EQ(2, ild(\"\\213(\", 2));\n  EXPECT_EQ(7, ild(\"\\2134\\205\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\2134\\315\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\2134\\325\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"\\213<$\", 3));\n  EXPECT_EQ(2, ild(\"\\213?\", 2));\n  EXPECT_EQ(3, ild(\"\\213@\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213C\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213E\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213G\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213H\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213K\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\213L$\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\213O\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213Q\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213S\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\213T$\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\213W\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213h\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213s\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\213t$\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\213u\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213w\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213{\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\213|$\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\213}\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\213\\177\\000\", 3));\n  EXPECT_EQ(6, ild(\"\\213\\200\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\213\\201\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\213\\222\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\213\\225\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\213\\260\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\213\\262\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\213\\271\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(2, ild(\"\\260\\000\", 2));\n  EXPECT_EQ(2, ild(\"\\262\\000\", 2));\n  EXPECT_EQ(5, ild(\"\\270\\000\\000\\000\\000\", 5));\n  EXPECT_EQ(5, ild(\"\\271\\000\\000\\000\\000\", 5));\n  EXPECT_EQ(5, ild(\"\\272\\000\\000\\000\\000\", 5));\n  EXPECT_EQ(5, ild(\"\\273\\000\\000\\000\\000\", 5));\n  EXPECT_EQ(5, ild(\"\\275\\000\\000\\000\\000\", 5));\n  EXPECT_EQ(5, ild(\"\\276\\000\\000\\000\\000\", 5));\n  EXPECT_EQ(5, ild(\"\\277\\000\\000\\000\\000\", 5));\n  EXPECT_EQ(1, ild(\"\\303\", 1));\n  EXPECT_EQ(3, ild(\"\\306\\001\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\306\\004\\003\\000\", 4));\n  EXPECT_EQ(7, ild(\"\\306\\005\\000\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"\\306\\006\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\306\\007\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\306@\\000\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\306B\\000\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\306C\\000\\000\", 4));\n  EXPECT_EQ(5, ild(\"\\306D$\\000\\000\", 5));\n  EXPECT_EQ(4, ild(\"\\306G\\000\\000\", 4));\n  EXPECT_EQ(8, ild(\"\\306\\204\\016\\000\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(7, ild(\"\\307\\004\\007\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(10, ild(\"\\307\\005\\000\\000\\000\\000\\000\\000\\000\\000\", 10));\n  EXPECT_EQ(7, ild(\"\\307@\\000\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\307B\\000\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(8, ild(\"\\307D$\\000\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(10, ild(\"\\307\\200\\000\\000\\000\\000\\000\\000\\000\\000\", 10));\n  EXPECT_EQ(11, ild(\"\\307\\204$\\000\\000\\000\\000\\000\\000\\000\\000\", 11));\n  EXPECT_EQ(2, ild(\"\\322\\301\", 2));\n  EXPECT_EQ(2, ild(\"\\323\\340\", 2));\n  EXPECT_EQ(2, ild(\"\\323\\342\", 2));\n  EXPECT_EQ(2, ild(\"\\323\\347\", 2));\n  EXPECT_EQ(2, ild(\"\\340\\000\", 2));\n  EXPECT_EQ(2, ild(\"\\342\\000\", 2));\n  EXPECT_EQ(5, ild(\"\\350\\000\\000\\000\\000\", 5));\n  EXPECT_EQ(5, ildlegacy(\"\\350\\000\\000\\000\\000\", 5));\n#ifndef DISABLE_METAL\n  EXPECT_EQ(3, ildreal(\"\\350\\000\\000\", 3));\n#endif\n  EXPECT_EQ(5, ild(\"\\350\\000\\203\\342\\000\", 5));\n  EXPECT_EQ(5, ild(\"\\351\\000\\000\\000\\000\", 5));\n  EXPECT_EQ(5, ild(\"\\351\\000\\203\\340\\000\", 5));\n  EXPECT_EQ(2, ild(\"\\353\\000\", 2));\n  EXPECT_EQ(2, ild(\"\\362\\256\", 2));\n  EXPECT_EQ(2, ild(\"\\363\\244\", 2));\n  EXPECT_EQ(2, ild(\"\\363\\303\", 2));\n  EXPECT_EQ(7, ild(\"\\377\\024\\305\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\377$\\305\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\377$\\315\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\377$\\325\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\377$\\365\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(2, ild(\"\\377\\320\", 2));\n  EXPECT_EQ(2, ild(\"\\377\\322\", 2));\n  EXPECT_EQ(2, ild(\"\\377\\340\", 2));\n  EXPECT_EQ(2, ild(\"\\336\\315\", 2));\n}\n\nTEST(ild, test386) {\n  EXPECT_EQ(3, ild(\"\\017\\224\\300\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\224\\301\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\224\\302\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\225\\300\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\225\\301\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\225\\302\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\226\\300\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\226\\302\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\227\\301\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\234\\301\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\243\\320\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\000\", 3));\n  EXPECT_EQ(8, ild(\"\\017\\266\\004\\225\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"\\017\\266\\004\\325\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(3, ild(\"\\017\\266\\007\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\010\", 3));\n  EXPECT_EQ(4, ild(\"\\017\\266\\014\\010\", 4));\n  EXPECT_EQ(8, ild(\"\\017\\266\\014\\325\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(3, ild(\"\\017\\266\\017\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\020\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266/\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\2660\", 3));\n  EXPECT_EQ(4, ild(\"\\017\\26640\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266<\\010\", 4));\n  EXPECT_EQ(3, ild(\"\\017\\266?\", 3));\n  EXPECT_EQ(4, ild(\"\\017\\266@\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266A\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266C\\000\", 4));\n  EXPECT_EQ(5, ild(\"\\017\\266D7\\000\", 5));\n  EXPECT_EQ(4, ild(\"\\017\\266F\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266G\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266H\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266K\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266O\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266P\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266R\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266S\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266W\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266X\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266_\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266p\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266s\\000\", 4));\n  EXPECT_EQ(5, ild(\"\\017\\266t$\\000\", 5));\n  EXPECT_EQ(4, ild(\"\\017\\266{\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266}\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\266\\177\\000\", 4));\n  EXPECT_EQ(7, ild(\"\\017\\266\\200\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\017\\266\\202\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(8, ild(\"\\017\\266\\204\\022\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(7, ild(\"\\017\\266\\207\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(8, ild(\"\\017\\266\\214\\020\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"\\017\\266\\224\\021\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"\\017\\266\\234$\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(3, ild(\"\\017\\266\\300\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\301\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\302\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\310\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\311\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\312\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\320\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\322\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\350\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\360\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\361\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\362\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\266\\371\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\267\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\2679\", 3));\n  EXPECT_EQ(4, ild(\"\\017\\267B\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\267E\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\267F\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\267G\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\267P\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\267W\\000\", 4));\n  EXPECT_EQ(5, ild(\"\\017\\267t$\\000\", 5));\n  EXPECT_EQ(4, ild(\"\\017\\267x\\000\", 4));\n  EXPECT_EQ(7, ild(\"\\017\\267\\200\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(8, ild(\"\\017\\267\\204\\000\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(3, ild(\"\\017\\267\\300\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\267\\307\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\267\\322\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\267\\366\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\267\\372\", 3));\n  EXPECT_EQ(4, ild(\"\\017\\272\\345\\000\", 4));\n  EXPECT_EQ(8, ild(\"\\017\\276\\004\\225\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"\\017\\276\\004\\325\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(8, ild(\"\\017\\276\\014\\325\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(4, ild(\"\\017\\276A\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\276F\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\276G\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\276J\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\276N\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\276O\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\017\\276V\\000\", 4));\n  EXPECT_EQ(7, ild(\"\\017\\276\\200\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"\\017\\276\\201\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(8, ild(\"\\017\\276\\204\\022\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(3, ild(\"\\017\\276\\370\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\277\\307\", 3));\n  EXPECT_EQ(3, ild(\"\\017\\277\\370\", 3));\n  EXPECT_EQ(4, ild(\"@\\017\\224\\306\", 4));\n  EXPECT_EQ(4, ild(\"@\\017\\224\\307\", 4));\n  EXPECT_EQ(4, ild(\"@\\017\\236\\305\", 4));\n  EXPECT_EQ(4, ild(\"@\\017\\266\\305\", 4));\n  EXPECT_EQ(4, ild(\"@\\017\\266\\307\", 4));\n  EXPECT_EQ(4, ild(\"@\\017\\266\\315\", 4));\n  EXPECT_EQ(4, ild(\"@\\017\\266\\316\", 4));\n  EXPECT_EQ(4, ild(\"@\\017\\266\\325\", 4));\n  EXPECT_EQ(4, ild(\"@\\017\\266\\366\", 4));\n  EXPECT_EQ(4, ild(\"@\\017\\266\\377\", 4));\n  EXPECT_EQ(4, ild(\"@\\017\\276\\307\", 4));\n  EXPECT_EQ(4, ild(\"A\\017\\224\\300\", 4));\n  EXPECT_EQ(4, ild(\"A\\017\\225\\304\", 4));\n  EXPECT_EQ(5, ild(\"A\\017\\266,\\020\", 5));\n  EXPECT_EQ(5, ild(\"A\\017\\2664\\000\", 5));\n  EXPECT_EQ(6, ild(\"A\\017\\266D$\\000\", 6));\n  EXPECT_EQ(6, ild(\"A\\017\\266|,\\000\", 6));\n  EXPECT_EQ(6, ild(\"A\\017\\267D$\\000\", 6));\n  EXPECT_EQ(4, ild(\"D\\017\\266\\007\", 4));\n  EXPECT_EQ(4, ild(\"D\\017\\266 \", 4));\n  EXPECT_EQ(5, ild(\"D\\017\\266$0\", 5));\n  EXPECT_EQ(4, ild(\"D\\017\\266'\", 4));\n  EXPECT_EQ(5, ild(\"D\\017\\266,\\010\", 5));\n  EXPECT_EQ(4, ild(\"D\\017\\266/\", 4));\n  EXPECT_EQ(5, ild(\"D\\017\\266G\\000\", 5));\n  EXPECT_EQ(5, ild(\"D\\017\\266k\\000\", 5));\n  EXPECT_EQ(5, ild(\"D\\017\\266u\\000\", 5));\n  EXPECT_EQ(5, ild(\"E\\017\\266\\014\\000\", 5));\n  EXPECT_EQ(5, ild(\"E\\017\\2664$\", 5));\n  EXPECT_EQ(5, ild(\"E\\017\\266u\\000\", 5));\n  EXPECT_EQ(4, ild(\"E\\017\\266\\300\", 4));\n  EXPECT_EQ(4, ild(\"E\\017\\267\\300\", 4));\n  EXPECT_EQ(4, ild(\"H\\017\\243\\316\", 4));\n  EXPECT_EQ(4, ild(\"H\\017\\243\\320\", 4));\n  EXPECT_EQ(4, ild(\"H\\017\\243\\321\", 4));\n  EXPECT_EQ(9, ild(\"H\\017\\276\\004\\325\\000\\000\\000\\000\", 9));\n  EXPECT_EQ(4, ild(\"H\\017\\276\\022\", 4));\n  EXPECT_EQ(4, ild(\"H\\017\\276\\307\", 4));\n  EXPECT_EQ(4, ild(\"H\\017\\276\\366\", 4));\n  EXPECT_EQ(4, ild(\"H\\017\\277\\022\", 4));\n  EXPECT_EQ(4, ild(\"H\\017\\277\\307\", 4));\n  EXPECT_EQ(4, ild(\"H\\017\\277\\366\", 4));\n  EXPECT_EQ(5, ild(\"f@\\017\\276\\307\", 5));\n  EXPECT_EQ(2, ild(\"\\363\\253\", 2));\n}\n\nTEST(ild, testBinary) {\n  EXPECT_EQ(2, ild(\"\\000\\000\", 2));\n  EXPECT_EQ(6, ild(\"\\000\\270\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(2, ild(\"\\000\\301\", 2));\n  EXPECT_EQ(2, ild(\"\\000\\377\", 2));\n  EXPECT_EQ(6, ild(\"\\001\\260\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(2, ild(\"\\001\\300\", 2));\n  EXPECT_EQ(2, ild(\"\\001\\301\", 2));\n  EXPECT_EQ(2, ild(\"\\001\\302\", 2));\n  EXPECT_EQ(2, ild(\"\\001\\305\", 2));\n  EXPECT_EQ(2, ild(\"\\001\\310\", 2));\n  EXPECT_EQ(2, ild(\"\\001\\311\", 2));\n  EXPECT_EQ(2, ild(\"\\001\\320\", 2));\n  EXPECT_EQ(2, ild(\"\\001\\322\", 2));\n  EXPECT_EQ(2, ild(\"\\001\\326\", 2));\n  EXPECT_EQ(2, ild(\"\\001\\360\", 2));\n  EXPECT_EQ(2, ild(\"\\001\\376\", 2));\n  EXPECT_EQ(3, ild(\"\\017\\257\\302\", 3));\n  EXPECT_EQ(2, ild(\"\\031\\300\", 2));\n  EXPECT_EQ(2, ild(\")\\302\", 2));\n  EXPECT_EQ(2, ild(\")\\303\", 2));\n  EXPECT_EQ(2, ild(\")\\305\", 2));\n  EXPECT_EQ(2, ild(\")\\335\", 2));\n  EXPECT_EQ(2, ild(\")\\350\", 2));\n  EXPECT_EQ(3, ild(\"8W\\000\", 3));\n  EXPECT_EQ(2, ild(\"9\\301\", 2));\n  EXPECT_EQ(2, ild(\"9\\302\", 2));\n  EXPECT_EQ(2, ild(\"9\\303\", 2));\n  EXPECT_EQ(2, ild(\"9\\305\", 2));\n  EXPECT_EQ(2, ild(\"9\\312\", 2));\n  EXPECT_EQ(2, ild(\"9\\320\", 2));\n  EXPECT_EQ(2, ild(\"9\\330\", 2));\n  EXPECT_EQ(2, ild(\"9\\353\", 2));\n  EXPECT_EQ(2, ild(\"9\\360\", 2));\n  EXPECT_EQ(2, ild(\"9\\361\", 2));\n  EXPECT_EQ(2, ild(\"9\\367\", 2));\n  EXPECT_EQ(2, ild(\"9\\371\", 2));\n  EXPECT_EQ(3, ild(\":C\\000\", 3));\n  EXPECT_EQ(3, ild(\":K\\000\", 3));\n  EXPECT_EQ(3, ild(\":S\\000\", 3));\n  EXPECT_EQ(2, ild(\"<\\000\", 2));\n  EXPECT_EQ(5, ild(\"=\\000\\000\\000\\000\", 5));\n  EXPECT_EQ(3, ild(\"@8\\361\", 3));\n  EXPECT_EQ(4, ild(\"@\\200\\376\\000\", 4));\n  EXPECT_EQ(4, ild(\"@\\200\\377\\000\", 4));\n  EXPECT_EQ(3, ild(\"A)\\314\", 3));\n  EXPECT_EQ(3, ild(\"A8\\355\", 3));\n  EXPECT_EQ(3, ild(\"A9\\301\", 3));\n  EXPECT_EQ(3, ild(\"A9\\304\", 3));\n  EXPECT_EQ(3, ild(\"A9\\306\", 3));\n  EXPECT_EQ(3, ild(\"A9\\320\", 3));\n  EXPECT_EQ(3, ild(\"A9\\321\", 3));\n  EXPECT_EQ(3, ild(\"A9\\335\", 3));\n  EXPECT_EQ(3, ild(\"A9\\354\", 3));\n  EXPECT_EQ(3, ild(\"A9\\356\", 3));\n  EXPECT_EQ(3, ild(\"A9\\365\", 3));\n  EXPECT_EQ(5, ild(\"A\\200<\\000\\000\", 5));\n  EXPECT_EQ(6, ild(\"A\\200|$\\000\\000\", 6));\n  EXPECT_EQ(4, ild(\"A\\200\\370\\000\", 4));\n  EXPECT_EQ(4, ild(\"A\\200\\371\\000\", 4));\n  EXPECT_EQ(7, ild(\"A\\201\\370\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(4, ild(\"A\\203\\370\\000\", 4));\n  EXPECT_EQ(4, ild(\"A\\203\\371\\000\", 4));\n  EXPECT_EQ(4, ild(\"A\\203\\373\\000\", 4));\n  EXPECT_EQ(4, ild(\"A\\203\\374\\000\", 4));\n  EXPECT_EQ(4, ild(\"A\\203\\375\\000\", 4));\n  EXPECT_EQ(4, ild(\"A\\203\\376\\000\", 4));\n  EXPECT_EQ(3, ild(\"A\\377\\301\", 3));\n  EXPECT_EQ(3, ild(\"A\\377\\302\", 3));\n  EXPECT_EQ(3, ild(\"A\\377\\304\", 3));\n  EXPECT_EQ(3, ild(\"A\\377\\306\", 3));\n  EXPECT_EQ(3, ild(\"A\\377\\307\", 3));\n  EXPECT_EQ(3, ild(\"A\\377\\310\", 3));\n  EXPECT_EQ(3, ild(\"A\\377\\317\", 3));\n  EXPECT_EQ(3, ild(\"D\\001\\310\", 3));\n  EXPECT_EQ(3, ild(\"D\\001\\350\", 3));\n  EXPECT_EQ(3, ild(\"D)\\300\", 3));\n  EXPECT_EQ(3, ild(\"D)\\321\", 3));\n  EXPECT_EQ(3, ild(\"D)\\335\", 3));\n  EXPECT_EQ(3, ild(\"D)\\341\", 3));\n  EXPECT_EQ(3, ild(\"D8\\301\", 3));\n  EXPECT_EQ(3, ild(\"D9\\302\", 3));\n  EXPECT_EQ(3, ild(\"D9\\305\", 3));\n  EXPECT_EQ(3, ild(\"D9\\307\", 3));\n  EXPECT_EQ(3, ild(\"D9\\311\", 3));\n  EXPECT_EQ(3, ild(\"D9\\341\", 3));\n  EXPECT_EQ(3, ild(\"D9\\343\", 3));\n  EXPECT_EQ(3, ild(\"D9\\345\", 3));\n  EXPECT_EQ(3, ild(\"D9\\350\", 3));\n  EXPECT_EQ(3, ild(\"D9\\363\", 3));\n  EXPECT_EQ(3, ild(\"E\\001\\342\", 3));\n  EXPECT_EQ(3, ild(\"E\\001\\344\", 3));\n  EXPECT_EQ(3, ild(\"E)\\304\", 3));\n  EXPECT_EQ(3, ild(\"E9\\356\", 3));\n  EXPECT_EQ(3, ild(\"E9\\357\", 3));\n  EXPECT_EQ(3, ild(\"E9\\364\", 3));\n  EXPECT_EQ(3, ild(\"E9\\376\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\300\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\301\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\302\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\306\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\310\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\312\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\320\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\321\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\322\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\336\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\337\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\357\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\360\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\362\", 3));\n  EXPECT_EQ(3, ild(\"H\\001\\370\", 3));\n  EXPECT_EQ(4, ild(\"H\\003G\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\003S\\000\", 4));\n  EXPECT_EQ(6, ild(\"H\\005\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(4, ild(\"H\\017\\257\\310\", 4));\n  EXPECT_EQ(4, ild(\"H\\017\\257\\312\", 4));\n  EXPECT_EQ(4, ild(\"H\\017\\257\\320\", 4));\n  EXPECT_EQ(3, ild(\"H)\\332\", 3));\n  EXPECT_EQ(6, ild(\"H-\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(3, ild(\"H9\\301\", 3));\n  EXPECT_EQ(3, ild(\"H9\\302\", 3));\n  EXPECT_EQ(3, ild(\"H9\\307\", 3));\n  EXPECT_EQ(3, ild(\"H9\\310\", 3));\n  EXPECT_EQ(3, ild(\"H9\\312\", 3));\n  EXPECT_EQ(3, ild(\"H9\\320\", 3));\n  EXPECT_EQ(3, ild(\"H9\\326\", 3));\n  EXPECT_EQ(3, ild(\"H9\\330\", 3));\n  EXPECT_EQ(3, ild(\"H9\\360\", 3));\n  EXPECT_EQ(3, ild(\"H9\\361\", 3));\n  EXPECT_EQ(3, ild(\"H9\\362\", 3));\n  EXPECT_EQ(3, ild(\"H9\\370\", 3));\n  EXPECT_EQ(6, ild(\"H=\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(7, ild(\"H\\201\\304\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"H\\201\\353\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"H\\201\\354\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"H\\201\\356\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(7, ild(\"H\\201\\377\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(5, ild(\"H\\203\\177\\000\\000\", 5));\n  EXPECT_EQ(4, ild(\"H\\203\\300\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\302\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\303\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\304\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\350\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\353\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\354\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\370\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\371\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\372\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\373\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\376\\000\", 4));\n  EXPECT_EQ(4, ild(\"H\\203\\377\\000\", 4));\n  EXPECT_EQ(3, ild(\"H\\367\\333\", 3));\n  EXPECT_EQ(3, ild(\"H\\367\\361\", 3));\n  EXPECT_EQ(3, ild(\"H\\367\\366\", 3));\n  EXPECT_EQ(3, ild(\"H\\367\\367\", 3));\n  EXPECT_EQ(3, ild(\"H\\377\\300\", 3));\n  EXPECT_EQ(3, ild(\"H\\377\\301\", 3));\n  EXPECT_EQ(3, ild(\"H\\377\\302\", 3));\n  EXPECT_EQ(3, ild(\"H\\377\\305\", 3));\n  EXPECT_EQ(3, ild(\"H\\377\\306\", 3));\n  EXPECT_EQ(3, ild(\"H\\377\\307\", 3));\n  EXPECT_EQ(3, ild(\"H\\377\\310\", 3));\n  EXPECT_EQ(3, ild(\"H\\377\\311\", 3));\n  EXPECT_EQ(3, ild(\"I\\001\\321\", 3));\n  EXPECT_EQ(3, ild(\"I)\\302\", 3));\n  EXPECT_EQ(3, ild(\"I\\367\\334\", 3));\n  EXPECT_EQ(3, ild(\"I\\367\\361\", 3));\n  EXPECT_EQ(3, ild(\"I\\377\\300\", 3));\n  EXPECT_EQ(3, ild(\"I\\377\\305\", 3));\n  EXPECT_EQ(3, ild(\"L\\001\\300\", 3));\n  EXPECT_EQ(3, ild(\"L\\001\\340\", 3));\n  EXPECT_EQ(3, ild(\"L\\001\\350\", 3));\n  EXPECT_EQ(4, ild(\"L\\003O\\000\", 4));\n  EXPECT_EQ(3, ild(\"L)\\300\", 3));\n  EXPECT_EQ(3, ild(\"f9\\312\", 3));\n  EXPECT_EQ(3, ild(\"f9\\320\", 3));\n  EXPECT_EQ(4, ild(\"f=\\000\\000\", 4));\n  EXPECT_EQ(5, ild(\"f\\201\\302\\000\\000\", 5));\n  EXPECT_EQ(5, ild(\"f\\201\\372\\000\\000\", 5));\n  EXPECT_EQ(5, ild(\"f\\201\\375\\000\\000\", 5));\n  EXPECT_EQ(5, ild(\"f\\203x\\000\\000\", 5));\n  EXPECT_EQ(4, ild(\"f\\203\\370\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\203\\371\\000\", 4));\n  EXPECT_EQ(4, ild(\"f\\203\\372\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\2008\\000\", 3));\n  EXPECT_EQ(7, ild(\"\\200=\\000\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(4, ild(\"\\200x\\000\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\200z\\000\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\200{\\000\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\200}\\000\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\200\\177\\000\\000\", 4));\n  EXPECT_EQ(3, ild(\"\\200\\371\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\200\\372\\000\", 3));\n  EXPECT_EQ(6, ild(\"\\201\\353\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\201\\372\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(6, ild(\"\\201\\377\\000\\000\\000\\000\", 6));\n  EXPECT_EQ(4, ild(\"\\203<$\\000\", 4));\n  EXPECT_EQ(8, ild(\"\\203<\\325\\000\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(7, ild(\"\\203=\\000\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(4, ild(\"\\203x\\000\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\203}\\000\\000\", 4));\n  EXPECT_EQ(4, ild(\"\\203\\177\\000\\000\", 4));\n  EXPECT_EQ(7, ild(\"\\203\\270\\000\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(3, ild(\"\\203\\301\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\302\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\307\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\350\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\351\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\352\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\370\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\371\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\372\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\373\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\375\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\376\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\203\\377\\000\", 3));\n  EXPECT_EQ(3, ild(\"\\367u\\000\", 3));\n  EXPECT_EQ(2, ild(\"\\367\\333\", 2));\n  EXPECT_EQ(3, ild(\"\\376C\\000\", 3));\n  EXPECT_EQ(2, ild(\"\\376\\310\", 2));\n  EXPECT_EQ(2, ild(\"\\376\\311\", 2));\n  EXPECT_EQ(2, ild(\"\\376\\312\", 2));\n  EXPECT_EQ(2, ild(\"\\377\\300\", 2));\n  EXPECT_EQ(2, ild(\"\\377\\301\", 2));\n  EXPECT_EQ(2, ild(\"\\377\\302\", 2));\n  EXPECT_EQ(2, ild(\"\\377\\303\", 2));\n  EXPECT_EQ(2, ild(\"\\377\\305\", 2));\n  EXPECT_EQ(2, ild(\"\\377\\306\", 2));\n  EXPECT_EQ(2, ild(\"\\377\\310\", 2));\n  EXPECT_EQ(2, ild(\"\\377\\312\", 2));\n  EXPECT_EQ(2, ild(\"\\377\\316\", 2));\n}\n\nTEST(ild, testWideNops) {\n  EXPECT_EQ(1, ild(\"\\220\", 1));\n  EXPECT_EQ(2, ild(\"f\\220\", 2));\n  EXPECT_EQ(3, ild(\"\\017\\037\\000\", 3));\n  EXPECT_EQ(4, ild(\"\\017\\037@\\000\", 4));\n  EXPECT_EQ(5, ild(\"\\017\\037D\\000\\000\", 5));\n  EXPECT_EQ(6, ild(\"f\\017\\037D\\000\\000\", 6));\n  EXPECT_EQ(7, ild(\"\\017\\037\\200\\000\\000\\000\\000\", 7));\n  EXPECT_EQ(8, ild(\"\\017\\037\\204\\000\\000\\000\\000\\000\", 8));\n  EXPECT_EQ(9, ild(\"f\\017\\037\\204\\000\\000\\000\\000\\000\", 9));\n}\n\n#ifndef DISABLE_BMI2\n\nTEST(ild, mulx) {\n  // mulx %rbx,%rdx,%rcx\n  char code[15] = \"\\xc4\\xe2\\xeb\\xf6\\xcb\";\n  EXPECT_EQ(0, DecodeInstruction(&xedd, code, 15, XED_MODE_LONG));\n  EXPECT_EQ(5, xedd.length);\n  EXPECT_EQ(2 << 8 | 0xf6, Mopcode(xedd.op.rde));\n  EXPECT_EQ(3, ModrmMod(xedd.op.rde));  // register operand\n  EXPECT_TRUE(Rexw(xedd.op.rde));       // 64-bit\n  EXPECT_EQ(1, ModrmReg(xedd.op.rde));  // rcx (arg1)\n  EXPECT_EQ(2, Vreg(xedd.op.rde));      // rdx (arg2)\n  EXPECT_EQ(3, ModrmRm(xedd.op.rde));   // rbx (arg3)\n}\n\nTEST(ild, shlx) {\n  // mulx %rbx,%rdx,%rcx\n  char code[15] = \"\\xc4\\xe2\\x71\\xf7\\xd8\";\n  EXPECT_EQ(0, DecodeInstruction(&xedd, code, 15, XED_MODE_LONG));\n  EXPECT_EQ(5, xedd.length);\n  EXPECT_EQ(2 << 8 | 0xf7, Mopcode(xedd.op.rde));\n  EXPECT_EQ(3, ModrmMod(xedd.op.rde));  // register operand\n  EXPECT_TRUE(!Rexw(xedd.op.rde));      // 32-bit\n  EXPECT_EQ(3, ModrmReg(xedd.op.rde));  //\n  EXPECT_EQ(1, Vreg(xedd.op.rde));      //\n  EXPECT_EQ(0, ModrmRm(xedd.op.rde));   //\n  EXPECT_TRUE(Osz(xedd.op.rde));        //\n}\n\n#endif /* DISABLE_BMI2 */\n"
  },
  {
    "path": "test/flat/flat.S",
    "content": ".globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/flat/flat.bin\n//\to//blink/blink o//test/flat/flat.bin\n\n\tmov\t$msg.len,%edx\t\t# arg 3 = strlen(msg)\n\tlea\tmsg(%rip),%rsi\t\t# arg 2 = msg\n\tmov\t$1,%edi\t\t\t# arg 1 = 1\n\tmov\t$1,%eax\t\t\t# __NR_write\n\tsyscall\n\n\tmov\t$0,%edi\t\t\t# arg1 = 0\n\tmov\t$231,%eax\t\t# __NR_exit\n\tsyscall\n\nmsg:\t.ascii\t\"hello! i am a flat executable.\\n\"\n\tmsg.len = . - msg\n"
  },
  {
    "path": "test/flat/flat.lds",
    "content": "ENTRY(_start)\nOUTPUT_FORMAT(binary)\n\nSECTIONS {\n  . = 0x400000;\n  .text : {\n    *(.text)\n    *(.rodata .rodata.*)\n  }\n  .bss : {\n    *(.bss)\n  }\n  /DISCARD/ : {\n    *(.*)\n  }\n}\n"
  },
  {
    "path": "test/flat/flat.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nTEST_FLAT_FILES := $(wildcard test/flat/*)\nTEST_FLAT_SRCS = $(filter %.S,$(TEST_FLAT_FILES))\nTEST_FLAT_OBJS = $(TEST_FLAT_SRCS:%.S=o/$(MODE)/x86_64/%.o)\nTEST_FLAT_BINS = $(TEST_FLAT_SRCS:%.S=o/$(MODE)/%.bin)\nTEST_FLAT_CHECKS = $(TEST_FLAT_BINS:%=%.ok)\n\nTEST_FLAT_LINK =\t\t\t\t\t\t\t\\\n\t\t$(VM)\t\t\t\t\t\t\t\\\n\t\to/third_party/gcc/x86_64/bin/x86_64-linux-musl-ld.bfd\t\\\n\t\t-T test/flat/flat.lds\t\t\t\t\t\\\n\t\t-static\t\t\t\t\t\t\t\\\n\t\t$<\t\t\t\t\t\t\t\\\n\t\t-o $@\n\n.PRECIOUS: o/$(MODE)/test/flat/%.bin\no/$(MODE)/test/flat/%.bin:\t\t\t\t\t\t\\\n\t\to/$(MODE)/x86_64/test/flat/%.o\t\t\t\t\\\n\t\to/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc\t\\\n\t\ttest/flat/flat.lds\t\t\t\t\t\\\n\t\t$(VM)\n\t@mkdir -p $(@D)\n\t$(TEST_FLAT_LINK)\n\n$(TEST_FLAT_OBJS): test/flat/flat.mk\n\n# the .com extension is for cosmopolitan/tool/emacs/ integration\no/$(MODE)/test/flat/%.com:\t\t\t\t\t\t\\\n\t\to/$(MODE)/test/flat/%.bin\t\t\t\t\\\n\t\to/$(MODE)/blink/blink\n\t@echo \"#!/bin/sh\" >$@\n\t@echo \"o/$(MODE)/blink/blink $< || exit\" >>$@\n\t@chmod +x $@\n\no/$(MODE)/test/flat/%.bin.ok: o/$(MODE)/test/flat/%.bin o/$(MODE)/blink/blink\n\t@mkdir -p $(@D)\n\to/$(MODE)/blink/blink $<\n\t@touch $@\n\no/$(MODE)/test/flat:\t\t\t\t\t\t\t\\\n\t$(TEST_FLAT_CHECKS)\n"
  },
  {
    "path": "test/func/README.md",
    "content": "# Blink Functional Tests\n\nBlink's \"functional tests\" are simple `x86_64-linux` programs written in\nC that are run both under Blink, and under the host `x86_64-linux`\nsystem for comparison. These tests are built using a statically compiled\nmusl-cross-make toolchain that the build system downloads automatically.\nIf the host system is not AMD64 Linux, then we fake it using `$(VM)`.\n\nFunctional tests also useful for testing various flag combinations:\n\n- `blink` checks JIT + LINEAR MEMORY works\n- `blink -j` checks INTERPRETED + LINEAR MEMORY works\n- `blink -m` checks JIT + VIRTUALIZED MEMORY works\n- `blink -jm` checks INTERPRETED + VIRTUALIZED MEMORY works\n- `blink -s` checks system call logging doesn't break things\n"
  },
  {
    "path": "test/func/busted_test.c",
    "content": "// 1. test SIGBUS is delivered to guest correctly\n// 2. test `blink -m` can reverse map a host addr\n// TODO(jart): terminates due to sigbus on cygwin\n// TODO(jart): why does silicon trap on the int3?\n#include <signal.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\nchar *map;\n\nvoid OnBusted(int sig, siginfo_t *si, void *vctx) {\n  if (sig != SIGBUS) _exit(8);\n  if (si->si_signo != SIGBUS) _exit(9);\n  if (si->si_code != BUS_ADRALN) {\n    // TODO(jart): Why do XNU and FreeBSD report BUS_ADRALN?\n    if (si->si_code != BUS_ADRERR) _exit(10);\n  }\n  if (si->si_addr != map + 65536) _exit(11);\n  _exit(0);\n}\n\nint main(int argc, char *argv[]) {\n  char path[] = \"/tmp/blink.test.XXXXXX\";\n  if (mkstemp(path) != 3) return 1;\n  if (unlink(path)) return 2;\n  map = (char *)mmap(0, 65536 * 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, 3, 0);\n  if (map == MAP_FAILED) return 5;\n  // ensure first page in file exists\n  if (ftruncate(3, 1)) return 3;\n  map[0] = 1;  // trigger page fault that loads the first page into memory\n  map[1] = 2;  // modifying memory past file eof is ok if it's within page\n  struct sigaction sa = {.sa_sigaction = OnBusted, .sa_flags = SA_SIGINFO};\n  if (sigaction(SIGBUS, &sa, 0)) return 4;\n  map[65536] = 1;  // trigger page fault to load second page of file\n  asm(\"int3\");     // it triggers SIGBUS immediately instead of this\n  return 7;\n}\n"
  },
  {
    "path": "test/func/cycle2_test.c",
    "content": "// checks non-obvious cycle doesn't prevent asynchronous signals\n#include <signal.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\nvoid OnSig(int sig) {\n  _exit(0);\n}\n\nint main(int argc, char *argv[]) {\n  ssize_t got;\n  int ws, pid;\n  if (!(pid = fork())) {\n    struct sigaction sa = {.sa_handler = OnSig};\n    sigaction(SIGUSR1, &sa, 0);\n    asm(\"\\\n\tnop\\n\\\n1:\tnop\\n\\\n\tjmp\t2f\\n\\\n2:\tnop\\n\\\n\tjmp\t1b\");\n  }\n  sleep(1);\n  kill(pid, SIGUSR1);\n  wait(&ws);\n  return WEXITSTATUS(ws);\n}\n"
  },
  {
    "path": "test/func/cycle_test.c",
    "content": "// checks obvious cycle doesn't prevent asynchronous signals\n#include <signal.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\nvoid OnSig(int sig) {\n  _exit(0);\n}\n\nint main(int argc, char *argv[]) {\n  ssize_t got;\n  int ws, pid;\n  if (!(pid = fork())) {\n    struct sigaction sa = {.sa_handler = OnSig};\n    sigaction(SIGUSR1, &sa, 0);\n    for (;;) {\n    }\n  }\n  sleep(1);\n  kill(pid, SIGUSR1);\n  wait(&ws);\n  return WEXITSTATUS(ws);\n}\n"
  },
  {
    "path": "test/func/eintr_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <signal.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n// signal delivery causes blocking i/o calls to return EINTR\n// see also norestart_test.c\n// see also restart_test.c\n\nint fds[2];\nvolatile int gotsig;\n\nvoid OnSig(int sig, siginfo_t *si, void *ptr) {\n  gotsig = 1;\n}\n\nint main(int argc, char *argv[]) {\n  char b;\n  ssize_t got;\n  int ws, pid;\n  sigaction(SIGUSR1, &(struct sigaction){.sa_sigaction = OnSig}, 0);\n  pipe(fds);\n  if (!(pid = fork())) {\n    close(fds[1]);\n    got = read(fds[0], &b, 1);\n    if (got == -1 && errno == EINTR && gotsig) {\n      _exit(0);\n    } else {\n      _exit(1);\n    }\n  }\n  close(fds[0]);\n  sleep(1);\n  kill(pid, SIGUSR1);\n  wait(&ws);\n  return WEXITSTATUS(ws);\n}\n"
  },
  {
    "path": "test/func/fstatat_at_empty_path.c",
    "content": "#define _GNU_SOURCE\n#include <fcntl.h>\n#include <stdlib.h>\n#include <sys/stat.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  struct stat st;\n  char path[] = \"/tmp/blink.test.XXXXXX\";\n  if (mkstemp(path) != 3) return 1;\n  if (unlink(path)) return 2;\n  if (write(3, \"hi\", 2) != 2) return 3;\n  if (fstatat(3, \"\", &st, AT_EMPTY_PATH)) return 4;\n  if (st.st_size != 2) return 5;\n  return 0;\n}\n"
  },
  {
    "path": "test/func/func.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nPKGS += TEST_FUNC\nTEST_FUNC_FILES := $(wildcard test/func/*)\n\nifeq ($(HOST_SYSTEM), Darwin)\nTEST_FUNC_FILES := $(filter-out test/func/busted_test.c,$(TEST_FUNC_FILES))\nendif\nifeq ($(HOST_OS), Cygwin)\nTEST_FUNC_FILES := $(filter-out test/func/busted_test.c,$(TEST_FUNC_FILES))\nendif\n\nTEST_FUNC_SRCS = $(filter %.c,$(TEST_FUNC_FILES))\nTEST_FUNC_OBJS = $(TEST_FUNC_SRCS:%.c=o/$(MODE)/x86_64/%.o)\nTEST_FUNC_BINS = $(TEST_FUNC_SRCS:%.c=o/$(MODE)/%.elf)\nTEST_FUNC_COMS = $(TEST_FUNC_SRCS:%.c=o/$(MODE)/%.com)\nTEST_FUNC_CHECKS = $(TEST_FUNC_SRCS:%.c=o/$(MODE)/%.com.ok)\nTEST_FUNC_EMULATES = $(foreach ARCH,$(ARCHITECTURES),$(foreach SRC,$(filter-out $(TEST_FUNC_NOEMU),$(TEST_FUNC_SRCS)),$(SRC:%.c=o/$(MODE)/$(ARCH)/%.elf.emulates)))\n\n# qemu static doesn't appear to emulate this correctly\nTEST_FUNC_NOEMU = test/func/busted_test.c\n\nTEST_FUNC_LINK =\t\t\t\t\t\t\t\\\n\t\t$(VM)\t\t\t\t\t\t\t\\\n\t\to/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc\t\\\n\t\t-static\t\t\t\t\t\t\t\\\n\t\t-Wl,-z,max-page-size=65536\t\t\t\t\\\n\t\t-Wl,-z,common-page-size=65536\t\t\t\t\\\n\t\t$<\t\t\t\t\t\t\t\\\n\t\t-o $@\n\no/$(MODE)/test/func/%.com.ok:\t\t\t\t\t\t\\\n\t\to/$(MODE)/test/func/%.com\t\t\t\t\\\n\t\to/$(MODE)/blink/blink\n\t$<\n\t@touch $@\n\n$(TEST_FUNC_OBJS): private CFLAGS = -O -g\n$(TEST_FUNC_OBJS): private CPPFLAGS = -isystem.\n\n.PRECIOUS: o/$(MODE)/test/func/%.elf\no/$(MODE)/test/func/%.elf:\t\t\t\t\t\t\\\n\t\to/$(MODE)/x86_64/test/func/%.o\t\t\t\t\\\n\t\to/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc\t\\\n\t\t$(VM)\n\t@mkdir -p $(@D)\n\t$(TEST_FUNC_LINK)\n\n$(TEST_FUNC_OBJS): test/func/func.mk\n\n.PRECIOUS: o/$(MODE)/test/func/%.com\no/$(MODE)/test/func/%.com:\t\t\t\t\t\t\\\n\t\to/$(MODE)/test/func/%.elf\t\t\t\t\\\n\t\to/$(MODE)/blink/blink\n\t@mkdir -p $(@D)\n\t@echo \"#!/bin/sh\" >$@\n\t@echo \"echo [test] $(VM) $< >&2\" >>$@\n\t@echo \"$(VM) $< || exit\" >>$@\n\t@echo \"echo [test] o/$(MODE)/blink/blink $< >&2\" >>$@\n\t@echo \"o/$(MODE)/blink/blink $< || exit\" >>$@\n\t@echo \"echo [test] o/$(MODE)/blink/blink -jm $< >&2\" >>$@\n\t@echo \"o/$(MODE)/blink/blink -jm $< || exit\" >>$@\n\t@echo \"echo [test] o/$(MODE)/blink/blink -m $< >&2\" >>$@\n\t@echo \"o/$(MODE)/blink/blink -m $< || exit\" >>$@\n\t@echo \"echo [test] o/$(MODE)/blink/blink -j $< >&2\" >>$@\n\t@echo \"o/$(MODE)/blink/blink -j $< || exit\" >>$@\n\t@echo \"echo [test] o/$(MODE)/blink/blink -L/dev/null -sss $< >&2\" >>$@\n\t@echo \"o/$(MODE)/blink/blink -L/dev/null -sss $< || exit\" >>$@\n\t@echo \"echo [test] o/$(MODE)/blink/blink -L/dev/null -msss $< >&2\" >>$@\n\t@echo \"o/$(MODE)/blink/blink -L/dev/null -msss $< || exit\" >>$@\n\t@chmod +x $@\n\n.PHONY: o/$(MODE)/test/func\no/$(MODE)/test/func:\t\t\t\t\t\t\t\\\n\t$(TEST_FUNC_CHECKS)\n\n.PHONY: o/$(MODE)/test/func/emulates\no/$(MODE)/test/func/emulates:\t\t\t\t\t\t\\\n\t$(TEST_FUNC_EMULATES)\n"
  },
  {
    "path": "test/func/futex_multiprocess_test.c",
    "content": "// test that futexes work across processes\n// clang-format off\n#include <stdio.h>\n#include <unistd.h>\n#include <pthread.h>\n#include <sys/mman.h>\n#include <sys/wait.h>\n#include <stdatomic.h>\n\nint main(int argc, char *argv[]) {\n  int ws;\n  FILE *f;\n  pid_t pid;\n  pthread_condattr_t ca;\n  pthread_mutexattr_t ma;\n  struct Shared {\n    atomic_int state;\n    pthread_cond_t cond;\n    pthread_mutex_t lock;\n  } *s;\n  if (!(f = tmpfile())) return 0;\n  if (ftruncate(fileno(f), 4096)) return 1;\n  if ((s = (struct Shared *)mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0)) == MAP_FAILED) return 2;\n  if (pthread_condattr_init(&ca)) return 3;\n  if (pthread_mutexattr_init(&ma)) return 4;\n  if (pthread_condattr_setpshared(&ca, PTHREAD_PROCESS_SHARED)) return 5;\n  if (pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED)) return 6;\n  if (pthread_cond_init(&s->cond, &ca)) return 7;\n  if (pthread_mutex_init(&s->lock, &ma)) return 8;\n  if (pthread_mutexattr_destroy(&ma)) return 9;\n  if (pthread_condattr_destroy(&ca)) return 10;\n  if ((pid = fork()) == -1) return 11;\n  if (!pid) {\n    alarm(15);\n    if (pthread_mutex_lock(&s->lock)) return 12;\n    s->state = 1;\n    if (pthread_cond_wait(&s->cond, &s->lock)) return 13;\n    if (pthread_mutex_unlock(&s->lock)) return 14;\n    while (s->state != 2);\n    if (pthread_mutex_lock(&s->lock)) return 15;\n    if (pthread_cond_signal(&s->cond)) return 16;\n    if (pthread_mutex_unlock(&s->lock)) return 17;\n    _exit(0);\n  }\n  alarm(15);\n  while (s->state != 1);\n  if (pthread_mutex_lock(&s->lock)) return 18;\n  if (pthread_cond_signal(&s->cond)) return 19;\n  if (pthread_mutex_unlock(&s->lock)) return 20;\n  if (pthread_mutex_lock(&s->lock)) return 21;\n  s->state = 2;\n  if (pthread_cond_wait(&s->cond, &s->lock)) return 22;\n  if (pthread_mutex_unlock(&s->lock)) return 23;\n  if (wait(&ws) != pid) return 24;\n  if (!WIFEXITED(ws)) return 25;\n  if (WEXITSTATUS(ws)) return 26;\n  if (pthread_mutex_destroy(&s->lock)) return 27;\n  if (pthread_cond_destroy(&s->cond)) return 28;\n  return 0;\n}\n"
  },
  {
    "path": "test/func/getrandom_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <stdlib.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n\n/*\n * assuming the system is working correctly there's a 1 in\n * 235716896562095165800448 chance this check should flake\n */\n#define BYTES 9\n#define TRIES 16\n\nvoid TestDataSeemsRandom(void) {\n  ssize_t rc;\n  size_t i, j;\n  int haszero, fails = 0;\n  for (i = 0; i < TRIES; ++i) {\n    unsigned char x[BYTES] = {0};\n    rc = syscall(SYS_getrandom, x, BYTES, 0);\n    if (rc == -1) exit(1);\n    if (rc != BYTES) exit(2);\n    for (haszero = j = 0; j < BYTES; ++j) {\n      if (!x[j]) haszero = 1;\n    }\n    if (haszero) ++fails;\n  }\n  if (fails >= TRIES) exit(3);\n}\n\nvoid TestApi(void) {\n  long x;\n  if (syscall(SYS_getrandom, 0, 0, 0) != 0) exit(4);\n  if (syscall(SYS_getrandom, (void *)-1, 1, 0) != -1) exit(5);\n  if (errno != EFAULT) exit(6);\n  if (syscall(SYS_getrandom, &x, sizeof(x), -1) != -1) exit(7);\n  if (errno != EINVAL) exit(8);\n}\n\nint main(int argc, char *argv[]) {\n  TestDataSeemsRandom();\n  TestApi();\n  return 0;\n}\n"
  },
  {
    "path": "test/func/largefile_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <fcntl.h>\n#include <stdlib.h>\n#include <sys/stat.h>\n\n#include \"test/test.h\"\n\n/**\n * @fileoverview Large File Tests\n *\n * This test ensures that the Blink Virtual Machine is able to host, on\n * 32-bit platforms, x86_64 binaries that perform 64-bit I/O operations\n */\n\n#define SIZE (5LL * 1024 * 1024 * 1024)\n\nvoid SetUp(void) {\n}\n\nvoid TearDown(void) {\n}\n\nTEST(largefile, test) {\n  struct stat st;\n  char path[] = \"/tmp/blink.test.XXXXXX\";\n  char b3[8], b2[8], b1[8] = {1, 2, 3, 4, 5, 6, 7, 8};\n  ASSERT_EQ(3, mkstemp(path));\n  ASSERT_EQ(0, close(3));\n  EXPECT_EQ(3, open(path, O_RDWR | O_CREAT | O_TRUNC, 0644));\n  EXPECT_EQ(0, ftruncate(3, SIZE));\n  EXPECT_EQ(0, fstat(3, &st));\n  EXPECT_EQ(SIZE, st.st_size);\n  EXPECT_EQ(8, pwrite(3, b1, 8, SIZE - 8));\n  EXPECT_EQ(8, pread(3, b2, 8, SIZE - 8));\n  EXPECT_EQ(0, memcmp(b1, b2, 8));\n  EXPECT_EQ(SIZE - 8, lseek(3, SIZE - 8, SEEK_SET));\n  EXPECT_EQ(8, read(3, b3, 8));\n  EXPECT_EQ(0, memcmp(b1, b3, 8));\n  EXPECT_EQ(0, close(3));\n  EXPECT_EQ(0, unlink(path));\n}\n"
  },
  {
    "path": "test/func/lock_test.c",
    "content": "#include <assert.h>\n#include <pthread.h>\n#include <stdatomic.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n#define THREADS    4\n#define ITERATIONS 10000\n\n_Alignas(128) static int a;\n_Alignas(128) static int b;\n_Alignas(128) static atomic_int lock;\n\nstatic void Lock(void) {\n  int x;\n  for (;;) {\n    x = atomic_exchange_explicit(&lock, 1, memory_order_acquire);\n    if (!x) break;\n  }\n}\n\nstatic void Unlock(void) {\n  atomic_store_explicit(&lock, 0, memory_order_release);\n}\n\nstatic void *Worker(void *arg) {\n  int i;\n  for (i = 0; i < ITERATIONS; ++i) {\n    Lock();\n    assert(b == a * 2);\n    ++a;\n    b = a * 2;\n    Unlock();\n  }\n  return 0;\n}\n\nint main(int argc, char *argv[]) {\n  int i;\n  pthread_t t[THREADS];\n  for (i = 0; i < THREADS; ++i) {\n    pthread_create(t + i, 0, Worker, 0);\n  }\n  for (i = 0; i < THREADS; ++i) {\n    pthread_join(t[i], 0);\n  }\n}\n"
  },
  {
    "path": "test/func/mem64_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <pthread.h>\n#include <stdatomic.h>\n\n#include \"test/test.h\"\n\n#define WORKERS    4\n#define ITERATIONS 100000\n\nvoid SetUp(void) {\n}\n\nvoid TearDown(void) {\n}\n\nstatic atomic_ulong word;\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic void *AddWorker(void *arg) {\n  int i;\n  unsigned long x;\n  for (i = 0; i < ITERATIONS; ++i) {\n    x = atomic_load_explicit(&word, memory_order_relaxed);\n    ASSERT_EQ(x & 0xffffffff, x >> 32);\n    x += 1ul | 1ul << 32;\n    atomic_store_explicit(&word, x, memory_order_relaxed);\n  }\n  return 0;\n}\n\nTEST(mem64, add) {\n  int i;\n  pthread_t t[WORKERS];\n  for (i = 0; i < WORKERS; ++i) {\n    ASSERT_EQ(0, pthread_create(t + i, 0, AddWorker, 0));\n  }\n  for (i = 0; i < WORKERS; ++i) {\n    ASSERT_EQ(0, pthread_join(t[i], 0));\n  }\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nstatic void *XaddWorker(void *arg) {\n  int i;\n  unsigned long x;\n  for (i = 0; i < ITERATIONS; ++i) {\n    x = atomic_fetch_add_explicit(&word, 1ul | 1ul << 32, memory_order_relaxed);\n    ASSERT_EQ(x & 0xffffffff, x >> 32);\n  }\n  return 0;\n}\n\nTEST(mem64, xadd) {\n  int i;\n  pthread_t t[WORKERS];\n  for (i = 0; i < WORKERS; ++i) {\n    ASSERT_EQ(0, pthread_create(t + i, 0, XaddWorker, 0));\n  }\n  for (i = 0; i < WORKERS; ++i) {\n    ASSERT_EQ(0, pthread_join(t[i], 0));\n  }\n}\n"
  },
  {
    "path": "test/func/mmap_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <fcntl.h>\n#include <sys/mman.h>\n\n#include \"blink/macros.h\"\n#include \"test/test.h\"\n\n#define pagesize 65536\n\nvoid SetUp(void) {\n}\n\nvoid TearDown(void) {\n}\n\nTEST(mmap, file_shared) {\n  FILE *f;\n  u8 *a, *b, *p;\n  // we initialize the file to contain this\n  ASSERT_NOTNULL(a = (u8 *)malloc(pagesize * 3));\n  memset(a, 'a', pagesize * 3);\n  // we're going to change the file to have this\n  ASSERT_NOTNULL(b = (u8 *)malloc(pagesize * 3));\n  memset(b, 'a', pagesize * 1);\n  memset(b + pagesize, 'b', pagesize * 2);\n  // create the file\n  ASSERT_NOTNULL(f = tmpfile());\n  ASSERT_EQ(3, fwrite(a, pagesize, 3, f));\n  // map the file into memory starting at the second page\n  EXPECT_NE((intptr_t)MAP_FAILED,\n            (intptr_t)(p = (u8 *)mmap(0, pagesize * 2, PROT_READ | PROT_WRITE,\n                                      MAP_SHARED, fileno(f), pagesize)));\n  // change the file via the memory mapping\n  memset(p, 'b', pagesize * 2);\n  EXPECT_NE(-1, msync(p, pagesize * 2, MS_SYNC));\n  // read the file back into memory and verify it's coherent\n  rewind(f);\n  ASSERT_EQ(3, fread(a, pagesize, 3, f));\n  ASSERT_EQ(0, memcmp(b, a, pagesize));\n  ASSERT_EQ(0, memcmp(b + pagesize, a + pagesize, pagesize));\n  ASSERT_EQ(0, memcmp(b + pagesize * 2, a + pagesize * 2, pagesize));\n  // perform cleanup duties\n  ASSERT_EQ(0, munmap(p, pagesize * 2));\n  ASSERT_EQ(0, fclose(f));\n  free(b);\n  free(a);\n}\n\nTEST(mmap, multiprocess_private_vs_shared) {\n  int ws, pid;\n  int stackvar;\n  int *sharedvar;\n  int *privatevar;\n  EXPECT_NE((intptr_t)MAP_FAILED,\n            (intptr_t)(sharedvar = mmap(0, pagesize, PROT_READ | PROT_WRITE,\n                                        MAP_SHARED | MAP_ANONYMOUS, -1, 0)));\n  EXPECT_NE((intptr_t)MAP_FAILED,\n            (intptr_t)(privatevar = mmap(0, pagesize, PROT_READ | PROT_WRITE,\n                                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)));\n  stackvar = 1;\n  *sharedvar = 1;\n  *privatevar = 1;\n  EXPECT_NE(-1, (pid = fork()));\n  if (!pid) {\n    ++stackvar;\n    ++*sharedvar;\n    ++*privatevar;\n    msync((void *)ROUNDDOWN((intptr_t)&stackvar, pagesize), pagesize, MS_SYNC);\n    EXPECT_NE(-1, msync(privatevar, pagesize, MS_SYNC));\n    EXPECT_NE(-1, msync(sharedvar, pagesize, MS_SYNC));\n    _exit(0);\n  }\n  EXPECT_NE(-1, waitpid(pid, &ws, 0));\n  EXPECT_EQ(1, stackvar);\n  EXPECT_EQ(2, *sharedvar);\n  EXPECT_EQ(1, *privatevar);\n  EXPECT_NE(-1, munmap(sharedvar, pagesize));\n  EXPECT_NE(-1, munmap(privatevar, pagesize));\n}\n\nTEST(mmap, suggestedAddressWithoutMapFixed_isUsedIfAvailable) {\n  void *want, *got1, *got2;\n  want = (void *)(intptr_t)0x300000000000;\n  got1 = mmap(want, pagesize, PROT_READ | PROT_WRITE,\n              MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  while (got1 == MAP_FAILED && errno == ENOMEM) {\n    want = (void *)((intptr_t)want >> 1);\n    ASSERT_EQ((intptr_t)want % pagesize, 0);\n    got1 = mmap(want, pagesize, PROT_READ | PROT_WRITE,\n                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  }\n  ASSERT_NE((intptr_t)MAP_FAILED, (intptr_t)got1);\n  got2 = mmap(want, pagesize, PROT_READ | PROT_WRITE,\n              MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  ASSERT_NE((intptr_t)MAP_FAILED, (intptr_t)got2);\n  ASSERT_NE((intptr_t)got1, (intptr_t)got2);\n  ASSERT_NE((intptr_t)want, (intptr_t)got2);\n  ASSERT_EQ(0, munmap(got1, pagesize));\n  ASSERT_EQ(0, munmap(got2, pagesize));\n}\n"
  },
  {
    "path": "test/func/munmap_test.c",
    "content": "#include <errno.h>\n#include <fcntl.h>\n#include <pthread.h>\n#include <stdatomic.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\n#define BYTES      10000\n#define THREADS    4\n#define ITERATIONS 256\n\n_Atomic(void *) buf;\n\nvoid *Worker(void *arg) {\n  void *b;\n  int i, fd;\n  ssize_t rc;\n  if ((fd = open(\"/dev/zero\", O_RDONLY)) == -1) {\n    fprintf(stderr, \"open failed: %s\", strerror(errno));\n    _exit(10);\n  }\n  for (i = 0; i < ITERATIONS; ++i) {\n    b = buf;\n    rc = read(fd, b, 10000);\n    if (rc == -1 && errno != EFAULT) _exit(2);\n  }\n  close(fd);\n  return 0;\n}\n\nvoid *Alloc(void) {\n  return mmap(0, BYTES, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1,\n              0);\n}\n\nint main(int argc, char *argv[]) {\n  int i;\n  pthread_t t[THREADS];\n  buf = Alloc();\n  for (i = 0; i < THREADS; ++i) {\n    if (pthread_create(t + i, 0, Worker, 0)) _exit(2);\n  }\n  for (i = 0; i < ITERATIONS; ++i) {\n    munmap(atomic_exchange(&buf, Alloc()), BYTES);\n  }\n  for (i = 0; i < THREADS; ++i) {\n    if (pthread_join(t[i], 0)) _exit(3);\n  }\n  if (munmap(buf, BYTES)) _exit(4);\n  return 0;\n}\n"
  },
  {
    "path": "test/func/noexec2_test.c",
    "content": "// test mprotect(rw) prevents code from being executed\n#include <signal.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\ntypedef int math_f(int, int);\n\nconst unsigned char kAdd[] = {\n    0x89, 0xf8,  // mov %edi,%eax\n    0x01, 0xf0,  // add %esi,%eax\n    0xc3,        // ret\n};\n\nvoid *p;\n\nvoid OnSigSegv(int sig, siginfo_t *si, void *vctx) {\n  if (si->si_addr != p) _exit(6);\n  if (si->si_code != SEGV_ACCERR) _exit(7);\n  _exit(0);\n}\n\nint main(int argc, char *argv[]) {\n  int i;\n  math_f *f;\n  p = mmap(0, 65536, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);\n  if (p == MAP_FAILED) return 1;\n  f = (math_f *)p;\n  memcpy(p, kAdd, sizeof(kAdd));\n  if (mprotect(p, 65536, PROT_READ | PROT_EXEC)) return 4;\n  if (f(20, 3) != 23) return 2;\n  if (f(20, 3) != 23) return 2;\n  struct sigaction sa = {.sa_sigaction = OnSigSegv, .sa_flags = SA_SIGINFO};\n  if (sigaction(SIGSEGV, &sa, 0)) return 3;\n  if (mprotect(p, 65536, PROT_READ | PROT_WRITE)) return 4;\n  f(20, 3);\n  return 5;\n}\n"
  },
  {
    "path": "test/func/noexec3_test.c",
    "content": "// test munmap() prevents code from being executed\n#include <signal.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\ntypedef int math_f(int, int);\n\nconst unsigned char kAdd[] = {\n    0x89, 0xf8,  // mov %edi,%eax\n    0x01, 0xf0,  // add %esi,%eax\n    0xc3,        // ret\n};\n\nvoid *p;\n\nvoid OnSigSegv(int sig, siginfo_t *si, void *vctx) {\n  if (si->si_addr != p) _exit(8);\n  if (si->si_code != SEGV_MAPERR) _exit(9);\n  _exit(0);\n}\n\nint main(int argc, char *argv[]) {\n  int i;\n  math_f *f;\n  p = mmap(0, 65536, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);\n  if (p == MAP_FAILED) return 1;\n  f = (math_f *)p;\n  memcpy(p, kAdd, sizeof(kAdd));\n  if (mprotect(p, 65536, PROT_READ | PROT_EXEC)) return 2;\n  if (f(20, 3) != 23) return 3;\n  if (f(20, 3) != 23) return 4;\n  struct sigaction sa = {.sa_sigaction = OnSigSegv, .sa_flags = SA_SIGINFO};\n  if (sigaction(SIGSEGV, &sa, 0)) return 5;\n  if (munmap(p, 65536)) return 6;\n  f(20, 3);\n  return 7;\n}\n"
  },
  {
    "path": "test/func/noexec_test.c",
    "content": "// tests memory can't be executed without exec permission\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE\n#endif\n#include <signal.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\ntypedef void func_t(void);\n\nconst unsigned char kCode[] = {\n    0xc3,  // ret\n};\n\nvoid *p;\n\nvoid OnSigSegv(int sig, siginfo_t *si, void *vctx) {\n  if (si->si_addr != p) _exit(5);\n  if (si->si_code != SEGV_ACCERR) _exit(6);\n  if ((void *)((ucontext_t *)vctx)->uc_mcontext.gregs[REG_RIP] != p) _exit(7);\n  _exit(0);\n}\n\nint main(int argc, char *argv[]) {\n  func_t *f;\n  p = mmap(0, 65536, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);\n  if (p == MAP_FAILED) return 2;\n  f = (func_t *)p;\n  memcpy(f, kCode, sizeof(kCode));\n  struct sigaction sa = {.sa_sigaction = OnSigSegv, .sa_flags = SA_SIGINFO};\n  if (sigaction(SIGSEGV, &sa, 0)) return 3;\n  f();\n  return 4;\n}\n"
  },
  {
    "path": "test/func/norestart_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <signal.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n// SA_RESTART doesn't apply to @norestart functions like sigsuspend()\n// see also restart_test.c\n// see also eintr_test.c\n\nvolatile int gotsig;\n\nvoid OnSig(int sig, siginfo_t *si, void *ptr) {\n  gotsig = 1;\n}\n\nint main(int argc, char *argv[]) {\n  sigset_t mask;\n  int rc, ws, pid;\n  sigfillset(&mask);\n  sigprocmask(SIG_BLOCK, &mask, 0);\n  sigaction(SIGUSR1,\n            &(struct sigaction){\n                .sa_sigaction = OnSig,\n                .sa_flags = SA_RESTART,\n            },\n            0);\n  if (!(pid = fork())) {\n    sigemptyset(&mask);\n    rc = sigsuspend(&mask);\n    if (rc == -1 && errno == EINTR && gotsig) {\n      _exit(0);\n    } else {\n      _exit(1);\n    }\n  }\n  kill(pid, SIGUSR1);\n  wait(&ws);\n  return WEXITSTATUS(ws);\n}\n"
  },
  {
    "path": "test/func/preadv_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <fcntl.h>\n#include <sys/uio.h>\n\n#include \"test/test.h\"\n\nchar bb1[5000];\nchar bb2[5000];\n\nvoid SetUp(void) {\n}\n\nvoid TearDown(void) {\n}\n\nTEST(preadv, errors) {\n  signed char b3[8];\n  ASSERT_EQ(3, open(\"/tmp\", O_RDWR | O_TMPFILE, 0644));\n  ASSERT_EQ(8, pwritev(3, (struct iovec[]){{b3, 8}}, 1, 0));\n  ASSERT_EQ(-1, preadv(3, (struct iovec[]){{0, 8}}, 1, 0));\n  ASSERT_EQ(EFAULT, errno);\n  ASSERT_EQ(0, preadv(3, (struct iovec[]){{b3, 8}}, 0, 0));\n  ASSERT_EQ(-1, preadv(3, (struct iovec[]){{b3, 8}}, -1, 0));\n  ASSERT_EQ(EINVAL, errno);\n  ASSERT_EQ(-1, preadv(3, (struct iovec[]){{b3, 8}}, 1, -1));\n  ASSERT_EQ(EINVAL, errno);\n  ASSERT_EQ(-1, preadv(3, (struct iovec[]){{b3, 8}}, 99999, 0));\n  ASSERT_EQ(EINVAL, errno);\n  ASSERT_EQ(0, close(3));\n}\n\nTEST(preadv, test) {\n  signed char b1[8] = {0, 1, 2, 3, 4, 5, 6, 7};\n  signed char b2[8] = {-1, -2, -3, -4, -5, -6, -7, -8};\n  signed char b3[8];\n  ASSERT_EQ(3, open(\"/tmp\", O_RDWR | O_TMPFILE, 0644));\n  ASSERT_EQ(16, pwritev(3, (struct iovec[]){{b1, 8}, {b2, 8}}, 2, 0));\n  ASSERT_EQ(8, preadv(3, (struct iovec[]){{b3, 8}}, 1, 8));\n  ASSERT_EQ(0, memcmp(b3, b2, 8));\n  ASSERT_EQ(8, preadv(3, (struct iovec[]){{b3, 4}, {b3 + 4, 4}}, 2, 0));\n  ASSERT_EQ(0, memcmp(b3, b1, 8));\n  ASSERT_EQ(0, close(3));\n}\n\nTEST(pwritev, test) {\n  ASSERT_EQ(3, open(\"/tmp\", O_RDWR | O_TMPFILE, 0644));\n  memset(bb1, 1, 5000);\n  ASSERT_EQ(5000, pwritev(3,\n                          (struct iovec[]){\n                              {bb1, 4097},\n                              {bb1 + 4097, 903},\n                          },\n                          2, 0));\n  ASSERT_EQ(5000, preadv(3,\n                         (struct iovec[]){\n                             {bb2, 4097},\n                             {bb2 + 4097, 903},\n                         },\n                         2, 0));\n  ASSERT_EQ(0, memcmp(bb1, bb2, 4000));\n  ASSERT_EQ(0, close(3));\n}\n"
  },
  {
    "path": "test/func/readonly_test.c",
    "content": "// test read-only memory protection works\n#include <signal.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\nvoid *p;\n\nvoid OnSigSegv(int sig, siginfo_t *si, void *vctx) {\n  if (si->si_addr != p) _exit(5);\n  if (si->si_code != SEGV_ACCERR) _exit(6);\n  _exit(0);\n}\n\nint main(int argc, char *argv[]) {\n  p = mmap(0, 65536, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);\n  if (p == MAP_FAILED) return 2;\n  struct sigaction sa = {.sa_sigaction = OnSigSegv, .sa_flags = SA_SIGINFO};\n  if (sigaction(SIGSEGV, &sa, 0)) return 3;\n  *(int *)p = 1;\n  return 4;\n}\n"
  },
  {
    "path": "test/func/restart_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <signal.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n// SA_RESTART inhibits EINTR on blocking calls after signal delivery\n// see also norestart_test.c\n// see also eintr_test.c\n\nint fds[2];\nvolatile int gotsig;\n\nvoid OnSig(int sig, siginfo_t *si, void *ptr) {\n  gotsig = 1;\n}\n\nint main(int argc, char *argv[]) {\n  char b;\n  ssize_t got;\n  int ws, pid;\n  sigaction(SIGUSR1,\n            &(struct sigaction){\n                .sa_sigaction = OnSig,\n                .sa_flags = SA_RESTART,\n            },\n            0);\n  pipe(fds);\n  if (!(pid = fork())) {\n    close(fds[1]);\n    got = read(fds[0], &b, 1);\n    if (got == 1 && gotsig) {\n      _exit(0);\n    } else {\n      _exit(1);\n    }\n  }\n  close(fds[0]);\n  sleep(1);\n  kill(pid, SIGUSR1);\n  write(fds[1], &b, 1);\n  wait(&ws);\n  return WEXITSTATUS(ws);\n}\n"
  },
  {
    "path": "test/func/robust_exit_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <assert.h>\n#include <errno.h>\n#include <pthread.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#define PCHECK(x)  \\\n  do {             \\\n    int rc_ = (x); \\\n    if (rc_) {     \\\n      errno = rc_; \\\n      perror(#x);  \\\n      exit(1);     \\\n    }              \\\n  } while (0)\n\nstatic pthread_mutex_t mtx;\n\nstatic void *OriginalOwnerThread(void *ptr) {\n  pthread_mutex_lock(&mtx);\n  pthread_exit(NULL);\n}\n\nstatic void WaitForOriginalOwnerThreadToDie(pthread_t thr) {\n  int rc;\n  for (;;) {\n    rc = pthread_kill(thr, 0);\n    if (rc == ESRCH) break;\n    assert(!rc);\n  }\n}\n\nint main(int argc, char *argv[]) {\n  int rc;\n  pthread_t thr;\n  pthread_mutexattr_t attr;\n  PCHECK(pthread_mutexattr_init(&attr));\n  PCHECK(pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST));\n  PCHECK(pthread_mutex_init(&mtx, &attr));\n  PCHECK(pthread_mutexattr_destroy(&attr));\n  PCHECK(pthread_create(&thr, 0, OriginalOwnerThread, 0));\n  WaitForOriginalOwnerThreadToDie(thr);\n  rc = pthread_mutex_lock(&mtx);\n  if (rc == EOWNERDEAD) {\n    PCHECK(pthread_mutex_consistent(&mtx));\n    PCHECK(pthread_mutex_unlock(&mtx));\n    exit(EXIT_SUCCESS);\n  } else if (!rc) {\n    fprintf(stderr, \"pthread_mutex_lock() unexpectedly succeeded\\n\");\n    exit(EXIT_FAILURE);\n  } else {\n    fprintf(stderr, \"pthread_mutex_lock() unexpectedly failed: %s\\n\",\n            strerror(rc));\n    exit(1);\n  }\n}\n"
  },
  {
    "path": "test/func/robust_kill_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <assert.h>\n#include <errno.h>\n#include <pthread.h>\n#include <signal.h>\n#include <stdatomic.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#define SCHECK(x)              \\\n  do {                         \\\n    if ((intptr_t)(x) == -1) { \\\n      perror(#x);              \\\n      exit(1);                 \\\n    }                          \\\n  } while (0)\n\n#define PCHECK(x)  \\\n  do {             \\\n    int rc_ = (x); \\\n    if (rc_) {     \\\n      errno = rc_; \\\n      perror(#x);  \\\n      exit(1);     \\\n    }              \\\n  } while (0)\n\nstatic struct {\n  atomic_int ready;\n  pthread_mutex_t mtx;\n} * shared;\n\nint main(int argc, char *argv[]) {\n  int rc, pid;\n  pthread_mutexattr_t attr;\n  if (1) return 0;  // TODO: Figure out how robust list works.\n  SCHECK(shared = mmap(0, 65536, PROT_READ | PROT_WRITE,\n                       MAP_SHARED | MAP_ANONYMOUS, -1, 0));\n  PCHECK(pthread_mutexattr_init(&attr));\n  PCHECK(pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST));\n  PCHECK(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED));\n  PCHECK(pthread_mutex_init(&shared->mtx, &attr));\n  PCHECK(pthread_mutexattr_destroy(&attr));\n  SCHECK(pid = fork());\n  if (!pid) {\n    PCHECK(pthread_mutex_lock(&shared->mtx));\n    shared->ready = 1;\n    for (;;) getppid();\n  }\n  while (!shared->ready) {\n  }\n  fprintf(stderr, \"killing\\n\");\n  SCHECK(kill(pid, SIGTERM));\n  SCHECK(wait(0));\n  fprintf(stderr, \"locking\\n\");\n  rc = pthread_mutex_lock(&shared->mtx);\n  fprintf(stderr, \"locked\\n\");\n  if (rc == EOWNERDEAD) {\n    fprintf(stderr, \"good\\n\");\n    PCHECK(pthread_mutex_consistent(&shared->mtx));\n    PCHECK(pthread_mutex_unlock(&shared->mtx));\n    exit(0);\n  } else if (!rc) {\n    fprintf(stderr, \"pthread_mutex_lock() unexpectedly succeeded\\n\");\n    exit(1);\n  } else {\n    fprintf(stderr, \"pthread_mutex_lock() unexpectedly failed: %s\\n\",\n            strerror(rc));\n    exit(1);\n  }\n}\n"
  },
  {
    "path": "test/func/select_timeout_test.c",
    "content": "// test kernel sys_select(timeout) is always modified\n// the linux kernel even appears to modify it on errors like einval!\n#include <sys/select.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  int rc;\n  int pfds[2];\n  fd_set rfds;\n  struct timeval tv = {0, 10 * 1000};\n  if (pipe(pfds)) return 1;\n  FD_ZERO(&rfds);\n  FD_SET(pfds[0], &rfds);\n  if (syscall(SYS_select, pfds[0] + 1, &rfds, 0, 0, &tv)) return 2;\n  if (tv.tv_sec) return 3;\n  if (tv.tv_usec) return 4;\n  return 0;\n}\n"
  },
  {
    "path": "test/func/shared_test.c",
    "content": "// checks if mmap(MAP_SHARED) works\n#include <stdio.h>\n#include <sys/mman.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#include \"config.h\"\n\nint main(int argc, char *argv[]) {\n#ifdef HAVE_MAP_SHARED\n  FILE *f;\n  void *map;\n  int ws, *x;\n  pid_t pid, rc;\n  if (!(f = tmpfile())) return 1;\n  if (ftruncate(fileno(f), sizeof(int))) return 2;\n  map = mmap(0, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fileno(f), 0);\n  if (map == MAP_FAILED) return 3;\n  x = (int *)map;\n  pid = fork();\n  if (pid == -1) return 4;\n  if (!pid) {\n    *x = 42;\n    msync(map, sizeof(int), MS_INVALIDATE);\n    _exit(0);\n  }\n  rc = wait(&ws);\n  if (rc == -1) return 5;\n  if (rc != pid) return 6;\n  if (!WIFEXITED(ws)) return 7;\n  if (WEXITSTATUS(ws)) return 8;\n  if (*x != 42) return 9;\n  return 0;\n#endif\n}\n"
  },
  {
    "path": "test/func/sigprocmask_test.c",
    "content": "#include <signal.h>\n\nvolatile int gotsigusr1;\nvolatile int gotsigusr2;\n\nvoid OnSigUsr1(int sig) {\n  ++gotsigusr1;\n}\n\nvoid OnSigUsr2(int sig) {\n  ++gotsigusr2;\n}\n\nint main(int argc, char *argv[]) {\n  sigset_t ss;\n  if (signal(SIGUSR1, OnSigUsr1) == SIG_ERR) return 1;\n  if (signal(SIGUSR2, OnSigUsr2) == SIG_ERR) return 2;\n  if (sigemptyset(&ss)) return 3;\n  if (sigaddset(&ss, SIGUSR1)) return 4;\n  if (sigaddset(&ss, SIGUSR2)) return 5;\n  if (sigprocmask(SIG_BLOCK, &ss, 0)) return 6;\n  // tkill() enqueues masked signals\n  if (raise(SIGUSR1)) return 7;\n  if (raise(SIGUSR1)) return 8;\n  if (raise(SIGUSR2)) return 9;\n  if (raise(SIGUSR2)) return 10;\n  if (gotsigusr1) return 11;\n  if (gotsigusr2) return 12;\n  // sigprocmask() triggers immediate delivery of deliverable signals\n  if (sigprocmask(SIG_UNBLOCK, &ss, 0)) return 13;\n  if (!gotsigusr1) return 14;\n  if (!gotsigusr2) return 15;\n  // a signal enqueued multiple times is only delivered once\n  if (gotsigusr1 != 1) return 16;\n  if (gotsigusr2 != 1) return 17;\n  return 0;\n}\n"
  },
  {
    "path": "test/func/smc1_test.c",
    "content": "// tests for class 1 self-modifying code\n// this is the portable prim/proper kind\n#include <string.h>\n#include <sys/mman.h>\n\nconst unsigned char kAdd[] = {\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x89, 0xf8,  // mov    %edi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x01, 0xf0,  // add    %esi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0xc3,        // ret\n};\n\nconst unsigned char kSub[] = {\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x89, 0xf8,  // mov    %edi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x29, 0xf0,  // sub    %esi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0xc3,        // ret\n};\n\ntypedef int math_f(int, int);\n\nint main(int argc, char *argv[]) {\n  void *p;\n  math_f *f;\n  p = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  if (p == MAP_FAILED) return 1;\n  f = (math_f *)p;\n  memcpy(p, kAdd, sizeof(kAdd));\n  if (mprotect(p, 4096, PROT_READ | PROT_EXEC)) return 2;\n  if (f(20, 3) != 23) return 3;\n  if (mprotect(p, 4096, PROT_READ | PROT_WRITE)) return 4;\n  memcpy(p, kSub, sizeof(kSub));\n  if (mprotect(p, 4096, PROT_READ | PROT_EXEC)) return 5;\n  if (f(20, 3) != 17) return 6;\n  if (munmap(p, 4096)) return 7;\n  return 0;\n}\n"
  },
  {
    "path": "test/func/smc2_test.c",
    "content": "// tests for class 2 self-modifying code\n// this is the kind intel's cpus support\n// namely option 1 from the intel manual\n// using indirect branches to other page\n#include <string.h>\n#include <sys/mman.h>\n\n// To write self-modifying code and ensure that it is compliant with\n// current and future versions of the IA-32 architectures, use one of\n// the following coding options:\n//\n// (* OPTION 1 *)\n// Store modified code (as data) into code segment;\n// Jump to new code or an intermediate location;\n// Execute new code;\n//\n// (* OPTION 2 *)\n// Store modified code (as data) into code segment;\n// Execute a serializing instruction; (* For example, CPUID instruction *)\n// Execute new code;\n//\n// ──Intel V.3 §8.1.3\n\nconst unsigned char kAdd[] = {\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x89, 0xf8,  // mov %edi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x01, 0xf0,  // add %esi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0xc3,        // ret\n};\n\nconst unsigned char kSub[] = {\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x89, 0xf8,  // mov %edi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x29, 0xf0,  // sub %esi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0xc3,        // ret\n};\n\ntypedef int math_f(int, int);\n\n// even though we're copying byte by byte, blink shouldn't segfault on\n// every byte, and it shouldn't need to clear caches on every byte--at\n// least not in the canonical jit'ed + linear memory optimization mode\n//\n//     make -j8 o//blink/blink o//test/func/smc2_test.elf\n//     o//blink/blink -Z o//test/func/smc2_test.elf\n//\nvoid SlowMemCpy(void *dest, const void *src, int size) {\n  int i;\n  volatile char *d = (volatile char *)dest;\n  volatile const char *s = (volatile const char *)src;\n  for (i = 0; i < size; ++i) {\n    d[i] = s[i];\n  }\n}\n\nint main(int argc, char *argv[]) {\n  int i;\n  void *p;\n  math_f *f;\n  p = mmap(0, 65536, PROT_READ | PROT_WRITE | PROT_EXEC,\n           MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  if (p == MAP_FAILED) return 1;\n  f = (math_f *)p;\n  for (i = 0; i < 10; ++i) {\n    SlowMemCpy(p, kAdd, sizeof(kAdd));\n    if (f(20, 3) != 23) return 2;\n    SlowMemCpy(p, kSub, sizeof(kSub));\n    if (f(20, 3) != 17) return 3;\n  }\n  if (munmap(p, 65536)) return 4;\n  return 0;\n}\n"
  },
  {
    "path": "test/func/smc3_test.c",
    "content": "// tests for class 3 self-modifying code\n// this is the kind intel's cpus support\n// namely option 1 from the intel manual\n// using a near branch to the local page\n#include <string.h>\n#include <sys/mman.h>\n\n// To write self-modifying code and ensure that it is compliant with\n// current and future versions of the IA-32 architectures, use one of\n// the following coding options:\n//\n// (* OPTION 1 *)\n// Store modified code (as data) into code segment;\n// Jump to new code or an intermediate location;\n// Execute new code;\n//\n// (* OPTION 2 *)\n// Store modified code (as data) into code segment;\n// Execute a serializing instruction; (* For example, CPUID instruction *)\n// Execute new code;\n//\n// ──Intel V.3 §8.1.3\n\nconst unsigned char kAdd[] = {\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x89, 0xf8,  // mov %edi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x01, 0xf0,  // add %esi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0xc3,        // ret\n};\n\nconst unsigned char kSub[] = {\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x89, 0xf8,  // mov %edi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0x29, 0xf0,  // sub %esi,%eax\n    0x90,        // nop\n    0x90,        // nop\n    0x90,        // nop\n    0xc3,        // ret\n};\n\n__attribute__((__noinline__)) static int f(int x, int y) {\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  asm(\"nop\");\n  return 0;\n}\n\n__attribute__((__noinline__)) static int Main(void) {\n  int i, n, prot;\n  prot = PROT_READ | PROT_WRITE | PROT_EXEC;\n  for (n = 65536; n; n -= 4096) {\n    if (!mprotect((void *)((long)f & -65536), n, prot)) {\n      break;\n    }\n  }\n  if (!n) return 2;\n  if (f(20, 3) != 0) return 3;\n  for (i = 0; i < 10; ++i) {\n    memcpy(f, kAdd, sizeof(kAdd));\n    if (f(20, 3) != 23) return i * 10 + 4;\n    memcpy(f, kSub, sizeof(kSub));\n    if (f(20, 3) != 17) return i * 10 + 5;\n  }\n  return 0;\n}\n\nint main(int argc, char *argv[]) {\n  return Main();\n}\n"
  },
  {
    "path": "test/func/socket_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <netinet/in.h>\n#include <sys/socket.h>\n\n#include \"test/test.h\"\n\nvoid SetUp(void) {\n}\n\nvoid TearDown(void) {\n}\n\nTEST(ipv4, test) {\n  int ws, pid;\n  char buf[16] = {0};\n  uint32_t addrsize = sizeof(struct sockaddr_in);\n  struct sockaddr_in addr = {\n      .sin_family = AF_INET,\n      .sin_addr.s_addr = htonl(0x7f000001),\n  };\n  ASSERT_EQ(3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));\n  ASSERT_EQ(0, bind(3, (struct sockaddr *)&addr, sizeof(addr)));\n  ASSERT_EQ(0, getsockname(3, (struct sockaddr *)&addr, &addrsize));\n  ASSERT_EQ(0, listen(3, SOMAXCONN));\n  ASSERT_NE(-1, (pid = fork()));\n  if (!pid) {\n    ASSERT_EQ(4, accept(3, (struct sockaddr *)&addr, &addrsize));\n    ASSERT_EQ(5, send(4, \"hello\", 5, 0));\n    ASSERT_EQ(0, close(4));\n    ASSERT_EQ(0, close(3));\n    _Exit(0);\n  }\n  EXPECT_EQ(0, close(3));\n  EXPECT_EQ(3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));\n  EXPECT_EQ(0, connect(3, (struct sockaddr *)&addr, sizeof(addr)));\n  EXPECT_EQ(5, read(3, buf, 16));\n  EXPECT_STREQ(\"hello\", buf);\n  EXPECT_EQ(0, close(3));\n  EXPECT_NE(-1, wait(&ws));\n  ASSERT_TRUE(WIFEXITED(ws));\n  ASSERT_EQ(0, WEXITSTATUS(ws));\n}\n"
  },
  {
    "path": "test/func/trap_cpuid_test.c",
    "content": "// test kernel lets us trap cpuid instruction\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE\n#endif\n#include <asm/prctl.h>\n#include <signal.h>\n#include <stdio.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n\n#define ARCH_GET_CPUID_ 0x1011\n#define ARCH_SET_CPUID_ 0x1012\n\nstatic void OnSigSegv(int sig, siginfo_t *si, void *vctx) {\n  ucontext_t *ctx = (ucontext_t *)vctx;\n  const char *code = (const char *)ctx->uc_mcontext.gregs[REG_RIP];\n  if (code[0] == 0x0F && code[1] == (char)0xA2) {\n    // we successfully trapped the cpuid instruction\n    ctx->uc_mcontext.gregs[REG_RAX] = 0x13370001;\n    ctx->uc_mcontext.gregs[REG_RBX] = 0x13370002;\n    ctx->uc_mcontext.gregs[REG_RCX] = 0x13370003;\n    ctx->uc_mcontext.gregs[REG_RDX] = 0x13370004;\n    ctx->uc_mcontext.gregs[REG_RIP] += 2;\n  } else {\n    _exit(20);\n  }\n}\n\nint main(int argc, char *argv[]) {\n  int ax, bx, cx, dx;\n  ax = cx = 0;\n  asm volatile(\"cpuid\" : \"+a\"(ax), \"=b\"(bx), \"+c\"(cx), \"=d\"(dx));\n  if (syscall(SYS_arch_prctl, ARCH_GET_CPUID_) != 1 ||\n      syscall(SYS_arch_prctl, ARCH_SET_CPUID_, 0) != 0) {\n    fprintf(stderr, \"skipping %s\\n\", argv[0]);\n    return 0;\n  }\n  if (syscall(SYS_arch_prctl, ARCH_GET_CPUID_) != 0) return 3;\n  struct sigaction sa = {.sa_sigaction = OnSigSegv};\n  if (sigaction(SIGSEGV, &sa, 0)) return 4;\n  ax = cx = 0;\n  asm volatile(\"cpuid\" : \"+a\"(ax), \"=b\"(bx), \"+c\"(cx), \"=d\"(dx));\n  if (ax != 0x13370001) return 5;\n  if (bx != 0x13370002) return 6;\n  if (cx != 0x13370003) return 7;\n  if (dx != 0x13370004) return 8;\n  return 0;\n}\n"
  },
  {
    "path": "test/func/trap_rdtsc_test.c",
    "content": "// test kernel lets us trap rdtsc instruction\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE\n#endif\n#include <signal.h>\n#include <stdint.h>\n#include <sys/prctl.h>\n#include <ucontext.h>\n#include <unistd.h>\n\n#define rdtsc()                                                  \\\n  ({                                                             \\\n    uint64_t rax_, rdx_;                                         \\\n    asm volatile(\"rdtsc\" : \"=a\"(rax_), \"=d\"(rdx_) : : \"memory\"); \\\n    rdx_ << 32 | rax_;                                           \\\n  })\n\nstatic void OnSigSegv(int sig, siginfo_t *si, void *vctx) {\n  ucontext_t *ctx = (ucontext_t *)vctx;\n  const char *code = (const char *)ctx->uc_mcontext.gregs[REG_RIP];\n  if (code[0] == 0x0f && code[1] == 0x31) {\n    ctx->uc_mcontext.gregs[REG_RDX] = 3;\n    ctx->uc_mcontext.gregs[REG_RAX] = 0x13370000;\n    ctx->uc_mcontext.gregs[REG_RIP] += 2;\n  } else {\n    _exit(20);\n  }\n}\n\nint main(int argc, char *argv[]) {\n  uint64_t x, y;\n  if (prctl(PR_SET_TSC, PR_TSC_ENABLE)) return 1;\n  x = rdtsc();\n  y = rdtsc();\n  if (x == y) return 2;\n  if (y < x) return 3;\n  struct sigaction sa = {.sa_sigaction = OnSigSegv};\n  if (sigaction(SIGSEGV, &sa, 0)) return 4;\n  if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV)) return 5;\n  if (rdtsc() != 0x313370000) return 6;\n  if (rdtsc() != 0x313370000) return 7;\n  return 0;\n}\n"
  },
  {
    "path": "test/func/trap_test.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2023 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <signal.h>\n\nvolatile int failed;\n\nvoid OnSig(int sig, siginfo_t *si, void *ptr) {\n  failed = 0;\n}\n\nint main(int argc, char *argv[]) {\n  sigaction(SIGTRAP, &(struct sigaction){.sa_sigaction = OnSig}, 0);\n  failed = 1;\n  asm(\"int3\");\n  return failed;\n}\n"
  },
  {
    "path": "test/metal/biosdisk.S",
    "content": "#include \"test/metal/mac.inc\"\n\n\t.section .head,\"ax\",@progbits\n\t.code16\n\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/metal/biosdisk.bin\n//\to//blink/blinkenlights -r o//test/metal/biosdisk.bin\n\n\tljmpw\t$0,$1f\n1:\n\t.test\t\"int 0x1E diskette parameter table should contain sane values\"\n\tlds\t%cs:(0x1e*4),%bx\t// %ds:%bx := table pointer\n\tmov\t%ds,%ax\t\t\t// test that pointer is not null\n\tor\t%bx,%ax\n\t.ne\n\tcmpb\t$2,3(%bx)\t\t// test that diskette I/O is using\n\t.e\t\t\t\t// 512 bytes per sector\n\tcmpb\t$8,4(%bx)\t\t// ...& at least 8 sectors per track\n\t.nc\n\n\ttest\t%dl,%dl\t\t\t// skip next test in unlikely case\n\tjne\t2f\t\t\t// this was not booted from floppy\n\t\t\t\t\t// drive A:\n\n\t.test\t\"floppy parameters from int 0x13 should be sane\"\n\txor\t%di,%di\t\t\t// get parameters for A:\n\tmov\t%di,%es\n\tmov\t$8,%ah\n\txor\t%cx,%cx\n\tint\t$0x13\n\t.nc\n\tcmp\t$8,%cl\t\t\t// test that maximum sector number\n\t.nc\t\t\t\t// per track makes sense\n\tcmp\t$40-1,%ch\t\t// test that maximum track number\n\t.nc\t\t\t\t// makes sense\n\ttest\t%dl,%dl\t\t\t// test that drive count makes sense\n\t.ne\n\tmov\t%es,%ax\t\t\t// test that parameter table pointer\n\tor\t%di,%ax\t\t\t// is not null\n\t.ne\n\tcmpb\t$2,%es:3(%di)\t\t// test parameter table values for\n\t.e\t\t\t\t// this drive\n\tcmpb\t$8,%es:4(%di)\n\t.nc\n\n2:\n\t.exit\n\n// fabricate a 160 KiB disk image (40 tracks × 1 side × 8 sectors per track)\n\n\t.global\t_sectors\n\t_sectors = 320\n\n\t.section .pad,\"a\",@progbits\n"
  },
  {
    "path": "test/metal/biostime.S",
    "content": "#include \"test/metal/mac.inc\"\n\n\t.section .head,\"ax\",@progbits\n\t.code16\n\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/metal/biostime.bin\n//\to//blink/blinkenlights -r o//test/metal/biostime.bin\n\n\tljmpw\t$0,$1f\n1:\n\t.test\t\"real time clock should not move much slower than system clock\"\n\tmov\t$5,%bp\n2:\n\tmov\t$2,%ah\t\t\t// get starting RTC time\n\tint\t$0x1a\n\t.nc\n\tmov\t%cl,%dl\n\tmov\t%dx,%si\n\tmov\t$0,%ah\t\t\t// get starting system time\n\tint\t$0x1a\n\tpush\t%cx\n\tpush\t%dx\n\tpop\t%edi\n3:\n\tmov\t$0,%ah\t\t\t// wait until at least 20 system clock\n\tint\t$0x1a\t\t\t// ticks (slightly more than 1s)\n\tpush\t%cx\t\t\t// have elapsed\n\tpush\t%dx\n\tpop\t%edx\n\tcmp\t$0x1800b0,%edx\n\t.c\n\tsub\t%edi,%edx\n\tjnc\t4f\n\tadd\t$0x1800b0,%edx\n4:\n\tcmp\t$20,%edx\n\tjb\t3b\n\tcmp\t$0x1800b0/2,%edx\n\tja\t1b\t\t\t// lolwut?\n\tmov\t$2,%ah\t\t\t// get new RTC time\n\tint\t$0x1a\n\t.nc\n\tmov\t%cl,%dl\n\tcmp\t%dx,%si\t\t\t// RTC time should have changed by now\n\t.nz\n\tdec\t%bp\t\t\t// retry this 5 times\n\tjnz\t2b\n\n\t.test\t\"system clock should not move much slower than real time clock\"\n5:\n\tmov\t$2,%ah\t\t\t// wait until RTC time rolls over\n\tint\t$0x1a\t\t\t// to next second\n\t.nc\n\tmov\t%cl,%dl\n\tmov\t%dx,%si\n6:\n\tmov\t$2,%ah\n\tint\t$0x1a\n\tmov\t%cl,%dl\n\tcmp\t%dx,%si\n\tje\t6b\n\tmov\t$5,%bp\n7:\n\tmov\t$0,%ah\t\t\t// get starting system time\n\tint\t$0x1a\n\tpush\t%cx\n\tpush\t%dx\n\tpop\t%edi\n\tmov\t$2,%ah\t\t\t// get starting RTC time\n\tint\t$0x1a\n\t.nc\n\tmov\t%cl,%dl\n\tmov\t%dx,%si\n8:\n\tmov\t$2,%ah\t\t\t// wait until RTC time rolls over\n\tint\t$0x1a\t\t\t// to next second\n\t.nc\n\tmov\t%cl,%dl\n\tcmp\t%dx,%si\n\tjz\t8b\n\tmov\t$0,%ah\t\t\t// system time should have advanced\n\tint\t$0x1a\t\t\t// by at least 16 ticks by now\n\tpush\t%cx\n\tpush\t%dx\n\tpop\t%edx\n\tsub\t%edi,%edx\n\tjnc\t9f\n\tadd\t$0x1800b0,%edx\n9:\n\tcmp\t$16,%edx\n\t.nc\n\tcmp\t$0x1800b0/2,%edx\n\tja\t5b\n\tdec\t%bp\n\tjnz\t7b\n\n\t.exit\n"
  },
  {
    "path": "test/metal/enter.S",
    "content": "#include \"test/metal/mac.inc\"\n\n\t.section .head,\"ax\",@progbits\n\t.code16\n\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/metal/enter.bin\n//\to//blink/blinkenlights -r o//test/metal/enter.bin\n\n\t.load32\t_start32\n\n\t.section .text,\"ax\",@progbits\n\t.code32\n\n#define MAGIC1\t\t0xacc31274\n#define MAGIC2\t\t0xa7fc\n#define MAGIC3\t\t0x40df\n#define MAGIC4\t\t0x8c34\n\n_start32:\n\t.test\t\"enterl stores frame pointer of size 4\"\n\tmov\t$MAGIC1,%ebx\n\tlea\t-4-MAGIC2(%esp),%eax\n\tlea\t-4(%esp),%ecx\n\tmov\t%esp,%edx\n\n\tmov\t%ebx,%ebp\n\tenterl\t$MAGIC2,$0\n\tcmp\t%esp,%eax\n\t.e\n\tcmp\t%ebp,%ecx\n\t.e\n\tcmp\t(%ebp),%ebx\n\t.e\n\n\t.test\t\"leavel restores frame pointer of size 4\"\n\tleavel\n\tcmp\t%edx,%esp\n\t.e\n\tcmp\t%ebx,%ebp\n\t.e\n\n\t.test\t\"enterw stores frame pointer of size 2\"\n\txor\t%sp,%sp\t\t\t// make sure %sp does not wrap\n\tsub\t$4,%esp\t\t\t// around 64 KiB boundary\n\n\tmov\t%esp,%ebx\n\tmov\t$MAGIC3,%bx\n\tlea\t-2-MAGIC4(%esp),%eax\n\tlea\t-2(%esp),%ecx\n\tmov\t%esp,%edx\n\n\tmov\t%ebx,%ebp\n\tenterw\t$MAGIC4,$0\n\tcmp\t%esp,%eax\n\t.e\n\tcmp\t%ebp,%ecx\n\t.e\n\tcmp\t(%ebp),%bx\n\t.e\n\n\t.test\t\"leavew restores frame pointer of size 2\"\n\tleavew\n\tcmp\t%edx,%esp\n\t.e\n\tmov\t%bx,%dx\n\tcmp\t%edx,%ebp\n\t.e\n\n\"test succeeded\":\n\t.exit\n"
  },
  {
    "path": "test/metal/gdt-idt-32.S",
    "content": "\t.section .head,\"ax\",@progbits\n\t.code16\n\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/metal/gdt-idt-32.bin\n//\to//blink/blinkenlights -r o//test/metal/gdt-idt-32.bin\n\n\tljmpw\t$0,$1f\n1:\n\tmov\t%cs,%ax\n\tcli\n\tmov\t%ax,%ss\n\tmov\t$_start,%sp\n\tmov\t%ax,%ds\n\tmov\t%ax,%es\n\tsidt\torig_idt\n\n//\tTest that we can load arbitrary values into the GDTR & IDTR, & that\n//\tthe loaded base addresses are of the correct widths\n\n\tcld\n\tmov\t$actual_out,%di\n\tmov\t$0xf6,%al\n\tmov\t$out_size,%cx\n\trep stosb\n\n\tlgdtw\tdt1\t\t\t// load GDTR, operand size 16 bits\n\t\t\t\t\t// => 24-bit base address\n\tsgdtw\tout1a\t\t\t// store GDTR: this will still dump a\n\t\t\t\t\t// 32-bit base address\n\tlgdtl\tdt1\t\t\t// load GDTR, operand size 32 bits\n\t\t\t\t\t// => 32-bit base address\n\tsgdtl\tout1b\t\t\t// store GDTR again\n\n\tlidtw\tdt2\t\t\t// now try messing with the IDTR\n\tsidtw\tout2a\n\tlidtl\tdt2\n\tsidtl\tout2b\n\n//\tNow load an actual GDT, switch to protected mode, & test that the\n//\tLSL instruction reads the correct limits from it\n//\tWhile at it, also check that for the `smsw` instruction (0f 01 /4)\n//\tthe reg/opcode field (/4) is not misinterpreted as an %sp operand\n\n\tlgdtw\tgood_gdtr\n\tmov\t$-1,%dx\n\tsmsw\t%dx\t\t\t// %dx := %cr0[15:0]...\n\tcmp\t$_start,%sp\t\t// ...not %sp := %cr0[15:0] !\n\tjnz\tfail\n\tor\t$1,%dl\n\tlmsw\t%dx\n\tjmp\t2f\n2:\n\n\tmov\t$GDT_DATA16_32K,%cx\n\tlsl\t%ecx,%eax\n\tmov\t%eax,out3a\n\tmov\t$GDT_DATA16_4G,%cl\n\tlsl\t%ecx,%eax\n\tmov\t%eax,out3b\n\tmov\t$GDT_DATA32_64K,%cl\n\tlsl\t%ecx,%eax\n\tmov\t%eax,out3c\n\tmov\t$GDT_DATA32_384M,%cl\n\tlsl\t%ecx,%eax\n\tmov\t%eax,out3d\n\n//\tBack to real mode\n\n\tmov\t%cr0,%eax\n\tand\t$~1,%al\n\tmov\t%eax,%cr0\n\tjmp\t3f\n3:\n\n//\tCompare actual output with expected output\n\n\tmov\t$expect_out,%si\n\tmov\t$actual_out,%di\n\tmov\t$out_size,%cx\n\trepz cmpsb\n\tjnz\tfail\n\n//\tTests passed!  Try to \"exit\" emulator with success status\n\n\tcli\n\tlidt\tbad_idt\n\txor\t%edi,%edi\n\tmov\t$231,%eax\n\tsyscall\t\t\t\t// this will triple fault on a real PC\n\nfail:\n\tlidt\torig_idt\n\tint3\n\tjmp\tfail\n\n\t.balign\t8\ndt1:\t.quad\t0x5b1ebd8d858e9801\ndt2:\t.quad\t0xc5a9b78fe8a862f1\n\nexpect_out:\n\t.quad\t0xf6f6008d858e9801\t// expected result of 1st SGDT\n\t.quad\t0xf6f6bd8d858e9801\t// expected result of 2nd SGDT\n\t.quad\t0xf6f6008fe8a862f1\t// expected result of 1st SIDT\n\t.quad\t0xf6f6b78fe8a862f1\t// expected result of 2nd SIDT\n\t.long\t0x00007fff\t\t// expected result of 1st LSL\n\t.long\t0xffffffff\t\t// expected result of 2nd LSL\n\t.long\t0x0000ffff\t\t// expected result of 3rd LSL\n\t.long\t0x17ffffff\t\t// expected result of 4th LSL\n\tout_size = . - expect_out\n\ngood_gdtr:\n\t.short\tgood_gdt_end-good_gdt-1\n\t.long\tgood_gdt\n\ngood_gdt:\n.quad\t0b0000000000000000000000000000000000000000000000000000000000000000 # 0\n.quad\t0b0000000000000000100100100000000000000000000000000111111111111111 # 8\n.quad\t0b0000000010001111100100100000000000000000000000001111111111111111 #16\n.quad\t0b0000000001000000100100100000000000000000000000001111111111111111 #24\n.quad\t0b0000000011000001100100100000000000000000000000000111111111111111 #32\ngood_gdt_end:\n\n\tGDT_DATA16_32K\t= 8\n\tGDT_DATA16_4G\t= 16\n\tGDT_DATA32_64K\t= 24\n\tGDT_DATA32_384M\t= 32\n\n\t.balign\t8\nbad_idt:\n\t.quad\t0\n\n\t.bss\n\n\t.balign\t8\norig_idt:\n\t.skip\t8\n\nactual_out:\nout1a:\t.skip\t8\nout1b:\t.skip\t8\nout2a:\t.skip\t8\nout2b:\t.skip\t8\nout3a:\t.skip\t4\nout3b:\t.skip\t4\nout3c:\t.skip\t4\nout3d:\t.skip\t4\n"
  },
  {
    "path": "test/metal/hello.S",
    "content": "\t.section .head,\"ax\",@progbits\n\t.code16\n\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/metal/hello.bin\n//\to//blink/blinkenlights -r o//test/metal/hello.bin\n\n\tljmpw\t$0,$1f\n1:\n\tmov\t%cs,%ax\n\tmov\t%ax,%ds\n\tmov\t$msg,%si\n\tcld\n2:\n\tlodsb\n\ttest\t%al,%al\n\tjz\t3f\n\tmov\t$0x0e,%ah\n\tmov\t$0x0007,%bx\n\tint\t$0x10\n\tjmp\t2b\n3:\n\tcli\n\tlidt\tbad_idt\n\txor\t%edi,%edi\n\tmov\t$231,%eax\n\tsyscall\t\t\t\t// this will triple fault on a real PC\n\nmsg:\n\t.asciz\t\"Hello world!\\r\\n\"\n\n\t.balign\t8\nbad_idt:\n\t.quad\t0\n"
  },
  {
    "path": "test/metal/int3.S",
    "content": "#include \"test/metal/mac.inc\"\n\n\t.section .head,\"ax\",@progbits\n\t.code16\n\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/metal/int3.bin\n//\to//blink/blinkenlights -r o//test/metal/int3.bin\n\n\tljmpw\t$0,$1f\n1:\n\t.test\t\"int3 should not halt execution if guest is hooking it\"\n\tmovw\t$9f,%cs:(0x03*4)\t// point int 3 vector at our own code\n\tmovw\t%cs,%cs:(0x03*4)+2\n\tint3\t\t\t\t// then invoke int 3\n2:\t\t\t\t\t// if the above happens to fall\n\tud2\t\t\t\t// through to the next instruction,\n\thlt\t\t\t\t// force something really bad (not\n\tjmp\t2b\t\t\t// an int 3!) to happen\n\n9:\t\t\t\t\t// if things go well, execution\n\t.exit\t\t\t\t// should reach here\n"
  },
  {
    "path": "test/metal/iret.S",
    "content": "\t.section .head,\"ax\",@progbits\n\t.code16\n\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/metal/iret.bin\n//\to//blink/blinkenlights -r o//test/metal/iret.bin\n\n0:\tljmpw\t$0,$1f\n\n\tRET_TO = 5215\n\t.subsection RET_TO\n1:\txor\t%ax,%ax\n\tmov\t%ax,%ss\n\tmov\t$0b,%sp\n\tmov\t$0x414,%ax\n\tmov\t%ax,%ds\n\tmov\t$0b11100011,%ah\n\tsahf\n\tjns\tfail\n\tjnz\tfail\n\tjp\tfail\n\tjnc\tfail\n\tpushfl\n\tlcalll\t$0x655,$11f-0x6550\n\n\t.subsection 2480\n11:\tmov\t$0b01000010,%ah\n\tsahf\n\tjs\tfail\n\tjnz\tfail\n\tjp\tfail\n\tjc\tfail\n\tiretl\n\n\t.subsection RET_TO\n\tjns\tfail\n\tjnz\tfail\n\tjp\tfail\n\tjnc\tfail\n\tcmp\t$0b01000010,%ah\n\tjnz\tfail\n\n\tmov\t$0b10011111,%ah\n\tsahf\n\tjns\tfail\n\tjz\tfail\n\tjnp\tfail\n\tjnc\tfail\n\tpushfw\n\tlcallw\t$0x554,$21f-0x5540\n\n\t.subsection 1555\n21:\tmov\t$0b00111000,%ah\n\tsahf\n\tjs\tfail\n\tjz\tfail\n\tjp\tfail\n\tjc\tfail\n\tiretw\n\n\t.subsection RET_TO\n\tjns\tfail\n\tjz\tfail\n\tjnp\tfail\n\tjnc\tfail\n\tcmp\t$0b00111000,%ah\n\tjnz\tfail\n\n\tcli\n\txor\t%edi,%edi\n\tmov\t%di,%ds\n\tlidt\tbad_idt\n\tmov\t$231,%eax\n\tsyscall\t\t\t\t// this will triple fault on a real PC\n\nfail:\n\tint3\n\thlt\n\tjmp\tfail\n\n\t.balign\t8\nbad_idt:\n\t.quad\t0\n"
  },
  {
    "path": "test/metal/lds-les.S",
    "content": "\t.section .head,\"ax\",@progbits\n\t.code16\n\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/metal/lds-les.bin\n//\to//blink/blinkenlights -r o//test/metal/lds-les.bin\n\n\tljmpw\t$0,$1f\n\n#define SEG1\t\t0x66d\n#define OFF1\t\t(loc1-0x66d0)\n#define MAGIC1\t\t0x5bd3610b\n\n#define SEG2\t\t0x79e\n#define OFF2\t\t(loc2-0x79e0)\n#define MAGIC2\t\t0x358f8b2e\n\n#define SEG3\t\t0x541\n#define OFF3\t\t(loc3-0x5410)\n#define MAGIC3\t\t0xca55bb07\n\n#define SEG4\t\t0x29f\n#define OFF4\t\t(loc4-0x29f0)\n#define MAGIC4\t\t0xb9fca8dc\n\n#define SEG5\t\t0x1c7\n#define OFF5A\t\t(-0x29ec8d34)\n#define OFF5B\t\t(loc5-0x1c70-OFF5A)\n#define MAGIC5\t\t0x9c948198\n\n#define SEG6\t\t0x323\n#define OFF6A\t\t(-0x03748378)\n#define OFF6B\t\t(loc6-0x3230-OFF6A)\n#define MAGIC6\t\t0x3f2c0b97\n\n#define SEG7\t\t0x41e\n#define OFF7\t\t(loc7-0x41e0)\n#define MAGIC7\t\t0xf1cab448\n\n1:\n\tor\t$-1,%ecx\n\tmov\t%ecx,%ebx\n\tmov\t%ecx,%esi\n\tmov\t%ecx,%edi\n\tmov\t%cx,%ds\n\tmov\t%cx,%es\n\n\tlds\t%cs:fp1,%bx\n\tcmp\t$OFF1,%bx\n\tjnz\tfail\n\tmov\t%ds,%ax\n\tcmp\t$SEG1,%ax\n\tjnz\tfail\n\tcmpl\t$MAGIC1,(%bx)\n\tjnz\tfail\n\n\tles\t%cs:fp2,%si\n\tcmp\t$OFF2,%si\n\tjnz\tfail\n\tmov\t%es,%ax\n\tcmp\t$SEG2,%ax\n\tjnz\tfail\n\tcmpl\t$MAGIC2,%es:(%si)\n\tjnz\tfail\n\n\tlds\t%cs:fp3,%edi\n\tcmp\t$OFF3,%edi\n\tjnz\tfail\n\tmov\t%ds,%ax\n\tcmp\t$SEG3,%ax\n\tjnz\tfail\n\tcmpl\t$MAGIC3,(%edi)\n\tjnz\tfail\n\n\tles\t%cs:fp4,%ebp\n\tcmp\t$OFF4,%ebp\n\tjnz\tfail\n\tmov\t%es,%ax\n\tcmp\t$SEG4,%ax\n\tjnz\tfail\n\tcmpl\t$MAGIC4,%es:(%ebp)\n\tjnz\tfail\n\n\tlfs\t%cs:fp5,%eax\n\tcmp\t$OFF5A,%eax\n\tjnz\tfail\n\tmov\t%fs,%bx\n\tcmp\t$SEG5,%bx\n\tjnz\tfail\n\tcmpl\t$MAGIC5,%fs:OFF5B(%eax)\n\tjnz\tfail\n\n\tlgs\t%cs:fp6,%ecx\n\tcmp\t$OFF6B,%ecx\n\tjnz\tfail\n\tmov\t%gs,%dx\n\tcmp\t$SEG6,%dx\n\tjnz\tfail\n\tcli\n\tmov\t$OFF6A,%esp\n\tcmpl\t$MAGIC6,%gs:(%esp,%ecx)\n\tjnz\tfail\n\n\tmov\t$_start-SEG7*0x10,%esp\n\tlss\t%cs:fp7,%si\n\tmov\t%ss,%bp\n\tcmp\t$SEG7,%bp\n\tjnz\tfail\n\tsti\n\tcmp\t$OFF7,%si\n\tjnz\tfail\n\tcmpl\t$MAGIC7,%ss:(%si)\n\tjnz\tfail\n\n//\tTests passed!  Try to \"exit\" emulator with success status\n\n\tcli\n\tlidt\tbad_idt\n\txor\t%edi,%edi\n\tmov\t$231,%eax\n\tsyscall\t\t\t\t// this will triple fault on a real PC\n\nfail:\n\tint3\n\tjmp\tfail\n\n\t.balign\t2\nfp1:\t.hword\tOFF1,SEG1\nfp2:\t.hword\tOFF2,SEG2\nfp3:\t.long\tOFF3\n\t.hword\tSEG3\nfp4:\t.long\tOFF4\n\t.hword\tSEG4\nfp5:\t.long\tOFF5A\n\t.hword\tSEG5\nfp6:\t.long\tOFF6B\n\t.hword\tSEG6\nfp7:\t.hword\tOFF7,SEG7\n\nloc1:\t.long\tMAGIC1\nloc2:\t.long\tMAGIC2\nloc3:\t.long\tMAGIC3\nloc4:\t.long\tMAGIC4\nloc5:\t.long\tMAGIC5\nloc6:\t.long\tMAGIC6\nloc7:\t.long\tMAGIC7\n\n\t.balign\t8\nbad_idt:\n\t.quad\t0\n"
  },
  {
    "path": "test/metal/ljmp-lcall.S",
    "content": "\t.section .head,\"ax\",@progbits\n\t.code16\n\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/metal/ljmp-lcall.bin\n//\to//blink/blinkenlights -r o//test/metal/ljmp-lcall.bin\n\n0:\tljmpw\t$0,$1f\n1:\txor\t%ax,%ax\n\tmov\t%ax,%ss\n\tmov\t$0b,%sp\n\tljmpw\t*%cs:21f\n\n\t.subsection 1027\n21:\t.hword\t11f-0x6aa0,0x6aa\n\n\tRET_TO = 4703\n\t.subsection RET_TO\n11:\tmov\t$0x30e,%ax\n\tmov\t%ax,%ds\n\tmov\t$0xa9e,%bx\n\tlcalll\t*22f-0xa9e-0x30e0(%bx)\n\n\t.subsection 2822\n22:\t.long\t12f-0x26b0\n\t.hword\t0x26b\n\n\t.subsection 2997\n12:\tadd\t$0x35fc-0x30e,%ax\n\tlretl\n\n\t.subsection RET_TO\n\tcmp\t$0x35fc,%ax\n\tjnz\tfail\n\tmovl\t$-0xafa8b409,%ecx\n\tljmpl\t*23f+0xafa8b409-0x30e0(%ecx)\n\n\t.subsection 367\n23:\t.long\t13f-0x6480\n\t.hword\t0x648\n\n\tRET_TO = 8148\n\t.subsection RET_TO\n13:\tmov\t$0x2ab,%ax\n\tmov\t%ax,%es\n\tmovl\t$-0x8f45a4df,%ebp\n\tlcallw\t*%es:24f+0x8f45a4df-0x2ab0(%ebp)\n\n\t.subsection 7391\n24:\t.hword\t14f-0x6820,0x682\n\n\t.subsection 141\n14:\txor\t%ebp,%ecx\n\tlretw\n\n\t.subsection RET_TO\n\tcmp\t$(-0xafa8b409)^(-0x8f45a4df),%ecx\n\tjnz\tfail\n\n\tcli\n\txor\t%edi,%edi\n\tmov\t%di,%ds\n\tlidt\tbad_idt\n\tmov\t$231,%eax\n\tsyscall\t\t\t\t// this will triple fault on a real PC\n\nfail:\n\tint3\n\thlt\n\tjmp\tfail\n\n\t.balign\t8\nbad_idt:\n\t.quad\t0\n"
  },
  {
    "path": "test/metal/mac.inc",
    "content": "// -*- mode: unix-assembly; indent-tabs-mode: t; tab-width: 8; coding: utf-8 -*-\n\n\t.macro\t.load16\n\tljmp\t$0,$101f\n101:\txor\t%ax,%ax\n\tmov\t%ax,%ds\n\tmov\t%ax,%es\n\tmov\t%ax,%ss\n\tmov\t$_start,%sp\n\tint\t$0x13\t\t\t// reset boot device (%ah = 0)\n\tmov\t$0x0200+_sectors-1,%ax\t// read remaining sectors of this\n\tmov\t$_start+512,%bx\t\t// test case\n\tmov\t$0x0002,%cx\n\tmov\t$0,%dh\n\tint\t$0x13\n\tjc\t101b\n\t.endm\n\n\t.macro\t.load32 entry:req\n\t.load16\n\tcli\t\t\t\t// switch to protected mode\n\tlgdtl\t103f\n\tmov\t%cr0,%eax\n\tor\t$1,%al\n\tmov\t%eax,%cr0\n\tjmp\t102f\n102:\tmov\t$16,%ax\n\tmov\t%ax,%ds\n\tmov\t%ax,%es\n\tmov\t%ax,%ss\n\tmovzwl\t0x0413,%esp\t\t// start stack at base memory top\n\tshll\t$10,%esp\n\tljmpl\t$8,$(\\entry)\t\t// really transition to 32-bit mode\n\t.balign\t8\n103:\t.short\t105f-104f-1\n\t.long\t104f\n\t.balign\t8\n104:\n.quad\t0b0000000000000000000000000000000000000000000000000000000000000000 # 0\n.quad\t0b0000000011001111100110100000000000000000000000001111111111111111 # 8\n.quad\t0b0000000011001111100100100000000000000000000000001111111111111111 #16\n105:\n\t.endm\n\n\t.macro\t.exit\n\tcli\n\tlidtl\t%cs:106f\n\txor\t%edi,%edi\n\txor\t%eax,%eax\n\tmov\t$231,%al\n\tsyscall\n\t.balign\t8\n106:\t.quad\t0\n\t.endm\n\n\t.macro\t.test name:req\nprologue\\@:\n\tjmp\t101f\n100:\tint3\n\thlt\n\tjmp\t100b\n101:\tnop\n\"\\name\":\n\t.endm\n\n\t.macro\t.c\n\tjnc\t100b\n\t.endm\n\t.macro\t.nc\n\tjc\t100b\n\t.endm\n\n\t.macro\t.e\n\tjne\t100b\n\t.endm\n\t.macro\t.ne\n\tje\t100b\n\t.endm\n\n\t.macro\t.z\n\tjnz\t100b\n\t.endm\n\t.macro\t.nz\n\tjz\t100b\n\t.endm\n\n\t.macro\t.s\n\tjns\t100b\n\t.endm\n\t.macro\t.ns\n\tjs\t100b\n\t.endm\n\n\t.macro\t.o\n\tjno\t100b\n\t.endm\n\t.macro\t.no\n\tjo\t100b\n\t.endm\n\n\t.macro\t.p\n\tjnp\t100b\n\t.endm\n\t.macro\t.np\n\tjp\t100b\n\t.endm\n\n\t.macro\t.sop\n\t.nz\n\t.s\n\t.nc\n\t.o\n\t.p\n\t.endm\n"
  },
  {
    "path": "test/metal/metal.lds",
    "content": "ENTRY(_start)\nOUTPUT_FORMAT(binary)\n\nSECTIONS {\n  . = 0x7c00;\n\n  .head : {\n    _base = .;\n    *(.head)\n\n    /*\n     * Fabricate a degenerate \"hard disk partition table\" that covers at\n     * least this bare metal program.  Fill up 1 partition table entry.\n     */\n    . =\t0x1be;\n    BYTE(0x80)\t\t\t\t/* 0=non-boot / 0x80=active */\n    BYTE(0)\t\t\t\t/* start head */\n    BYTE(1)\t\t\t\t/* start sector[5:0], cylinder[9:8] */\n    BYTE(0)\t\t\t\t/* start cylinder[7:0] */\n    BYTE(0x7f)\t\t\t\t/* filesystem type */\n    BYTE(0xff)\t\t\t\t/* end head */\n    BYTE(0xff)\t\t\t\t/* end sector[5:0], cylinder[9:8] */\n    BYTE(0xff)\t\t\t\t/* end cylinder[7:0] */\n    LONG(0)\t\t\t\t/* c₀*Cₙ + h₀*Hₙ + s₀*Sₙ */\n    LONG(0xffffffff)\t\t\t/* sector count */\n\n    /* Add the boot record signature. */\n    . = 0x1fe;\n    SHORT(0xaa55);\n  } = 0\n\n  .text : {\n    *(.text .text.*)\n    . = ALIGN(0x10);\n    *(.rodata .rodata.*)\n    . = ALIGN(0x10);\n    *(.data .data.*)\n    _edata = .;\n  }\n\n  PROVIDE(_sectors = ALIGN(_edata - _base, 512) / 512);\n\n  .bss : {\n    *(.bss .bss.*)\n    *(COMMON)\n  }\n\n  .pad : {\n    /*\n     * If the program defines both a _sectors value & a .pad section, then\n     * pad the image up to the requested sector count.  This allows us to\n     * fabricate disk images that follow particular disk geometries.\n     */\n    . = MAX(., _base + _sectors * 512 - SIZEOF(.pad));\n    *(.pad .pad.*)\n  } = 0xF6\n\n  /DISCARD/ : {\n    *(.*)\n  }\n}\n"
  },
  {
    "path": "test/metal/metal.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nTEST_METAL_FILES := $(wildcard test/metal/*)\nTEST_METAL_SRCS = $(filter %.S,$(TEST_METAL_FILES))\nTEST_METAL_OBJS = $(TEST_METAL_SRCS:%.S=o/$(MODE)/x86_64-gcc49/%.o)\nTEST_METAL_BINS = $(TEST_METAL_SRCS:%.S=o/$(MODE)/%.bin)\nTEST_METAL_CHECKS = $(TEST_METAL_BINS:%=%.ok)\n\nTEST_METAL_LINK =\t\t\t\t\t\t\t\t\\\n\t\t$(VM)\t\t\t\t\t\t\t\t\\\n\t\to/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-ld.bfd\t\\\n\t\t-T test/metal/metal.lds\t\t\t\t\t\t\\\n\t\t-static\t\t\t\t\t\t\t\t\\\n\t\t$<\t\t\t\t\t\t\t\t\\\n\t\t-o $@\n\n.PRECIOUS: o/$(MODE)/test/metal/%.bin\no/$(MODE)/test/metal/%.bin:\t\t\t\t\t\t\t\\\n\t\to/$(MODE)/x86_64-gcc49/test/metal/%.o\t\t\t\t\\\n\t\to/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc\t\\\n\t\ttest/metal/metal.lds\t\t\t\t\t\t\\\n\t\t$(VM)\n\t@mkdir -p $(@D)\n\t$(TEST_METAL_LINK)\n\n$(TEST_METAL_OBJS): test/metal/metal.mk test/metal/mac.inc\n\no/$(MODE)/test/metal/%.bin.ok:\t\t\t\t\t\t\\\n\t\to/$(MODE)/test/metal/%.bin\t\t\t\t\\\n\t\to/$(MODE)/blink/blinkenlights\n\t@mkdir -p $(@D)\n\to/$(MODE)/blink/blinkenlights -r -t $<\n\t@touch $@\n\no/$(MODE)/test/metal:\t\t\t\t\t\t\t\\\n\t$(TEST_METAL_CHECKS)\n"
  },
  {
    "path": "test/metal/pusha-popa.S",
    "content": "\t.section .head,\"ax\",@progbits\n\t.code16\n\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/metal/pusha-popa.bin\n//\to//blink/blinkenlights -r o//test/metal/pusha-popa.bin\n\n0:\tljmpw\t$0,$1f\n\n1:\txor\t%ax,%ax\n\tmov\t%ax,%ds\n\tmov\t%ax,%es\n\tmov\t%ax,%ss\n\n\t/* longword with high half being z & low half being w */\n#define SMUSH(z, w)\t((((z) & 0xffff) << 16) | ((w) & 0xffff))\n\n#define MAGIC0\t\t0x84de\n#define INI_SP\t\t0x7c00\n#define INI_ESP\t\tSMUSH(MAGIC0, INI_SP)\n\n\tmov\t$INI_ESP,%esp\n\n\tint\t$0x13\t\t\t// reset boot device (%ah = 0)\n\tmov\t$0x0200+_sectors-1,%ax\t// read remaining sectors of this\n\tmov\t$0b+512,%bx\t\t// test case\n\tmov\t$0x0002,%cx\n\tmov\t$0,%dh\n\tint\t$0x13\n\tjc\t1b\n\n#define MAGIC1\t\t0x6f692002\n#define MAGIC2\t\t0x8556ab1b\n#define MAGIC3\t\t0x1bc6f7f7\n#define MAGIC4\t\t0x60540962\n#define MAGIC5\t\t0xf2b8c5fd\n#define MAGIC6\t\t0x705a9a7f\n#define MAGIC7\t\t0x08500349\n#define MAGIC8\t\t0xdf7601c3\n\n\tmov\t$MAGIC1,%eax\n\tmov\t$MAGIC2,%ecx\n\tmov\t$MAGIC3,%edx\n\tmov\t$MAGIC4,%ebx\n\tmov\t$MAGIC5,%ebp\n\tmov\t$MAGIC6,%esi\n\tmov\t$MAGIC7,%edi\n\tpushal\n/*\n * now %sp                                                      INI_SP\n * ↓       +4      +8      +12     +16     +20     +24     +28     ↓\n * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┐\n * │MAGIC7 │MAGIC6 │MAGIC5 │INI_ESP│MAGIC4 │MAGIC3 │MAGIC2 │MAGIC1 │\n * └───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┘\n *   %edi    %esi    %ebp   initial  %edx    %ecx    %ebx    %eax\n *                           %esp\n */\n\n\tcmp\t$INI_ESP-32,%esp\n\tjnz\tfail\n\tmov\t$MAGIC8,%ebp\n\tmov\t%sp,%bp\n\tcmpl\t$MAGIC1,28(%bp)\n\tjnz\tfail\n\tcmpl\t$MAGIC2,24(%bp)\n\tjnz\tfail\n\tcmpl\t$MAGIC3,20(%bp)\n\tjnz\tfail\n\tcmpl\t$MAGIC4,16(%bp)\n\tjnz\tfail\n\tcmpl\t$INI_ESP,12(%bp)\n\tjnz\tfail\n\tcmpl\t$MAGIC5,8(%bp)\n\tjnz\tfail\n\tcmpl\t$MAGIC6,4(%bp)\n\tjnz\tfail\n\tcmpl\t$MAGIC7,(%bp)\n\tjnz\tfail\n\n#define MAGIC9\t\t0x63b5007e\n\n\tmov\t$MAGIC9,%edi\n\taddr32 popaw  // the `addr32' (0x67) prefix should have no effect!\n/*\n *                              now %sp                         INI_SP\n *                                 ↓                               ↓\n * ┌───┬───┬───┬───┬───┬───┬───┬───┬───────┬───────┬───────┬───────┐\n * │MAGIC7 │MAGIC6 │MAGIC5 │INI_ESP│MAGIC4 │MAGIC3 │MAGIC2 │MAGIC1 │\n * └───┴───┴───┴───┴───┴───┴───┴───┴───────┴───────┴───────┴───────┘\n *  %di %si %bp     %bx %dx %cx %ax\n */\n\n\t/* high half of x combined with low half of y */\n#define HL(x, y)\t(((x) & ~0xffff) | ((y) & 0xffff))\n\n\tcmp\t$HL(MAGIC1, MAGIC0),%eax\n\tjnz\tfail\n\tcmp\t$HL(MAGIC2, INI_ESP),%ecx\n\tjnz\tfail\n\tcmp\t$HL(MAGIC3, MAGIC5 >> 16),%edx\n\tjnz\tfail\n\tcmp\t$HL(MAGIC4, MAGIC5),%ebx\n\tjnz\tfail\n\tcmp\t$INI_ESP-16,%esp\n\tjnz\tfail\n\tcmp\t$HL(MAGIC8, MAGIC6),%ebp\n\tjnz\tfail\n\tcmp\t$HL(MAGIC6, MAGIC7 >> 16),%esi\n\tjnz\tfail\n\tcmp\t$HL(MAGIC9, MAGIC7),%edi\n\tjnz\tfail\n\n#define MAGIC10\t\t0x35ff\n#define MAGIC11\t\t0x45de\n#define MAGIC12\t\t0xe0e4\n#define MAGIC13\t\t0x43ab\n#define MAGIC14\t\t0x44819457\n#define MAGIC15\t\t0x92d11944\n#define MAGIC16\t\t0xf5136466\n\n\tmov\t$MAGIC10,%ax\n\tmov\t$MAGIC11,%cx\n\tmov\t$MAGIC12,%dx\n\tmov\t$MAGIC13,%bx\n\tmov\t$MAGIC14,%ebp\n\tmov\t$MAGIC15,%esi\n\tmov\t$MAGIC16,%edi\n\taddr32 pushaw\t\t\t// `addr32' (0x67) should be ignored\n/*\n * now %sp                        sp₂                           INI_SP\n * ↓       +4      +8      +12     ↓                               ↓\n * ┌───┬───┬───┬───┬───┬───┬───┬───┬───────┬───────┬───────┬───────┐\n * │M₁₆│M₁₅│M₁₄│sp₂│M₁₃│M₁₂│M₁₁│M₁₀│MAGIC4 │MAGIC3 │MAGIC2 │MAGIC1 │\n * └───┴───┴───┴───┴───┴───┴───┴───┴───────┴───────┴───────┴───────┘\n *  %di %si %bp     %bx %dx %cx %ax\n */\n\n\tmov\t%sp,%bp\n\tcmpl\t$SMUSH(MAGIC10, MAGIC11),12(%bp)\n\tjnz\tfail\n\n\tpopal\n/*\n *                                sp₂                        %sp = INI_SP\n *                                 ↓                               ↓\n * ┌───┬───┬───┬───┬───┬───┬───┬───┬───────┬───────┬───────┬───────┐\n * │M₁₆│M₁₅│M₁₄│sp₂│M₁₃│M₁₂│M₁₁│M₁₀│MAGIC4 │MAGIC3 │MAGIC2 │MAGIC1 │\n * └───┴───┴───┴───┴───┴───┴───┴───┴───────┴───────┴───────┴───────┘\n *  └─────┘ └─────┘ └─────┘          %ebx    %edx    %ecx    %eax\n *   %edi    %esi    %ebp\n */\n\n\tcmp\t$MAGIC1,%eax\n\tjnz\tfail\n\tcmp\t$MAGIC2,%ecx\n\tjnz\tfail\n\tcmp\t$MAGIC3,%edx\n\tjnz\tfail\n\tcmp\t$MAGIC4,%ebx\n\tjnz\tfail\n\tcmp\t$INI_ESP,%esp\n\tjnz\tfail\n\tcmp\t$SMUSH(MAGIC12, MAGIC13),%ebp\n\tjnz\tfail\n\tcmp\t$SMUSH(INI_SP - 16, MAGIC14),%esi\n\tjnz\tfail\n\tcmp\t$SMUSH(MAGIC15, MAGIC16),%edi\n\tjnz\tfail\n\n#define GDT_LEGACY_CODE\t8\n#define GDT_LEGACY_DATA\t16\n\n\tcli\n\tlgdtl\tgood_gdtr\n\tmov\t%cr0,%eax\n\tor\t$1,%al\n\tmov\t%eax,%cr0\n\tljmpw\t$GDT_LEGACY_CODE,$2f\n\nfail:\n\tint3\n\thlt\n\tjmp\tfail\n\n\t.balign\t8\nbad_idt:\n\t.quad\t0\n\n\t.section .text,\"ax\",@progbits\n\n\t.code32\n\n#define PM_ESP\t\t0x00020004\t// in 32-bit mode, try starting with\n\t\t\t\t\t// a value of %esp that will force\n\t\t\t\t\t// a carry/borrow in the high half\n\t\t\t\t\t// when we push or pop stuff\n\n2:\tmov\t$GDT_LEGACY_DATA,%ax\n\tmov\t%ax,%ds\n\tmov\t%ax,%es\n\tmov\t%ax,%ss\n\tmov\t$PM_ESP,%esp\n\n#define MAGIC17\t\t0xcd2814e8\n#define MAGIC18\t\t0xb7912036\n#define MAGIC19\t\t0xf98a2750\n#define MAGIC20\t\t0x1f6574af\n#define MAGIC21\t\t0xbb4a9d2a\n#define MAGIC22\t\t0x9a86ec5a\n#define MAGIC23\t\t0x33662e67\n\n\tmov\t$MAGIC17,%eax\n\tmov\t$MAGIC18,%ecx\n\tmov\t$MAGIC19,%edx\n\tmov\t$MAGIC20,%ebx\n\tmov\t$MAGIC21,%ebp\n\tmov\t$MAGIC22,%esi\n\tmov\t$MAGIC23,%edi\n\tpushal\n\tcmp\t$PM_ESP-32,%esp\n\tjnz\tfail\n\n#define MAGIC24\t\t0xad707a8a\n\n\tmov\t$MAGIC24,%edi\n\taddr16 popaw\t\t\t// `addr16' (0x67) should be ignored\n/*\n *                             now %esp                         PM_ESP\n *                                 ↓                               ↓\n * ┌───┬───┬───┬───┬───┬───┬───┬───┬───────┬───────┬───────┬───────┐\n * │MAGIC23│MAGIC22│MAGIC21│PM_ESP │MAGIC20│MAGIC19│MAGIC18│MAGIC17│\n * └───┴───┴───┴───┴───┴───┴───┴───┴───────┴───────┴───────┴───────┘\n *  %di %si %bp     %bx %dx %cx %ax\n */\n\n\tcmpw\t$(MAGIC22 >> 16),-10(%esp)\n\tjnz\tfail\n\tcmp\t$HL(MAGIC17, PM_ESP >> 16),%eax\n\tjnz\tfail\n\tcmp\t$HL(MAGIC18, PM_ESP),%ecx\n\tjnz\tfail\n\tcmp\t$HL(MAGIC19, MAGIC21 >> 16),%edx\n\tjnz\tfail\n\tcmp\t$HL(MAGIC20, MAGIC21),%ebx\n\tjnz\tfail\n\tcmp\t$PM_ESP-16,%esp\n\tjnz\tfail\n\tcmp\t$HL(MAGIC21, MAGIC22),%ebp\n\tjnz\tfail\n\tcmp\t$HL(MAGIC22, MAGIC23 >> 16),%esi\n\tjnz\tfail\n\tcmp\t$HL(MAGIC24, MAGIC23),%edi\n\tjnz\tfail\n\n#define MAGIC25\t\t0x205de5bd\n\n\tmov\t$MAGIC25,%eax\n\tpopaw\n/*\n *                                                             now %esp =\n *                                                              PM_ESP\n *                                                                 ↓\n * ┌───────┬───────┬───────┬───────┬───┬───┬───┬───┬───┬───┬───┬───┐\n * │MAGIC23│MAGIC22│MAGIC21│PM_ESP │MAGIC20│MAGIC19│MAGIC18│MAGIC17│\n * └───────┴───────┴───────┴───────┴───┴───┴───┴───┴───┴───┴───┴───┘\n *                                  %di %si %bp     %bx %dx %cx %ax\n */\n\tcmpw\t$(MAGIC19 >> 16),-10(%esp)\n\tjnz\tfail\n\tcmp\t$HL(MAGIC25, MAGIC17 >> 16),%eax\n\tjnz\tfail\n\tcmp\t$HL(MAGIC18, MAGIC17),%ecx\n\tjnz\tfail\n\tcmp\t$HL(MAGIC19, MAGIC18 >> 16),%edx\n\tjnz\tfail\n\tcmp\t$HL(MAGIC20, MAGIC18),%ebx\n\tjnz\tfail\n\tcmp\t$PM_ESP,%esp\n\tjnz\tfail\n\tcmp\t$HL(MAGIC21, MAGIC19),%ebp\n\tjnz\tfail\n\tcmp\t$HL(MAGIC22, MAGIC20 >> 16),%esi\n\tjnz\tfail\n\tcmp\t$HL(MAGIC24, MAGIC20),%edi\n\tjnz\tfail\n\n\tcli\t\t\t\t// tests passed\n\txor\t%edi,%edi\n\tlidt\tbad_idt\n\tmov\t$231,%eax\n\tsyscall\t\t\t\t// this will triple fault on a real PC\n\n\t.section .rodata,\"a\",@progbits\n\ngood_gdtr:\n\t.short\tgood_gdt_end-good_gdt-1\n\t.long\tgood_gdt\n\n\t.balign\t8\n\ngood_gdt:\n.quad\t0b0000000000000000000000000000000000000000000000000000000000000000 # 0\n.quad\t0b0000000011001111100110100000000000000000000000001111111111111111 # 8\n.quad\t0b0000000011001111100100100000000000000000000000001111111111111111 #16\ngood_gdt_end:\n"
  },
  {
    "path": "test/metal/ssemov.S",
    "content": "#include \"config.h\"\n#include \"test/metal/mac.inc\"\n\n\t.section .head,\"ax\",@progbits\n\t.code16\n.globl\t_start\n_start:\n\n//\tsse moves in bare metal mode\n//\tmake -j8 o//blink o//test/metal/ssemov.bin\n//\to//blink/blinkenlights -r o//test/metal/ssemov.bin\n\n#define CR0_MP\t\t(1<<1)\n#define CR0_EM\t\t(1<<2)\n#define CR4_OSFXSR\t(1<<9)\n#define CR4_OSXMMEXCPT\t(1<<10)\n\n\t.load16\n\n\t.test\t\"enable sse2\"\n\txor\t%eax,%eax\n\tinc\t%ax\n\tcpuid\n\ttest\t$1<<26,%edx\t\t// test for sse2 capability\n\t.ne\n\tmov\t%cr0,%eax\t\t// enable sse\n\tand\t$~CR0_EM,%al\n\tor\t$CR0_MP,%al\n\tmov\t%eax,%cr0\n\tmov\t%cr4,%eax\n\tor\t$CR4_OSFXSR|CR4_OSXMMEXCPT,%ax\n\tmov\t%eax,%cr4\n\n\t.test\t\"sse mov unaligned\"\n\tand\t$-16,%sp\n\tsub\t$17,%sp\n\tmovdqu\tonetwo,%xmm0\n\tmovdqu\t%xmm0,%xmm0\n\tmovdqu\t%xmm0,(%esp)\n\tmov\t(%esp),%eax\n\tmov\t4(%esp),%esi\n\tmov\t8(%esp),%edx\n\tmov\t12(%esp),%edi\n\tmov\t$0x11111111,%ecx\n\tcmp\t%ecx,%eax\n\t.e\n\tcmp\t%ecx,%esi\n\t.e\n\tmov\t$0x22222222,%ecx\n\tcmp\t%ecx,%edx\n\t.e\n\tcmp\t%ecx,%edi\n\t.e\n\n\t.test\t\"sse mov aligned\"\n\tand\t$-16,%sp\n\tsub\t$16,%sp\n\tmovdqa\tonetwo,%xmm7\n\tmovdqa\t%xmm7,%xmm6\n\tmovdqa\t%xmm6,(%esp)\n\tmov\t(%esp),%eax\n\tmov\t4(%esp),%esi\n\tmov\t8(%esp),%edx\n\tmov\t12(%esp),%edi\n\tmov\t$0x11111111,%ecx\n\tcmp\t%ecx,%eax\n\t.e\n\tcmp\t%ecx,%esi\n\t.e\n\tmov\t$0x22222222,%ecx\n\tcmp\t%ecx,%edx\n\t.e\n\tcmp\t%ecx,%edi\n\t.e\n\n\t.test\t\"sse mov unaligned #2\"\n\tand\t$-16,%sp\n\tsub\t$16,%sp\n\tmovups\tonetwo,%xmm7\n\tmovups\t%xmm7,%xmm6\n\tmovups\t%xmm6,(%esp)\n\tmov\t(%esp),%eax\n\tmov\t4(%esp),%esi\n\tmov\t8(%esp),%edx\n\tmov\t12(%esp),%edi\n\tmov\t$0x11111111,%ecx\n\tcmp\t%ecx,%eax\n\t.e\n\tcmp\t%ecx,%esi\n\t.e\n\tmov\t$0x22222222,%ecx\n\tcmp\t%ecx,%edx\n\t.e\n\tcmp\t%ecx,%edi\n\t.e\n\tjmp\t2f\n\n\t.section .text,\"ax\",@progbits\n\n2:\n#ifndef DISABLE_ROM\n\t.test\t\"sse mov unaligned into ROM area\"\n\tmov\t$0xf000,%ax\n\tmov\t%ax,%es\n\tmov\t$0xfff0-1,%bx\n\tmovdqu\t%es:(%bx),%xmm3\n\tmovdqu\t%xmm3,saverom\n\tmov\t%es:16(%bx),%al\n\tmov\t%al,saverom+16\n\tmovdqu\tonetwo,%xmm1\n\tmovdqu\t%xmm1,%xmm2\n\tmovdqu\t%xmm2,%es:(%bx)\n\tmovdqu\t%es:(%bx),%xmm4\n\tpcmpeqb\t%xmm4,%xmm1\n\tpmovmskb %xmm1,%eax\n\tinc\t%ax\n\t.ne\n\tmovdqu\t%es:(%bx),%xmm5\n\tpcmpeqb\t%xmm3,%xmm5\n\tpmovmskb %xmm5,%eax\n\tinc\t%ax\n\t.e\n\tmov\t%es:(%bx),%eax\n\tcmp\tsaverom,%eax\n\t.e\n\tmov\t%es:4(%bx),%eax\n\tcmp\tsaverom+4,%eax\n\t.e\n\tmov\t%es:8(%bx),%eax\n\tcmp\tsaverom+8,%eax\n\t.e\n\tmov\t%es:12(%bx),%eax\n\tcmp\tsaverom+12,%eax\n\t.e\n\n\t.test\t\"sse mov aligned into ROM area\"\n\tinc\t%bx\n\tmovdqa\tonetwo,%xmm1\n\tmovdqa\t%xmm1,%xmm2\n\tmovdqa\t%xmm2,%es:(%bx)\n\tpcmpeqb\t%es:(%bx),%xmm1\n\tpmovmskb %xmm1,%eax\n\tinc\t%ax\n\t.ne\n\tmovdqu\tsaverom+1,%xmm6\n\tpcmpeqb\t%es:(%bx),%xmm6\n\tpmovmskb %xmm6,%eax\n\tinc\t%ax\n\t.e\n\tmov\t%es:(%bx),%eax\n\tcmp\tsaverom+1,%eax\n\t.e\n\tmov\t%es:4(%bx),%eax\n\tcmp\tsaverom+1+4,%eax\n\t.e\n\tmov\t%es:8(%bx),%eax\n\tcmp\tsaverom+1+8,%eax\n\t.e\n\tmov\t%es:12(%bx),%eax\n\tcmp\tsaverom+1+12,%eax\n\t.e\n#endif /* !DISABLE_ROM */\n\n\"test succeeded\":\n\t.exit\n\n\t.align\t16\nonetwo:\t.quad\t0x1111111111111111,0x2222222222222222\n\n.lcomm\tsaverom,17\n"
  },
  {
    "path": "test/metal/string.S",
    "content": "#include \"config.h\"\n\n\t.section .head,\"ax\",@progbits\n\t.code16\n\n.globl\t_start\n_start:\n\n//\tmake -j8 o//blink o//test/metal/string.bin\n//\to//blink/blinkenlights -r o//test/metal/string.bin\n\n0:\tljmpw\t$0,$1f\n\nehead\t= 0b+0x200\n\n1:\txor\t%ax,%ax\n\tmov\t%ax,%ss\n\tmov\t$ehead+0x1000,%sp\n\n\torl\t$-1,%ss:ehead\t\t// place something that is not the\n\t\t\t\t\t// same as our first instruction just\n\t\t\t\t\t// after our loaded boot sector\n\n\tmov\t$0x41a0/0x10,%ax\n\tmov\t%ax,%ds\n\tsub\t$0x200/0x10,%ax\n\tmov\t%ax,%es\n\tmov\t$ehead-1-0x41a0,%si\t// try to make 9 copies of our own\n\tmov\t%si,%di\t\t\t// code, by copying backwards\n\tmov\t$9*0x200,%cx\t\t// starting from 0x7c00+0x200-1\n\tstd\n\trep movsb\n\n\tmov\t$0x1250/0x10,%ax\t// check there are now exactly 10\n\tmov\t%ax,%ds\t\t\t// copies of the same boot code\n\tmov\t$0x27e0/0x10,%ax\n\tmov\t%ax,%es\n\tmov\t$-1,%cx\n\tmov\t$0b-0x1250-9*0x200,%si\n\tmov\t$0b-0x27e0-8*0x200,%di\n\tcld\n\trepe cmpsw\n\tje\tfail\n\tcmp\t$-2-9*0x200/2,%cx\n\tjne\tfail\n\n#ifndef DISABLE_ROM\n\tmov\t$0x3370/0x10,%ax\n\tmov\t%ax,%ds\n\tmov\t$0xf000+0xe920/0x10,%ax\n\tmov\t%ax,%es\n\tmov\t$0xfff0-0xe920,%di\n\n\tmov\t%es:(%di),%eax\t\t// make a copy of the CPU \"power on\n\tmov\t%eax,good_poweron-0x3370 // restart\" ROM code at 0xf000:0xfff0\n\tmov\t%es:4(%di),%eax\n\tmov\t%eax,good_poweron+4-0x3370\n\tmov\t%es:8(%di),%eax\n\tmov\t%eax,good_poweron+8-0x3370\n\tmov\t%es:12(%di),%eax\n\tmov\t%eax,good_poweron+12-0x3370\n\n\tmov\t$16,%cx\t\t\t// try to overwrite 0xf000:0xfff0\n\tmov\t$bad_poweron-0x3370,%si\n\tcld\n\trep movsb\n\n\tmov\t$0xf000+0xaa30/0x10,%ax\t// check that the ROM is unchanged\n\tmov\t%ax,%ds\n\tmov\t$0x7340/0x10,%ax\n\tmov\t%ax,%es\n\tmov\t$0xfff0-0xaa30,%si\n\tmov\t$good_poweron-0x7340,%di\n\tmov\t$4,%cl\n\trepe cmpsl\n\tjne\tfail\n\n\tdec\t%si\t\t\t// also check that the ROM does not\n\tdec\t%si\t\t\t// match the bad \"power on\" code we\n\tmov\t$8,%cl\t\t\t// tried to fill it with\n\tmov\t$bad_poweron+(16-2)-0x7340,%di\n\tstd\n\tcmp\t%ax,%ax\t\t\t// force ZF = 1 here as an extra test\n\trepe cmpsw\n\tje\tfail\n\n\tmov\t$0x06e0/0x10,%ax\t// try to overwrite 0xf000:0xfff0,\n\tmov\t%ax,%ds\t\t\t// but backwards, shortword-wise,\n\tmov\t$0xf000+0xe470/0x10,%ax\t// & unaligned\n\tmov\t%ax,%es\n\tmov\t$0xfffd-0xe470,%di\n\tmov\t$bad_poweron+14-0x06e0,%si\n\tmov\t$7,%cx\n\tstd\n\trep movsw\n\n\tmov\t$0xf000+0xb400/0x10,%ax\t// check again that the ROM is\n\tmov\t%ax,%ds\t\t\t// unchanged\n\tmov\t$0x1c90/0x10,%ax\n\tmov\t%ax,%es\n\tmov\t%es:good_poweron-0x1c90,%eax\n\tcmp\t0xfff0-0xb400,%eax\n\tjnz\tfail\n\tmov\t%es:good_poweron+4-0x1c90,%eax\n\tcmp\t0xfff4-0xb400,%eax\n\tjnz\tfail\n\tmov\t%es:good_poweron+8-0x1c90,%eax\n\tcmp\t0xfff8-0xb400,%eax\n\tjnz\tfail\n\tmov\t%es:good_poweron+12-0x1c90,%eax\n\tcmp\t0xfffc-0xb400,%eax\n\tjnz\tfail\n#endif /* !DISABLE_ROM */\n\n\tcli\t\t\t\t// test succeeded\n\txor\t%edi,%edi\n\tmov\t%di,%ds\n\tlidt\tbad_idt\n\tmov\t$231,%eax\n\tsyscall\t\t\t\t// this will triple fault on a real PC\n\nfail:\n\tud2\n\thlt\n\tjmp\tfail\n\n\t.balign\t8\nbad_idt:\n\t.quad\t0\nbad_poweron:\n\t.quad\t0x31bc50ea79cfccb5,0x11ade0c823d42d59\ngood_poweron:\n\t.skip\t16\n"
  },
  {
    "path": "test/metalrom/hello.S",
    "content": "#include \"blink/biosrom.h\"\n\n.macro\thvcall\tcallno:req\n .if\t(\\callno) == 0\n\t.byte\t0x0F\n\t.byte\t0xFF\n\t.byte\t0077\n .else\n   .if\t(\\callno) >= -0x80 && (\\callno) <= 0x7f\n\t.byte\t0x0F\n\t.byte\t0xFF\n\t.byte\t0177\n\t.byte\t(\\callno)\n   .else\n\taddr16\n\t.byte\t0x0F\n\t.byte\t0xFF\n\t.byte\t0277\n\t.short\t(\\callno)\n   .endif\n .endif\n.endm\n\n\t.section .text,\"ax\",@progbits\n\t.code16\n\n//\tmake -j8 o//blink o//test/metalrom/hello.bin\n//\to//blink/blinkenlights -r -B o//test/metalrom/hello.bin \\\n//\t  third_party/sectorlisp/sectorlisp-friendly.bin\n\n_start_1:\n\tmov\t%cs,%ax\n\tmov\t%ax,%ds\n\n\tcmp\t$kBiosSeg,%ax\t\t// test that %cs is sane\n\tjnz\tfail\n\n\tcmp\t$-4,%sp\t\t\t// test that the stack pointer is sane\n\tja\tfail\n\n\tcall\t1f\t\t\t// test that %ip is sane\n1:\n\tpop\t%ax\n\tcmp\t$1b,%ax\n\tjnz\tfail\n\n\tpop\t%ax\t\t\t// test that we arrived here from\n\tpop\t%dx\t\t\t// the call near linear address 0xFFFF0\n\tmovzwl\t%ax,%eax\t\t// (per visible value of caller %cs)\n\tmovzwl\t%dx,%edx\n\tshl\t$4,%edx\n\tadd\t%edx,%eax\n\tcmp\t$kBiosBase+9f,%eax\n\tjnz\tfail\n\n\tmov\t$0x40000000,%eax\t// test that we are running under a\n\tcltd\t\t\t\t// Blink VM\n\txor\t%ebx,%ebx\n\txor\t%ecx,%ecx\n\tcpuid\n\txor\t$0x322809ae,%ebx\n\tcmp\t$('G' | 'e' << 8 | 'n' << 16 | 'u' << 24) ^ 0x322809ae,%ebx\n\tjnz\tfail\n\txor\t$0xd1b18562,%ecx\n\tcmp\t$('i' | 'n' << 8 | 'e' << 16 | 'B' << 24) ^ 0xd1b18562,%ecx\n\tjnz\tfail\n\txor\t$0x7421628a,%edx\n\tcmp\t$('l' | 'i' << 8 | 'n' << 16 | 'k' << 24) ^ 0x7421628a,%edx\n\tjnz\tfail\n\n\tmov\t$hello,%si\t\t// say hello\n\tcld\n2:\n\tlodsb\n\ttest\t%al,%al\n\tjz\t3f\n\tout\t%al,$0xE9\n\tmov\t$0x0e,%ah\n\tmov\t$0x0007,%bx\n\thvcall\t0x10\n\tjmp\t2b\n\n3:\n\tcli\t\t\t\t// report success\n\tlidtw\t%cs:bad_idtr\n\txor\t%edi,%edi\n\tmov\t$231,%eax\n\tsyscall\t\t\t\t// this will triple fault on a real PC\n\nfail:\n\tcli\n\thlt\n\tjmp\tfail\n\n\t.section .rodata,\"a\",@progbits\n\n\t.balign\t8\nbad_idtr:\n\t.quad\t0\nhello:\n\t.asciz\t\"Hello world!\\r\\n\"\n\n\t.section .fixedaddr.0xfff0,\"ax\",@progbits\n.globl\t_start\n_start:\n\tcli\n\txor\t%esp,%esp\n\tmov\t%sp,%ss\n\tlcallw\t$kBiosSeg,$_start_1\n9:\n"
  },
  {
    "path": "test/metalrom/metalrom.lds",
    "content": "ENTRY(_start)\nOUTPUT_FORMAT(binary)\n\nSECTIONS {\n  .text (0xfff0 - ALIGN(_edata - _base, 0x10)) : {\n    _base = .;\n    *(.text .text.*)\n    . = ALIGN(0x10);\n    *(.rodata .rodata.*)\n    . = ALIGN(0x10);\n    *(.data .data.*)\n    _edata = .;\n  }\n\n  .fixedaddr.0xfff0 0xfff0 : {\n    *(.fixedaddr.0xfff0 .fixedaddr.0xfff0.*)\n  }\n\n  .fixedaddr.0xffff 0xffff : {\n    BYTE(0)\n  }\n\n  /DISCARD/ : {\n    *(.*)\n  }\n}\n"
  },
  {
    "path": "test/metalrom/metalrom.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nTEST_METALROM_FILES := $(wildcard test/metalrom/*)\nTEST_METALROM_SRCS = $(filter %.S,$(TEST_METALROM_FILES))\nTEST_METALROM_HDRS = $(filter %.h,$(TEST_METALROM_FILES))\nTEST_METALROM_OBJS = $(TEST_METALROM_SRCS:%.S=o/$(MODE)/x86_64-gcc49/%.o)\nTEST_METALROM_BINS = $(TEST_METALROM_SRCS:%.S=o/$(MODE)/%.bin)\nTEST_METALROM_CHECKS = $(TEST_METALROM_BINS:%=%.ok)\n\nTEST_METALROM_LINK =\t\t\t\t\t\t\t\t\\\n\t\t$(VM)\t\t\t\t\t\t\t\t\\\n\t\to/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-ld.bfd\t\\\n\t\t-T test/metalrom/metalrom.lds\t\t\t\t\t\\\n\t\t-static\t\t\t\t\t\t\t\t\\\n\t\t$<\t\t\t\t\t\t\t\t\\\n\t\t-o $@\n\n.PRECIOUS: o/$(MODE)/test/metalrom/%.bin\no/$(MODE)/test/metalrom/%.bin:\t\t\t\t\t\t\t\\\n\t\to/$(MODE)/x86_64-gcc49/test/metalrom/%.o\t\t\t\\\n\t\to/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc\t\\\n\t\ttest/metalrom/metalrom.lds\t\t\t\t\t\\\n\t\t$(VM)\n\t@mkdir -p $(@D)\n\t$(TEST_METALROM_LINK)\n\n$(TEST_METALROM_OBJS):\t\t\t\t\t\t\t\\\n\t\ttest/metalrom/metalrom.mk\t\t\t\t\\\n\t\t$(TEST_METALROM_HDRS)\t\t\t\t\t\\\n\t\t$(BLINK_HDRS)\n\no/$(MODE)/test/metalrom/%.bin.ok:\t\t\t\t\t\\\n\t\to/$(MODE)/test/metalrom/%.bin\t\t\t\t\\\n\t\to/$(MODE)/blink/blinkenlights\t\t\t\t\\\n\t\tthird_party/sectorlisp/sectorlisp-friendly.bin\n\t@mkdir -p $(@D)\n\to/$(MODE)/blink/blinkenlights\t\t\t\t\t\\\n\t\t-r\t\t\t\t\t\t\t\\\n\t\t-t\t\t\t\t\t\t\t\\\n\t\t-B $<\t\t\t\t\t\t\t\\\n\t\tthird_party/sectorlisp/sectorlisp-friendly.bin\n\t@touch $@\n\no/$(MODE)/test/metalrom:\t\t\t\t\t\t\t\\\n\t$(TEST_METALROM_CHECKS)\n"
  },
  {
    "path": "test/test.h",
    "content": "#ifndef TEST_TEST_H_\n#define TEST_TEST_H_\n#include <ctype.h>\n#include <errno.h>\n#include <inttypes.h>\n#include <math.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#include \"blink/machine.h\"\n\n#define TEST(GROUP, NAME)                                             \\\n  void GROUP##_##NAME(void);                                          \\\n  __attribute__((__constructor__)) void GROUP##_##NAME##_init(void) { \\\n    static struct Test test;                                          \\\n    test.func = GROUP##_##NAME;                                       \\\n    test.next = g_testing.tests;                                      \\\n    g_testing.tests = &test;                                          \\\n  }                                                                   \\\n  void GROUP##_##NAME(void)\n\n#define ASSERT_EQ(WANT, GOT, ...)                                 \\\n  AssertionInt64(AssertEq, true, \"ASSERT_EQ\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n#define EXPECT_EQ(WANT, GOT, ...)                                  \\\n  AssertionInt64(AssertEq, false, \"EXPECT_EQ\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n\n#define ASSERT_NE(WANT, GOT, ...)                                 \\\n  AssertionInt64(AssertNe, true, \"ASSERT_NE\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n#define EXPECT_NE(WANT, GOT, ...)                                  \\\n  AssertionInt64(AssertNe, false, \"EXPECT_NE\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n\n#define ASSERT_LE(WANT, GOT, ...)                                 \\\n  AssertionInt64(AssertLe, true, \"ASSERT_LE\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n#define EXPECT_LE(WANT, GOT, ...)                                  \\\n  AssertionInt64(AssertLe, false, \"EXPECT_LE\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n\n#define ASSERT_GE(WANT, GOT, ...)                                 \\\n  AssertionInt64(AssertGe, true, \"ASSERT_GE\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n#define EXPECT_GE(WANT, GOT, ...)                                  \\\n  AssertionInt64(AssertGe, false, \"EXPECT_GE\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n\n#define ASSERT_LT(WANT, GOT, ...)                                 \\\n  AssertionInt64(AssertLt, true, \"ASSERT_LT\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n#define EXPECT_LT(WANT, GOT, ...)                                  \\\n  AssertionInt64(AssertLt, false, \"EXPECT_LT\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n\n#define ASSERT_GT(WANT, GOT, ...)                                 \\\n  AssertionInt64(AssertGt, true, \"ASSERT_GT\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n#define EXPECT_GT(WANT, GOT, ...)                                  \\\n  AssertionInt64(AssertGt, false, \"EXPECT_GT\", __FILE__, __LINE__, \\\n                 __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n\n#define ASSERT_STREQ(WANT, GOT, ...)                                  \\\n  AssertionStr(AssertStreq, true, \"ASSERT_STREQ\", __FILE__, __LINE__, \\\n               __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n#define EXPECT_STREQ(WANT, GOT, ...)                                   \\\n  AssertionStr(AssertStreq, false, \"EXPECT_STREQ\", __FILE__, __LINE__, \\\n               __FUNCTION__, WANT, #WANT, GOT, #GOT, \" \" __VA_ARGS__)\n\n#define ASSERT_NOTNULL(GOT, ...)                                       \\\n  AssertionInt64(AssertNe, true, \"ASSERT_NOTNULL\", __FILE__, __LINE__, \\\n                 __FUNCTION__, 0, \"NULL\", (i64)(intptr_t)(GOT), #GOT,  \\\n                 \" \" __VA_ARGS__)\n#define EXPECT_NOTNULL(GOT, ...)                                        \\\n  AssertionInt64(AssertNe, false, \"EXPECT_NOTNULL\", __FILE__, __LINE__, \\\n                 __FUNCTION__, 0, \"NULL\", (i64)(intptr_t)(GOT), #GOT,   \\\n                 \" \" __VA_ARGS__)\n\n#define ASSERT_TRUE(GOT, ...)                                            \\\n  AssertionBool(true, true, __FILE__, __LINE__, __FUNCTION__, GOT, #GOT, \\\n                \" \" __VA_ARGS__)\n#define EXPECT_TRUE(GOT, ...)                                             \\\n  AssertionBool(true, false, __FILE__, __LINE__, __FUNCTION__, GOT, #GOT, \\\n                \" \" __VA_ARGS__)\n\n#define ASSERT_FALSE(GOT, ...)                                            \\\n  AssertionBool(false, true, __FILE__, __LINE__, __FUNCTION__, GOT, #GOT, \\\n                \" \" __VA_ARGS__)\n#define EXPECT_FALSE(GOT, ...)                                             \\\n  AssertionBool(false, false, __FILE__, __LINE__, __FUNCTION__, GOT, #GOT, \\\n                \" \" __VA_ARGS__)\n\n#define ASSERT_LDBL_EQ(WANT, GOT, ...)                                      \\\n  do {                                                                      \\\n    long double Got, Want;                                                  \\\n    Got = GOT;                                                              \\\n    Want = WANT;                                                            \\\n    if (isnan(Got) || isnan(Want) || fabsl(Got - Want) > 0.00000001) {      \\\n      fprintf(stderr, \"error:%s:%d: %s() ASSERT_LDBL_EQ failed:\", __FILE__, \\\n              __LINE__, __FUNCTION__);                                      \\\n      fprintf(stderr, \" \" __VA_ARGS__);                                     \\\n      fprintf(stderr,                                                       \\\n              \"\\n\\twant %Lg (%s)\\n\"                                         \\\n              \"\\tgot  %Lg (%s)\\n\",                                          \\\n              Want, #WANT, Got, #GOT);                                      \\\n      exit(1);                                                              \\\n    }                                                                       \\\n  } while (0)\n\n#define SPAWN(METHOD)                     \\\n  {                                       \\\n    int child, _failed = g_testing.fails; \\\n    ASSERT_NE(-1, (child = METHOD()));    \\\n    if (!child) {\n\n#define EXITS(CODE) \\\n  PARENT()          \\\n  WAIT(Exit, CODE)\n\n#define TERMS(SIG) \\\n  PARENT()         \\\n  WAIT(Term, SIG)\n\n#define PARENT()                                      \\\n  _Exit(MAX(0, MIN(255, g_testing.fails - _failed))); \\\n  }\n\n#define WAIT(KIND, CODE)                                 \\\n  WaitFor##KIND(__FILE__, __LINE__, #CODE, CODE, child); \\\n  }\n\nstruct Test {\n  struct Test *next;\n  void (*func)(void);\n};\n\nstruct Tests {\n  int fails;\n  struct Test *tests;\n} g_testing;\n\nstruct Garbage {\n  struct Garbage *next;\n  void *ptr;\n} * g_garbage;\n\nvoid SetUp(void);\nvoid TearDown(void);\n\nvoid *Gc(void *ptr) {\n  struct Garbage *g;\n  g = (struct Garbage *)malloc(sizeof(struct Garbage));\n  g->ptr = ptr;\n  g->next = g_garbage;\n  g_garbage = g;\n  return ptr;\n}\n\nvoid Collect(struct Garbage *g) {\n  if (!g) return;\n  Collect(g->next);\n  free(g->ptr);\n  free(g);\n}\n\nchar *Format(const char *Format, ...) {\n  char *s;\n  va_list va;\n  s = (char *)Gc(malloc(64));\n  va_start(va, Format);\n  vsnprintf(s, 64, Format, va);\n  va_end(va);\n  return s;\n}\n\nstatic void AssertionInt64(bool pred(int64_t, int64_t), bool isfatal,\n                           const char *test, const char *file, int line,\n                           const char *func, int64_t want, const char *wantstr,\n                           int64_t got, const char *gotstr, const char *fmt,\n                           ...) {\n  va_list va;\n  if (!pred(want, got)) {\n    int err = errno;\n    fprintf(stderr, \"error:%s:%d: %s() %s failed:\", file, line, func, test);\n    va_start(va, fmt);\n    vfprintf(stderr, fmt, va);\n    va_end(va);\n    fprintf(stderr,\n            \"\\n\\twant %\" PRId64 \" (%#\" PRIx64 \") %s\\n\"\n            \"\\tgot  %\" PRId64 \" (%#\" PRIx64 \") %s\\n\"\n            \"\\terrno = %d (%s)\\n\",\n            want, want, wantstr, got, got, gotstr, err, strerror(err));\n    if (isfatal) {\n      exit(1);\n    } else {\n      ++g_testing.fails;\n    }\n  }\n}\n\nstatic void AssertionStr(bool pred(const char *, const char *), bool isfatal,\n                         const char *test, const char *file, int line,\n                         const char *func, const char *want,\n                         const char *wantstr, const char *got,\n                         const char *gotstr, const char *fmt, ...) {\n  va_list va;\n  char *gotcopy;\n  char *wantcopy;\n  if (!pred(want, got)) {\n    fprintf(stderr, \"error:%s:%d: %s() %s failed:\", file, line, func, test);\n    va_start(va, fmt);\n    vfprintf(stderr, fmt, va);\n    va_end(va);\n    // we should ideally display an escaped version, but this should be\n    // sufficient to not lose one's mind, when the strings are the same\n    // but one of them contains invisible ansi escape sequences.\n    gotcopy = strdup(got);\n    wantcopy = strdup(want);\n    for (long i = 0; gotcopy[i]; ++i) {\n      if (!isprint(gotcopy[i])) {\n        gotcopy[i] = '?';\n      }\n    }\n    for (long i = 0; wantcopy[i]; ++i) {\n      if (!isprint(wantcopy[i])) {\n        wantcopy[i] = '?';\n      }\n    }\n    fprintf(stderr,\n            \"\\n\"\n            \"\\twant %s (%s)\\n\"\n            \"\\tgot  %s (%s)\\n\",\n            wantcopy, wantstr, gotcopy, gotstr);\n    free(gotcopy);\n    free(wantcopy);\n    if (isfatal) {\n      exit(1);\n    } else {\n      ++g_testing.fails;\n    }\n  }\n}\n\nstatic void AssertionBool(bool need, bool isfatal, const char *file, int line,\n                          const char *func, bool got, const char *gotstr,\n                          const char *fmt, ...) {\n  va_list va;\n  if (got != need) {\n    fprintf(stderr, \"error:%s:%d: %s() ASSERT_%s failed:\", file, line, func,\n            need ? \"TRUE\" : \"FALSE\");\n    va_start(va, fmt);\n    vfprintf(stderr, fmt, va);\n    va_end(va);\n    fprintf(stderr, \"\\n\\t%s\\n\", gotstr);\n    if (isfatal) {\n      exit(1);\n    } else {\n      ++g_testing.fails;\n    }\n  }\n}\n\nstatic bool AssertStreq(const char *want, const char *got) {\n  return !strcmp(want, got);\n}\n\nstatic bool AssertEq(int64_t want, int64_t got) {\n  return want == got;\n}\n\nstatic bool AssertNe(int64_t want, int64_t got) {\n  return want != got;\n}\n\nstatic bool AssertLe(int64_t want, int64_t got) {\n  return want <= got;\n}\n\nstatic bool AssertGe(int64_t want, int64_t got) {\n  return want >= got;\n}\n\nstatic bool AssertLt(int64_t want, int64_t got) {\n  return want < got;\n}\n\nstatic bool AssertGt(int64_t want, int64_t got) {\n  return want > got;\n}\n\nstatic void WaitForExit(const char *file, int line, const char *code, int rc,\n                        int pid) {\n  int ws;\n  char host[64];\n  ASSERT_NE(-1, wait(&ws));\n  if (WIFEXITED(ws)) {\n    if (WEXITSTATUS(ws) == rc) {\n      return;\n    }\n    fprintf(stderr,\n            \"%s:%d: test failed\\n\"\n            \"\\tEXITS(%s)\\n\"\n            \"\\t  want WEXITSTATUS(%d)\\n\"\n            \"\\t   got WEXITSTATUS(%d)\\n\",\n            file, line, code, rc, WEXITSTATUS(ws));\n  } else if (WIFSIGNALED(ws)) {\n    fprintf(stderr,\n            \"%s:%d: test failed\\n\"\n            \"\\tEXITS(%s)\\n\"\n            \"\\t  want _Exit(%d)\\n\"\n            \"\\t   got WTERMSIG(%s)\\n\",\n            file, line, code, rc, strsignal(WTERMSIG(ws)));\n  } else if (WIFSTOPPED(ws)) {\n    fprintf(stderr,\n            \"%s:%d: test failed\\n\"\n            \"\\tEXITS(%s)\\n\"\n            \"\\t  want _Exit(%d)\\n\"\n            \"\\t   got WSTOPSIG(%s)\\n\",\n            file, line, code, rc, strsignal(WSTOPSIG(ws)));\n  } else {\n    fprintf(stderr,\n            \"%s:%d: test failed\\n\"\n            \"\\tEXITS(%s)\\n\"\n            \"\\t  want _Exit(%d)\\n\"\n            \"\\t   got ws=%#x\\n\",\n            file, line, code, rc, ws);\n  }\n  if (gethostname(host, sizeof(host))) {\n    strcpy(host, \"unknown\");\n  }\n  fprintf(stderr, \"\\t%s\\n\", host);\n  exit(1);\n}\n\nstatic void WaitForTerm(const char *file, int line, const char *code, int sig,\n                        int pid) {\n  int ws;\n  char host[64];\n  ASSERT_NE(-1, waitpid(pid, &ws, 0));\n  if (WIFSIGNALED(ws)) {\n    if (WTERMSIG(ws) == sig) {\n      return;\n    }\n    fprintf(stderr,\n            \"%s:%d: test failed\\n\"\n            \"\\tTERMS(%s)\\n\"\n            \"\\t  want WTERMSIG(%s)\\n\"\n            \"\\t   got WTERMSIG(%s)\\n\",\n            file, line, code, strsignal(sig), strsignal(WTERMSIG(ws)));\n  } else if (WIFEXITED(ws)) {\n    fprintf(stderr,\n            \"%s:%d: test failed\\n\"\n            \"\\tTERMS(%s)\\n\"\n            \"\\t  want WTERMSIG(%s)\\n\"\n            \"\\t   got _Exit(%d)\\n\",\n            file, line, code, strsignal(sig), WEXITSTATUS(ws));\n  } else if (WIFSTOPPED(ws)) {\n    fprintf(stderr,\n            \"%s:%d: test failed\\n\"\n            \"\\tTERMS(%s)\\n\"\n            \"\\t  want WTERMSIG(%s)\\n\"\n            \"\\t   got WSTOPSIG(%s)\\n\",\n            file, line, code, strsignal(sig), strsignal(WSTOPSIG(ws)));\n  } else {\n    fprintf(stderr,\n            \"%s:%d: test failed\\n\"\n            \"\\tTERMS(%s)\\n\"\n            \"\\t  want WTERMSIG(%s)\\n\"\n            \"\\t   got ws=%#x\\n\",\n            file, line, code, strsignal(sig), ws);\n  }\n  if (gethostname(host, sizeof(host))) {\n    strcpy(host, \"unknown\");\n  }\n  fprintf(stderr, \"\\t%s\\n\", host);\n  exit(1);\n}\n\n_Noreturn void TerminateSignal(struct Machine *m, int sig) {\n  abort();\n}\n\nint main(int argc, char *argv[]) {\n  struct Test *test;\n  for (test = g_testing.tests; test; test = test->next) {\n    SetUp();\n    test->func();\n    TearDown();\n    Collect(g_garbage);\n  }\n  return g_testing.fails;\n}\n\n#endif /* TEST_TEST_H_ */\n"
  },
  {
    "path": "test/test.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nemulates = o/$(MODE)/$1.ok $(foreach ARCH,$(ARCHITECTURES),o/$(MODE)/$(ARCH)/$1.emulates)\n\n# make -j8 o//test/alu\n# very time consuming tests of our core arithmetic ops\n# https://github.com/jart/cosmopolitan/blob/master/test/tool/build/lib/optest.c\n# https://github.com/jart/cosmopolitan/blob/master/test/tool/build/lib/alu_test.c\n# https://github.com/jart/cosmopolitan/blob/master/test/tool/build/lib/bsu_test.c\no/$(MODE)/test/alu:\t\t\t\t\t\t\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/alu_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/bsu_test.com)\n\t@mkdir -p $(@D)\n\t@touch $@\n\n# make -j8 o//test/sse\n# fast and fairly comprehensive tests for our simd instructions\n# https://github.com/jart/cosmopolitan/blob/master/test/libc/intrin/intrin_test.c\no/$(MODE)/test/sse:\t\t\t\t\t\t\t\t\\\n\t\t$(call emulates,third_party/cosmo/8/intrin_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/popcnt_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/pshuf_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/pmulhrsw_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/divmul_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/palignr_test.com)\n\t@mkdir -p $(@D)\n\t@touch $@\n\n# make -j8 o//test/lib\n# test some c libraries\no/$(MODE)/test/lib:\t\t\t\t\t\t\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/atoi_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/qsort_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/kprintf_test.com)\n\t@mkdir -p $(@D)\n\t@touch $@\n\n# make -j8 o//test/sys\n# test linux system call emulation\no/$(MODE)/test/sys:\t\t\t\t\t\t\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/renameat_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/clock_gettime_test.com)\t\\\n\t\t$(call emulates,third_party/cosmo/2/clock_getres_test.com)\t\\\n\t\t$(call emulates,third_party/cosmo/2/clock_nanosleep_test.com)\t\\\n\t\t$(call emulates,third_party/cosmo/2/access_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/chdir_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/closefrom_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/commandv_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/dirstream_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/dirname_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/clone_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/fileexists_test.com)\t\\\n\t\t$(call emulates,third_party/cosmo/2/getcwd_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/lseek_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/mkdir_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/makedirs_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/nanosleep_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/readlinkat_test.com)\t\\\n\t\t$(call emulates,third_party/cosmo/2/symlinkat_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/tls_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/tmpfile_test.com)\t\t\\\n\t\t$(call emulates,third_party/cosmo/2/xslurp_test.com)\n\t@mkdir -p $(@D)\n\t@touch $@\n\no/$(MODE)/%.runs: o/$(MODE)/%\n\t$<\n\t@touch $@\n\no/$(MODE)/i486/%.runs: o/$(MODE)/i486/% o/third_party/qemu/4/qemu-i386 $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-i386 $<\n\t@touch $@\no/$(MODE)/m68k/%.runs: o/$(MODE)/m68k/% o/third_party/qemu/4/qemu-m68k $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-m68k $<\n\t@touch $@\no/$(MODE)/x86_64/%.runs: o/$(MODE)/x86_64/% o/third_party/qemu/4/qemu-x86_64 $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-x86_64 -cpu core2duo $<\n\t@touch $@\no/$(MODE)/x86_64-gcc49/%.runs: o/$(MODE)/x86_64-gcc49/% o/third_party/qemu/4/qemu-x86_64 $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-x86_64 -cpu core2duo $<\n\t@touch $@\no/$(MODE)/arm/%.runs: o/$(MODE)/arm/% o/third_party/qemu/4/qemu-arm $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-arm $<\n\t@touch $@\no/$(MODE)/aarch64/%.runs: o/$(MODE)/aarch64/% o/third_party/qemu/4/qemu-aarch64 $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-aarch64 $<\n\t@touch $@\no/$(MODE)/riscv64/%.runs: o/$(MODE)/riscv64/% o/third_party/qemu/4/qemu-riscv64 $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-riscv64 $<\n\t@touch $@\no/$(MODE)/mips/%.runs: o/$(MODE)/mips/% o/third_party/qemu/4/qemu-mips $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-mips $<\n\t@touch $@\no/$(MODE)/mipsel/%.runs: o/$(MODE)/mipsel/% o/third_party/qemu/4/qemu-mipsel $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-mipsel $<\n\t@touch $@\no/$(MODE)/mips64/%.runs: o/$(MODE)/mips64/% o/third_party/qemu/4/qemu-mips64 $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-mips64 $<\n\t@touch $@\no/$(MODE)/mips64el/%.runs: o/$(MODE)/mips64el/% o/third_party/qemu/4/qemu-mips64el $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-mips64el $<\n\t@touch $@\no/$(MODE)/s390x/%.runs: o/$(MODE)/s390x/% o/third_party/qemu/4/qemu-s390x $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-s390x $<\n\t@touch $@\no/$(MODE)/microblaze/%.runs: o/$(MODE)/microblaze/% o/third_party/qemu/4/qemu-microblaze $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-microblaze $<\n\t@touch $@\no/$(MODE)/powerpc/%.runs: o/$(MODE)/powerpc/% o/third_party/qemu/4/qemu-ppc $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-ppc $<\n\t@touch $@\no/$(MODE)/powerpc64le/%.runs: o/$(MODE)/powerpc64le/% o/third_party/qemu/4/qemu-ppc64le $(VM)\n\t$(VM) o/third_party/qemu/4/qemu-ppc64le $<\n\t@touch $@\n\no/$(MODE)/i486/%.emulates: % o/$(MODE)/i486/blink/blink o/third_party/qemu/4/qemu-i386 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-i386 o/$(MODE)/i486/blink/blink $<\n\t@touch $@\no/$(MODE)/m68k/%.emulates: % o/$(MODE)/m68k/blink/blink o/third_party/qemu/4/qemu-m68k $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-m68k o/$(MODE)/m68k/blink/blink $<\n\t@touch $@\no/$(MODE)/x86_64/%.emulates: % o/$(MODE)/x86_64/blink/blink o/third_party/qemu/4/qemu-x86_64 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-x86_64 -cpu core2duo o/$(MODE)/x86_64/blink/blink $<\n\t@touch $@\no/$(MODE)/x86_64-gcc49/%.emulates: % o/$(MODE)/x86_64-gcc49/blink/blink o/third_party/qemu/4/qemu-x86_64 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-x86_64 -cpu core2duo o/$(MODE)/x86_64-gcc49/blink/blink $<\n\t@touch $@\no/$(MODE)/arm/%.emulates: % o/$(MODE)/arm/blink/blink o/third_party/qemu/4/qemu-arm $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-arm o/$(MODE)/arm/blink/blink $<\n\t@touch $@\no/$(MODE)/aarch64/%.emulates: % o/$(MODE)/aarch64/blink/blink o/third_party/qemu/4/qemu-aarch64 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-aarch64 o/$(MODE)/aarch64/blink/blink $<\n\t@touch $@\no/$(MODE)/riscv64/%.emulates: % o/$(MODE)/riscv64/blink/blink o/third_party/qemu/4/qemu-riscv64 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-riscv64 o/$(MODE)/riscv64/blink/blink $<\n\t@touch $@\no/$(MODE)/mips/%.emulates: % o/$(MODE)/mips/blink/blink o/third_party/qemu/4/qemu-mips $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-mips o/$(MODE)/mips/blink/blink $<\n\t@touch $@\no/$(MODE)/mipsel/%.emulates: % o/$(MODE)/mipsel/blink/blink o/third_party/qemu/4/qemu-mipsel $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-mipsel o/$(MODE)/mipsel/blink/blink $<\n\t@touch $@\no/$(MODE)/mips64/%.emulates: % o/$(MODE)/mips64/blink/blink o/third_party/qemu/4/qemu-mips64 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-mips64 o/$(MODE)/mips64/blink/blink $<\n\t@touch $@\no/$(MODE)/mips64el/%.emulates: % o/$(MODE)/mips64el/blink/blink o/third_party/qemu/4/qemu-mips64el $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-mips64el o/$(MODE)/mips64el/blink/blink $<\n\t@touch $@\no/$(MODE)/s390x/%.emulates: % o/$(MODE)/s390x/blink/blink o/third_party/qemu/4/qemu-s390x $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-s390x o/$(MODE)/s390x/blink/blink $<\n\t@touch $@\no/$(MODE)/microblaze/%.emulates: % o/$(MODE)/microblaze/blink/blink o/third_party/qemu/4/qemu-microblaze $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-microblaze o/$(MODE)/microblaze/blink/blink $<\n\t@touch $@\no/$(MODE)/powerpc/%.emulates: % o/$(MODE)/powerpc/blink/blink o/third_party/qemu/4/qemu-ppc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-ppc o/$(MODE)/powerpc/blink/blink $<\n\t@touch $@\no/$(MODE)/powerpc64le/%.emulates: % o/$(MODE)/powerpc64le/blink/blink o/third_party/qemu/4/qemu-ppc64le $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-ppc64le o/$(MODE)/powerpc64le/blink/blink $<\n\t@touch $@\n\no/$(MODE)/i486/%.emulates: o/$(MODE)/% o/$(MODE)/i486/blink/blink o/third_party/qemu/4/qemu-i386 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-i386 o/$(MODE)/i486/blink/blink $<\n\t@touch $@\no/$(MODE)/m68k/%.emulates: o/$(MODE)/% o/$(MODE)/m68k/blink/blink o/third_party/qemu/4/qemu-m68k $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-m68k o/$(MODE)/m68k/blink/blink $<\n\t@touch $@\no/$(MODE)/x86_64/%.emulates: o/$(MODE)/% o/$(MODE)/x86_64/blink/blink o/third_party/qemu/4/qemu-x86_64 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-x86_64 -cpu core2duo o/$(MODE)/x86_64/blink/blink $<\n\t@touch $@\no/$(MODE)/x86_64-gcc49/%.emulates: o/$(MODE)/% o/$(MODE)/x86_64-gcc49/blink/blink o/third_party/qemu/4/qemu-x86_64 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-x86_64 -cpu core2duo o/$(MODE)/x86_64-gcc49/blink/blink $<\n\t@touch $@\no/$(MODE)/arm/%.emulates: o/$(MODE)/% o/$(MODE)/arm/blink/blink o/third_party/qemu/4/qemu-arm $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-arm o/$(MODE)/arm/blink/blink $<\n\t@touch $@\no/$(MODE)/aarch64/%.emulates: o/$(MODE)/% o/$(MODE)/aarch64/blink/blink o/third_party/qemu/4/qemu-aarch64 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-aarch64 o/$(MODE)/aarch64/blink/blink $<\n\t@touch $@\no/$(MODE)/riscv64/%.emulates: o/$(MODE)/% o/$(MODE)/riscv64/blink/blink o/third_party/qemu/4/qemu-riscv64 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-riscv64 o/$(MODE)/riscv64/blink/blink $<\n\t@touch $@\no/$(MODE)/mips/%.emulates: o/$(MODE)/% o/$(MODE)/mips/blink/blink o/third_party/qemu/4/qemu-mips $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-mips o/$(MODE)/mips/blink/blink $<\n\t@touch $@\no/$(MODE)/mipsel/%.emulates: o/$(MODE)/% o/$(MODE)/mipsel/blink/blink o/third_party/qemu/4/qemu-mipsel $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-mipsel o/$(MODE)/mipsel/blink/blink $<\n\t@touch $@\no/$(MODE)/mips64/%.emulates: o/$(MODE)/% o/$(MODE)/mips64/blink/blink o/third_party/qemu/4/qemu-mips64 $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-mips64 o/$(MODE)/mips64/blink/blink $<\n\t@touch $@\no/$(MODE)/mips64el/%.emulates: o/$(MODE)/% o/$(MODE)/mips64el/blink/blink o/third_party/qemu/4/qemu-mips64el $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-mips64el o/$(MODE)/mips64el/blink/blink $<\n\t@touch $@\no/$(MODE)/s390x/%.emulates: o/$(MODE)/% o/$(MODE)/s390x/blink/blink o/third_party/qemu/4/qemu-s390x $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-s390x o/$(MODE)/s390x/blink/blink $<\n\t@touch $@\no/$(MODE)/microblaze/%.emulates: o/$(MODE)/% o/$(MODE)/microblaze/blink/blink o/third_party/qemu/4/qemu-microblaze $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-microblaze o/$(MODE)/microblaze/blink/blink $<\n\t@touch $@\no/$(MODE)/powerpc/%.emulates: o/$(MODE)/% o/$(MODE)/powerpc/blink/blink o/third_party/qemu/4/qemu-ppc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-ppc o/$(MODE)/powerpc/blink/blink $<\n\t@touch $@\no/$(MODE)/powerpc64le/%.emulates: o/$(MODE)/% o/$(MODE)/powerpc64le/blink/blink o/third_party/qemu/4/qemu-ppc64le $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/qemu/4/qemu-ppc64le o/$(MODE)/powerpc64le/blink/blink $<\n\t@touch $@\n\no/$(MODE)/test:\t\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/test/blink\n\no/$(MODE)/test/emulates:\t\t\t\t\t\t\t\\\n\to/$(MODE)/test/blink/emulates\n"
  },
  {
    "path": "third_party/.clang-format",
    "content": "DisableFormat: true\nSortIncludes: Never\n"
  },
  {
    "path": "third_party/coi-serviceworker/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 Guido Zuidhof\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "third_party/coi-serviceworker/README.md",
    "content": "# coi-serviceworker \n![npm](https://img.shields.io/npm/v/coi-serviceworker) ![size](https://img.shields.io/github/size/gzuidhof/coi-serviceworker/coi-serviceworker.min.js)\n\nCross-origin isolation ([COOP and COEP](https://web.dev/coop-coep/)) through a service worker for situations in which you can't control the headers (e.g. GH pages).\n\n\n## Usage\n\n1. Download `coi-serviceworker.js` (or `coi-serviceworker.min.js`).\n2. Put it next to your index file (or in any folder above it)\n3. Add to your HTML file:\n    ```html\n    <script src=\"coi-serviceworker.js\"></script>\n    ```\n\nThis script will reload the page on the user's first load to magically add the required COOP and COEP headers in a service worker.\n\n**Rules**:\n* It must be in a separate file, you can't bundle it along with your app. \n* It can't be loaded from a CDN: it must be served from your own origin.\n* Your page will still need to be either served from HTTPS, or served from localhost.\n\n\n### Extra credits: download from NPM\n\nYou can install this package from npm:\n```\nnpm i --save coi-serviceworker\n```\n\nYou will still have to tell your bundler to put the file alongside your bundle. Something like this will do the trick:\n\n```shell\ncp node_modules/coi-serviceworker/coi-serviceworker.js dist/\n```\n\n## Customization\nYou can customize the behavior by defining a variable `coi` in the global scope (i.e. on the `window` object):\n\n```javascript\nwindow.coi = {\n    // // A function that is run to decide whether to register the SW or not.\n    // You could for instance make this return a value based on whether you actually need to be cross origin isolated or not.\n    shouldRegister: () => true,\n    // If this function returns true, any existing service worker will be deregistered (and nothing else will happen).\n    shouldDeregister: () => false,\n    // A function that is run to decide whether to use \"Cross-Origin-Embedder-Policy: credentialless\" or not.\n    // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy#browser_compatibility\n    coepCredentialless: () => !(navigator.userAgent.indexOf(\"CriOS\") > -1 || !window.chrome),\n    // Override this if you want to prompt the user and do reload at your own leisure. Maybe show the user a message saying:\n    // \"Click OK to refresh the page to enable <...>\"\n    doReload: () => window.location.reload(),\n    // Set to true if you don't want coi to log anything to the console.\n    quiet: false\n}\n```\n\nLibrary and idea based on @stefnotch's [blog post](https://dev.to/stefnotch/enabling-coop-coep-without-touching-the-server-2d3n).\n\n## License\nMIT\n\n![Carp or Koi Artwork](https://i.imgur.com/HVyWe6T.jpeg)\n> Carp or Koi (1926) by Ohara Koson. Original from the Los Angeles County Museum of Art. Public Domain CC0 image.\n"
  },
  {
    "path": "third_party/coi-serviceworker/coi-serviceworker.js",
    "content": "/*! coi-serviceworker v0.1.6 - Guido Zuidhof, licensed under MIT */\nlet coepCredentialless = false;\nif (typeof window === 'undefined') {\n    self.addEventListener(\"install\", () => self.skipWaiting());\n    self.addEventListener(\"activate\", (event) => event.waitUntil(self.clients.claim()));\n\n    self.addEventListener(\"message\", (ev) => {\n        if (!ev.data) {\n            return;\n        } else if (ev.data.type === \"deregister\") {\n            self.registration\n                .unregister()\n                .then(() => {\n                    return self.clients.matchAll();\n                })\n                .then(clients => {\n                    clients.forEach((client) => client.navigate(client.url));\n                });\n        } else if (ev.data.type === \"coepCredentialless\") {\n            coepCredentialless = ev.data.value;\n        }\n    });\n\n    self.addEventListener(\"fetch\", function (event) {\n        const r = event.request;\n        if (r.cache === \"only-if-cached\" && r.mode !== \"same-origin\") {\n            return;\n        }\n\n        const request = (coepCredentialless && r.mode === \"no-cors\")\n            ? new Request(r, {\n                credentials: \"omit\",\n            })\n            : r;\n        event.respondWith(\n            fetch(request)\n                .then((response) => {\n                    if (response.status === 0) {\n                        return response;\n                    }\n\n                    const newHeaders = new Headers(response.headers);\n                    newHeaders.set(\"Cross-Origin-Embedder-Policy\",\n                        coepCredentialless ? \"credentialless\" : \"require-corp\"\n                    );\n                    newHeaders.set(\"Cross-Origin-Opener-Policy\", \"same-origin\");\n\n                    return new Response(response.body, {\n                        status: response.status,\n                        statusText: response.statusText,\n                        headers: newHeaders,\n                    });\n                })\n                .catch((e) => console.error(e))\n        );\n    });\n\n} else {\n    (() => {\n        // You can customize the behavior of this script through a global `coi` variable.\n        const coi = {\n            shouldRegister: () => true,\n            shouldDeregister: () => false,\n            coepCredentialless: () => false,\n            doReload: () => window.location.reload(),\n            quiet: false,\n            ...window.coi\n        };\n\n        const n = navigator;\n\n        if (n.serviceWorker && n.serviceWorker.controller) {\n            n.serviceWorker.controller.postMessage({\n                type: \"coepCredentialless\",\n                value: coi.coepCredentialless(),\n            });\n\n            if (coi.shouldDeregister()) {\n                n.serviceWorker.controller.postMessage({ type: \"deregister\" });\n            }\n        }\n\n        // If we're already coi: do nothing. Perhaps it's due to this script doing its job, or COOP/COEP are\n        // already set from the origin server. Also if the browser has no notion of crossOriginIsolated, just give up here.\n        if (window.crossOriginIsolated !== false || !coi.shouldRegister()) return;\n\n        if (!window.isSecureContext) {\n            !coi.quiet && console.log(\"COOP/COEP Service Worker not registered, a secure context is required.\");\n            return;\n        }\n\n        // In some environments (e.g. Chrome incognito mode) this won't be available\n        if (n.serviceWorker) {\n            n.serviceWorker.register(window.document.currentScript.src).then(\n                (registration) => {\n                    !coi.quiet && console.log(\"COOP/COEP Service Worker registered\", registration.scope);\n\n                    registration.addEventListener(\"updatefound\", () => {\n                        !coi.quiet && console.log(\"Reloading page to make use of updated COOP/COEP Service Worker.\");\n                        coi.doReload();\n                    });\n\n                    // If the registration is active, but it's not controlling the page\n                    if (registration.active && !n.serviceWorker.controller) {\n                        !coi.quiet && console.log(\"Reloading page to make use of COOP/COEP Service Worker.\");\n                        coi.doReload();\n                    }\n                },\n                (err) => {\n                    !coi.quiet && console.error(\"COOP/COEP Service Worker failed to register:\", err);\n                }\n            );\n        }\n    })();\n}\n"
  },
  {
    "path": "third_party/cosmo/2/_timespec_test.com.dbg.gz.sha256",
    "content": "fa12339aded86054bf0302eb4b046b16efd98b09262143058754516545bd0850 *third_party/cosmo/2/_timespec_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/_timespec_test.com.gz.sha256",
    "content": "c3b7a7ba984ce739aa18162e22278a9c09c83a8e8f5f8efc83ae1998b9bbf157 *third_party/cosmo/2/_timespec_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/a64l_test.com.dbg.gz.sha256",
    "content": "982088e75a02f0a4a232f58787dbf903c9beb4974b0cf104109e5c44ca05cf78 *third_party/cosmo/2/a64l_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/a64l_test.com.gz.sha256",
    "content": "357d44b371c926ffe75f13d0032d631f4c6fed7c7c0c2db435b8df0e9f2d65ba *third_party/cosmo/2/a64l_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/abort_test.com.dbg.gz.sha256",
    "content": "34ad05dd7a1bb1dae333eb71abf331deabb4241ad45365bcfcbf483c4f52407d *third_party/cosmo/2/abort_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/abort_test.com.gz.sha256",
    "content": "22e4212e190a087649fa492a7b657627e45522c2cb4385f446313374af039cae *third_party/cosmo/2/abort_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/access_test.com.dbg.gz.sha256",
    "content": "068d2f7f40f0342735165150619758d562a67646c3ef1174adb474aa559d9a8b *third_party/cosmo/2/access_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/access_test.com.gz.sha256",
    "content": "8b8e02bcb2d33347352fa1938af581bc44875736985cc5db388b9aa225fcba54 *third_party/cosmo/2/access_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/acos_test.com.dbg.gz.sha256",
    "content": "eafa0f999536532a267e1bce8167ea68dd4b8ac458520900605c2cebf3e86212 *third_party/cosmo/2/acos_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/acos_test.com.gz.sha256",
    "content": "7a16aef2623076ed9b044e818cd5747a513ae2696def6be7ae9acd55b4c56967 *third_party/cosmo/2/acos_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/acosh_test.com.dbg.gz.sha256",
    "content": "9d61ccb14173e9d8260a681891e4d071a20fca8eed10fdb073648a40e067bffb *third_party/cosmo/2/acosh_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/acosh_test.com.gz.sha256",
    "content": "7014d4a2ccc0309b460ba104d16363be3b4407d4c68463b080a0be924a223069 *third_party/cosmo/2/acosh_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/alaw_test.com.dbg.gz.sha256",
    "content": "72bc44ff7ac030961463e7754b9401c796fc7cb2785cf5364b55a556ea82116f *third_party/cosmo/2/alaw_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/alaw_test.com.gz.sha256",
    "content": "dd24f1f8b0ce26c9c2220d5d656dfee04cb0e2603186b377f468d84dd65f676f *third_party/cosmo/2/alaw_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/alu_test.com.dbg.gz.sha256",
    "content": "63dcd6c6319ecf0c435f625a81916dfe300ba5d2cc04f5e4a22aece0a3d0d79e *third_party/cosmo/2/alu_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/alu_test.com.gz.sha256",
    "content": "3c0ff6cfea18e9a090b9daf53565060ca17c11b2fc51eda22d880a3664c70969 *third_party/cosmo/2/alu_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/appendresourcereport_test.com.dbg.gz.sha256",
    "content": "25532fa6b62bef9b6bcf1c659c54de8aefeace6fec037453bd543369ddc7222b *third_party/cosmo/2/appendresourcereport_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/appendresourcereport_test.com.gz.sha256",
    "content": "78ffae83701234644a838a5b113bf13b6afbe21eb676a3f4edb66f3621d2477f *third_party/cosmo/2/appendresourcereport_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/arch_prctl_test.com.dbg.gz.sha256",
    "content": "e9c76b6970e1683170ea6b578a2d784e8071248ac0ee0ec22c8f0a5e4b2ed1f3 *third_party/cosmo/2/arch_prctl_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/arch_prctl_test.com.gz.sha256",
    "content": "a5962f5fb4f7bfa873f3462c2cf79de7afed0b337b9a05ddc4b501280746c66c *third_party/cosmo/2/arch_prctl_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/arena_test.com.dbg.gz.sha256",
    "content": "5ff1492cb39bcf225832c23d57c442caa43b98f19e7a5dd16011fc07f082f156 *third_party/cosmo/2/arena_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/arena_test.com.gz.sha256",
    "content": "453e4581f27ad4126c2d41a0161dea5266d7dd4d52fea4c89850c12e3e90918f *third_party/cosmo/2/arena_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/argon2_test.com.dbg.gz.sha256",
    "content": "595e206c54898dc9aec0a2d53c0430df2922e297284ba00b3b918628e30eb130 *third_party/cosmo/2/argon2_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/argon2_test.com.gz.sha256",
    "content": "a841ae0fedb12e241f0705abd40acae0289f42ddd652685681ba1d883f7c3d72 *third_party/cosmo/2/argon2_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/args_test.com.dbg.gz.sha256",
    "content": "6373d461ea37dc728ec3009727615f0b60b00c7977a7152b6def3171b018ffd2 *third_party/cosmo/2/args_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/args_test.com.gz.sha256",
    "content": "28635607ed1d0acdfc3f60ec4d6eb8aaa93e841efc7a565701617e15b8ebcae0 *third_party/cosmo/2/args_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/arraylist_test.com.dbg.gz.sha256",
    "content": "80fbbf4a9fa6e0fc12b74d537ec59157cd78d3c52977bdfda2008861d0c4ddf5 *third_party/cosmo/2/arraylist_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/arraylist_test.com.gz.sha256",
    "content": "1f2c82e6cbaaf1a4c2689a5ef80d540fafdb92df39bb7f67d336e2432168bbc7 *third_party/cosmo/2/arraylist_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/asan_test.com.dbg.gz.sha256",
    "content": "5b2988255729a6ad830332ab1638943e406bce1a788f307905cea705401bb2d9 *third_party/cosmo/2/asan_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/asan_test.com.gz.sha256",
    "content": "32839f149c14c03462f0b0e20e058ee84537878ba63d219b89e18404be5c3997 *third_party/cosmo/2/asan_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/asin_test.com.dbg.gz.sha256",
    "content": "35b0623096815acbb7368e6601c3332986846701986978ea3ea536edf405807e *third_party/cosmo/2/asin_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/asin_test.com.gz.sha256",
    "content": "a04c4c425038603ab019eb204a3a93c016389be4124cbefb9c9328a165e5afe2 *third_party/cosmo/2/asin_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/asinh_test.com.dbg.gz.sha256",
    "content": "95bee87bfc7d8e711cea21ad4c6266c4309e2db29db6d4bc57a3f844dff862d0 *third_party/cosmo/2/asinh_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/asinh_test.com.gz.sha256",
    "content": "04c8ca48a79725053ce4d1e2c6d1e780eaa2a000670d5755e769447cc5664ef8 *third_party/cosmo/2/asinh_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/asmdown_test.com.dbg.gz.sha256",
    "content": "e747fae8e36d2ce3949e185eb6bda987354b69fe3ed74165e1d611356f1b5bd2 *third_party/cosmo/2/asmdown_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/asmdown_test.com.gz.sha256",
    "content": "64723fde003e6181edcec818d29bd3f12b7b48e30e290ff228ea3c9c419f6836 *third_party/cosmo/2/asmdown_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atan2_test.com.dbg.gz.sha256",
    "content": "ced5aea2869020e039ab537177c22d92dfeb0d379dbc06838203c09893327b68 *third_party/cosmo/2/atan2_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atan2_test.com.gz.sha256",
    "content": "e7bd88efe2006b4da980aa62610da79f5fc9960f76aed122e9ee3bb43b877085 *third_party/cosmo/2/atan2_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atan2l_test.com.dbg.gz.sha256",
    "content": "3622689fe93671bdf6f658a5cd59b0e7f02b70e414b64582b664add3188f3f1d *third_party/cosmo/2/atan2l_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atan2l_test.com.gz.sha256",
    "content": "40f8cef79643346a68694036a44c357c887a514df98ab69d84b0fe0f03741e6a *third_party/cosmo/2/atan2l_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atan_test.com.dbg.gz.sha256",
    "content": "3ea187c5bb2f7426e5a12ce10c6632abaf33c8c8d70fc85b4972104f5669eb10 *third_party/cosmo/2/atan_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atan_test.com.gz.sha256",
    "content": "ad9cce522b51d0ca2260e44c9eb1f54d9af5e072d6886e80ceed6ceb8462c191 *third_party/cosmo/2/atan_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atanh_test.com.dbg.gz.sha256",
    "content": "62302916e428e3fea613839a175958a8113fa271ed097625360ab5fa1c5609d4 *third_party/cosmo/2/atanh_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atanh_test.com.gz.sha256",
    "content": "c139ad097ba3f49b6b3a73423e30300439010723fd5e3e4e95b2e7eecd0bf1f6 *third_party/cosmo/2/atanh_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atanl_test.com.dbg.gz.sha256",
    "content": "2a75bda2e3b24d048f912404a03b8cc39a5362978b945f481f4fcaeede71a44d *third_party/cosmo/2/atanl_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atanl_test.com.gz.sha256",
    "content": "0f325b80be7495b275ab7434266156620f352ddc95cd00244550e4481b4b5899 *third_party/cosmo/2/atanl_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atoi_test.com.dbg.gz.sha256",
    "content": "e004edefa7a8d663dfe11c4b0b83db50d8a82f60d5d27a88148ab342118c7bd9 *third_party/cosmo/2/atoi_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/atoi_test.com.gz.sha256",
    "content": "4fe27818721ae622163deda1807de2c7e9518509fe34fecedea864e071387a19 *third_party/cosmo/2/atoi_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/backtrace_test.com.dbg.gz.sha256",
    "content": "7e813c31dd843dfac077b060ce2dac58bd202050d786c1110bfa2d371f567a0a *third_party/cosmo/2/backtrace_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/backtrace_test.com.gz.sha256",
    "content": "7765421e7a4482987987395fbf9b4100481e24000873861ec4cc9392f68c54ea *third_party/cosmo/2/backtrace_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/basename_test.com.dbg.gz.sha256",
    "content": "eb43fd8323e71358b51d181040d72b7436ed800185e288455da42c0ee94dc66e *third_party/cosmo/2/basename_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/basename_test.com.gz.sha256",
    "content": "622bb8e8c63813a7e35d6b6936ea18175db51d5acd1b30f3625dc58a27367058 *third_party/cosmo/2/basename_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bextra_test.com.dbg.gz.sha256",
    "content": "55bb4effc5aaadd8894d87071d1cb8ef2b3750dd0b25255caa893c759281cd92 *third_party/cosmo/2/bextra_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bextra_test.com.gz.sha256",
    "content": "f119bfaa8656abd4910116c2cc848f9f9b8f744bc7925539029c6655558629fb *third_party/cosmo/2/bextra_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bilinearscale_test.com.dbg.gz.sha256",
    "content": "266470a52146d2f4f826b1dce97c30e595733db8193283c27e405d474bec9820 *third_party/cosmo/2/bilinearscale_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bilinearscale_test.com.gz.sha256",
    "content": "7f2a3fb0c2e0e5c044098a4f70ed22297be58e7a9016e03120b060ce32f4feb2 *third_party/cosmo/2/bilinearscale_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bisectcarleft_test.com.dbg.gz.sha256",
    "content": "778c6447439d6a4fede508caec4efd1ef5a884583ac53ad0eef7b41f86b4388f *third_party/cosmo/2/bisectcarleft_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bisectcarleft_test.com.gz.sha256",
    "content": "3f6a472986af28c2843ca136b81c5b8f2076d1c8e3589ebe73a316bc3813ddd6 *third_party/cosmo/2/bisectcarleft_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bitreverse_test.com.dbg.gz.sha256",
    "content": "44a3a0d9d8e178d2051320f5f788ec92727bfd901e96dd63bd52855a75756c45 *third_party/cosmo/2/bitreverse_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bitreverse_test.com.gz.sha256",
    "content": "8a29e1489a7eea7cde052ff365d1d3cc4007931650aded9fa1e45cd4f7ddbb78 *third_party/cosmo/2/bitreverse_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bitscan_test.com.dbg.gz.sha256",
    "content": "f22d82cb3b4f093350f970c0a93466054310536ffa3736ca5f7537ae6b1e0777 *third_party/cosmo/2/bitscan_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bitscan_test.com.gz.sha256",
    "content": "ff47676e77c86e30dd2a494a147a03480cfd6972d62297d8820c7bd815d91bdb *third_party/cosmo/2/bitscan_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/blake2_test.com.dbg.gz.sha256",
    "content": "ab740fa25d488c61f8d3c97d85a6d7ed245eda7db46c021e504a5d7dd67dd52b *third_party/cosmo/2/blake2_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/blake2_test.com.gz.sha256",
    "content": "ba75e9c763e6b9e04d27eac3d19756d2042665a35ebe660ba53755ce9930159a *third_party/cosmo/2/blake2_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/brk_test.com.dbg.gz.sha256",
    "content": "ffa8c9b9e3ee55f6ff070188a61cc4867629494b3e3c92ca6f39eb6723fc9d06 *third_party/cosmo/2/brk_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/brk_test.com.gz.sha256",
    "content": "5d8096d29734b06a5a89090a4777f4d0d327cf40e8d7ea531bf23ca096c0cf06 *third_party/cosmo/2/brk_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bsr_test.com.dbg.gz.sha256",
    "content": "9692fbb184a838e114a91f7fae1a7372bd282b15066528d438ad8d2392de949a *third_party/cosmo/2/bsr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bsr_test.com.gz.sha256",
    "content": "2bfba82ff99edd0016c4653fd45695659246c8d767d67365c185d7625801fc4b *third_party/cosmo/2/bsr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bsu_test.com.dbg.gz.sha256",
    "content": "11ec6f7ca41a0b8a0ffb75c91c9c0c9c447ef07c5ccb5301037602071b401640 *third_party/cosmo/2/bsu_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bsu_test.com.gz.sha256",
    "content": "60560521f307362fea76aadd318e54722b410938913e451277c07dc589eb2d01 *third_party/cosmo/2/bsu_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bzero_test.com.dbg.gz.sha256",
    "content": "935e583ffb6cde1456d4cd8168f0cf784cdb835e3fec6505caa0712032504d57 *third_party/cosmo/2/bzero_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/bzero_test.com.gz.sha256",
    "content": "ce50b8bfe5c17c672b582c0f64fb04e33f92b05abed6140ea25b95f42f803ea7 *third_party/cosmo/2/bzero_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cas_test.com.dbg.gz.sha256",
    "content": "c74e74ccd83fd5d1b2f3c2130c4fe1f8ec5751811aaf212c06d3daa085a4370b *third_party/cosmo/2/cas_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cas_test.com.gz.sha256",
    "content": "a06f56d1130decbede78e016c12b3ad0e0009d5d71c7cfda3fb0e7a543f4aaf5 *third_party/cosmo/2/cas_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cbrt_test.com.dbg.gz.sha256",
    "content": "e2c0da571c8caf7107cacb81b3ee5527ecc74f39f3d1069dd411e0516b18edbd *third_party/cosmo/2/cbrt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cbrt_test.com.gz.sha256",
    "content": "bb32cefe57adf35db078b350e088d05377a83a0925de3cc2b50c76eaba8b5334 *third_party/cosmo/2/cbrt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ceil_test.com.dbg.gz.sha256",
    "content": "80a722ccb8fb04e804a41a01cd0316897bedace988e0f9b05c4ed62f4bc78c32 *third_party/cosmo/2/ceil_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ceil_test.com.gz.sha256",
    "content": "b50e1b1a43ddd8c87625315947970ad2830403b8579d9489f449af2a76d40503 *third_party/cosmo/2/ceil_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cescapec_test.com.dbg.gz.sha256",
    "content": "a9cf870b8e7b27ed36e654af59985e9081988ce53b0410d9e0d88e1192834e50 *third_party/cosmo/2/cescapec_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cescapec_test.com.gz.sha256",
    "content": "8b924769300d339d075b770c7f624f198ce0dc6bd6591745ca8a1e5f4197abc5 *third_party/cosmo/2/cescapec_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/chdir_test.com.dbg.gz.sha256",
    "content": "e19cf73faa244759f6e82faff92838e266534b827917e8c1d340ea04560a7b5b *third_party/cosmo/2/chdir_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/chdir_test.com.gz.sha256",
    "content": "69c4bf086b8634f0d8180f137074082aa34b60207d3d3874645cc21ca4f1f961 *third_party/cosmo/2/chdir_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/classifypath_test.com.dbg.gz.sha256",
    "content": "e775f5a676ea102c6b19625ccd64f4832c1dbe4ecb6df23bcc79c13fd99ec463 *third_party/cosmo/2/classifypath_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/classifypath_test.com.gz.sha256",
    "content": "dd5004f6767fa4133e48a35b63de4225755be4f9e726aef1b6ce00e360d8f8d3 *third_party/cosmo/2/classifypath_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/clock_getres_test.com.dbg.gz.sha256",
    "content": "d08518297f0755c34e23efa6104fb95e46aabaf87eef18ecae0d3a18c2bbc5c7 *third_party/cosmo/2/clock_getres_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/clock_getres_test.com.gz.sha256",
    "content": "d02ec8db1289abe22801fba032c5e34dce679757de6af32cbe0bc54d404df102 *third_party/cosmo/2/clock_getres_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/clock_gettime_test.com.dbg.gz.sha256",
    "content": "eb4ede5bd65e9baeb0e291b5d4cb05b038336e8725c89f4479a2ed8931b5bc58 *third_party/cosmo/2/clock_gettime_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/clock_gettime_test.com.gz.sha256",
    "content": "8ef8e429de8463e7996a78f521694ac603ba6e6f04d5d309c1a0f962aded8fe4 *third_party/cosmo/2/clock_gettime_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/clock_nanosleep_test.com.dbg.gz.sha256",
    "content": "2d7fb960fdb5a237a3124e4f7690f25182419813d72780ed85c9cbb12320204d *third_party/cosmo/2/clock_nanosleep_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/clock_nanosleep_test.com.gz.sha256",
    "content": "18229e4793a4b2259d9cbee49f35cddaf584895aacf5da8fb602535c7c49dba1 *third_party/cosmo/2/clock_nanosleep_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/clone_test.com.dbg.gz.sha256",
    "content": "5b668bc58fcb5487005ca4955ad231cc9b752248236b7ca353a9760b6beccb25 *third_party/cosmo/2/clone_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/clone_test.com.gz.sha256",
    "content": "5a0bd0b24e59a5455c5215ee1c1b3a9f0b541583e619c04eee7373d76e4dcb46 *third_party/cosmo/2/clone_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/closefrom_test.com.dbg.gz.sha256",
    "content": "8669576e16e5b4c679a00adfc90f5fbc36a7bb6cd403bcbd3ecef7c15d1e4b55 *third_party/cosmo/2/closefrom_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/closefrom_test.com.gz.sha256",
    "content": "b1c921218bcff2800994f5ac456d103245f3b69a33e8d5793a68ab785e1c5d05 *third_party/cosmo/2/closefrom_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/commandv_test.com.dbg.gz.sha256",
    "content": "a222485868f7657545a8d80220963600682f9c8e5bb440d6dadc7f41b2942140 *third_party/cosmo/2/commandv_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/commandv_test.com.gz.sha256",
    "content": "20471cadc2c36cbe2873b41a1afd0cf458f95c196b4f2b3886e4bff1cc0658d5 *third_party/cosmo/2/commandv_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/comparednsnames_test.com.dbg.gz.sha256",
    "content": "defa40e435c97f32eddbd0847e698646a77f90dea62368f90df0791d3ea26d38 *third_party/cosmo/2/comparednsnames_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/comparednsnames_test.com.gz.sha256",
    "content": "d075469b2674731ee551f782de44e5878a7a6ef4c0d3adb9a95f220762abeeaf *third_party/cosmo/2/comparednsnames_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/complex_test.com.dbg.gz.sha256",
    "content": "0fb2476848c1cc9415ac8d69a33f9fda8d74321a85a96943795d1ae1dc7b6587 *third_party/cosmo/2/complex_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/complex_test.com.gz.sha256",
    "content": "83ff8d48e8eedccf1bee680d01fff3305201254db5ce7be6cde39976afbb8d7c *third_party/cosmo/2/complex_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/convoindex_test.com.dbg.gz.sha256",
    "content": "f0e6852e77edf7da16d61603a500dca2aaa21302bc5c414a734df950a00be3eb *third_party/cosmo/2/convoindex_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/convoindex_test.com.gz.sha256",
    "content": "bcbaf8f248b9a8063208aee1c71ce578abf4e56eeabc7c4230485a0f3e6f148c *third_party/cosmo/2/convoindex_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/copy_file_range_test.com.dbg.gz.sha256",
    "content": "0a1951ec14ece54f79cbae0e1f0118e11960fd7c6a510796076ea648f8c760fd *third_party/cosmo/2/copy_file_range_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/copy_file_range_test.com.gz.sha256",
    "content": "a3aa9d2a395a995ff807fc65e2762486c558c00869e908217688aed335c21c25 *third_party/cosmo/2/copy_file_range_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/copysign_test.com.dbg.gz.sha256",
    "content": "9c6d84ac6cf730341ec3c265a7627ba80e17f5fd6b63885f42dc835ab3ba2a13 *third_party/cosmo/2/copysign_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/copysign_test.com.gz.sha256",
    "content": "c4ef5a596afa9edce6060bb1cf33e212adc584aa79597306f78a6bb77b8dd4d3 *third_party/cosmo/2/copysign_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cos_test.com.dbg.gz.sha256",
    "content": "9b996a21d476ef36f5a2b3e68ade6b28c992b289d80cbd75dc7549b12037d9dd *third_party/cosmo/2/cos_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cos_test.com.gz.sha256",
    "content": "74d5707fc9278a021fe0595c7cfa8dced23d01b67c8491b5f0d038ba7911a0d1 *third_party/cosmo/2/cos_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cosh_test.com.dbg.gz.sha256",
    "content": "5fa9426db3cc97cac4b453b14344d229011a3df35a3ea081bc59961ab2673cca *third_party/cosmo/2/cosh_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cosh_test.com.gz.sha256",
    "content": "06ad8a6b949342f9a49654eee1f8d821ced16fdc30883b9c3ed7b0ff658e2d41 *third_party/cosmo/2/cosh_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/countbits_test.com.dbg.gz.sha256",
    "content": "0931c8b1a95b31ba79fb997e46de24e0f4ba0f5abd8631f929845ee26e7e2d24 *third_party/cosmo/2/countbits_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/countbits_test.com.gz.sha256",
    "content": "679ddd4a5d9ad974c9b5fd9cea5aec0f53c93f61f393c531e374c911e0d3f236 *third_party/cosmo/2/countbits_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/counter_test.com.dbg.gz.sha256",
    "content": "acf36a0f239a1655989d75ab9e21ed72a1ac5101870b0b9d5efeacf5dda01156 *third_party/cosmo/2/counter_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/counter_test.com.gz.sha256",
    "content": "4f2d8195128711bd57a89f607463e19b79e0b63c5dedc1c644060e36add16fde *third_party/cosmo/2/counter_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/crc32_test.com.dbg.gz.sha256",
    "content": "1f65c501bde8591d68ffda8ebdad543183c554ed2eb75c6ee9150fe131192ea2 *third_party/cosmo/2/crc32_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/crc32_test.com.gz.sha256",
    "content": "45cbe576a8422d9e7c833a58be5e2927654d41f4278a1e6d9b083253bdcf5715 *third_party/cosmo/2/crc32_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/crc32c_test.com.dbg.gz.sha256",
    "content": "528ca4850bf85e04d6928afb9f411ec21172b1686c41fd7a1ee55d2731ec81ac *third_party/cosmo/2/crc32c_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/crc32c_test.com.gz.sha256",
    "content": "a610fa92c4ad20c0f75b0bda95a7fb6385ba51f27aed39904b2eb52a79928466 *third_party/cosmo/2/crc32c_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/crc32z_test.com.dbg.gz.sha256",
    "content": "bf105b965394764931e561f66b1c97fee88943df713b7e73a08007333378b578 *third_party/cosmo/2/crc32z_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/crc32z_test.com.gz.sha256",
    "content": "7b06b218d2ddc84b81cf94f8bdedb9521d40e994a1bdef218b943cbc9c1b989e *third_party/cosmo/2/crc32z_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/critbit0_test.com.dbg.gz.sha256",
    "content": "d535510105431718ab02cd5c0b26b5a187fec048cf474074b2363b2547736dd9 *third_party/cosmo/2/critbit0_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/critbit0_test.com.gz.sha256",
    "content": "a6925bc7aa799ec4d7e3139c41d937a6e8313150919c1a9c9d8e9b2a1a727354 *third_party/cosmo/2/critbit0_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/crypt_test.com.dbg.gz.sha256",
    "content": "8a7ee78079812b8eec204e9aa2d42e70bb3c5d43644591ca6b2f4cd26e04ba09 *third_party/cosmo/2/crypt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/crypt_test.com.gz.sha256",
    "content": "f3051bdd8a372fc268d1ed6feaf63cf4892118c3d5e6219d7ac3965dae7f465f *third_party/cosmo/2/crypt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/csqrt_test.com.dbg.gz.sha256",
    "content": "9514c56a10dd4ec4d12d0c3fa617e0ba63a0b4188379e1e6860c6e80f08edb0a *third_party/cosmo/2/csqrt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/csqrt_test.com.gz.sha256",
    "content": "db746edc802a206f4492e36cb77ef7e114a5f68375589ac67e024f0c23331bfd *third_party/cosmo/2/csqrt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cv_test.com.dbg.gz.sha256",
    "content": "73a267229f3e57bb3055b503359bd45d13f746638359d17521cd1b0c2b93332d *third_party/cosmo/2/cv_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cv_test.com.gz.sha256",
    "content": "818ca4be3091b383d30fc59ea1e6856920587598a8b316df2b32574a52dbbf85 *third_party/cosmo/2/cv_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cv_wait_example_test.com.dbg.gz.sha256",
    "content": "fcd5aa3f02b389419ffe3ce5e353a92f7a05ac7b1fc07d7d40d2dda25ac651de *third_party/cosmo/2/cv_wait_example_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/cv_wait_example_test.com.gz.sha256",
    "content": "21552614d568300e2c5a640ce5d09dc6da91f88ef34b559f4dd5eed019039cb6 *third_party/cosmo/2/cv_wait_example_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/daemon_test.com.dbg.gz.sha256",
    "content": "b9e101f31abe01184a7ddc287a867f8674b03660b580a7839618e4ff11173a61 *third_party/cosmo/2/daemon_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/daemon_test.com.gz.sha256",
    "content": "3d1da0d45a074c3e7954b6d8dd48f1d1d7e609578dc2f36caff17d9240c824c5 *third_party/cosmo/2/daemon_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/decodebase64_test.com.dbg.gz.sha256",
    "content": "42d8322b6f51ac749016618494b7d2e52c6cceb106cda4c946082594a4366efb *third_party/cosmo/2/decodebase64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/decodebase64_test.com.gz.sha256",
    "content": "0ee7056a28076683ceea639b95c59994c61982bb9d8fdc7a1022eee051a0d78c *third_party/cosmo/2/decodebase64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/decodelatin1_test.com.dbg.gz.sha256",
    "content": "be27123830ccd54d7f7a51aa86b30ecd2873dd12a1320145c9ae53e460f95ba1 *third_party/cosmo/2/decodelatin1_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/decodelatin1_test.com.gz.sha256",
    "content": "dff25ab23e92efd335424d58a8babb47b748b09ccaeac3dda5d24c4ed30ed937 *third_party/cosmo/2/decodelatin1_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/describeflags_test.com.dbg.gz.sha256",
    "content": "a449017ae2da3a6c0cef1fe95dcb778003fc82db75c7557be8e54f613e786c19 *third_party/cosmo/2/describeflags_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/describeflags_test.com.gz.sha256",
    "content": "66dc906949cedc1a3b72095818ad11a5cad340aab42d153a9fcb6b7fd1e25822 *third_party/cosmo/2/describeflags_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/describegidlist_test.com.dbg.gz.sha256",
    "content": "aaa18bf8477f97e2ce1e2feef90ff9315ac1a82bc4649abcf7fc66cbdf5d9b82 *third_party/cosmo/2/describegidlist_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/describegidlist_test.com.gz.sha256",
    "content": "6dd8ed2169b520ecec44ef0ed705f10fc161edd1382740ec25b899bdb3c9bf01 *third_party/cosmo/2/describegidlist_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/describesigset_test.com.dbg.gz.sha256",
    "content": "1aaa624108c672ca33d3d1773b638bcf24d32b1398c0437a3f1ed76940f55c1a *third_party/cosmo/2/describesigset_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/describesigset_test.com.gz.sha256",
    "content": "529a2b88b10c6ce65e0b5edca4797a70aaa9dd91bbe895959e426ba85a648ad2 *third_party/cosmo/2/describesigset_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/describesyn_test.com.dbg.gz.sha256",
    "content": "3a377832ba050acb012d7986521fbdda771274d3210a65699b9d110e066c8584 *third_party/cosmo/2/describesyn_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/describesyn_test.com.gz.sha256",
    "content": "622c1b5f0e4b38cb30ed850bf1d9f410b1ea2be03383804230ad2b8ca586c458 *third_party/cosmo/2/describesyn_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/devrand_test.com.dbg.gz.sha256",
    "content": "c030012c9a7df15f8ab143fea81adb0489fe5bd96d60585395957411ec49e6d4 *third_party/cosmo/2/devrand_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/devrand_test.com.gz.sha256",
    "content": "3acf250ccd56a6c6dacac55033ee3836ed1ebe8150cac496bb1b34608bcb6d8a *third_party/cosmo/2/devrand_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/diagnose_syscall_test.com.dbg.gz.sha256",
    "content": "b8b03d62918e2a43bdf2a81bce59ce1bf1ce4bd356d0a9bd529a798d17040041 *third_party/cosmo/2/diagnose_syscall_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/diagnose_syscall_test.com.gz.sha256",
    "content": "ed7e6b06d90ea153db108e32f64b2df2712ca7ed0519a399c149ce38a5758f9d *third_party/cosmo/2/diagnose_syscall_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dirname_test.com.dbg.gz.sha256",
    "content": "ce20bb2bbfdb12bbc74afe2a15b92f8e9e94735c578e9c9541dd859a056ce08a *third_party/cosmo/2/dirname_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dirname_test.com.gz.sha256",
    "content": "139f1c57f929ef75b6ed31c5c2edeee4a81f9eca6af5d6bc83d4fe9407984930 *third_party/cosmo/2/dirname_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dirstream_test.com.dbg.gz.sha256",
    "content": "de9110cd7753c8012c1f62a0f3d1726859a1977c87ab2ff79178b67847941508 *third_party/cosmo/2/dirstream_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dirstream_test.com.gz.sha256",
    "content": "bcf18629d26fc7325ee8b9e386add3d21b4b89e0e97ff0d4196ea710d4d5df0a *third_party/cosmo/2/dirstream_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/disinst_test.com.dbg.gz.sha256",
    "content": "3b3e1fb6d5a8c24c331403bb39c0e4ee1b7ba72d11c35658a4f0c3a046197570 *third_party/cosmo/2/disinst_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/disinst_test.com.gz.sha256",
    "content": "b0a85a2d21ed7c75ef892eee82d3d421fbb8ba746a182f899b223b423895e81d *third_party/cosmo/2/disinst_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/division_test.com.dbg.gz.sha256",
    "content": "888c5a8a6e9a21a9e0600e2e419c428f36d47277906827fe227b48d3645ffe64 *third_party/cosmo/2/division_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/division_test.com.gz.sha256",
    "content": "f84e51b76b4b42682f9c4551527e342ea7163e492ce5f7bb2bc1f45eae64f91f *third_party/cosmo/2/division_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/divmul_test.com.dbg.gz.sha256",
    "content": "1e453a5a1912ca926aa9f58cb9809e1a97b75363f7c7a91fa65e20ae72bde60d *third_party/cosmo/2/divmul_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/divmul_test.com.gz.sha256",
    "content": "2352657fda319cc4ce8be01a27bd4d6c473c6f475baccc66bc7c8ccbf0bbcf25 *third_party/cosmo/2/divmul_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/djbsort_test.com.dbg.gz.sha256",
    "content": "1e9be639a6b9a77043bfa68428537123d94ba60742c3be09f44be1fa8e3de5ba *third_party/cosmo/2/djbsort_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/djbsort_test.com.gz.sha256",
    "content": "8bef821608dd4c02ab6c72736636f94966506d901a9cf6c31ae7968230361c66 *third_party/cosmo/2/djbsort_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dll_test.com.dbg.gz.sha256",
    "content": "d5981e86b6f0842e74e229178c78b656dcbfe9fd64eada1d698f0f42710c24d8 *third_party/cosmo/2/dll_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dll_test.com.gz.sha256",
    "content": "8b971b96037f68138eb651b605044de5f3a07805d6f39531b0e813f5e29e692e *third_party/cosmo/2/dll_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dnsheader_test.com.dbg.gz.sha256",
    "content": "e954742debdb2da636d48319eaffcbea71dac84056d83e4022c103bde201aa93 *third_party/cosmo/2/dnsheader_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dnsheader_test.com.gz.sha256",
    "content": "b69f392f4ec8a42035c58319fa477f46ae1a3319b1a1b437283536fcccad60f0 *third_party/cosmo/2/dnsheader_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dnsquestion_test.com.dbg.gz.sha256",
    "content": "dde4c771d0115fd1ffbcf42aba0fb2796b75c91af0a9d9bdfe2f624311faee52 *third_party/cosmo/2/dnsquestion_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dnsquestion_test.com.gz.sha256",
    "content": "32c75cb6321e18255fa30c60d5f1e1ca2f309b27c721210bcee9f2fa0cb21cd9 *third_party/cosmo/2/dnsquestion_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dos2errno_test.com.dbg.gz.sha256",
    "content": "821580e904b1e1e829566069bb63d69d8089b9f92c1f3c485f5438bca04ff1f2 *third_party/cosmo/2/dos2errno_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dos2errno_test.com.gz.sha256",
    "content": "ad7b70df8bfe3cd4e9e093593e91f389ba6c538f2b6ee299e9c7795a5dba013f *third_party/cosmo/2/dos2errno_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dumphexc_test.com.dbg.gz.sha256",
    "content": "b9c950d5caf173849cef0d06b4876edf215b44fc610d3862471ef8c67d193082 *third_party/cosmo/2/dumphexc_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dumphexc_test.com.gz.sha256",
    "content": "1c751e48e19db7d30ba11cb1b3c4d640dfd3803a23f5131f49ac0c75251a1748 *third_party/cosmo/2/dumphexc_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dup_test.com.dbg.gz.sha256",
    "content": "8c55589404c53b9c2256c8457a6eca35fd474e087bc82833b4152013d4ce3ada *third_party/cosmo/2/dup_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/dup_test.com.gz.sha256",
    "content": "b0d44d5e2742631d92190d1c254fb0a7112f45eaef8f5089e673e3297a0616c7 *third_party/cosmo/2/dup_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ecvt_test.com.dbg.gz.sha256",
    "content": "eb0d1f0035c5cfada08d16c7248d170a8f3063cb61f0aa42ec62b2b558044218 *third_party/cosmo/2/ecvt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ecvt_test.com.gz.sha256",
    "content": "62aca7a59cc63ab8c1e4983617d732c563fb44b2c46359151d62a09fb206b688 *third_party/cosmo/2/ecvt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/encodebase64_test.com.dbg.gz.sha256",
    "content": "3c2e0556b7a50d22e9bd7ab7efabca281742b87df1ac52aca9a653f042efb1d5 *third_party/cosmo/2/encodebase64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/encodebase64_test.com.gz.sha256",
    "content": "96220cf7c44bcbd52bea0a98c60c7ae69b035c0cfba33a0181f31c510c2748b9 *third_party/cosmo/2/encodebase64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/encodehttpheadervalue_test.com.dbg.gz.sha256",
    "content": "3dbbd0449e9d181bfea6e9f09e79c1e8137bc1b2bd68d639b3f1bef75d9dca57 *third_party/cosmo/2/encodehttpheadervalue_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/encodehttpheadervalue_test.com.gz.sha256",
    "content": "4ced361c21efa3244bde457395eec7fba600da4d11b5c8332874323050c296a7 *third_party/cosmo/2/encodehttpheadervalue_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/encodenf32_test.com.dbg.gz.sha256",
    "content": "28dce62f74c28836fb40d80df468cd10e5928100c10795224b2b3cd39bb9a43c *third_party/cosmo/2/encodenf32_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/encodenf32_test.com.gz.sha256",
    "content": "183684169b5f21491589670ea1f11cfdc9269c156a7790f50b4521836857bd44 *third_party/cosmo/2/encodenf32_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/erf_test.com.dbg.gz.sha256",
    "content": "f929bf2a5c1c08ca0114ab2c8df813da8e27238c9b28193eab3712238c35fc02 *third_party/cosmo/2/erf_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/erf_test.com.gz.sha256",
    "content": "024874ac43d8a823728526211ba3c632f8146c19c62a3de8ae141812f56a70d3 *third_party/cosmo/2/erf_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/escapehtml_test.com.dbg.gz.sha256",
    "content": "39359020db51ece1afb66674d29ac2ccc0664e09b757eb7ce38876dd811a75be *third_party/cosmo/2/escapehtml_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/escapehtml_test.com.gz.sha256",
    "content": "2b050bec54886e0015fa8285725db7899433e83d713f7cfc232454e7805043e9 *third_party/cosmo/2/escapehtml_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/escapejsstringliteral_test.com.dbg.gz.sha256",
    "content": "ba7de5afcdd0b60e242c8ca5fd26d1c879c7e57265f4b47167b933bb23647f5a *third_party/cosmo/2/escapejsstringliteral_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/escapejsstringliteral_test.com.gz.sha256",
    "content": "ff19036f39314b79ba763e9d2b8efd1a028363d85d7eb1d045a2e77c47f92246 *third_party/cosmo/2/escapejsstringliteral_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/escapeurlparam_test.com.dbg.gz.sha256",
    "content": "d40a3fce01402e5067a8f100ec365b29185643c7e22e3ba92cf54800028d6525 *third_party/cosmo/2/escapeurlparam_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/escapeurlparam_test.com.gz.sha256",
    "content": "beb4ebb9980cdf184b8faff23fb205fed61f3b5d51d65895be49b2cea9e86201 *third_party/cosmo/2/escapeurlparam_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/everest_test.com.dbg.gz.sha256",
    "content": "fcd3538c65fdf79298926bf60db8e192036aef20a023b8343a84e2d659118a70 *third_party/cosmo/2/everest_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/everest_test.com.gz.sha256",
    "content": "8fcd80bb2a6a387fca28e88194c7aed817df0ac8196c1a944ab4978c41df0f45 *third_party/cosmo/2/everest_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/execve_test.com.dbg.gz.sha256",
    "content": "f7fba42eda2fd4e5c3d82c26d5859aeb730fd8db12383d5562ce795d774359ec *third_party/cosmo/2/execve_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/execve_test.com.gz.sha256",
    "content": "f2ba06720974702f0839595c48f6e133831fc57983c6b66bf4efe4e927d164d5 *third_party/cosmo/2/execve_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/exit_test.com.dbg.gz.sha256",
    "content": "9e6d84cd03dfecc50353bbbb57b7f98a83842b019c20d22c6e2886728ae50b2b *third_party/cosmo/2/exit_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/exit_test.com.gz.sha256",
    "content": "08fe11832da07b07b93ffdeb3866833c0f387ac4fd202d5bba18758bbdf229ea *third_party/cosmo/2/exit_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/exp10_test.com.dbg.gz.sha256",
    "content": "5a499407f67e49f8802055ad5ab2dd0b57155b8e3792eea7b152954341412d9f *third_party/cosmo/2/exp10_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/exp10_test.com.gz.sha256",
    "content": "419dfbcd489da36820a0b7ab5ef5763c79adc247a780454b3ef55ddb34a0a738 *third_party/cosmo/2/exp10_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/exp2_test.com.dbg.gz.sha256",
    "content": "57581f377e8367350a78d5a6df055ff5f49d54adc275bb3a1aa384a158229438 *third_party/cosmo/2/exp2_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/exp2_test.com.gz.sha256",
    "content": "3df7b8f4f1b55df55675c9ece30796d06f28962324dd02e3ea914d95e567fe5a *third_party/cosmo/2/exp2_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/exp2l_test.com.dbg.gz.sha256",
    "content": "a56b8b2a4d836a07357aa1a153ee6c1b008dd109e9fd44983e4917ced66283a7 *third_party/cosmo/2/exp2l_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/exp2l_test.com.gz.sha256",
    "content": "ec97de1b2f0ce4dd01c1a38fadf29b3e8fcb8b7d34411eec3d2bc6a178f1f9d1 *third_party/cosmo/2/exp2l_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/exp_test.com.dbg.gz.sha256",
    "content": "5b921c57f4500d272471972ce7ba39ca8852245f7903f36b5a920fd2bac145ff *third_party/cosmo/2/exp_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/exp_test.com.gz.sha256",
    "content": "1aaa883df95c2eaa549e0f8a957f1e3d53119763732885221ef488250a2d81d8 *third_party/cosmo/2/exp_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/expm1_test.com.dbg.gz.sha256",
    "content": "bc3c4659476dba58bbd78534c8836686d24dca522ec5dbb63bb0151ae2c7df90 *third_party/cosmo/2/expm1_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/expm1_test.com.gz.sha256",
    "content": "707244b76f3f0d5f234b170ef273ce9624d41d11b0be6be969ae8f97660ef4ba *third_party/cosmo/2/expm1_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fabs_test.com.dbg.gz.sha256",
    "content": "ebe52d05e367c6871a82343fc8d133469e5041275e365c39335cc55a6fa45197 *third_party/cosmo/2/fabs_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fabs_test.com.gz.sha256",
    "content": "c0939b151a38ca4466cf24416baca690867031d6ecf572db22b1bc5db4dfdb4a *third_party/cosmo/2/fabs_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fcntl_test.com.dbg.gz.sha256",
    "content": "53e79e4ff57961dbf8da716e3ceef7b8d7df6722867dbab07250a95da052ccbb *third_party/cosmo/2/fcntl_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fcntl_test.com.gz.sha256",
    "content": "6965b196983560ee194b7cf6d0482dbca359e7cdb24d3a5b0f45e5a20b7d54a1 *third_party/cosmo/2/fcntl_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fexecve_test.com.dbg.gz.sha256",
    "content": "9a2bfd10596ad252b7bf1e16b4426bda828f3e815c8151192f953b857f492179 *third_party/cosmo/2/fexecve_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fexecve_test.com.gz.sha256",
    "content": "9ef160684d51cd99cfcc5cfe4786e103a6a264af8ac3040a2a521d508cabc61d *third_party/cosmo/2/fexecve_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ffs_test.com.dbg.gz.sha256",
    "content": "c26b6688444328cb44bea36b003db023b2006e64ff3fdf5150be94e3bbaaad97 *third_party/cosmo/2/ffs_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ffs_test.com.gz.sha256",
    "content": "952325142ae09229ee367f16fd5f4defc649d2d4f3912455d3b041e99b1fa327 *third_party/cosmo/2/ffs_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fgetln_test.com.dbg.gz.sha256",
    "content": "0f39976f335ebbbd2a48166a7817198768f85e1e832022dfa2d194d61cb7097a *third_party/cosmo/2/fgetln_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fgetln_test.com.gz.sha256",
    "content": "cd05d32de9fa92095e82c63875016f88be1e27959f2c2286205ec3e2a7d4878b *third_party/cosmo/2/fgetln_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fgets_test.com.dbg.gz.sha256",
    "content": "ef772a9986faadd35dc800085b74b0451751268f6b0c3db941af42971af0aee7 *third_party/cosmo/2/fgets_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fgets_test.com.gz.sha256",
    "content": "9bb1038f2ff9c4e261611bb2ec1867720f66d299493456a022f2421f2fc3fec1 *third_party/cosmo/2/fgets_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fgetwc_test.com.dbg.gz.sha256",
    "content": "3e447feade39dec34f1375b581cbb80024dbd77478be2b2f7c77c33af1dc1fc6 *third_party/cosmo/2/fgetwc_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fgetwc_test.com.gz.sha256",
    "content": "c1b02407c34e04a14453df8f92d2b5efc1c9e1e56835fa269cc53d8cb4dd8e19 *third_party/cosmo/2/fgetwc_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fileexists_test.com.dbg.gz.sha256",
    "content": "dfbffe3ab1baec968b55715adedc52b24255945007447762e638bd6f6c894406 *third_party/cosmo/2/fileexists_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fileexists_test.com.gz.sha256",
    "content": "84e5e23c7b8509fa2f944ceeb538e6b5b48c9429a426b95e3fca68e2004fda18 *third_party/cosmo/2/fileexists_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/findcontenttype_test.com.dbg.gz.sha256",
    "content": "9dc77af76868a67f1ec57f570ba5ae3f566d309de160811c7574971dc1d10347 *third_party/cosmo/2/findcontenttype_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/findcontenttype_test.com.gz.sha256",
    "content": "5b0b0d063c061bb5e816a02808f821786437689b6465df2f68727969af29442f *third_party/cosmo/2/findcontenttype_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fingersyn_test.com.dbg.gz.sha256",
    "content": "91c83b74eb7fdb1e9be4cac9da0708862be9941a1dc28aa7eae31deac049606c *third_party/cosmo/2/fingersyn_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fingersyn_test.com.gz.sha256",
    "content": "4f1182402c1d8f37a8af146eef213ff35645625384dd11ebd6abfbe793a929e8 *third_party/cosmo/2/fingersyn_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/floor_test.com.dbg.gz.sha256",
    "content": "0ee46adbe85e178438e6ab71086962084f79c2775896bef5e31e343e3ca315d9 *third_party/cosmo/2/floor_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/floor_test.com.gz.sha256",
    "content": "19e728034ecaabf7af6bb0c137821c144c12d6f57a7dc0159ebeb53965d2bbb3 *third_party/cosmo/2/floor_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fmemopen_test.com.dbg.gz.sha256",
    "content": "90c63de8e428d93824e6bed71e794f917de91f199d0d0022fc392229edfa7adc *third_party/cosmo/2/fmemopen_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fmemopen_test.com.gz.sha256",
    "content": "c3fadb837252eb9c2c6ccd9c2e1e7367cbf939462cc767241011066eed14e926 *third_party/cosmo/2/fmemopen_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fmod_test.com.dbg.gz.sha256",
    "content": "a3eab887743ee6c0da9fb4f95a6e9daadfd9f8b0f7fbfc373e0faf79171283ee *third_party/cosmo/2/fmod_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fmod_test.com.gz.sha256",
    "content": "d8a66cb658cb014287270235fcdbf6558b099a357d2d8014e3fdb05de6b68d1b *third_party/cosmo/2/fmod_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fmt_test.com.dbg.gz.sha256",
    "content": "ca665f87ab6c3ce727389e9cc4dcd78a5df10336083d756c548f468646a1f158 *third_party/cosmo/2/fmt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fmt_test.com.gz.sha256",
    "content": "aebcc8bf062d47240b8beaaf37de823a017c90b3c3f0ef6384565f011c1e3325 *third_party/cosmo/2/fmt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fork_test.com.dbg.gz.sha256",
    "content": "3215ac6defda3006fb65e84394340db0a7fd7c40e1969256f73580fb37e3515a *third_party/cosmo/2/fork_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fork_test.com.gz.sha256",
    "content": "4b108559419a474074c25956c7f89407638d6831b28f82ca418e094046b082e3 *third_party/cosmo/2/fork_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatbinary64_test.com.dbg.gz.sha256",
    "content": "9bb34dfcd79905192a191803153b3ef417d56da444c5caffac3e751834eecf89 *third_party/cosmo/2/formatbinary64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatbinary64_test.com.gz.sha256",
    "content": "d84907df3aaa418c4773481329f2827e154e50933663a933f20cb4ca5badc44e *third_party/cosmo/2/formatbinary64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatflex64_test.com.dbg.gz.sha256",
    "content": "51ef84e3be99d7a0c4e7edc98087300d3632a9d983e665d11c3db2769edd2c18 *third_party/cosmo/2/formatflex64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatflex64_test.com.gz.sha256",
    "content": "ca0e5d4ad5eb8de0c433a4f2e8f9aba54bc1a86d74a368a7a6d9e4b2f6aebdfe *third_party/cosmo/2/formatflex64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formathex64_test.com.dbg.gz.sha256",
    "content": "afdfc9cfd0e7f84a21847eaffe6c975112c35b1cdaae9cde82e096e578dfdddd *third_party/cosmo/2/formathex64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formathex64_test.com.gz.sha256",
    "content": "43c044e8bfde0c47966c5de7fce75faa3fe10b24a1139e5fc38aa8f9da70a610 *third_party/cosmo/2/formathex64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formathttpdatetime_test.com.dbg.gz.sha256",
    "content": "1948818dcae2c150b875001bad2eda5c2b5e75879e378fe1e52219a22a1bef74 *third_party/cosmo/2/formathttpdatetime_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formathttpdatetime_test.com.gz.sha256",
    "content": "9baca7033b31f798e853902c9bb8504088f57c75a0c320602c6afa652d05c6ce *third_party/cosmo/2/formathttpdatetime_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatint32_test.com.dbg.gz.sha256",
    "content": "ac33894de2c7904f6295e69ae27bc29530bb30d6753ef08978231bca7f206ac0 *third_party/cosmo/2/formatint32_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatint32_test.com.gz.sha256",
    "content": "fc1f834f09c14e51ffbcbc974d079494a05b8a457d01e1c262427f35e27e6c9d *third_party/cosmo/2/formatint32_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatint64_test.com.dbg.gz.sha256",
    "content": "190ccd3b4911e0b0f73acb50291a2ad7099a3e452a45ba320988c94a7eec43f7 *third_party/cosmo/2/formatint64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatint64_test.com.gz.sha256",
    "content": "6da02914bd7716e76e52e1eb2c918f638ffcb87cb2659c4b700af62f69a4c91a *third_party/cosmo/2/formatint64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatint64thousands_test.com.dbg.gz.sha256",
    "content": "8e60884f0cb117ee317e677b8b73a172f5fef7a162cdd6ee2c58698fc25cec51 *third_party/cosmo/2/formatint64thousands_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatint64thousands_test.com.gz.sha256",
    "content": "01bafb2b005c9fd14cdac35ee168e1b37ae0b48e6ad7a8f5e5cda77e95060c55 *third_party/cosmo/2/formatint64thousands_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatoctal32_test.com.dbg.gz.sha256",
    "content": "264ce4fe8c9ea14b320d5e1aeeb9ff33507623569cd4ef18a0402c7e7dd8b4e7 *third_party/cosmo/2/formatoctal32_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatoctal32_test.com.gz.sha256",
    "content": "63a408b7389ca192a6fe43d99b1b04420607417e6ad96f95c7892291589bdc5d *third_party/cosmo/2/formatoctal32_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatoctal64_test.com.dbg.gz.sha256",
    "content": "444492de3007688fa3384a6b2b73a8fa00c6cf697c3fdc28465b88e52f0428a3 *third_party/cosmo/2/formatoctal64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/formatoctal64_test.com.gz.sha256",
    "content": "b049483dff909b84f6fc247b74f07116caff39bbc90dc04bfbe3757e63807dec *third_party/cosmo/2/formatoctal64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fputc_test.com.dbg.gz.sha256",
    "content": "8163ba55600d8ecd32303e34db586837012219c01b19bb1bcd56f0df32283562 *third_party/cosmo/2/fputc_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fputc_test.com.gz.sha256",
    "content": "4b3e049596d99d68cea41b93909e7ffb7255f47fe75dbd57fa47bfdaf057a3a9 *third_party/cosmo/2/fputc_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fputs_test.com.dbg.gz.sha256",
    "content": "ab033faa6ed06a7487b2eb133b8a8b9934283c0647c7c434db1fa7263e31b901 *third_party/cosmo/2/fputs_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fputs_test.com.gz.sha256",
    "content": "daf14431b790a97c4fbb85f91a5b1cca6ac257d9dfd55340b2b278eed817a82c *third_party/cosmo/2/fputs_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fread_test.com.dbg.gz.sha256",
    "content": "e960c0130c3490886d9df7e3968aee267073e3a86fa04206d15207ae5fb1fa97 *third_party/cosmo/2/fread_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fread_test.com.gz.sha256",
    "content": "3cb80e97dd6e61ae6fdd5a598d14cd231bcfab54855930e87f8da0ec0762c1a2 *third_party/cosmo/2/fread_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/freopen_test.com.dbg.gz.sha256",
    "content": "f4cebebcfe22cd0a33640428496b895be851a17d1a9cd417ac71ac5657598ba8 *third_party/cosmo/2/freopen_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/freopen_test.com.gz.sha256",
    "content": "a14f2291219188ef0006fa965bcba961efeb5e103ef1c0f8168ba60792814278 *third_party/cosmo/2/freopen_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fseeko_test.com.dbg.gz.sha256",
    "content": "2528d7fad6bd01cd0ac284725297a13203deef7defd95ee59224f6b3a37b85df *third_party/cosmo/2/fseeko_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fseeko_test.com.gz.sha256",
    "content": "62b486ed3e9b971e7e289dff0256ccb962349f77d0e8ecfdf33ae60b32ebc2b4 *third_party/cosmo/2/fseeko_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fsum_test.com.dbg.gz.sha256",
    "content": "14ed5fdcb4f78e4ed2cf2e833b91d3849a48dd4401059edc82366336a3d4fb7c *third_party/cosmo/2/fsum_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fsum_test.com.gz.sha256",
    "content": "3bc5d2fd9195fc754049c29a88eb59f063f8eff0ecec0192521f47655d6dd4b5 *third_party/cosmo/2/fsum_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ftell_test.com.dbg.gz.sha256",
    "content": "b42311f2d4707d5e4f9d246fbf97815e06b594efcc9a47f6722335aa37e86893 *third_party/cosmo/2/ftell_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ftell_test.com.gz.sha256",
    "content": "7a36f38bedfe5d72dcc48fcec2b4d17466ce6dc23739f1e7aa9f298b5ea81b36 *third_party/cosmo/2/ftell_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fun_test.com.dbg.gz.sha256",
    "content": "8c748dde89cae3affc363b04677a9350381249c41c37d592739bd6a84131cb86 *third_party/cosmo/2/fun_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fun_test.com.gz.sha256",
    "content": "4e5b72f298d61a48221295d489c8f467071180a2e1466a20f6c6bd72debe58f8 *third_party/cosmo/2/fun_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fwrite_test.com.dbg.gz.sha256",
    "content": "4a277968122db5c0a5d019324ac1e8052e886909b31ae38747ab7e1eaedc4010 *third_party/cosmo/2/fwrite_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/fwrite_test.com.gz.sha256",
    "content": "a79fa764621662fc29154e36fcf48905ada3d4a0da6e5eb2d006c2b476594dc2 *third_party/cosmo/2/fwrite_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/gamma_test.com.dbg.gz.sha256",
    "content": "536553b8e919e1060333350691decab2302262bc484df8b7fdbd8bd74e553649 *third_party/cosmo/2/gamma_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/gamma_test.com.gz.sha256",
    "content": "f99b540df2e6937a01f0314526bcc5e1d24eaf2c782cd7bd245ba4f0c8349ba8 *third_party/cosmo/2/gamma_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/gclongjmp_test.com.dbg.gz.sha256",
    "content": "afe3dccecba471e00e0f7cbfb0142b28be30708fe05cf99c295eebcddd03a22e *third_party/cosmo/2/gclongjmp_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/gclongjmp_test.com.gz.sha256",
    "content": "aa5f9999c6b6622aa0878ef8f398244a2f22fddeddb701c20600b7408af634b4 *third_party/cosmo/2/gclongjmp_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getargs_test.com.dbg.gz.sha256",
    "content": "00f9d65d4facf3505ac40cdc06d041185b62f24bc0140e5b232058b856fbd4e4 *third_party/cosmo/2/getargs_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getargs_test.com.gz.sha256",
    "content": "6f0421dce3482bb279f83ea2a94cac5d87bdc612579ffe4c27b72f9fd35dfd82 *third_party/cosmo/2/getargs_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getciphersuite_test.com.dbg.gz.sha256",
    "content": "81c1d8bf18748b9b28bc7a1afa647e071be19a0873e76be63ad3cfa82e62db15 *third_party/cosmo/2/getciphersuite_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getciphersuite_test.com.gz.sha256",
    "content": "ad1f90df971289e58f876ae1bcd8aefe49f9a324e5a0c791003acbe0b891117b *third_party/cosmo/2/getciphersuite_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getcontext_test.com.dbg.gz.sha256",
    "content": "bb926db48835ade47ea27d8d7b33568cc1b44c67919dede26305b24b6d7fdabd *third_party/cosmo/2/getcontext_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getcontext_test.com.gz.sha256",
    "content": "7cd4c3a0c505e57f1372b869affdf845fe768f2336a76b1a5fb66b5a230aa7c2 *third_party/cosmo/2/getcontext_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getcwd_test.com.dbg.gz.sha256",
    "content": "7ece7b2a2bddaf50c49876461af75dc257df0f3f0c35f0a4d3ba72255cc712bd *third_party/cosmo/2/getcwd_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getcwd_test.com.gz.sha256",
    "content": "2085af3b863b6ce1581ee25d9726843b7e215d78b667d7485c54370e63cf62fd *third_party/cosmo/2/getcwd_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getdelim_test.com.dbg.gz.sha256",
    "content": "cdd45f683344b1a34d280d0c87d25546c4477d3cf599a6dffafbc89ab6f31f99 *third_party/cosmo/2/getdelim_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getdelim_test.com.gz.sha256",
    "content": "95aa74ad48b1ad4029e2d030d44f392002e1d6a5d13fe5dcdfb3b8709a9fa341 *third_party/cosmo/2/getdelim_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getdosargv_test.com.dbg.gz.sha256",
    "content": "50f27e4753c08c2757a680c3e6054251de75fff569a366e0c1f99e15f414837a *third_party/cosmo/2/getdosargv_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getdosargv_test.com.gz.sha256",
    "content": "5513f70052e5daf495b636701229bfe2f81fb4495b427c7d36c413585111214f *third_party/cosmo/2/getdosargv_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getdosenviron_test.com.dbg.gz.sha256",
    "content": "dc553d634196d2c776a67504cde496ce751b9a975d00feb18c10192894cc26fe *third_party/cosmo/2/getdosenviron_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getdosenviron_test.com.gz.sha256",
    "content": "959807fd31b45e14011c0173b13132987236cf12dc00b0485598daf2068b4abd *third_party/cosmo/2/getdosenviron_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getentropy_test.com.dbg.gz.sha256",
    "content": "81419cd84e63e22028a1ca1e42b5835cc981f6f760afeebc56893c5f763f3a0d *third_party/cosmo/2/getentropy_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getentropy_test.com.gz.sha256",
    "content": "07998d00e31521c3c70a842520c72a63275ccb01253216ccac1c0268e3f2051c *third_party/cosmo/2/getentropy_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getenv_test.com.dbg.gz.sha256",
    "content": "f5ef59ea5a83d2974035fd46f12708bd3a39368a7b2b9e4f10a384f9be0c36bd *third_party/cosmo/2/getenv_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getenv_test.com.gz.sha256",
    "content": "33129db368f501d632dba1d87fc7ad4ad53c5176f1f1196a0087601829dfcd44 *third_party/cosmo/2/getenv_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getgroups_test.com.dbg.gz.sha256",
    "content": "eb5a566efd19663c355b8732dd0d46f4ba06eb0971b2de0b421439b4534e233e *third_party/cosmo/2/getgroups_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getgroups_test.com.gz.sha256",
    "content": "4683d4852fd5d844e503656ea4fa141a085faa6064ab396002ec725de580e2fc *third_party/cosmo/2/getgroups_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getintegercoefficients8_test.com.dbg.gz.sha256",
    "content": "3199d2ac4f26888eaf2b10ecc9d950e80599d8af87534aba2c1c50e3947d995e *third_party/cosmo/2/getintegercoefficients8_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getintegercoefficients8_test.com.gz.sha256",
    "content": "c2ba4262e41e564be1d8e0cc20d75ba1343d6abfbab86e4e0a9ffa330d52e603 *third_party/cosmo/2/getintegercoefficients8_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getintegercoefficients_test.com.dbg.gz.sha256",
    "content": "b956792d4333ae9d25891036af5b68fad122e4c9295eebd13b561f614aa29119 *third_party/cosmo/2/getintegercoefficients_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getintegercoefficients_test.com.gz.sha256",
    "content": "bb5a8c2afcce9234890f5e989e84b1c7f4fe5a78a7cd872fc439e8dec4fba7f4 *third_party/cosmo/2/getintegercoefficients_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getitimer_test.com.dbg.gz.sha256",
    "content": "c41c13f1f77fdbebf6061b02908eef49b51c489232d5a05f1cbec9155488bc5f *third_party/cosmo/2/getitimer_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getitimer_test.com.gz.sha256",
    "content": "7f1c6058515039fefe6e11660ac76df04e8ec648c30ba2b1605216d8a51ab0c3 *third_party/cosmo/2/getitimer_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getpriority_test.com.dbg.gz.sha256",
    "content": "c71131a80863dd7869e2e04b905d815b51661b61b909df2417f29c2b187cff5f *third_party/cosmo/2/getpriority_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getpriority_test.com.gz.sha256",
    "content": "2fb5666ad0d7e73da09d4d92ffac055c2d4b85b1a3b98c29fcb691b3f15a634e *third_party/cosmo/2/getpriority_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getrandom_test.com.dbg.gz.sha256",
    "content": "643607fde6dbda1fa5ba0bf468b170aa747c9aae96fc48c8ef2c507408e94bb5 *third_party/cosmo/2/getrandom_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/getrandom_test.com.gz.sha256",
    "content": "662920d1f8b1d394b742c7976803a2f285802f06a134ee5c31c0e4581ad772c9 *third_party/cosmo/2/getrandom_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/grow_test.com.dbg.gz.sha256",
    "content": "36ae164187fc5746fc49664a4c02636a8a86d529f2b3e7b8668ee0d1809ee8db *third_party/cosmo/2/grow_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/grow_test.com.gz.sha256",
    "content": "2fa4b14405cfe803b46e8436656e19df5cc0fd45223d286b861ead973589a22f *third_party/cosmo/2/grow_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/gz_test.com.dbg.gz.sha256",
    "content": "1836a84c4794e62599de88c649a5a2cdd4d7c599b5d16f10855301d75408a371 *third_party/cosmo/2/gz_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/gz_test.com.gz.sha256",
    "content": "9ecf8a237547a0440b51d9038860374d274217e302907b7cb7f9fa48d438539f *third_party/cosmo/2/gz_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/halfblit_test.com.dbg.gz.sha256",
    "content": "872b2ae0409910ce681e177ebdaaabddcd288103429b63abe9358ee79a0519b8 *third_party/cosmo/2/halfblit_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/halfblit_test.com.gz.sha256",
    "content": "c464a3db220dc441257c9dc7291b8ec84286e63af6b3e906fe05136f4656b666 *third_party/cosmo/2/halfblit_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/hascontrolcodes_test.com.dbg.gz.sha256",
    "content": "ab02c442e0c77ba70ca8fe887ffc0032a8152dedf5872821416ce7818ae9a058 *third_party/cosmo/2/hascontrolcodes_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/hascontrolcodes_test.com.gz.sha256",
    "content": "5a4df550670c9f3cec776b3da21b07610007761470c7b0a9844be837b134bc53 *third_party/cosmo/2/hascontrolcodes_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/hexpcpy_test.com.dbg.gz.sha256",
    "content": "ac75562a2eb046383e7bce3f8fc7e27326835cb985a1eeb70d88e6349e780148 *third_party/cosmo/2/hexpcpy_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/hexpcpy_test.com.gz.sha256",
    "content": "ada42d0d612ff5ed44d71fdc525c5cdfb77147df26c69d5ddf8d413a1e05f45e *third_party/cosmo/2/hexpcpy_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/highwayhash64_test.com.dbg.gz.sha256",
    "content": "5cf97482dcb2bb05afe52b700258273a722b7bad08153debee738e79327892fe *third_party/cosmo/2/highwayhash64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/highwayhash64_test.com.gz.sha256",
    "content": "bd8cbcde32718bf2618b7c142e7eaf3dbad2d819441a993b359832adb307eeef *third_party/cosmo/2/highwayhash64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/hypot_test.com.dbg.gz.sha256",
    "content": "a8d834b5c9be57ec1a5aded5b0b557b08a1eb95d9fab247f94383f305a8f3499 *third_party/cosmo/2/hypot_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/hypot_test.com.gz.sha256",
    "content": "1071afbd62a6189cbe28a409310faf6c82ac0a44d9f79d3bd053dc0e4cfbf47b *third_party/cosmo/2/hypot_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/iconv_test.com.dbg.gz.sha256",
    "content": "a624163c1b28d07af091457058aaad91644b03d2116bc755bb6d0b45e651c792 *third_party/cosmo/2/iconv_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/iconv_test.com.gz.sha256",
    "content": "e516ad38c84ec5caf12ed346cd59f0462897bfd8a171c44a9ca50c7e894f11c9 *third_party/cosmo/2/iconv_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/illumination_test.com.dbg.gz.sha256",
    "content": "0261f2145220e46ccab08c50396fa8068ef269b56dc07b2099f2b7a7729c5830 *third_party/cosmo/2/illumination_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/illumination_test.com.gz.sha256",
    "content": "0205aa8a7da103e2dbaf0dd808d1415dd4ba8ae45dae289ae30018f35d98477b *third_party/cosmo/2/illumination_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ilogb_test.com.dbg.gz.sha256",
    "content": "62ac77f3d4fff95c017f4423f317b3365d4bde01e6c43607e82a61c309d998cc *third_party/cosmo/2/ilogb_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ilogb_test.com.gz.sha256",
    "content": "d67959ddc9a05853dd35d9fc52054c2abe308b9f7f643696b43f00d16e51a622 *third_party/cosmo/2/ilogb_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/imaxdiv_test.com.dbg.gz.sha256",
    "content": "a1ec4cb7567465b7f8826ebe23f522cd6196117ec0a70e8a4795d170475a0f03 *third_party/cosmo/2/imaxdiv_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/imaxdiv_test.com.gz.sha256",
    "content": "b2850d35fc469ce39678f1c033e9e066f5681e6f147ece0d68d9f7755a8ccb9d *third_party/cosmo/2/imaxdiv_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/indentlines_test.com.dbg.gz.sha256",
    "content": "37006c075f4bccf55e174e5ad8476711a4d9a902422e5c86ad69bf8a63a58c2f *third_party/cosmo/2/indentlines_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/indentlines_test.com.gz.sha256",
    "content": "40a7b9ecb204d828689c3affa54f32402a968f23840edeec662943d8c7dc344b *third_party/cosmo/2/indentlines_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/inet_ntoa_test.com.dbg.gz.sha256",
    "content": "4ce09fe654e7a9aa2473611fa5ea2ac3b867860ff973ab962deffc750fede6d9 *third_party/cosmo/2/inet_ntoa_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/inet_ntoa_test.com.gz.sha256",
    "content": "e03cc9aa842be4d3e11bf076bf632f174eb72f1d2f835d65321a1567f5e2bf98 *third_party/cosmo/2/inet_ntoa_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/inet_ntop_test.com.dbg.gz.sha256",
    "content": "7949648699cb2eaaaaa3b438a2b6f7fe9338e16175356e46bd9128bd6931983e *third_party/cosmo/2/inet_ntop_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/inet_ntop_test.com.gz.sha256",
    "content": "6022f20a32c694bad9e1e573fbac7a0dfefff75fcf5fa9d3d3671075d0e9d770 *third_party/cosmo/2/inet_ntop_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/inet_pton_test.com.dbg.gz.sha256",
    "content": "8151177fc7a6c617a7c3a55075c1818c85cfefa6c70feabbde41320c3d7812c7 *third_party/cosmo/2/inet_pton_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/inet_pton_test.com.gz.sha256",
    "content": "7a0277f80fba647ffe7f701d898c310968812fdfe6e74d1ae091e1850ca9473e *third_party/cosmo/2/inet_pton_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/integralarithmetic_test.com.dbg.gz.sha256",
    "content": "867d6043fed687e653d198db1b1df2d283b8dda535849be017f31d0d932e6764 *third_party/cosmo/2/integralarithmetic_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/integralarithmetic_test.com.gz.sha256",
    "content": "0389b021ac4acc3241026d52ecb582c9f4826e85e2a1a31ff4c08049dea435d3 *third_party/cosmo/2/integralarithmetic_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/interner_test.com.dbg.gz.sha256",
    "content": "95b3c454d317a71ba34c62891c9601087df6618dfbc855418a716bd2b25014e6 *third_party/cosmo/2/interner_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/interner_test.com.gz.sha256",
    "content": "4797298b2e3ac6ff2e7038400a3408e3209c4aba7ac1ffc16a3307128edba26f *third_party/cosmo/2/interner_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/inv3_test.com.dbg.gz.sha256",
    "content": "f1b752e7051ab20d96eaed05ab6ba62da5bbebb5358358708a8b1cfa18c95165 *third_party/cosmo/2/inv3_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/inv3_test.com.gz.sha256",
    "content": "f645f820ad0e5e4e3be73d722668989bf91f0d3817af26418bfee9f5a971a01f *third_party/cosmo/2/inv3_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ioctl_siocgifconf_test.com.dbg.gz.sha256",
    "content": "533f7ea23fe63ee0a0cd25cf62bdc3de8a3c7b1f6591e8b44ed5c3242fb6e880 *third_party/cosmo/2/ioctl_siocgifconf_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ioctl_siocgifconf_test.com.gz.sha256",
    "content": "17045d46d14021c07ba95c38ed6e6b03632fbe72df88b2b48f2e4e8748295890 *third_party/cosmo/2/ioctl_siocgifconf_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/iovs_test.com.dbg.gz.sha256",
    "content": "350b508db0aca82e7ded5b7beb3485a018395996786f96b154663b370e74761a *third_party/cosmo/2/iovs_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/iovs_test.com.gz.sha256",
    "content": "3fdc24276fac6c7a3b57ef6814bec2bd588c02f4fcaf8f64ca52438626150672 *third_party/cosmo/2/iovs_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/isacceptablehost_test.com.dbg.gz.sha256",
    "content": "6d644607360a46d2a06d9f502e504c52c36370be876e163d7c8cc64da524eaa0 *third_party/cosmo/2/isacceptablehost_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/isacceptablehost_test.com.gz.sha256",
    "content": "be2a97ff6880d64931057db43378208894a701bf1ac3b5f767de48f88c8193b2 *third_party/cosmo/2/isacceptablehost_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/isacceptablepath_test.com.dbg.gz.sha256",
    "content": "ab2c6b5478497e1d048953b7966462964efe008fceb412e18dec7531be69a306 *third_party/cosmo/2/isacceptablepath_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/isacceptablepath_test.com.gz.sha256",
    "content": "0b369bca7f4af28823f94fe4d3e09c05ae711a4862c4801f1bf1d7a08fd9fa23 *third_party/cosmo/2/isacceptablepath_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ismimetype_test.com.dbg.gz.sha256",
    "content": "5d066b150415da1ac1ee3d0d076ad3ba88a02f51c815710523cb8fa2cab01a4d *third_party/cosmo/2/ismimetype_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ismimetype_test.com.gz.sha256",
    "content": "3f8753a2612756b72a55f661fde363804c541b51e24c1f2d066da945e5586ca9 *third_party/cosmo/2/ismimetype_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/isnocompressext_test.com.dbg.gz.sha256",
    "content": "32f462b319f4681679cb097e570d95cc81a3871ab363bec5cd48f8a4c761b905 *third_party/cosmo/2/isnocompressext_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/isnocompressext_test.com.gz.sha256",
    "content": "820d206bda17106fe90115498a47e6ecc6188814ea00378a6debf8489fe98457 *third_party/cosmo/2/isnocompressext_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/iso8601_test.com.dbg.gz.sha256",
    "content": "7b3e9eef4c51fc44f2bf8fc178babfe4975ba7a18e994152801ff939e9c0057a *third_party/cosmo/2/iso8601_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/iso8601_test.com.gz.sha256",
    "content": "8841581f8bdc43419a0b525a703e05fd043a1d12d5649eeac10a20c335870f9d *third_party/cosmo/2/iso8601_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/isreasonablepath_test.com.dbg.gz.sha256",
    "content": "ddb3353b74b5ee953a94b4512bda09b56309ecc245b772f1d038f4b5d56654de *third_party/cosmo/2/isreasonablepath_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/isreasonablepath_test.com.gz.sha256",
    "content": "fe5aae804528c2d33717f28e0d6ff857c7b70f912fe2e4842ff5e39f79ce2fb5 *third_party/cosmo/2/isreasonablepath_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/isutf8_test.com.dbg.gz.sha256",
    "content": "ea4c084d17065493596f8033bfc87be5266dba8a8fd70132bb3939bbf18d03a8 *third_party/cosmo/2/isutf8_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/isutf8_test.com.gz.sha256",
    "content": "5edc7cf6f594143a438501b6b4a3bcaf33ca4d585e91d2d4d739a0364761352a *third_party/cosmo/2/isutf8_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/itoa64radix16_test.com.dbg.gz.sha256",
    "content": "a373bab161ede9da4151603ae88b14822f819c60948117b66ba01f6a33c4b746 *third_party/cosmo/2/itoa64radix16_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/itoa64radix16_test.com.gz.sha256",
    "content": "0193c55eefc72f73095deae3b61e3a027119785183d49aa3b2aae428a92fb6dc *third_party/cosmo/2/itoa64radix16_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/itsatrap_test.com.dbg.gz.sha256",
    "content": "11d5deec3312269773209f65221ed0752b33694fb364224f37dae9b099a7d346 *third_party/cosmo/2/itsatrap_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/itsatrap_test.com.gz.sha256",
    "content": "76484104a536fdd196fc154338ca2051455232799167acf05bac5c547d18b5d4 *third_party/cosmo/2/itsatrap_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/javadown_test.com.dbg.gz.sha256",
    "content": "a60200457d52a89baa14aec2c0659b32d1e4cd27bc62355209e2aa728bc670fd *third_party/cosmo/2/javadown_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/javadown_test.com.gz.sha256",
    "content": "72190341d4d020134c769c5475220da47e8d93dc34f2524c691f4e554b7f448c *third_party/cosmo/2/javadown_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/joinpaths_test.com.dbg.gz.sha256",
    "content": "23e74d7785a9aa5ec3f40500fc9f504eb33546f8f3d82e46191005ca4fad535c *third_party/cosmo/2/joinpaths_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/joinpaths_test.com.gz.sha256",
    "content": "b420712bc3eb56ef55b53f901d73fe16cc57bde4ab310512f5a206be382cca68 *third_party/cosmo/2/joinpaths_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/joinstrlist_test.com.dbg.gz.sha256",
    "content": "87241442bbb3911206d63f591964f4965af0d728cf3cb30c7a0c95cd20f87033 *third_party/cosmo/2/joinstrlist_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/joinstrlist_test.com.gz.sha256",
    "content": "9272af11b89bb6fe26596d3af56f788fa347225632f103172d6505f8a330f2ea *third_party/cosmo/2/joinstrlist_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/kbase36_test.com.dbg.gz.sha256",
    "content": "41ecc70c1a6f6ca328682f6f83563e31628ac7ed5d963dd7b25bb66935530a47 *third_party/cosmo/2/kbase36_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/kbase36_test.com.gz.sha256",
    "content": "5763a473c77a5fe8964da533b24769e4ccd59c896b0f9ec2a0c5cdc744ae61ac *third_party/cosmo/2/kbase36_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/kcp437_test.com.dbg.gz.sha256",
    "content": "7da2b2363c69074d79a1adeec70165ddd5b57ecbe962da088f87dbc9c783b968 *third_party/cosmo/2/kcp437_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/kcp437_test.com.gz.sha256",
    "content": "362e283d0bb91360351661839d768e64537050ccb5a7622af210f13f7986f65c *third_party/cosmo/2/kcp437_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/kprintf_test.com.dbg.gz.sha256",
    "content": "e6582254e7fc253d655537709801055d6a4d9b11ac235605ff27e5e791688e27 *third_party/cosmo/2/kprintf_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/kprintf_test.com.gz.sha256",
    "content": "d8ec72756ef85677fc9465286cc4e8bbc810a938188dbd62df67783f9bc7980a *third_party/cosmo/2/kprintf_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ldexp_test.com.dbg.gz.sha256",
    "content": "a717217f384fa3c76244fd1b4ae40b8a76e7102a1786db3abd0005d013aa2d75 *third_party/cosmo/2/ldexp_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ldexp_test.com.gz.sha256",
    "content": "d094242874639a913f77037307c85b2a58b89b9cba336fcd7f5ea7c584ab5321 *third_party/cosmo/2/ldexp_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lengthuint64_test.com.dbg.gz.sha256",
    "content": "87414910ee5055d568149734cfd090efcf9d18d3cf669f6bfc96bd0354a16bbb *third_party/cosmo/2/lengthuint64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lengthuint64_test.com.gz.sha256",
    "content": "d1e49a3a849e26a08f2136c751f2f08a8cf9fba0a9dab83e4d7ae233aedf8064 *third_party/cosmo/2/lengthuint64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lock2_test.com.dbg.gz.sha256",
    "content": "b687ed9f27318fbcce2660e5265ba59870d6777d82dc1ff428edc7b89209095a *third_party/cosmo/2/lock2_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lock2_test.com.gz.sha256",
    "content": "fed1324f63894a853f2a2d42f776426dc843eec9b498a22d26197646dd72b14f *third_party/cosmo/2/lock2_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lock_ofd_test.com.dbg.gz.sha256",
    "content": "7697adb980b37dc473b5dc4d52938fc0b2b3621cfbf72c8861cf0b05e292d341 *third_party/cosmo/2/lock_ofd_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lock_ofd_test.com.gz.sha256",
    "content": "23a84487bcaf66491fcbd6940e8d902550e5bb1a9998e9c7633f362332ad7f88 *third_party/cosmo/2/lock_ofd_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lock_test.com.dbg.gz.sha256",
    "content": "5773f35d0a40e615c325a714db5faa664860d97b44c6b0b2822f51abcab062de *third_party/cosmo/2/lock_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lock_test.com.gz.sha256",
    "content": "861de42ba4e1aada689b9243c202dd1c95f2079f02d958050afd2338c529ced5 *third_party/cosmo/2/lock_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lockipc_test.com.dbg.gz.sha256",
    "content": "681cbccc5a938ef9ed5039d739768d31c8727e155317593d10ec0b119126aa8f *third_party/cosmo/2/lockipc_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lockipc_test.com.gz.sha256",
    "content": "df1d5582d9858cf5d1cd71e46ee4ad45b03540c3feb0181d2f349822e5081427 *third_party/cosmo/2/lockipc_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lockscale_test.com.dbg.gz.sha256",
    "content": "7e0cdf8046f3081ad1077387227e49eee564e3d5daf91388f29d634796044755 *third_party/cosmo/2/lockscale_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lockscale_test.com.gz.sha256",
    "content": "f07569afadc793271d9dcbce70252708699f44e61d96fda24bb9179bc0d10b47 *third_party/cosmo/2/lockscale_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/log10_test.com.dbg.gz.sha256",
    "content": "5a88f623901ef09283a9560fd2cce11db417e93e6d014e0ccd87606bf62bb4b9 *third_party/cosmo/2/log10_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/log10_test.com.gz.sha256",
    "content": "d647e2ad8a3f162ed600b1a2f63e2b2f3a86219d2558e569d38c8784f3ab6d63 *third_party/cosmo/2/log10_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/log1p_test.com.dbg.gz.sha256",
    "content": "7ece073d8c261ca4edebf4b6b5fbacd2c3b6ce99024ce1e3a2d13fe3169ba2c1 *third_party/cosmo/2/log1p_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/log1p_test.com.gz.sha256",
    "content": "a775dac605b0efe1855a849fa7d2c4468ffb09af53876805929fb865e574c4b7 *third_party/cosmo/2/log1p_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/log2_test.com.dbg.gz.sha256",
    "content": "9b172efa27854d6fae1789bda147d7091356fcfd15310d25635661217b0dd4c1 *third_party/cosmo/2/log2_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/log2_test.com.gz.sha256",
    "content": "21cf424e3e382df15a6c64b66335d7233674645536dd5d8d338ee6784c2eab19 *third_party/cosmo/2/log2_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/log_test.com.dbg.gz.sha256",
    "content": "121232703186c42eccace93d2deca105dacce7ad7fe0e7c4e4e9186b8015cadc *third_party/cosmo/2/log_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/log_test.com.gz.sha256",
    "content": "7603da056abe74d4c317bbc6832d040f391eec95732f637038411ac0ed4cdd8b *third_party/cosmo/2/log_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/logb_test.com.dbg.gz.sha256",
    "content": "7d1cc2182377196dcc5d2e2664f5a99c0088aa71dbc7878a01e53570812e815d *third_party/cosmo/2/logb_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/logb_test.com.gz.sha256",
    "content": "424de909d19f661c4dc3d69e08a81fac76000516cb8639f4692477ae3419030c *third_party/cosmo/2/logb_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/longsort_test.com.dbg.gz.sha256",
    "content": "00c879a9b8da282af5a984aa3360fff0d2392a2946dd6640f5c1e4708da62464 *third_party/cosmo/2/longsort_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/longsort_test.com.gz.sha256",
    "content": "4b2882316d3c4450595a868adaadc5c5480ea803589fa377aa5d252108c70624 *third_party/cosmo/2/longsort_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lseek_test.com.dbg.gz.sha256",
    "content": "f72dd55bfe8b282ad371865c6818fc12777f36adc7444b2d386aad9cc9550dcf *third_party/cosmo/2/lseek_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lseek_test.com.gz.sha256",
    "content": "c51bc452e175613673c98a1cf4838e0979c1fce894fa761becceea9f76886358 *third_party/cosmo/2/lseek_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lz4decode_test.com.dbg.gz.sha256",
    "content": "49983f4f0c48fb85d074201f4b07cbf8c63b3e059cf72331fbebe3b3eb443b43 *third_party/cosmo/2/lz4decode_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/lz4decode_test.com.gz.sha256",
    "content": "6481095b0137cb5c6d91f1c0065bddfbe6a3c9167b1070aea259f4a883cc8f30 *third_party/cosmo/2/lz4decode_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/machine_test.com.dbg.gz.sha256",
    "content": "4437d59fdefbcf0e2d17be65cf44ce76c1c152a6cc09a2dc798ecf29eac5993d *third_party/cosmo/2/machine_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/machine_test.com.gz.sha256",
    "content": "f96971189fe9f88cc543a1471a9fe615351f2d4ab13b89cfbaeeef75ba1cf1f8 *third_party/cosmo/2/machine_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/magikarp_test.com.dbg.gz.sha256",
    "content": "8c717f4bb995e57a3e89909f2757d8d86324eda3d20e5d48bb29e77e83d54e10 *third_party/cosmo/2/magikarp_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/magikarp_test.com.gz.sha256",
    "content": "fba0d3cca5c154c039f5e6d76e07af4368a01fa48ce4c9f6ade1caeebe738219 *third_party/cosmo/2/magikarp_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/makedirs_test.com.dbg.gz.sha256",
    "content": "8028ddbe9ca4fe669bb9a0d5a5c999b608de64f1a3d721788752ef985e0b60e6 *third_party/cosmo/2/makedirs_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/makedirs_test.com.gz.sha256",
    "content": "94c3c37ddeb782140605f6824f5d9d8300e4f1ee78f8d40b93a7cd4217bbd3c8 *third_party/cosmo/2/makedirs_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/malloc_test.com.dbg.gz.sha256",
    "content": "03fc7c2b5ae1416f85797a00b135d2838ecbb8b5cb1cdd9a232aff0e1e079207 *third_party/cosmo/2/malloc_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/malloc_test.com.gz.sha256",
    "content": "badf632181fd03358c5ceb2a8c28bca8bf0ff2482530beb789fb754eb481b1ac *third_party/cosmo/2/malloc_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mbedtls_test.com.dbg.gz.sha256",
    "content": "9067281f5018763113d73e09e252380f4d07b1e603217a17f7b933566ee9cd66 *third_party/cosmo/2/mbedtls_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mbedtls_test.com.gz.sha256",
    "content": "ce50f28aa9d8221940a16b338f18866c84816c6285de8167881f0962faab2fc4 *third_party/cosmo/2/mbedtls_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/measureentropy_test.com.dbg.gz.sha256",
    "content": "93cec08eeda7a3287a803657350fbfcc1d1e1d4a0543e6bf18e30e40bcc501b3 *third_party/cosmo/2/measureentropy_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/measureentropy_test.com.gz.sha256",
    "content": "25f88fbc25c3ae7c7cf4338abb5f46a25bbd9f3f2c91a1b7e90b722b42c0f4d7 *third_party/cosmo/2/measureentropy_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memcasecmp_test.com.dbg.gz.sha256",
    "content": "3d21d6d3a464592ebdfec6f5f083f24e7272261399b105d4d0744117b31f7951 *third_party/cosmo/2/memcasecmp_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memcasecmp_test.com.gz.sha256",
    "content": "c6fc5ec55b7eeb3864520e27bb2f16f1ba10262e3de9e721be5f824aed8e8f39 *third_party/cosmo/2/memcasecmp_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memccpy_test.com.dbg.gz.sha256",
    "content": "178771c7b5d4b579c6d420fdaa083165fab7e8eba8d434df40905773c2f488f4 *third_party/cosmo/2/memccpy_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memccpy_test.com.gz.sha256",
    "content": "14550c7423fb6dce05c023ad588cbe667a9a1fe0ef15d302899c7ee053c16a8e *third_party/cosmo/2/memccpy_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memcmp_test.com.dbg.gz.sha256",
    "content": "ca3207db06158b15c76d208e735cbc7d5d6bf3f349d65b02763bcb787a5c4504 *third_party/cosmo/2/memcmp_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memcmp_test.com.gz.sha256",
    "content": "a79f0e95f350b9a5ac13c3e807fe159cf52396d779ae9bc758f6eca8dbeaa884 *third_party/cosmo/2/memcmp_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memcpy_test.com.dbg.gz.sha256",
    "content": "678e68f2b86afe19a84f393c1483224c5e26ac8bbb8d29e076e1c5aafbf665b4 *third_party/cosmo/2/memcpy_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memcpy_test.com.gz.sha256",
    "content": "0d9f555ec0c0939b4595eb3ff7ca6676d9edacc0f6d452b83cc5032f37c7f132 *third_party/cosmo/2/memcpy_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memfrob_test.com.dbg.gz.sha256",
    "content": "1098f7d4ddc2530f58e8a3ba7371dd8e342123072011eec4b9bcd2e24d38d6c6 *third_party/cosmo/2/memfrob_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memfrob_test.com.gz.sha256",
    "content": "d27a70f71fe85400f6c2b6710a973a6d5df6de64f4de3afea4d24fc6d0aea246 *third_party/cosmo/2/memfrob_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memmem_test.com.dbg.gz.sha256",
    "content": "feac23ab6872dcafeb252ff46fb0fc9809e162e3682829f1a64f2291a034d0a9 *third_party/cosmo/2/memmem_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memmem_test.com.gz.sha256",
    "content": "75a04036d701af907b85778ff3a84408c459824237ae5e4ccd609c2299abbe0e *third_party/cosmo/2/memmem_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memmove_test.com.dbg.gz.sha256",
    "content": "bf46ca95bb4657f6a4d81618d79f3f93761a8366bde8ab63ebf918c751a157ff *third_party/cosmo/2/memmove_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memmove_test.com.gz.sha256",
    "content": "7beef583ced89f16bbb8a1dc9525417302a1e1cb3c9589177d8519a6733fe48d *third_party/cosmo/2/memmove_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memory_test.com.dbg.gz.sha256",
    "content": "4b376d59ee97349cfe43a87b488f7138ced4e816421efedecea9826d16932b87 *third_party/cosmo/2/memory_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memory_test.com.gz.sha256",
    "content": "f8a37334f2dfeca797e1ab76d0a94193d8a6934baec7c0d388794d33cd757fc4 *third_party/cosmo/2/memory_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memrchr16_test.com.dbg.gz.sha256",
    "content": "24cb50cf061392ac98be278cdd0da4fe6592dbe1a38e140f06e7b13a68d2e350 *third_party/cosmo/2/memrchr16_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memrchr16_test.com.gz.sha256",
    "content": "078d426dfcab8964f1c3d0c0e3a40ddfeef9b6546e566639ab287050e4e19772 *third_party/cosmo/2/memrchr16_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memrchr_test.com.dbg.gz.sha256",
    "content": "e49645a6a0f2bad1d02693850ebdbd7a3113bae16a0dcb234c9aefec8e5af818 *third_party/cosmo/2/memrchr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memrchr_test.com.gz.sha256",
    "content": "0cd14f467c1a27d77c0dd99d6a028c2dbd686b2959f57b269ef6c06ffe5b35c9 *third_party/cosmo/2/memrchr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memset_test.com.dbg.gz.sha256",
    "content": "06ca14383b19c4435a54bd6bd32ade0175f0863cc94fd9bb338aa8206b64c6db *third_party/cosmo/2/memset_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memset_test.com.gz.sha256",
    "content": "23f3abb9f28959a66167b094aab97027e73a94068c41f149552c6441e6967b52 *third_party/cosmo/2/memset_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memtrack_test.com.dbg.gz.sha256",
    "content": "ecdf844e6fb63056b53c51fd6269b70c74e03d25a00d7a45045eee40e449d995 *third_party/cosmo/2/memtrack_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/memtrack_test.com.gz.sha256",
    "content": "fe7d18b2ddcccbc9adb299c2370cc7ba4d1a560359f21ee77ef0ea87eaa4ee81 *third_party/cosmo/2/memtrack_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mkdir_test.com.dbg.gz.sha256",
    "content": "23ba648375433aee0d8bfed50ebb426372eb962f8cfa5183240864243bd05427 *third_party/cosmo/2/mkdir_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mkdir_test.com.gz.sha256",
    "content": "5c4fbcad5bf4a9ccebcf4caf824b5db7dab47a201c7dd5ffb7ee10a98f27b0c5 *third_party/cosmo/2/mkdir_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mkntcmdline_test.com.dbg.gz.sha256",
    "content": "6dcae375bb9be30c8c2f868b2797ac50e24298a9ed7e06c0c16a6165c60285b6 *third_party/cosmo/2/mkntcmdline_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mkntcmdline_test.com.gz.sha256",
    "content": "970485d6fb9200a4d7f0152cd691c30535846f7697270721757de7a9b7e43ec2 *third_party/cosmo/2/mkntcmdline_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mkntenvblock_test.com.dbg.gz.sha256",
    "content": "28f1c17d098a9607eb65d1b7b9d109b98002d461b3385150c3566a1d208ddf62 *third_party/cosmo/2/mkntenvblock_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mkntenvblock_test.com.gz.sha256",
    "content": "69404f142a9907868f670953aa542e394ecb11fd278b92ae7cd5f926ecb793a0 *third_party/cosmo/2/mkntenvblock_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mkntpath_test.com.dbg.gz.sha256",
    "content": "41670f81aed64cd9c44e5c5ad76f062ee63fbd59486ac63a6c47f27b28b9455c *third_party/cosmo/2/mkntpath_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mkntpath_test.com.gz.sha256",
    "content": "a76058ffb2162c25d8eaa777cff51a49a04be116b7211d659db2a336083fa565 *third_party/cosmo/2/mkntpath_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mkostempsm_test.com.dbg.gz.sha256",
    "content": "cfd77f94f0b019badbf12c1643444afe7cdc7eafad38fc452316e452a2266055 *third_party/cosmo/2/mkostempsm_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mkostempsm_test.com.gz.sha256",
    "content": "901d79ceffd97e0416a32af3ac075461548eb599d925f2fc4d16f4c4987259c4 *third_party/cosmo/2/mkostempsm_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mmap_test.com.dbg.gz.sha256",
    "content": "24320053d253f2cb5adbcd73d12642e095d5cbee58bb7f139ce2fdd32614e0f4 *third_party/cosmo/2/mmap_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mmap_test.com.gz.sha256",
    "content": "b05d3395cf82c6a714644400b07de30a2a67d7bcee5f0a4d2f95b27a964be993 *third_party/cosmo/2/mmap_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/modrm_test.com.dbg.gz.sha256",
    "content": "fc573db4b44ccbb58971728a3881a9e9c78f66fae4eadf149e1f691507f68aaf *third_party/cosmo/2/modrm_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/modrm_test.com.gz.sha256",
    "content": "5e966fb3918fe6d2eaa4ca6fa37e31b445bc3d5c7c39c2826afed406388d5b8d *third_party/cosmo/2/modrm_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/morton_test.com.dbg.gz.sha256",
    "content": "bf7dd317f3afcbde44c996627fac77c5ec055287ca790f30030075f93e2a3cad *third_party/cosmo/2/morton_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/morton_test.com.gz.sha256",
    "content": "160c688772dccf737c449983ca006509c407a78994a9e1d7b1ad1bda9f244e68 *third_party/cosmo/2/morton_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mprotect_test.com.dbg.gz.sha256",
    "content": "b1aea0a56e12c55d0d297c5f3a1c070a5b5804c1fbde765679cd3abde1310299 *third_party/cosmo/2/mprotect_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mprotect_test.com.gz.sha256",
    "content": "887951a3940d5f81be1447723a294dff6836912acbde3360674c2675d73bec4f *third_party/cosmo/2/mprotect_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mt19937_test.com.dbg.gz.sha256",
    "content": "a1dbcaf13f3085c2214c9c67445886ad030113863f6f030c0f30bea80dc9f33f *third_party/cosmo/2/mt19937_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mt19937_test.com.gz.sha256",
    "content": "cc3b746f052378521bfe0a549bd8863102685eca428f18f5716d3d7876806176 *third_party/cosmo/2/mt19937_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mu_starvation_test.com.dbg.gz.sha256",
    "content": "0c8a07a0cff141083a3b65e3363e6487360f67563fe00d46ef189c9fcb567428 *third_party/cosmo/2/mu_starvation_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mu_starvation_test.com.gz.sha256",
    "content": "d6609b53f9cc34a34d759a2a3c89b76bc186ac22d6dcc465b0163230fa6265bd *third_party/cosmo/2/mu_starvation_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mu_test.com.dbg.gz.sha256",
    "content": "f9f56b6a98ccc723ad85b462eaa44f57e271679c3383c7569839121f310b21d1 *third_party/cosmo/2/mu_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mu_test.com.gz.sha256",
    "content": "63ea8c6c369a5f369213eb1dfabbd1e4ff7502601af698b8c960b5bf57ff5a27 *third_party/cosmo/2/mu_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mu_wait_example_test.com.dbg.gz.sha256",
    "content": "2d2c16ad4232c57fae9c61f92eae71ff8e3a95d18dd86e0f8cc3d7cb28bcfd91 *third_party/cosmo/2/mu_wait_example_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mu_wait_example_test.com.gz.sha256",
    "content": "2f42b030167daa9a289eb4eb59a491d8858cdee0923d2a944e02a98319e76bad *third_party/cosmo/2/mu_wait_example_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mu_wait_test.com.dbg.gz.sha256",
    "content": "e363510691ef19c4f470dc763f2ddbb64b82291b40b9879d7ade45afd82ea591 *third_party/cosmo/2/mu_wait_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mu_wait_test.com.gz.sha256",
    "content": "e287ef4069462f445d41ade63e743ebfcc94dd033ca5792c606d7602b5a099d0 *third_party/cosmo/2/mu_wait_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mulaw_test.com.dbg.gz.sha256",
    "content": "2117d369da1ceae17ea9833d8e0e7b3a12f54b825567dd78e66f990c1738f88f *third_party/cosmo/2/mulaw_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/mulaw_test.com.gz.sha256",
    "content": "8f2e08d87dc5e7ad697f8af42bcdb644f9ee06a1c6dad3d3b5cf8d81c9812ec9 *third_party/cosmo/2/mulaw_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/nanosleep_test.com.dbg.gz.sha256",
    "content": "6fe7a594c63e74113eca70602d42cb5f49bfe46706133c0d675940ca27907069 *third_party/cosmo/2/nanosleep_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/nanosleep_test.com.gz.sha256",
    "content": "5421b2ba4d696c0da2ece1cefaee111c7bbe593da72eaa8b60bbc436949ceb57 *third_party/cosmo/2/nanosleep_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/nointernet_test.com.dbg.gz.sha256",
    "content": "527922ebf5dbde376e87aa746aeb744f541a25a40aa0770074b4ab4af21ea72c *third_party/cosmo/2/nointernet_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/nointernet_test.com.gz.sha256",
    "content": "40a24431c60b7141b79d09c10b04212deaf01a55ee07ac4a47150aabb4cb96d4 *third_party/cosmo/2/nointernet_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/note_test.com.dbg.gz.sha256",
    "content": "22531925190f88f7675c19b8a1bba52cc39234f9476c1feb716a1c3b6e5648e7 *third_party/cosmo/2/note_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/note_test.com.gz.sha256",
    "content": "9f9666e9c5d2cf64ca27e1eafa9a48eb966b594f3ae27d39b6a0d74d64d748b1 *third_party/cosmo/2/note_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/nsync_test.com.dbg.gz.sha256",
    "content": "3aef603bbcbf6a22da89c6f4dd6e52e154fe4acb566a34dc7b6e18456853ddba *third_party/cosmo/2/nsync_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/nsync_test.com.gz.sha256",
    "content": "723dd2b96eca1f635cf44871402f135017c5650f8bc0440df8804a65a7401cd4 *third_party/cosmo/2/nsync_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/omg_test.com.dbg.gz.sha256",
    "content": "feb631fcf7458db82e540e5466fad83e3a93a1d77f8adcb986d4b3f1f7e21e9f *third_party/cosmo/2/omg_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/omg_test.com.gz.sha256",
    "content": "10a3c29664bdd636510d3e61d213b9d341477ca31f48e192ac4f63677a7fcb88 *third_party/cosmo/2/omg_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/once_test.com.dbg.gz.sha256",
    "content": "fd5e11ce578626211d4495c74901f99faa4429cefd0db0875aa302c855c36342 *third_party/cosmo/2/once_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/once_test.com.gz.sha256",
    "content": "1b217834a7bc4348baf7791bcd68469146cdeab8467286dd94ca8413e151ef72 *third_party/cosmo/2/once_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/open_test.com.dbg.gz.sha256",
    "content": "5cbf1d5be4a126b8c1a06b6fa5f2364a1a66d9633a8e4b9097e573288afeb891 *third_party/cosmo/2/open_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/open_test.com.gz.sha256",
    "content": "34d836a1b8378f4e190dd4505d8ec1bf416a3c451dd89733e16312104e6df042 *third_party/cosmo/2/open_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/openbsd_test.com.dbg.gz.sha256",
    "content": "4fe25c901a408a337d62719811ce1bd4e9c2b2397fed1abbefb7fae19d0dd26f *third_party/cosmo/2/openbsd_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/openbsd_test.com.gz.sha256",
    "content": "f34302823886055024e0189241b8ffb29be17574c40235b42b2df93d244fba51 *third_party/cosmo/2/openbsd_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/palandprintf_test.com.dbg.gz.sha256",
    "content": "464976f25befa044fb89a9e0bf683de0d010b8eff52a9e47acecee3008708972 *third_party/cosmo/2/palandprintf_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/palandprintf_test.com.gz.sha256",
    "content": "b64b567c4b546325342688ae6607d1ef8d3101422c91b99c33ac9176407d8240 *third_party/cosmo/2/palandprintf_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/palignr_test.com.dbg.gz.sha256",
    "content": "6276fd7147e9a03b52d62e85a4c87afa5d0505a72c885cd708072f8c7b1c2801 *third_party/cosmo/2/palignr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/palignr_test.com.gz.sha256",
    "content": "b52fcf7facaad60cd19f24d8f7e66110fe7ec67ec92b0c5191a8df0f6765eec8 *third_party/cosmo/2/palignr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsecidr_test.com.dbg.gz.sha256",
    "content": "e98015908d15524fafe10e85d815845a1e703b03fed6066084bb5112edd789df *third_party/cosmo/2/parsecidr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsecidr_test.com.gz.sha256",
    "content": "fbb174a638b1122a5e08a6238d159a96864ea87ac5e1cd4a1f5cc3ca3adf9f88 *third_party/cosmo/2/parsecidr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsecontentlength_test.com.dbg.gz.sha256",
    "content": "4110fa235a840dde9780ba56bd6231e0d5f4429158ddf8f25a0413cee2311946 *third_party/cosmo/2/parsecontentlength_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsecontentlength_test.com.gz.sha256",
    "content": "bb63e29bb6d3da4f24d51766b7a0b4b9c47212d23427514f4c514ecb52d14915 *third_party/cosmo/2/parsecontentlength_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parseforwarded_test.com.dbg.gz.sha256",
    "content": "0483d5c584beb743eb4ab0f6915c839cb9c03c7a337d7e3af4457195c8a50e18 *third_party/cosmo/2/parseforwarded_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parseforwarded_test.com.gz.sha256",
    "content": "687f0394a718e12469922266f046c7c90b56784f69eafeb2e0e04a6f66338377 *third_party/cosmo/2/parseforwarded_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsehoststxt_test.com.dbg.gz.sha256",
    "content": "c00df83837b663674e98809b42c450ab27da1b74320382d81faee42fc3105bee *third_party/cosmo/2/parsehoststxt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsehoststxt_test.com.gz.sha256",
    "content": "6707b83867b3d2c6dc556a0d20f2f2056ec9248f3e950dceb139b6bb0c831950 *third_party/cosmo/2/parsehoststxt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsehttpdatetime_test.com.dbg.gz.sha256",
    "content": "3440e0fd7a7073d841aeb5937385b12f2f9ca89e065fb5daabf3f397eeecf0bf *third_party/cosmo/2/parsehttpdatetime_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsehttpdatetime_test.com.gz.sha256",
    "content": "ad660ae0ec5eae2fc63c18a06c85cd3a84df65d4c0fdf5a1d212a7e92454f1f5 *third_party/cosmo/2/parsehttpdatetime_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsehttpmessage_test.com.dbg.gz.sha256",
    "content": "de918e4e54577478d1856152fe20a20e85bd5db27769fd8a3cc65ba6fcced308 *third_party/cosmo/2/parsehttpmessage_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsehttpmessage_test.com.gz.sha256",
    "content": "2f0721c17b97f109b613a7c92b014e0e75b2cdcfd5cd32cbab2fe5077127df47 *third_party/cosmo/2/parsehttpmessage_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsehttprange_test.com.dbg.gz.sha256",
    "content": "c2c0fe5aaca3000987621e6130a1a5777222eb355a0f79877332719264b975e7 *third_party/cosmo/2/parsehttprange_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parsehttprange_test.com.gz.sha256",
    "content": "3797782745735c9b222abc1e643ebb05e2a583fb3a9559908eb88febec99fc81 *third_party/cosmo/2/parsehttprange_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parseip_test.com.dbg.gz.sha256",
    "content": "0da62f37490b820b986d2ce16e843ecc51d881911f291b268daa95c2a1fd32ef *third_party/cosmo/2/parseip_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parseip_test.com.gz.sha256",
    "content": "3793ea4d241dffaea3421437e0a3b84a2c803061b48d420a9a7ce064add4025f *third_party/cosmo/2/parseip_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parseresolvconf_test.com.dbg.gz.sha256",
    "content": "13dacfc8905382072a74ff8e05b32ccd2c01bac1e870305ac4f7e241e5e259f7 *third_party/cosmo/2/parseresolvconf_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parseresolvconf_test.com.gz.sha256",
    "content": "5cf9af2443255178fb94301528c394aed2b6096abd01d2c75fb8f42ef2f4f440 *third_party/cosmo/2/parseresolvconf_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parseurl_test.com.dbg.gz.sha256",
    "content": "0f5e836108fd82c9e1d2ed63e190e39f5f5a3f2d0366ab319acf2b6189ff328e *third_party/cosmo/2/parseurl_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/parseurl_test.com.gz.sha256",
    "content": "3d2f20a255be78843a3899591894dfe9f4fef604c5faeb489460227b4ffb694f *third_party/cosmo/2/parseurl_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pascalifydnsname_test.com.dbg.gz.sha256",
    "content": "b97b640d196f57c295b4154b6e25701f71a08e307aa94d73c937217f74c4e2fd *third_party/cosmo/2/pascalifydnsname_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pascalifydnsname_test.com.gz.sha256",
    "content": "028e8986d60ad3a1dbb2c32ef9ef58e90e9d00ebd259428844e57f4527bfe37a *third_party/cosmo/2/pascalifydnsname_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pcmpstr_test.com.dbg.gz.sha256",
    "content": "270a57db1103cb5fe5e36e2f97c6cdc4385945732e4f8b003e5e731745f35568 *third_party/cosmo/2/pcmpstr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pcmpstr_test.com.gz.sha256",
    "content": "3952d152cf2e1e4221fa8a918f6f32920e2de1d5259612647f6453d9bbe7fbd6 *third_party/cosmo/2/pcmpstr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pingpong_test.com.dbg.gz.sha256",
    "content": "89d26b9b9aac079f5e12fe286cfeb60ac86f55a391c00a9a955b854390a8d20e *third_party/cosmo/2/pingpong_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pingpong_test.com.gz.sha256",
    "content": "8c5e9424163bdfbfe734e27571a9142aadd98bf6dccd96d8dabe88785ac4eb89 *third_party/cosmo/2/pingpong_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pledge2_test.com.dbg.gz.sha256",
    "content": "8de8753f112d1d790180ac4b05ffbd6471f03e5e9626adf25c9fb9fb40ffb561 *third_party/cosmo/2/pledge2_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pledge2_test.com.gz.sha256",
    "content": "95450d8db76bbbc1112ae81e84a9fdbd37d7f744eadca5e83f92690c7bf8d149 *third_party/cosmo/2/pledge2_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pledge_test.com.dbg.gz.sha256",
    "content": "10dd1f3ef7b709216a455d0b4763ae1a740ae9c04f9deae2512f472aeb4e5872 *third_party/cosmo/2/pledge_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pledge_test.com.gz.sha256",
    "content": "9f21d4cc6edc98993f55efa66324fedb09bf0fb848d360b8b78dfbd26bfdfcdf *third_party/cosmo/2/pledge_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/plinko_test.com.dbg.gz.sha256",
    "content": "8c24b1eb027c5906631cfc4823a4c3279610794272073ee71156e278208b45d2 *third_party/cosmo/2/plinko_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/plinko_test.com.gz.sha256",
    "content": "2464269f73c9a5612e5cd7e9811ee791de99d71c9520398da56588c3826e4367 *third_party/cosmo/2/plinko_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pmulhrsw_test.com.dbg.gz.sha256",
    "content": "33aa0a7bcf766934f96b64b30308b94d8e8d438541c007c16e4b88f79a12f779 *third_party/cosmo/2/pmulhrsw_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pmulhrsw_test.com.gz.sha256",
    "content": "13b6674409b5d6c6844789d431c633c2254f1c4ff265e61c5cb9a0a233cd2ee0 *third_party/cosmo/2/pmulhrsw_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/poll_test.com.dbg.gz.sha256",
    "content": "9e118d9063ec84d44a61645bca9c366dd5e487d8b39f4bfc55ec2582833a06a3 *third_party/cosmo/2/poll_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/poll_test.com.gz.sha256",
    "content": "9642b9eb9cb6af6f7e3cd39810f844abdabbd5a3b5a2649c79cf08d6ad442c76 *third_party/cosmo/2/poll_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/popcnt_test.com.dbg.gz.sha256",
    "content": "22f8c0746e78fd3998b610ebf6644c9f44809bba3a68a2aad5335421a4010aa5 *third_party/cosmo/2/popcnt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/popcnt_test.com.gz.sha256",
    "content": "01b4e728daec992f2a2e4ec21c9d36343e41b186888c4b3d64d2905e5a57a484 *third_party/cosmo/2/popcnt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/popen_test.com.dbg.gz.sha256",
    "content": "c158d6aa8b8a2097da60f3348542a9666a33fbd847aa9234d29e37eb80ee6ee5 *third_party/cosmo/2/popen_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/popen_test.com.gz.sha256",
    "content": "b7320aa725a8d47a3cd66527d50b86264e309633e3f7ba20e56176c8effa7cb8 *third_party/cosmo/2/popen_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/posix_fadvise_test.com.dbg.gz.sha256",
    "content": "1a4a0d705336d9adfb52309ff30fe0904d4ee8ecfd2b3fb1df2cd04f95fc1f98 *third_party/cosmo/2/posix_fadvise_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/posix_fadvise_test.com.gz.sha256",
    "content": "b13d930cab6b35961cd71afac40f187155bcc22756b5f6f54244ee7820a41c81 *third_party/cosmo/2/posix_fadvise_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/posix_spawn_test.com.dbg.gz.sha256",
    "content": "5150b4b1b95d1b51737a656d8582052fa3485fbe532824767807534766d570e6 *third_party/cosmo/2/posix_spawn_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/posix_spawn_test.com.gz.sha256",
    "content": "6cc1086b98ac734f430eb2f717581e7513173cf820c14482b73e3a25be42c10d *third_party/cosmo/2/posix_spawn_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pow10_test.com.dbg.gz.sha256",
    "content": "265b2f239a21accabab0c0aa406a037a2412cea7fd170036bde1e1b6b2182bc1 *third_party/cosmo/2/pow10_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pow10_test.com.gz.sha256",
    "content": "9d50aea3ce34d607179d66dcd160c0bf58596bdff65cbda583edc89507018aab *third_party/cosmo/2/pow10_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/powl_test.com.dbg.gz.sha256",
    "content": "574c984e3e4e601e48b41743de692261af56f45a24298256af281680011849d7 *third_party/cosmo/2/powl_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/powl_test.com.gz.sha256",
    "content": "4a2a5da9461e437481d48eddbfd02bd3acf12b806d15211d849c924b5d5b5b75 *third_party/cosmo/2/powl_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pread_test.com.dbg.gz.sha256",
    "content": "d7ed17f32b09056999dd5150d3103d88e74b1096ae066a41623bd7459dba17f9 *third_party/cosmo/2/pread_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pread_test.com.gz.sha256",
    "content": "fa23c945cd36d72bda1a6462c275b8214ebe6ede8a7fe02ce2750c1a0941bd89 *third_party/cosmo/2/pread_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/preadv_test.com.dbg.gz.sha256",
    "content": "f0464611099c956c2f3efdf7dc4dc03e2f21f7860a7fa21ff151f5a91641d4e8 *third_party/cosmo/2/preadv_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/preadv_test.com.gz.sha256",
    "content": "a062f6d2585d40041bbc923a88274350ef380559ec71564f4ab8e465c4ab66ff *third_party/cosmo/2/preadv_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/printargs_test.com.dbg.gz.sha256",
    "content": "c87e10a06be315a22c06993cd63a7f4963b622774f8747642599c4f58adb1aca *third_party/cosmo/2/printargs_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/printargs_test.com.gz.sha256",
    "content": "44bc076ead398c250ea2f69e303bea858919faca7fa8e0aa41e62a8f02358527 *third_party/cosmo/2/printargs_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/prototxt_test.com.dbg.gz.sha256",
    "content": "d60d3eb290715e1a7397edbbe51b294fea52210888fc114dc68658e8472dac59 *third_party/cosmo/2/prototxt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/prototxt_test.com.gz.sha256",
    "content": "45fe32054858bdf6c945642b942aeaa4a585d83ed5644c7b5acb9bf0f51fb3a0 *third_party/cosmo/2/prototxt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pshuf_test.com.dbg.gz.sha256",
    "content": "8a8f8c30249cdfee4e349babad18ca6ceb04051ccdea9c9f6eb227639482a9c5 *third_party/cosmo/2/pshuf_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pshuf_test.com.gz.sha256",
    "content": "39d677a82ae462d7601acf6a8d9d85746e6a01ddc70f64f1e1942adab4e3addb *third_party/cosmo/2/pshuf_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_atfork_test.com.dbg.gz.sha256",
    "content": "8830aaa436d43980375370f65bebdd0a7f5dcea6e3a3c0c41d78f31570413d1b *third_party/cosmo/2/pthread_atfork_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_atfork_test.com.gz.sha256",
    "content": "d81304a820c3ad930fbc027da2a2de0bd8faa97f44f36be2ca1b9e39477ba250 *third_party/cosmo/2/pthread_atfork_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_barrier_wait_test.com.dbg.gz.sha256",
    "content": "996ce4887d9936eda01e3a0b8e119e3b3328155ad6c561308867fa610c44cc73 *third_party/cosmo/2/pthread_barrier_wait_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_barrier_wait_test.com.gz.sha256",
    "content": "dfd1c9627e8e5dbd6033e43c180419db235cae4073186c3cbe72a97aa46e2b2a *third_party/cosmo/2/pthread_barrier_wait_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_cancel_test.com.dbg.gz.sha256",
    "content": "4ac8af933b0f482a2c09170096f85ac8ffec886dd9ae2cfbf604a008819b3f38 *third_party/cosmo/2/pthread_cancel_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_cancel_test.com.gz.sha256",
    "content": "09eaeba7c4d18a85155d849f08819b39d30658628c5021d89eec1b447d8ab869 *third_party/cosmo/2/pthread_cancel_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_cond_signal_test.com.dbg.gz.sha256",
    "content": "fdddac58927017beebb8795cad942b91e680f2cc8c351a574d497404a3429ae0 *third_party/cosmo/2/pthread_cond_signal_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_cond_signal_test.com.gz.sha256",
    "content": "bbba18107a0800a6d1af40aa41f2ed54adaf80614542bd4c737656192b85bfad *third_party/cosmo/2/pthread_cond_signal_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_create_test.com.dbg.gz.sha256",
    "content": "0ea07383beb6dd927a0b600fcd90782cf1e14678a787bbaad88cbd7220e0fc41 *third_party/cosmo/2/pthread_create_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_create_test.com.gz.sha256",
    "content": "d327c401e5eaf92ceb5f90368c9bb7e584480da987c803fbfd987d8320086892 *third_party/cosmo/2/pthread_create_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_detach_test.com.dbg.gz.sha256",
    "content": "4194106f334b0cc7feab49fcc0f865e360f7f19aee172a29e238eee969fdaf38 *third_party/cosmo/2/pthread_detach_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_detach_test.com.gz.sha256",
    "content": "e7a98180949685bac7a7c2081372eddba8cadb9c857d39bba9cf9c41dd9dff1c *third_party/cosmo/2/pthread_detach_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_exit_test.com.dbg.gz.sha256",
    "content": "7784a26790d342f6b24f8c73c2832ba339629d0fe7b3986b8bf7cd94945bcbd1 *third_party/cosmo/2/pthread_exit_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_exit_test.com.gz.sha256",
    "content": "c93846b3c601bf608f9ce9f9c6a594c0e22acfacdc2b5e13e87b1a6736f30b01 *third_party/cosmo/2/pthread_exit_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_key_create_test.com.dbg.gz.sha256",
    "content": "3944c49178ced4d1e6ec25f99c80dc45bab726b7c25dd461619df86bc441205e *third_party/cosmo/2/pthread_key_create_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_key_create_test.com.gz.sha256",
    "content": "0ac8bf575bdc63c88af61bfe008ffc8fe61c222be6dfe64daf61245a82221bdf *third_party/cosmo/2/pthread_key_create_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_kill_test.com.dbg.gz.sha256",
    "content": "d3271abbcec21425bb0ab7902031eeba6f669e7fc3b4417b74d7c2fb98f7f125 *third_party/cosmo/2/pthread_kill_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_kill_test.com.gz.sha256",
    "content": "435f45043ddf4d4e44c8e162795d2044ff6ae5651d01238659a819e4771070ac *third_party/cosmo/2/pthread_kill_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_mutex_lock2_test.com.dbg.gz.sha256",
    "content": "72cfeb0b0bc91d3de96962fc182d806a0b5f26fb5291eb7213e83d82a984f7c3 *third_party/cosmo/2/pthread_mutex_lock2_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_mutex_lock2_test.com.gz.sha256",
    "content": "c65fb4682a440bdf6df8b2f0f13a497273013d82c050a5fc4c186d47bf2b31e6 *third_party/cosmo/2/pthread_mutex_lock2_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_mutex_lock_test.com.dbg.gz.sha256",
    "content": "f0896e9ce8c132ff7e1507692908cab92f1e06e2060ebd85093e41e37c3130e3 *third_party/cosmo/2/pthread_mutex_lock_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_mutex_lock_test.com.gz.sha256",
    "content": "e234713bc92fa658bc8e9a38ad536b4f0edd48357f48b055a80f0d21391c0923 *third_party/cosmo/2/pthread_mutex_lock_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_once_test.com.dbg.gz.sha256",
    "content": "b39d8d4d48d23b06a36bd7dacafe28f16713e8d08cb6f7a1b2263d004cdbc2a3 *third_party/cosmo/2/pthread_once_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_once_test.com.gz.sha256",
    "content": "1f5c6622d7511c03f3b72c712a908afdc7c71437522ed228db1ff514964ffeae *third_party/cosmo/2/pthread_once_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_rwlock_rdlock_test.com.dbg.gz.sha256",
    "content": "b25273cc7cc38b98f063bf9062228c3a538425ac629b991cd47f65d918117788 *third_party/cosmo/2/pthread_rwlock_rdlock_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_rwlock_rdlock_test.com.gz.sha256",
    "content": "d8b07ef1d1d52488f49d689b00f3714093aff769e3181029e27648a122199098 *third_party/cosmo/2/pthread_rwlock_rdlock_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_setname_np_test.com.dbg.gz.sha256",
    "content": "95bbb433853fc9d580f1a5d9282c98af402859aeaee37df5688ccb3ab6669214 *third_party/cosmo/2/pthread_setname_np_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_setname_np_test.com.gz.sha256",
    "content": "36c9b690a24c75ce1e3a4a445eb034ef65a942ebc69b2a3f81aca2ac493e2264 *third_party/cosmo/2/pthread_setname_np_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_spin_lock_test.com.dbg.gz.sha256",
    "content": "c9253c7fac98fed0db9d0222113a1f9908174813025e1714f74845e76529e326 *third_party/cosmo/2/pthread_spin_lock_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pthread_spin_lock_test.com.gz.sha256",
    "content": "10bd69ae8099711f4cce9c586df084494982ec4c26a886dd70e10cfccd63fb6d *third_party/cosmo/2/pthread_spin_lock_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ptrace_test.com.dbg.gz.sha256",
    "content": "e0f0d172e6ad0354161c2472a7cb62d145f69a593d4c1d790a302e51d3e10ab5 *third_party/cosmo/2/ptrace_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ptrace_test.com.gz.sha256",
    "content": "1860b84f7251db2f1641bc4d88a7fa678be1500aa88e70037e003d4f90383458 *third_party/cosmo/2/ptrace_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pty_test.com.dbg.gz.sha256",
    "content": "b9c5b0efae93498c82afb5478a4f80cd59f0284f42d99b02f05d322b57a2eb85 *third_party/cosmo/2/pty_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pty_test.com.gz.sha256",
    "content": "0219e5b71b3d0ff31d81d5dc7a2e4c316842d2f91f04e78e1b9fe2db94b290c0 *third_party/cosmo/2/pty_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/putenv_test.com.dbg.gz.sha256",
    "content": "c52c7ee432a3bdac0d30dcb0bb80d8d7934291d7cf2104e8ad0f398d59aa4de1 *third_party/cosmo/2/putenv_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/putenv_test.com.gz.sha256",
    "content": "e79689beaad790159ab920624a1d376503c4fdf2a4ccf6440c30c17d7a971ffe *third_party/cosmo/2/putenv_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pwrite_test.com.dbg.gz.sha256",
    "content": "957f84c738c144f3f46afedbe537c993632f02278085891a89af30f05bc6b5ca *third_party/cosmo/2/pwrite_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/pwrite_test.com.gz.sha256",
    "content": "aafc963493bdc8641cff377a3a6a28a32d9cbcc3cbdc34ccf0f7cc5c89cdb1fb *third_party/cosmo/2/pwrite_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/qsort_test.com.dbg.gz.sha256",
    "content": "41e0dd947608b56afb5bd9cb6d52acfb75249996d9cc99a82c991ec20f087d88 *third_party/cosmo/2/qsort_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/qsort_test.com.gz.sha256",
    "content": "47af44bda67e9c3557f9bb0185345aae2f013943c964497424fa3b5904be1c29 *third_party/cosmo/2/qsort_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/raise_race_test.com.dbg.gz.sha256",
    "content": "dc90d6d8767dc6c2abbaff811a3492796585755aa60e76bfbc9b02d3da4ebcbf *third_party/cosmo/2/raise_race_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/raise_race_test.com.gz.sha256",
    "content": "463183fba06c1a5179cc1ec7459e0beb6d3fff8c3094d50e210862fe5469b31f *third_party/cosmo/2/raise_race_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/raise_test.com.dbg.gz.sha256",
    "content": "aa732f8ff4415634eeeca102ac03bccdb448b698890de562090b04251f1ea2f8 *third_party/cosmo/2/raise_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/raise_test.com.gz.sha256",
    "content": "82f3ced9e60699a6614e0e2698e2b6aa1c8490ae58610e72b8c767ccddf2fb49 *third_party/cosmo/2/raise_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/rand64_test.com.dbg.gz.sha256",
    "content": "6cb7985151cad6a82ecce7ecf1eeee2d04cbec64e678cbba6ae031148ac53089 *third_party/cosmo/2/rand64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/rand64_test.com.gz.sha256",
    "content": "ec18678128d07be110f1ead46662bbaa2a5c06a2e9dd3c03157770249c99461a *third_party/cosmo/2/rand64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/rand_test.com.dbg.gz.sha256",
    "content": "5ce0e5155c8d7b0eeee1269a3ddab60fcbafe9eae7bf253068dad8bf21667925 *third_party/cosmo/2/rand_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/rand_test.com.gz.sha256",
    "content": "bee6eb7e7a108f7072ccef4e7e9b68e968f7bc75039dd2a03bb66fe7863e8cec *third_party/cosmo/2/rand_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/read_test.com.dbg.gz.sha256",
    "content": "e8a9a0a8c162b945da40ecfce3a4ff5f0e55eb23f83eb466ef7c6f5f0a693d3e *third_party/cosmo/2/read_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/read_test.com.gz.sha256",
    "content": "ec8c22fa6918a37244df94b0caa529b01fa70f9262007051e23a19e858f1e4e5 *third_party/cosmo/2/read_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/readansi_test.com.dbg.gz.sha256",
    "content": "2ce31f453a10b0e42ca39ebb64ffc881ca0fa65f4a1d4fac371dbc8b03a067c7 *third_party/cosmo/2/readansi_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/readansi_test.com.gz.sha256",
    "content": "44d9d574f5185755666d655cd7e42c74fd352703d8a226401e2987de22914b01 *third_party/cosmo/2/readansi_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/readlinkat_test.com.dbg.gz.sha256",
    "content": "251230ab5b7f14ee2b211cda28d2e48f99a1bbfa8020501534c228c15eac1779 *third_party/cosmo/2/readlinkat_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/readlinkat_test.com.gz.sha256",
    "content": "0891de755332373e7bc3d903be36f72de5ed375e2447acef6ddfd28a4d7f3e8d *third_party/cosmo/2/readlinkat_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/realloc_in_place_test.com.dbg.gz.sha256",
    "content": "fa9a01b118b0b70266e1fbb690dba38b68f04e784765f2cec42b04549a996972 *third_party/cosmo/2/realloc_in_place_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/realloc_in_place_test.com.gz.sha256",
    "content": "055a37b28b72acf40e7916545c5114adf011a16b91b59ee20ac22aaacbb48000 *third_party/cosmo/2/realloc_in_place_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/redbean_test.com.dbg.gz.sha256",
    "content": "3b6f7689739bc2cb1c6ff1f95cf3dfb3afa23fe9c65b576f4675daaef23638b2 *third_party/cosmo/2/redbean_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/redbean_test.com.gz.sha256",
    "content": "ab1b75356696cbaef8d942b813549b047a73ca24dcb5bc27eeec7cd1e52978b0 *third_party/cosmo/2/redbean_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/regex_test.com.dbg.gz.sha256",
    "content": "95cb414c767d44ff8e093565c5d93ee5334e08b004efcb21a2737458cb832321 *third_party/cosmo/2/regex_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/regex_test.com.gz.sha256",
    "content": "5ac50fab0989ab7b4994c28b2be0df4201537d967abf955bf6406bb255bd37f5 *third_party/cosmo/2/regex_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/renameat_test.com.dbg.gz.sha256",
    "content": "cc3f4b03ec4948e914f5afe0e3bf43de678dcda38fcce36e1280699a2959f39b *third_party/cosmo/2/renameat_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/renameat_test.com.gz.sha256",
    "content": "5c2c9063eb3c2f5ec818d9af406fec804a3d77fb7f1538db3641acf6f96d8460 *third_party/cosmo/2/renameat_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/replacestr_test.com.dbg.gz.sha256",
    "content": "08267108d1e2c17e191b6ee5bd053b7fce7574560eca8a0ff4adb263a0de2d2f *third_party/cosmo/2/replacestr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/replacestr_test.com.gz.sha256",
    "content": "b2849af2858dc465462acc2f4a72570f1206c5fbe41c9c5a555bfe5107174d50 *third_party/cosmo/2/replacestr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/reservefd_test.com.dbg.gz.sha256",
    "content": "b81169624e29f251c8528e4da4a5519ec793b93d3dd4878399e5f454c8348595 *third_party/cosmo/2/reservefd_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/reservefd_test.com.gz.sha256",
    "content": "0861822186520f1df9b23b7b2c6e5c7ede19283c1b9dd1c51d7c709557b6aa9d *third_party/cosmo/2/reservefd_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/resolvehostsreverse_test.com.dbg.gz.sha256",
    "content": "55df6dfe924acc83fdb9495603b78b9576b3686db413330409630726b0f55303 *third_party/cosmo/2/resolvehostsreverse_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/resolvehostsreverse_test.com.gz.sha256",
    "content": "03ecc0a9231a8fa1e454b5d6b4fe1523b4c835bb6d9e97ddb2a07dcd155547c8 *third_party/cosmo/2/resolvehostsreverse_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/resolvehoststxt_test.com.dbg.gz.sha256",
    "content": "e0d78c6d6715fbf18fdc84921d638c1155471b475848deefd83ef6143541794c *third_party/cosmo/2/resolvehoststxt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/resolvehoststxt_test.com.gz.sha256",
    "content": "1c97c7a2b33453ebd96e546d84b2feb663e69c41d1aa355e384dcd0e2814601f *third_party/cosmo/2/resolvehoststxt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/reverse_test.com.dbg.gz.sha256",
    "content": "7b8a649203703afa71c63819034a90fcd0438da95d53dbdf55f83a03835f8cc4 *third_party/cosmo/2/reverse_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/reverse_test.com.gz.sha256",
    "content": "84047c8cad3e0a96b31179f12afd37feca24b652bde20057a62f6d48ca83bf0f *third_party/cosmo/2/reverse_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/rgb2ansi_test.com.dbg.gz.sha256",
    "content": "6e400a33e9c6d4b8ddda9f3d906a9f76c4a19a6d04fa78f6ff73abb7c7a9640c *third_party/cosmo/2/rgb2ansi_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/rgb2ansi_test.com.gz.sha256",
    "content": "0bc8d8884593194a130c59a3e7851ab280595b7c1ec50d3eed5cd318c8965c57 *third_party/cosmo/2/rgb2ansi_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/rngset_test.com.dbg.gz.sha256",
    "content": "16a844f17e55b43f0f481e096a5b27613087cf9318cc68dbbf2baafea8686862 *third_party/cosmo/2/rngset_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/rngset_test.com.gz.sha256",
    "content": "8b84008dcc3b43d16bd05ad5efe186ac6abe31758f13d6c9c1a6570c9796dc7f *third_party/cosmo/2/rngset_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/round_test.com.dbg.gz.sha256",
    "content": "68c32e7640a3a6908f470bd8b8ce9097ecb92b8ef47c13b21bb216afed0f5140 *third_party/cosmo/2/round_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/round_test.com.gz.sha256",
    "content": "c7e3cb380f6c12afeadcf2c6a7677d69f15b964dd63ed3be3cc55829e7aee898 *third_party/cosmo/2/round_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/rounddown2pow_test.com.dbg.gz.sha256",
    "content": "267f470e53c78076aab56b9649f75e625644ba9e3ef03f601ab8def505c16916 *third_party/cosmo/2/rounddown2pow_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/rounddown2pow_test.com.gz.sha256",
    "content": "43a3c42b254c587b40681bc08d0395a0bf99d275603434afe066a67f7fa1b1d2 *third_party/cosmo/2/rounddown2pow_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/roundup2log_test.com.dbg.gz.sha256",
    "content": "39c5e80a80b905755300eec7a5dbe9a7638460e2d8c2bda707a6442562d34b38 *third_party/cosmo/2/roundup2log_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/roundup2log_test.com.gz.sha256",
    "content": "6073e10e044517a2050a3d7a07b81bc4c6a0a7b6ca6cf7451cb8e593f1df1b1a *third_party/cosmo/2/roundup2log_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/roundup2pow_test.com.dbg.gz.sha256",
    "content": "607797eeeeb97a4a1901fb8d4712fcacea3579cc59560f6b041276e81c9dd8bc *third_party/cosmo/2/roundup2pow_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/roundup2pow_test.com.gz.sha256",
    "content": "036f28b9de0c141f1bc1bd44b8735b26581a35c3af3c320bdb036241aef74e7f *third_party/cosmo/2/roundup2pow_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sad16x8n_test.com.dbg.gz.sha256",
    "content": "01065e6da2b3bf0ddc63275ae894e2e3a7915a77d4c632659def8079648209c0 *third_party/cosmo/2/sad16x8n_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sad16x8n_test.com.gz.sha256",
    "content": "e7f141868dc3f7519c6fdd98108ad64446f814b26e79e96d21a621cf24aca756 *third_party/cosmo/2/sad16x8n_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/scale_test.com.dbg.gz.sha256",
    "content": "bac12d1a5962277e4d312f980198d4d16fcba992f5b2e41aa90384afc07902f4 *third_party/cosmo/2/scale_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/scale_test.com.gz.sha256",
    "content": "5cc89b207965c04cd3a23c9c25fdd6d775e7710fd366bfa37474e9670b8c45d3 *third_party/cosmo/2/scale_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/scalevolume_test.com.dbg.gz.sha256",
    "content": "31e5959860c9e1e96ea54c7a1470afec9f77218cd24e7de0ef22d64ba7abd409 *third_party/cosmo/2/scalevolume_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/scalevolume_test.com.gz.sha256",
    "content": "b1566e10de51db9859312d9c52f0bcb5d4663930ecac41e7fc79fd4561bea5b2 *third_party/cosmo/2/scalevolume_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sched_getaffinity_test.com.dbg.gz.sha256",
    "content": "a8e5d51f6de0b700cb5b3b4ea6b887292212cef534c9e1662626f1113357c24e *third_party/cosmo/2/sched_getaffinity_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sched_getaffinity_test.com.gz.sha256",
    "content": "06a4cbb523c6a50f1611f8a9aacb45013159b19f4a57f3352ff6b0d289c3f55b *third_party/cosmo/2/sched_getaffinity_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sched_setscheduler_test.com.dbg.gz.sha256",
    "content": "1478abc3ce90a9a4d864c6a6662d5fa0ba69ffe709dd017506a33c58fd30b278 *third_party/cosmo/2/sched_setscheduler_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sched_setscheduler_test.com.gz.sha256",
    "content": "90a7b88a4e937e4e6e4f22a588d484965c6aa51dea3f43bd78ed3e8d6602191c *third_party/cosmo/2/sched_setscheduler_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sched_yield_test.com.dbg.gz.sha256",
    "content": "cb33fa7e1257f41daf4a37bd69bfcc4c5c11b854f1fe3b906fbe7fdb9f21b37e *third_party/cosmo/2/sched_yield_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sched_yield_test.com.gz.sha256",
    "content": "473584a36f348b5950549eca2d3010cd9282ba960d042ff65e1c50a9c43ae800 *third_party/cosmo/2/sched_yield_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/seccomp_test.com.dbg.gz.sha256",
    "content": "3326c73a47dc3f2630b816c6abeff8f7cf22b8a637ffaa2352d6aa00a72b2cf6 *third_party/cosmo/2/seccomp_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/seccomp_test.com.gz.sha256",
    "content": "89a167df3849febc358eed799ffb43f9278723b78668425209ab873ad8a243b0 *third_party/cosmo/2/seccomp_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/secp384r1_test.com.dbg.gz.sha256",
    "content": "b089dbb0578ed2a9be74ed8697a90e9a7ee99e5dac5002d446b5e4bcb69bcd8c *third_party/cosmo/2/secp384r1_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/secp384r1_test.com.gz.sha256",
    "content": "fc0328b3f31d6cb9e6cf1dd8a629ee030d119ffadb44ed81ada4bf5b64c0a436 *third_party/cosmo/2/secp384r1_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/select_test.com.dbg.gz.sha256",
    "content": "a891ed186cfd833a7849c3dcc953e95eec52c39ba19361d818c42b263a28b7b5 *third_party/cosmo/2/select_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/select_test.com.gz.sha256",
    "content": "041af3dd90142e541af59ef0cb33cee9503cfb942229eef31cdb8924f3074bd1 *third_party/cosmo/2/select_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sem_open_test.com.dbg.gz.sha256",
    "content": "0ad0f283603197d6705cc3336fca03ce4cbba6970cfc9c5fa3f96b8e7c955a6f *third_party/cosmo/2/sem_open_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sem_open_test.com.gz.sha256",
    "content": "d70aaf367899c5ef1727cf7fa17c7a42aede922e00def6055dba07bfac5208d6 *third_party/cosmo/2/sem_open_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sem_timedwait_test.com.dbg.gz.sha256",
    "content": "927ae752ac936112b4e5fb7fc9d8122e63c1be2c1d566d4d03dd7c74ff577d2d *third_party/cosmo/2/sem_timedwait_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sem_timedwait_test.com.gz.sha256",
    "content": "5a3889514ec88d5361c5559fb06dd99a897f2623dfa4750053664043d1b5ca50 *third_party/cosmo/2/sem_timedwait_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sendfile_test.com.dbg.gz.sha256",
    "content": "665cf289d5e653e8df455914b7cce5686b41fc7149ff8dbf6dfa14ce57bb0440 *third_party/cosmo/2/sendfile_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sendfile_test.com.gz.sha256",
    "content": "660f6d142946577be17d1eccc5c45e807899514087923f2813221c0326795a88 *third_party/cosmo/2/sendfile_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sendrecvmsg_test.com.dbg.gz.sha256",
    "content": "de1bfcb80e685f2e30dd118b32ed8a53f1f8fad3da84f84aec267380c2835839 *third_party/cosmo/2/sendrecvmsg_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sendrecvmsg_test.com.gz.sha256",
    "content": "a37d156da9f39e3bb9a4b7de04f1b9730729021cbbb15d58661b145944b73c72 *third_party/cosmo/2/sendrecvmsg_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/servicestxt_test.com.dbg.gz.sha256",
    "content": "8b67e6590a2cb35856ec5b245d141a752a0ce81be745c9277f1c87321f75f010 *third_party/cosmo/2/servicestxt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/servicestxt_test.com.gz.sha256",
    "content": "10c9e37b5aa5ab265d2ca40529810250d8803efece79ee0300156938246545f8 *third_party/cosmo/2/servicestxt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/setitimer_test.com.dbg.gz.sha256",
    "content": "29c9159a37b07d0f1183fe0cfa6d54e77786fdfa6a2befc33b6e86ab069deb9b *third_party/cosmo/2/setitimer_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/setitimer_test.com.gz.sha256",
    "content": "639b579331090fdf6d3efca402370405a96f57294b0b99b6dad779cc46c9eced *third_party/cosmo/2/setitimer_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/setlocale_test.com.dbg.gz.sha256",
    "content": "c37757d1d2794e81d31e725963e0c5a7b36b60ddace635e6c4a0990c2745a2b5 *third_party/cosmo/2/setlocale_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/setlocale_test.com.gz.sha256",
    "content": "043e3764995929caed33c9b68e09c0126ee233e4a54e971d86eeece6292f1123 *third_party/cosmo/2/setlocale_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/setrlimit_test.com.dbg.gz.sha256",
    "content": "2af50510275bd51acf2bb8e85f3576f6fa5c0f88526be9551f19638187bda966 *third_party/cosmo/2/setrlimit_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/setrlimit_test.com.gz.sha256",
    "content": "f4fb62821b54e65123320e078a148103c6685255e5b733a8220eea56c999b85c *third_party/cosmo/2/setrlimit_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/setsockopt_test.com.dbg.gz.sha256",
    "content": "c6268b99357ec952108397ac1f8e488ba81492c7e425dcbde0a2aace6ecaebde *third_party/cosmo/2/setsockopt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/setsockopt_test.com.gz.sha256",
    "content": "3d0ddf1b538ec21d8092a982a9868352601133e3ad96ed5994befd9aaacfd96f *third_party/cosmo/2/setsockopt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/signal_test.com.dbg.gz.sha256",
    "content": "a103bde47b38c6fd92699022638f9b17ef3996e70ccc7d430d71f734741a3c9a *third_party/cosmo/2/signal_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/signal_test.com.gz.sha256",
    "content": "d36176fd3a02bcd4019d7b3dc046e985455b86d92e4e1c10e0434efb56058b2d *third_party/cosmo/2/signal_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sigpending_test.com.dbg.gz.sha256",
    "content": "a499c0d40e0a87a6c314e297e11f7ecd8e2f33a05d9b887dd09f72b4a16c8fda *third_party/cosmo/2/sigpending_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sigpending_test.com.gz.sha256",
    "content": "500848bbd6ea12f9ba5a93c0aa8c58393e74a979bb8f62729e51aa75353e3fe7 *third_party/cosmo/2/sigpending_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sigprocmask_test.com.dbg.gz.sha256",
    "content": "6fd9ea7cbaa7e4eebbbfa1f30624bd83ca1e957904e4e084f9cac8cf51538b5e *third_party/cosmo/2/sigprocmask_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sigprocmask_test.com.gz.sha256",
    "content": "434706c79540ea18c2dc394960d925bfb718cf1e2b8dde1cd0ea8c2dad460cf4 *third_party/cosmo/2/sigprocmask_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sigsetjmp_test.com.dbg.gz.sha256",
    "content": "59602543e39d1d47d9fd7467fdf0cbcd837f9e405b93cbc17f4b8100ba031ab6 *third_party/cosmo/2/sigsetjmp_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sigsetjmp_test.com.gz.sha256",
    "content": "5fb6fafbd352277b6e33d0f6b2627eb053adf1123ea09c994ce495d86a9cd1e0 *third_party/cosmo/2/sigsetjmp_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sigsuspend_test.com.dbg.gz.sha256",
    "content": "fcfe6debfa632790248145f91a31526e1dfc7bb9617a74736381129b1a979bba *third_party/cosmo/2/sigsuspend_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sigsuspend_test.com.gz.sha256",
    "content": "ccde77da3b71d67079ac1341131abc1243fc0141e57aab5666bc25e0719fdf28 *third_party/cosmo/2/sigsuspend_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sigtimedwait_test.com.dbg.gz.sha256",
    "content": "a25eb54d38c47b8f15f96a2809f45b7aa2e8c323fc61463c63e0d95b7bab2880 *third_party/cosmo/2/sigtimedwait_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sigtimedwait_test.com.gz.sha256",
    "content": "36857f06e1f26b814dc147cf024c446fac44e2db59f381fe64d071703703a0b3 *third_party/cosmo/2/sigtimedwait_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sin_test.com.dbg.gz.sha256",
    "content": "1c0a57c0b0b57b7661f9d781c87613f7364ed248ccdd28cca4cbcb5c76a27d6b *third_party/cosmo/2/sin_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sin_test.com.gz.sha256",
    "content": "7960263948d384fdd1813ccbe404013a9adb5c1a142ce8ea1c4f24417c5ee321 *third_party/cosmo/2/sin_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sincos_test.com.dbg.gz.sha256",
    "content": "fac2a3e10ffc1db91dbb9eeabce8c8628c2604f22c13cb3539fa3a1c5fc83231 *third_party/cosmo/2/sincos_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sincos_test.com.gz.sha256",
    "content": "c296541ac46fbc19aa4bb36077c8be239628fdcd397800603559db56fe7750c4 *third_party/cosmo/2/sincos_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sinh_test.com.dbg.gz.sha256",
    "content": "6236bd37c535ad88f95387abc08e7da71897d22b2a1e19a83c89ce101ba4b861 *third_party/cosmo/2/sinh_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sinh_test.com.gz.sha256",
    "content": "202616dc554c689278bcae4689835817205d117d54e7e08288b4588894c559df *third_party/cosmo/2/sinh_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sizetol_test.com.dbg.gz.sha256",
    "content": "2485143d186c5fe57062f28a5726cf0d859e47bd2da65ca22bfd1e52e4e79bc1 *third_party/cosmo/2/sizetol_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sizetol_test.com.gz.sha256",
    "content": "7510777cda51a56f23dfd4f62ca66a7e86c19af040a2f67dc1644450c0381bfa *third_party/cosmo/2/sizetol_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sleb128_test.com.dbg.gz.sha256",
    "content": "dbd47188c7968d8a043ffe8b438ee91c1399a6765bd772ea28286bef79248177 *third_party/cosmo/2/sleb128_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sleb128_test.com.gz.sha256",
    "content": "966f030d77c166c10820c47dfb3d2a3068d5493b6041dc4395278dc1cbcabce4 *third_party/cosmo/2/sleb128_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/snprintf_test.com.dbg.gz.sha256",
    "content": "fddf813c5ac3a12056ea0c490584b3881f9852bedf8a1daca3e9124a6a273302 *third_party/cosmo/2/snprintf_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/snprintf_test.com.gz.sha256",
    "content": "311217a01cf64278e977b8bf7a5d76e6fd9c82b759cf92b933ca66bcd7984b02 *third_party/cosmo/2/snprintf_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/socket_test.com.dbg.gz.sha256",
    "content": "61c1a8a0ba1ca92566fd643c73641d7098ca238b3b64d4ecbf60e22441bf8ea3 *third_party/cosmo/2/socket_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/socket_test.com.gz.sha256",
    "content": "c6965dd0afea222dbfa75cbbb0043458323e81ffc0efe068d8f523a55f586bee *third_party/cosmo/2/socket_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/socketpair_test.com.dbg.gz.sha256",
    "content": "69caa48e75deb9b92b0fbec762d284217156949a78cd55c08fe95dec2f8479bb *third_party/cosmo/2/socketpair_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/socketpair_test.com.gz.sha256",
    "content": "f4d4803d0a5d665452dd8f038b1ead1add422dc971377df42af8df5a5fe8bb91 *third_party/cosmo/2/socketpair_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sortedints_test.com.dbg.gz.sha256",
    "content": "95379ca4379db57d852a33d3e4511849a38ba8d622365967bca36cd6fa8f5154 *third_party/cosmo/2/sortedints_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sortedints_test.com.gz.sha256",
    "content": "917a141dbeb25dc330095369052e40b2a4afbe79fb3709dd989bf956f9ec1c9d *third_party/cosmo/2/sortedints_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/spawn_test.com.dbg.gz.sha256",
    "content": "1b9281d5c0b960c89da0b8541628e24fb010c2593110cbc2e56f3152de6af7c6 *third_party/cosmo/2/spawn_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/spawn_test.com.gz.sha256",
    "content": "061560376a20c4ed09b211baedc5aa950d3b746a4169c87cb05d4fe71f912039 *third_party/cosmo/2/spawn_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/splice_test.com.dbg.gz.sha256",
    "content": "c03805ca215775923d6cbc84ff45295da21fe81a0c5d0c07791649aa040351e5 *third_party/cosmo/2/splice_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/splice_test.com.gz.sha256",
    "content": "0aff112115918607083b9e197d976b2309ccc756388023a1b1dd9b442b07b24e *third_party/cosmo/2/splice_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sprintf_s_test.com.dbg.gz.sha256",
    "content": "c8ddb5ddc0d65d214e85cb3a4fb27a1265dd54b64f54dd54994e84e3670e300e *third_party/cosmo/2/sprintf_s_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sprintf_s_test.com.gz.sha256",
    "content": "8e137d0d28674d195e6bac39ebb16e13c5b5f6469d12092a434837b2a46471a6 *third_party/cosmo/2/sprintf_s_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sqrt_test.com.dbg.gz.sha256",
    "content": "111af1e179c357558254d0e15aa63613a4b5579163ae164906659ce2a4171c5f *third_party/cosmo/2/sqrt_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sqrt_test.com.gz.sha256",
    "content": "bf2447ccd775a0e1f4edbc55d2fb7e0c08a776f978d76938923a97f3df9e58b6 *third_party/cosmo/2/sqrt_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sscanf_test.com.dbg.gz.sha256",
    "content": "0f0e8cdaf8429051c2c049d2710aa3ab411a0d58fb1b29d2c61912cdbff782c5 *third_party/cosmo/2/sscanf_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sscanf_test.com.gz.sha256",
    "content": "810ce06561753783ca8764320cd81ac306664f835555745ab080f4accb9e042d *third_party/cosmo/2/sscanf_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/stackrw_test.com.dbg.gz.sha256",
    "content": "c0924317f7fb5c8f3ffe75aa6d5329e283120b5bba2ee58aa498f76b92bf8a06 *third_party/cosmo/2/stackrw_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/stackrw_test.com.gz.sha256",
    "content": "24747a155a923a921d7362890cb87273df03fb30215801b2c9f19f5b790d1641 *third_party/cosmo/2/stackrw_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/stackrwx_test.com.dbg.gz.sha256",
    "content": "45c37f5598038c7c136858baa6247657df70e5ee136371a799cbc800f42cfb8d *third_party/cosmo/2/stackrwx_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/stackrwx_test.com.gz.sha256",
    "content": "10d8b5c9b97718d3c9fe2e49216f0b77c96e804c67b660299c1df1ae5b365ddc *third_party/cosmo/2/stackrwx_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/stat_test.com.dbg.gz.sha256",
    "content": "e01185f1fa66d4e315d808783bdb46a64205861a09e0ca47e53472824a62dd96 *third_party/cosmo/2/stat_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/stat_test.com.gz.sha256",
    "content": "ae30c90bf560542460732c3c787852c7e3cb7f4f769589ae7e68d2b1910ea72a *third_party/cosmo/2/stat_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/statfs_test.com.dbg.gz.sha256",
    "content": "705750bcbdd7fef23db62023f7558dca4669ec9b7874e1571935aea8ca4bd2f6 *third_party/cosmo/2/statfs_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/statfs_test.com.gz.sha256",
    "content": "4471b8db6fae9659f8e6745d578a359a2ff6352330f96bc6421c1cf4c21dec38 *third_party/cosmo/2/statfs_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/str_test.com.dbg.gz.sha256",
    "content": "ded03ed781de3f465f34818a339de8d8338071624effaa472fffa60704dffae0 *third_party/cosmo/2/str_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/str_test.com.gz.sha256",
    "content": "1fad3b777124f041bf91fabf11b4df8d946003cb0d525359dbb459d635124940 *third_party/cosmo/2/str_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcasecmp_test.com.dbg.gz.sha256",
    "content": "cfdc1f7ab5d4bf7fc9ae60890c357a0e95081bee988bc8f891c29307adbeea63 *third_party/cosmo/2/strcasecmp_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcasecmp_test.com.gz.sha256",
    "content": "9357f1e3060fb46b40021c83a9b6d198d935409a66dce6522edce55d150f4bad *third_party/cosmo/2/strcasecmp_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcaseconv_test.com.dbg.gz.sha256",
    "content": "53e8418c344876b726159278d09c2d95a7a5f74000fcd376a604bc60cf69a91d *third_party/cosmo/2/strcaseconv_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcaseconv_test.com.gz.sha256",
    "content": "b590f3c389066c1f891a1d8c869137c5359ecf3c83792624fc71872847d529f1 *third_party/cosmo/2/strcaseconv_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcasestr_test.com.dbg.gz.sha256",
    "content": "31b00b68c794b23336bbcd5dfea2b13057792a5a353159046ec70655b289206a *third_party/cosmo/2/strcasestr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcasestr_test.com.gz.sha256",
    "content": "f2c20619172d02cc73faee7c5e6f5e9ddebf1041db9dd2f2e430957dedf93ce4 *third_party/cosmo/2/strcasestr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcat_test.com.dbg.gz.sha256",
    "content": "5ece08563c698e65b7341d67e504d2e92970953e1f5b8f4c282f67ef6cea9bad *third_party/cosmo/2/strcat_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcat_test.com.gz.sha256",
    "content": "51d18fd6cd4958987e01ff830db134c24a60486d91463fae21f0c1e6312f69bf *third_party/cosmo/2/strcat_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strchr_test.com.dbg.gz.sha256",
    "content": "cf2934f816ab0eca2e1f887558844e6d5995bb5e72c515aba31e8c8b9d83a2af *third_party/cosmo/2/strchr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strchr_test.com.gz.sha256",
    "content": "684c3b22bdc8eb71856b1961a59be5cbf97a086eee3c0c12edbec39c4700086a *third_party/cosmo/2/strchr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strclen_test.com.dbg.gz.sha256",
    "content": "63a2a31630a45d6cecb2334ba9d3429ea7ad43fcf0702742e5c455551f0d5a62 *third_party/cosmo/2/strclen_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strclen_test.com.gz.sha256",
    "content": "0158b1c9879a57dd2784d6f74d40d097aadea81d153f983ab07e112f2136251b *third_party/cosmo/2/strclen_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcmp_test.com.dbg.gz.sha256",
    "content": "0fc9427474f15bd8a980ab1a080a88fe38628697e0c3096c02499faee383b8fe *third_party/cosmo/2/strcmp_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcmp_test.com.gz.sha256",
    "content": "863c10bd8f188f8d3aedd9bc43a76b7b3b6fb5cdf80526166f64800bb7052a97 *third_party/cosmo/2/strcmp_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcpy_test.com.dbg.gz.sha256",
    "content": "499726487cd03f7c76328adc6df54e1066ddab7229629237f7fd2c6d361d0fb7 *third_party/cosmo/2/strcpy_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcpy_test.com.gz.sha256",
    "content": "aa9a1435ff5892e4283ae7bae2d0f8e19fa2c619b90df0f781c6cf7d3b44b2b8 *third_party/cosmo/2/strcpy_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcspn_test.com.dbg.gz.sha256",
    "content": "cea196f592ab97662d588ae9347fc0251589d39eeed132e576ddb36d5ad14a45 *third_party/cosmo/2/strcspn_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strcspn_test.com.gz.sha256",
    "content": "ad75864b1859fdff3b675279634c333f27b837ae046d6dcf2bd104b90b2a4f87 *third_party/cosmo/2/strcspn_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strdup_test.com.dbg.gz.sha256",
    "content": "f0471d34c63c9748708cecb516332e8bb3c0c7f444751a15fde3391d69655ac3 *third_party/cosmo/2/strdup_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strdup_test.com.gz.sha256",
    "content": "7a757cf96971b047ec6205cfe6dc2d8957189d1e35d30b8e70a501896a3afce5 *third_party/cosmo/2/strdup_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strerror_r_test.com.dbg.gz.sha256",
    "content": "074737f13180e4e438f1744896661c9632f4c670fa4c638f0010d2bcc0f5b48c *third_party/cosmo/2/strerror_r_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strerror_r_test.com.gz.sha256",
    "content": "407c25db3839d56e7a8a44f3f319f6aaf9d1933df8a85a10c6756c4da844cdbd *third_party/cosmo/2/strerror_r_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strftime_test.com.dbg.gz.sha256",
    "content": "ba4eb363153c02b7e95e3c389890188f2525217cd907952d93ecc6f2801f9c0f *third_party/cosmo/2/strftime_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strftime_test.com.gz.sha256",
    "content": "41c4ac71667d3843b769d8c058e78a4f005550c18bbc8c8c1dc29757ce26f92d *third_party/cosmo/2/strftime_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/stripcomponents_test.com.dbg.gz.sha256",
    "content": "899952ca12b342341a15cb2886e6bf0441894b9a939ea6ea1b6c51c4123f64c5 *third_party/cosmo/2/stripcomponents_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/stripcomponents_test.com.gz.sha256",
    "content": "84932ac4a8a44a53a972f6adf33de604a8fd6a713459dcb0a15b16260dbcc129 *third_party/cosmo/2/stripcomponents_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/stripexts_test.com.dbg.gz.sha256",
    "content": "7cd7207a8443a669d38da76f5527a821e1a885c6ff85a07b755b87134ee895e1 *third_party/cosmo/2/stripexts_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/stripexts_test.com.gz.sha256",
    "content": "47753a9501df30fb4f3ecac6e3b291a806165ece7538955d85b0273674f4b79a *third_party/cosmo/2/stripexts_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strlcpy_test.com.dbg.gz.sha256",
    "content": "1e47e2401e3383c37c546bbf88bb4fab1ff36f65875c5620f6e32590999a811e *third_party/cosmo/2/strlcpy_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strlcpy_test.com.gz.sha256",
    "content": "a9e6fe76296455fd05a9ab9ac24a1788c6858d61384bfbe08876774b2116f13e *third_party/cosmo/2/strlcpy_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strlen_test.com.dbg.gz.sha256",
    "content": "54b269dced3e31328f09c6cbb2aa17c2e308f79d3bbdb96ca02cbf24a2e6a4f5 *third_party/cosmo/2/strlen_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strlen_test.com.gz.sha256",
    "content": "2471d44fbbfdcb7e760dd81e87f95876301ab4a1a7710fbff3ac2e092515d07c *third_party/cosmo/2/strlen_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strnlen_test.com.dbg.gz.sha256",
    "content": "6ab12007253e4e98dddffb64cf322998305cf3222f4b36f7da01c1bc2c34df03 *third_party/cosmo/2/strnlen_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strnlen_test.com.gz.sha256",
    "content": "69104b13079f08f6c6619430519594d27e47586e0fc88de43dd0d26fdd66b31e *third_party/cosmo/2/strnlen_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strnwidth_test.com.dbg.gz.sha256",
    "content": "16764c6f59079a43542e9f3470c3901b33fce9195d2209777194ba2d8172e104 *third_party/cosmo/2/strnwidth_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strnwidth_test.com.gz.sha256",
    "content": "6c1bb69eed505555e26ffe09b601e82501b1f825cb7e989a4e38535a56483946 *third_party/cosmo/2/strnwidth_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strpbrk_test.com.dbg.gz.sha256",
    "content": "9a282c0bcbd1eedfb555400b3b9d6d39b3b26bf2aac34e729b8c42bc84801208 *third_party/cosmo/2/strpbrk_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strpbrk_test.com.gz.sha256",
    "content": "8c4cb441ccb4b86c2c0950813833044076f5e7a8299e1f62483d01145c6e572b *third_party/cosmo/2/strpbrk_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strrchr_test.com.dbg.gz.sha256",
    "content": "81dd2993dea1e8200cdda9229eccd2ad98ea7906f3a160c15d3272ae5905de05 *third_party/cosmo/2/strrchr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strrchr_test.com.gz.sha256",
    "content": "2cb7b6c248bb0edadfc592314d5cd399ca35e7cdbf6118d33929061f3729bcb2 *third_party/cosmo/2/strrchr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strsak32_test.com.dbg.gz.sha256",
    "content": "9b58e90193f10ee7b4a731daa0b1528165df1046772519ee39c57bc1a13fd53e *third_party/cosmo/2/strsak32_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strsak32_test.com.gz.sha256",
    "content": "51ff8644af79f5fb95fb616143f24e6449178e95a25e357c2079ad2448c7367e *third_party/cosmo/2/strsak32_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strsignal_r_test.com.dbg.gz.sha256",
    "content": "636188f85d34d506d208854fc73209970e8a3ae8f439dd344be3ace99cf6bbac *third_party/cosmo/2/strsignal_r_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strsignal_r_test.com.gz.sha256",
    "content": "2180b0a3b8b421d1bdc19014b1e2a635c93f54d4a77d0d126942b1c8fa3cb19d *third_party/cosmo/2/strsignal_r_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strstr_test.com.dbg.gz.sha256",
    "content": "446a06192701708d69d2a1cdd04d257cc5e7a4f0e786c5a1a4c7508bd8622c5d *third_party/cosmo/2/strstr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strstr_test.com.gz.sha256",
    "content": "d41186a88f8676df8a491e0221d8e08988329b1d54466d9a886fbfe43d3d96f8 *third_party/cosmo/2/strstr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strtod_test.com.dbg.gz.sha256",
    "content": "0c96002acc3faae07d5785d56211907cbfc4751b518f3cbd57bd4f609f07ad27 *third_party/cosmo/2/strtod_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strtod_test.com.gz.sha256",
    "content": "fca4af926a0aa4c79999f7e2489212f23baac7881ae2b5dfc8cb2e9402a0396f *third_party/cosmo/2/strtod_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strtok_r_test.com.dbg.gz.sha256",
    "content": "38cd119e2933a6eb060612e44108c5a4de418f1329b9cf8f383aa582b171200c *third_party/cosmo/2/strtok_r_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strtok_r_test.com.gz.sha256",
    "content": "76b451ff8950958308ce70e291d36f05c0c506d129e63108dc6acbe6bca6a727 *third_party/cosmo/2/strtok_r_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strtolower_test.com.dbg.gz.sha256",
    "content": "82cbb92f4e71dc83261687c29f5549afa6b7a11bad760f61fb71ba71952ee98b *third_party/cosmo/2/strtolower_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/strtolower_test.com.gz.sha256",
    "content": "8ec03d5b03606a3d0c0ff4244ec5b0d23fe128eb04c8f477a63e6f8de594039b *third_party/cosmo/2/strtolower_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/symlinkat_test.com.dbg.gz.sha256",
    "content": "493e36aa34e78c259b5fe88419211ea4885f186eb6cd099a7d0dee74b1162871 *third_party/cosmo/2/symlinkat_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/symlinkat_test.com.gz.sha256",
    "content": "8b1e62144021c3e366600071d40cddece64665e195bf164162c8017398fd3bcb *third_party/cosmo/2/symlinkat_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sys_ptrace_test.com.dbg.gz.sha256",
    "content": "55733bfa6398f83032e02ae4557237907e053514b24028d187de8b4b1c1fa031 *third_party/cosmo/2/sys_ptrace_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/sys_ptrace_test.com.gz.sha256",
    "content": "a7e767fd7c63f93e5a7655c72562ec809d2f85dc9a5779532c675ff035b828ea *third_party/cosmo/2/sys_ptrace_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/system_test.com.dbg.gz.sha256",
    "content": "0d98b15a2d6763a75559a7a576810dec05c5fadebdaa2e026e138d85f187d0dc *third_party/cosmo/2/system_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/system_test.com.gz.sha256",
    "content": "dadf2f2814a3b573287ef05f3a6bd58e46592259a85588b47ed0fbc3c4bcc3a0 *third_party/cosmo/2/system_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tan_test.com.dbg.gz.sha256",
    "content": "650da38e2d641267e0d6b58b13ea92b2c699d208c8737da2d6a729052ea3cc0c *third_party/cosmo/2/tan_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tan_test.com.gz.sha256",
    "content": "37d6cc558b9575fe5162d07305c4e942163405b5431203ab08bdcc21824d2b06 *third_party/cosmo/2/tan_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tanh_test.com.dbg.gz.sha256",
    "content": "405de53fd60f6beeb12ece7f72b901cc6dbf0f67d5dcb3761f5631c29155f42c *third_party/cosmo/2/tanh_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tanh_test.com.gz.sha256",
    "content": "8def315d8ca21a64bd4f47ff4f842adbc3fa7747b481d8dd85f066b546f2e9ce *third_party/cosmo/2/tanh_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tarjan_test.com.dbg.gz.sha256",
    "content": "9ed43efecf46e03923955fd540f5208efeda0b931a84d3eb8882d9fb5f11374e *third_party/cosmo/2/tarjan_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tarjan_test.com.gz.sha256",
    "content": "28887dd7fc71fd57ecf9de97bb66648e63a1f163a5c4ec72ecfab2604e68b4c9 *third_party/cosmo/2/tarjan_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.cbc.com.dbg.gz.sha256",
    "content": "894fab3f7608a186376cb3c98a690c33b7ae89ead0dbc6ba89b230499eaa011a *third_party/cosmo/2/test_suite_aes.cbc.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.cbc.com.gz.sha256",
    "content": "85ef9656311e876fb6000fc6842239df1baa7585e8c373fd3cbf94c34a4d40c5 *third_party/cosmo/2/test_suite_aes.cbc.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.cfb.com.dbg.gz.sha256",
    "content": "9712913da373635b9c4669f47eb96245c9d879faed1d185ee68af95ddaceb233 *third_party/cosmo/2/test_suite_aes.cfb.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.cfb.com.gz.sha256",
    "content": "ef856ae59ad36e83f0001886aa7fa087152edb70f636d3c991a529fde7b78f2c *third_party/cosmo/2/test_suite_aes.cfb.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.ecb.com.dbg.gz.sha256",
    "content": "900175ad2aefea31f4debd6393f7fe200337ebdde7521fc6563ebe10312b61a5 *third_party/cosmo/2/test_suite_aes.ecb.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.ecb.com.gz.sha256",
    "content": "f80e528ab2c19e7dd9a7ac84b0bc9843b53aca3a7c60260dc7b9ac2c44c319cd *third_party/cosmo/2/test_suite_aes.ecb.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.ofb.com.dbg.gz.sha256",
    "content": "407f2ee28e374d56db5a8a3218ee73774754a7339a14efaa051a0ded1e4c1f81 *third_party/cosmo/2/test_suite_aes.ofb.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.ofb.com.gz.sha256",
    "content": "ccf18590dde976c4adec13de308b3121e25d01348bf1ecd851c22b001dc80de2 *third_party/cosmo/2/test_suite_aes.ofb.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.rest.com.dbg.gz.sha256",
    "content": "fd49cf14394c22fc8ca0284b1163b786d54ac1b6f405dd6d127e4539cd6ec04d *third_party/cosmo/2/test_suite_aes.rest.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.rest.com.gz.sha256",
    "content": "c031bf898be86893ed89237b41637c2faf2d366d0c9e7a20478b9ae42a18b039 *third_party/cosmo/2/test_suite_aes.rest.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.xts.com.dbg.gz.sha256",
    "content": "fff373a956b0799b63692a1db51dca1a6002488269d9fbcc32bbd2ac0f43acf8 *third_party/cosmo/2/test_suite_aes.xts.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_aes.xts.com.gz.sha256",
    "content": "de47fe92e462ae08f6be6645b37fcf1e50f734b8b3d5b9e9f20262a47bf86a7b *third_party/cosmo/2/test_suite_aes.xts.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_asn1parse.com.dbg.gz.sha256",
    "content": "df475367fed6ebc5a4c90e0fa322b371ebeafcb85df76306ed9ca0c0402f7354 *third_party/cosmo/2/test_suite_asn1parse.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_asn1parse.com.gz.sha256",
    "content": "faf14a16be13ec8f1a8cd6a3a660bf65146d78548931400c884f554c305e1d0b *third_party/cosmo/2/test_suite_asn1parse.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_asn1write.com.dbg.gz.sha256",
    "content": "ac1a38ee95eb25c57e058922ad2085ef829b88d0ef8b29b084326055fc969a19 *third_party/cosmo/2/test_suite_asn1write.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_asn1write.com.gz.sha256",
    "content": "cb00a47b20461642baec09e55346793175c34433c7995583496a5c6dc06c444c *third_party/cosmo/2/test_suite_asn1write.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_base64.com.dbg.gz.sha256",
    "content": "65cc6c19515143ddf869d23807a0ba54b72acb2ac75d1aa5ef88a0d7c6011de0 *third_party/cosmo/2/test_suite_base64.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_base64.com.gz.sha256",
    "content": "fa4b67f2b9a7389bdcd857dc5aa73323672683e7ad4615cb4203be6e1fb17dc1 *third_party/cosmo/2/test_suite_base64.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_blowfish.com.dbg.gz.sha256",
    "content": "8613cf2d1c15d56aa9fbd9742c886e52c5a822449976d6e2d061c6aea54f312d *third_party/cosmo/2/test_suite_blowfish.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_blowfish.com.gz.sha256",
    "content": "6b038652bf5db4dd46a3794f0edcb5e19a47e8e4906fa0f9a6e58089024e4ef1 *third_party/cosmo/2/test_suite_blowfish.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_chacha20.com.dbg.gz.sha256",
    "content": "aafc9874ba08db8655e9cf97b76d4cf9dea9f6b989150de3b71c326a844e9c9e *third_party/cosmo/2/test_suite_chacha20.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_chacha20.com.gz.sha256",
    "content": "b36a06829d7c6028a07905096090fb3876e75fe3197406dcb00b49e48654284f *third_party/cosmo/2/test_suite_chacha20.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_chachapoly.com.dbg.gz.sha256",
    "content": "e47f3309d28814d2f50528cc84065ba8aed63b251bfc7a8c7e4b4a3553074d25 *third_party/cosmo/2/test_suite_chachapoly.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_chachapoly.com.gz.sha256",
    "content": "eaa6eb3a014b151df48aa34fe665dd4baabf514c3f0488a45e03d96fcf01fbc1 *third_party/cosmo/2/test_suite_chachapoly.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.aes.com.dbg.gz.sha256",
    "content": "6fcb85b26fc6e4f2c834e24eee82a17f9d5888d5def684a176ea69051e5ff7f7 *third_party/cosmo/2/test_suite_cipher.aes.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.aes.com.gz.sha256",
    "content": "d4758026ef45385dcd7a9a1e2d6c35c5d89b2c15e181d7bf24216f52cedb2d14 *third_party/cosmo/2/test_suite_cipher.aes.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.blowfish.com.dbg.gz.sha256",
    "content": "6cc199eb3345c3db99374f127248a2244977af08ef8da5fb953e3b262e133d5d *third_party/cosmo/2/test_suite_cipher.blowfish.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.blowfish.com.gz.sha256",
    "content": "b64f1bbd67c2d0b57e6f025a0f60821b2502c49e924863e1180118e9ade99bc6 *third_party/cosmo/2/test_suite_cipher.blowfish.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.ccm.com.dbg.gz.sha256",
    "content": "9e770989a32d00c5c15ce95f5f45cea0ed8087aec0aae76852a8b9e1a0040693 *third_party/cosmo/2/test_suite_cipher.ccm.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.ccm.com.gz.sha256",
    "content": "86bae6c7494e2b306ebc58962a54fad86dc1305e61a921721011d6be46269d35 *third_party/cosmo/2/test_suite_cipher.ccm.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.chacha20.com.dbg.gz.sha256",
    "content": "15268eedfa1f449947b00ebfea513e33f1914d816b228c83eabe295453f0d0f8 *third_party/cosmo/2/test_suite_cipher.chacha20.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.chacha20.com.gz.sha256",
    "content": "1836de894fa43f9924d6fca53c86329aac83821f636fdd334098950668de088f *third_party/cosmo/2/test_suite_cipher.chacha20.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.chachapoly.com.dbg.gz.sha256",
    "content": "7ff112c75aad82d4f1718ae09a1be4eea6d4fb6847e6526e880535c9a8d5f1be *third_party/cosmo/2/test_suite_cipher.chachapoly.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.chachapoly.com.gz.sha256",
    "content": "fa07693949806d03e113ced0b4c50203a5aeeecf89194dbb0e63292c2abbb572 *third_party/cosmo/2/test_suite_cipher.chachapoly.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.des.com.dbg.gz.sha256",
    "content": "6c33a24e5acfd4e5d991f98526bf5df5b347412970013bda6fa030e37d471b57 *third_party/cosmo/2/test_suite_cipher.des.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.des.com.gz.sha256",
    "content": "4c09ded73b0f07cc6c30704bc7d4d1c018385edb450708d145d4d19d5734b4e3 *third_party/cosmo/2/test_suite_cipher.des.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.gcm.com.dbg.gz.sha256",
    "content": "ef0174340d4a18ce45b996308dd6e71b561090a63db25b671aa791b6c32a4abb *third_party/cosmo/2/test_suite_cipher.gcm.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.gcm.com.gz.sha256",
    "content": "b6a4d9f8e2c3833fc4db91bb3d0247b37d432b7bb7247e8c962df37afe24ca99 *third_party/cosmo/2/test_suite_cipher.gcm.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.misc.com.dbg.gz.sha256",
    "content": "b53a2c3049f2c5b5e448cc1108af0603125d37a06b671262c24b6cd202d6c97a *third_party/cosmo/2/test_suite_cipher.misc.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.misc.com.gz.sha256",
    "content": "f33386a818a8f043e82ff4f4676f3caf5c7fc79383333348d40645b3ab1b245c *third_party/cosmo/2/test_suite_cipher.misc.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.nist_kw.com.dbg.gz.sha256",
    "content": "ef138326dc1cd5c6d237933c292a4021cce99219c220d870fd2beeb871943d44 *third_party/cosmo/2/test_suite_cipher.nist_kw.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.nist_kw.com.gz.sha256",
    "content": "25e49bd42eb4ebcd30ca9f8e038b491436fb9754475579f3a758267ddf0bc137 *third_party/cosmo/2/test_suite_cipher.nist_kw.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.null.com.dbg.gz.sha256",
    "content": "975c66d7d10a8a9876d89c985527067175010df28b0dd12e1e21b9f78774dcc6 *third_party/cosmo/2/test_suite_cipher.null.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.null.com.gz.sha256",
    "content": "17ab5d41bcbe8f0bc3111a097b031477d182135bad2eb1fe85807d12572b478b *third_party/cosmo/2/test_suite_cipher.null.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.padding.com.dbg.gz.sha256",
    "content": "477d11e79dc81d456e2ed5d5a0dfbfaf80377c6e0fad5538729e58e2345d552c *third_party/cosmo/2/test_suite_cipher.padding.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_cipher.padding.com.gz.sha256",
    "content": "a20d4ec658cc17032b87817eb77fa14e7be9d0e9a5915945f2c3ff330fc51afb *third_party/cosmo/2/test_suite_cipher.padding.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_ctr_drbg.com.dbg.gz.sha256",
    "content": "b51cac9e0b878223ba1f0778b46939d34947ee48017ea896e95d2e068922e79d *third_party/cosmo/2/test_suite_ctr_drbg.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_ctr_drbg.com.gz.sha256",
    "content": "dcd6752e8f36ae0bd97b0776980eb5b43c9097aedb3c6d35e9bc9ce6ed8fb72e *third_party/cosmo/2/test_suite_ctr_drbg.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_des.com.dbg.gz.sha256",
    "content": "49d83828d5490f707562258f4317176570a54a57bccf28dc4380f63875382cde *third_party/cosmo/2/test_suite_des.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_des.com.gz.sha256",
    "content": "78f9943113cd2e5aec3e29c6184f9f99c6ee8e36856b58c3b84d71f4952e5575 *third_party/cosmo/2/test_suite_des.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_dhm.com.dbg.gz.sha256",
    "content": "08d201d1643e8e886278b49119a03fdd966bb2bb2ae323fa6944817544a44c15 *third_party/cosmo/2/test_suite_dhm.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_dhm.com.gz.sha256",
    "content": "d4df29df3f0b35091550b5b1356c23a74e899039193c12f091d274521e59fe44 *third_party/cosmo/2/test_suite_dhm.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_ecdh.com.dbg.gz.sha256",
    "content": "dd475853821de50b013587e76a08dbd72b1a88d9a6cce82bd33c861ba34748e7 *third_party/cosmo/2/test_suite_ecdh.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_ecdh.com.gz.sha256",
    "content": "26bee59d291de22cf4b13a6acfeff42ae5c962b99efdbdbc517c13ffcbf5aa62 *third_party/cosmo/2/test_suite_ecdh.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_ecdsa.com.dbg.gz.sha256",
    "content": "c13d985b61d70496078ddec8209ff28e5519441210e002958a8961da04665c3d *third_party/cosmo/2/test_suite_ecdsa.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_ecdsa.com.gz.sha256",
    "content": "bee3fdf9db9d02b4a916f51306beeb1cb4b1b1042817d3cf44f605ba1b221b5c *third_party/cosmo/2/test_suite_ecdsa.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_ecp.com.dbg.gz.sha256",
    "content": "2bc77353222fd885ba0a7fa202e2c62f54cc4f86352f299d425bbf4655409a99 *third_party/cosmo/2/test_suite_ecp.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_ecp.com.gz.sha256",
    "content": "3e1476f611051f8fb10113a9882e921eb9b5c0b3326c40311ef23c1005f49beb *third_party/cosmo/2/test_suite_ecp.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_entropy.com.dbg.gz.sha256",
    "content": "86bbdcde1fa2a2be63b80ea21bffd19aa2a160741109ec147a73e957cc1b6873 *third_party/cosmo/2/test_suite_entropy.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_entropy.com.gz.sha256",
    "content": "d11be302f5b192fb4b2bcd06b7595428f6c928a5350ef0540b7c100403f36368 *third_party/cosmo/2/test_suite_entropy.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_error.com.dbg.gz.sha256",
    "content": "c22d51506abda5ecc5be8eee178d3b87f8c16ea0324ca332b87851af5c2c2fcd *third_party/cosmo/2/test_suite_error.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_error.com.gz.sha256",
    "content": "8a0b55f0223fb7c51ff55e31359a2aa7fc78735f3b95ef1ee1206b710ccf0ba4 *third_party/cosmo/2/test_suite_error.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes128_de.com.dbg.gz.sha256",
    "content": "f93c4b630d0a62cbb4fe5b8e4f1d1b74478b990e6fd0054febba745fc13b6546 *third_party/cosmo/2/test_suite_gcm.aes128_de.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes128_de.com.gz.sha256",
    "content": "9feb3efb18daae46b2edf45cac274866c373c54c4088d21388bc9292ba320fd5 *third_party/cosmo/2/test_suite_gcm.aes128_de.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes128_en.com.dbg.gz.sha256",
    "content": "a93d30a707a4081a5297b1951e0603b146aeddbc111bc4359f68f7920600731f *third_party/cosmo/2/test_suite_gcm.aes128_en.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes128_en.com.gz.sha256",
    "content": "8fbe37baefee1497c1463c30bfe2fdbdd29005be4de70a71c2c7ec2c48922c67 *third_party/cosmo/2/test_suite_gcm.aes128_en.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes192_de.com.dbg.gz.sha256",
    "content": "725d29c76d1f1260e3450028d7814d7d74bf0e4f219a989e523a8e04a9e07604 *third_party/cosmo/2/test_suite_gcm.aes192_de.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes192_de.com.gz.sha256",
    "content": "4fb0a16802c8a7ec81a49f6ac70715bad4eef77849958e0c7b875838bdee2e78 *third_party/cosmo/2/test_suite_gcm.aes192_de.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes192_en.com.dbg.gz.sha256",
    "content": "1eb290aa263c9eb0bd5cd1e97b8213f4c11d6bde63f66f9e8fdbb5cf50905a55 *third_party/cosmo/2/test_suite_gcm.aes192_en.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes192_en.com.gz.sha256",
    "content": "7cdf8cd41236bd644110490f90b17013c99a569e1e2e065ac8fcbf2777fb6847 *third_party/cosmo/2/test_suite_gcm.aes192_en.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes256_de.com.dbg.gz.sha256",
    "content": "46f2a120ee328552c3d028a60dbeb3806bf2e67a67c6d8612de34cba65aa873b *third_party/cosmo/2/test_suite_gcm.aes256_de.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes256_de.com.gz.sha256",
    "content": "11e13598fd23569046e2897e3fd2027f405de48d24c1b024ab39cd69c50a97d7 *third_party/cosmo/2/test_suite_gcm.aes256_de.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes256_en.com.dbg.gz.sha256",
    "content": "0608eef00f9d8a7c0d915dcfc8d66f5a6fa5678dd1c76c8832eda33ec75c2fae *third_party/cosmo/2/test_suite_gcm.aes256_en.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.aes256_en.com.gz.sha256",
    "content": "ae1ca6400387c91b9990d9c832147966feb62a5ef549e9bf44bf26351d972dfc *third_party/cosmo/2/test_suite_gcm.aes256_en.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.misc.com.dbg.gz.sha256",
    "content": "2801f04c0a84f23a4fd53079cd9af8b15cf568a28c43cf1e2b0d91503c03a74c *third_party/cosmo/2/test_suite_gcm.misc.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_gcm.misc.com.gz.sha256",
    "content": "1408e57f7d12edb532015f7b46ac8ee5adf140769beca9932145d8d4c0bc1e62 *third_party/cosmo/2/test_suite_gcm.misc.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_hkdf.com.dbg.gz.sha256",
    "content": "b9358479dd205b4a0f306c1585b8aa6a7262cc0b0d167414cf8e288e6d050173 *third_party/cosmo/2/test_suite_hkdf.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_hkdf.com.gz.sha256",
    "content": "3d49b88013e2fc991caa404830c7c7d87dbf3af7d3d7c7b96638079fee55b79e *third_party/cosmo/2/test_suite_hkdf.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_hmac_drbg.misc.com.dbg.gz.sha256",
    "content": "ecebd3cdd7cf31dc3df5dc2bf7b01ef28e26b015d3963d34a7e863edaad40203 *third_party/cosmo/2/test_suite_hmac_drbg.misc.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_hmac_drbg.misc.com.gz.sha256",
    "content": "bc1dfae4b46b31376306e044f1fe5374b8a47b27d643551a603c36d35ae9a4fb *third_party/cosmo/2/test_suite_hmac_drbg.misc.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_hmac_drbg.no_reseed.com.dbg.gz.sha256",
    "content": "e5357685088b05e9b03c133d47e7c3fbf43d82b21b1fe577e1e0e97e2898c5cc *third_party/cosmo/2/test_suite_hmac_drbg.no_reseed.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_hmac_drbg.no_reseed.com.gz.sha256",
    "content": "a1f60eb97eb9686c67202664bf7b3e522c02bbecf26e7ff85def4734fec10fae *third_party/cosmo/2/test_suite_hmac_drbg.no_reseed.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_hmac_drbg.nopr.com.dbg.gz.sha256",
    "content": "a9ca22ac108cd807e56b389d8e0af6c90036af0e170bf3286e622bcdf3cb636e *third_party/cosmo/2/test_suite_hmac_drbg.nopr.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_hmac_drbg.nopr.com.gz.sha256",
    "content": "c18bf8137abf43385360043b9196ed0c81f23c31966b8d3261cbc9881590e790 *third_party/cosmo/2/test_suite_hmac_drbg.nopr.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_hmac_drbg.pr.com.dbg.gz.sha256",
    "content": "7871587e9853ba38a21869eb40b0d258e1bc8f6555b92876604a09a71265d2e9 *third_party/cosmo/2/test_suite_hmac_drbg.pr.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_hmac_drbg.pr.com.gz.sha256",
    "content": "63fa5e629f52d759e50cbe54b9e9764d3a9da590e8c801a9a58574934a0d206a *third_party/cosmo/2/test_suite_hmac_drbg.pr.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_md.com.dbg.gz.sha256",
    "content": "8da5330ec3e5b72a73afb8f654cbd92830a39c69b9bcc8e7cf11424651e3dd42 *third_party/cosmo/2/test_suite_md.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_md.com.gz.sha256",
    "content": "c21b65e7830f0472bee74a8aaef8ca9cfa902fa9e38b9a3379d7fdf6f420c800 *third_party/cosmo/2/test_suite_md.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_mdx.com.dbg.gz.sha256",
    "content": "b170332f148ec143fe70b46a31bc5179c6f54cad2ebbfdd365ff0071bb718d12 *third_party/cosmo/2/test_suite_mdx.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_mdx.com.gz.sha256",
    "content": "8097c1a58f35d3c44d9753e10daeb2d5e41e47fefbe47ddd8fddd023e4496e0b *third_party/cosmo/2/test_suite_mdx.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_memory_buffer_alloc.com.dbg.gz.sha256",
    "content": "663020496a1e887988f5d2984fee5bdf83d4a9085437372584fce59d004e3588 *third_party/cosmo/2/test_suite_memory_buffer_alloc.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_memory_buffer_alloc.com.gz.sha256",
    "content": "76001252ed21c20fc551fc85ab672db7e037cffec592b412fc6c9dcac26404df *third_party/cosmo/2/test_suite_memory_buffer_alloc.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_mpi.com.dbg.gz.sha256",
    "content": "5f81ff565e415381e39c6e8a83bccf6c71cb427d699802f57ef9814f7ef5ed46 *third_party/cosmo/2/test_suite_mpi.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_mpi.com.gz.sha256",
    "content": "8a6dcc7caf054fadf088fe751dda009ec8e94f9a9c7cc3d751a08a864feba7a7 *third_party/cosmo/2/test_suite_mpi.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_net.com.dbg.gz.sha256",
    "content": "8b3b0a39b2ba7db6af5fc2bd665b4314af468c916dab6701c9d79e004ec5d442 *third_party/cosmo/2/test_suite_net.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_net.com.gz.sha256",
    "content": "604a687fe7a1754b1bb76a60d008c0abf371b0403adfada1dee0250249902e21 *third_party/cosmo/2/test_suite_net.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_nist_kw.com.dbg.gz.sha256",
    "content": "85ae2696ce045b3182409fdc9d177895d8115d581d887c36b7c7ba3a82cad660 *third_party/cosmo/2/test_suite_nist_kw.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_nist_kw.com.gz.sha256",
    "content": "3573f6ff68389a670e4fe6d49542a41b22a8206c6e49d6988da607ac2f6c773b *third_party/cosmo/2/test_suite_nist_kw.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_oid.com.dbg.gz.sha256",
    "content": "b2831aa2667484cbeefffdb0b16fc75de9f3b8a0833a4a5ad09467eaf40cc45f *third_party/cosmo/2/test_suite_oid.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_oid.com.gz.sha256",
    "content": "bcee392d443a401434881dada76f07f47a9e761c54eb4a542794e2046a8a2890 *third_party/cosmo/2/test_suite_oid.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pem.com.dbg.gz.sha256",
    "content": "c61fc25dbf9eafbc9465d851f44a8b0193928066ce2caac029318417f18f97d3 *third_party/cosmo/2/test_suite_pem.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pem.com.gz.sha256",
    "content": "278802f87a33e8721184ded72bbfaa1c967aa86265e51e9744a3a025fa20a202 *third_party/cosmo/2/test_suite_pem.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pk.com.dbg.gz.sha256",
    "content": "67a171acd8950cd45fec51b93c947f6f7ef249b57d8acb3b11afa9ad30058820 *third_party/cosmo/2/test_suite_pk.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pk.com.gz.sha256",
    "content": "325a8266957c475769682131cbeaa18f61cbdb4ee4bfdd796303dff9f3440a49 *third_party/cosmo/2/test_suite_pk.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pkcs1_v15.com.dbg.gz.sha256",
    "content": "443fae48e511b3248aa23af4bf302d49911865444446db9fa4de4fdf8f52ac94 *third_party/cosmo/2/test_suite_pkcs1_v15.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pkcs1_v15.com.gz.sha256",
    "content": "59e9db28eddb0634db95aa24e4a751c3ee00351c36d5f1ab5cd0e309d901ec5b *third_party/cosmo/2/test_suite_pkcs1_v15.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pkcs1_v21.com.dbg.gz.sha256",
    "content": "bf3970a2a905a810e49a7efd8946d80c8cde78bdf6755689396947aa1c74e4e7 *third_party/cosmo/2/test_suite_pkcs1_v21.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pkcs1_v21.com.gz.sha256",
    "content": "3b47bc730bc0edb13822c82e5d84dfba424e655d9756d03b426958d7dec679ad *third_party/cosmo/2/test_suite_pkcs1_v21.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pkcs5.com.dbg.gz.sha256",
    "content": "09dc26ffad20edeca9aa8026094a1b40baa4097a5aae12d05a356e00573ecb01 *third_party/cosmo/2/test_suite_pkcs5.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pkcs5.com.gz.sha256",
    "content": "2439c701673bbf4b6641a495b8ba1adfe96b3c54e798da6d803670177fc04239 *third_party/cosmo/2/test_suite_pkcs5.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pkparse.com.dbg.gz.sha256",
    "content": "0e92e4c45c6ea07592a30eb23867bfe0618779b68b0306b373446620b78fc62a *third_party/cosmo/2/test_suite_pkparse.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pkparse.com.gz.sha256",
    "content": "5a9ca5de49e6cf52337abd053b8338bd0e5be6f907faffd9db971e29d798fb80 *third_party/cosmo/2/test_suite_pkparse.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pkwrite.com.dbg.gz.sha256",
    "content": "d61ff6776b99e4ece99415e138f9b8eb36590ce25b11cca72bb9dc6098f062fa *third_party/cosmo/2/test_suite_pkwrite.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_pkwrite.com.gz.sha256",
    "content": "4a6aa7684d06758651777882de8355ebb75d5db3d02c28e50ca3384dab4e13a7 *third_party/cosmo/2/test_suite_pkwrite.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_poly1305.com.dbg.gz.sha256",
    "content": "3d547c4d3ff9899f215c8ac8c78708854feb5bb0e83c800ab179df3df5c9a1c2 *third_party/cosmo/2/test_suite_poly1305.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_poly1305.com.gz.sha256",
    "content": "7f3a04b03aecb53228975b38f09c8d5d9fc7b206b5fdb646955e4b192186cebb *third_party/cosmo/2/test_suite_poly1305.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_random.com.dbg.gz.sha256",
    "content": "76bc16fde4881d11c0ab6bb8f019d07544ff46d6e2304bae545f670121fa2883 *third_party/cosmo/2/test_suite_random.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_random.com.gz.sha256",
    "content": "d081021d4f45d3fdb1c2284444889e4fa055d10e05e8ce11b752ca55d262a969 *third_party/cosmo/2/test_suite_random.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_rsa.com.dbg.gz.sha256",
    "content": "13bdef2f6ad8b7706998b8b576874978c0d5f007dce231ba021ea799721bd12b *third_party/cosmo/2/test_suite_rsa.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_rsa.com.gz.sha256",
    "content": "d014f1cf1ce9ef4a7f5024c1ad42bb43569bb305b201f94487539588489eb801 *third_party/cosmo/2/test_suite_rsa.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_shax.com.dbg.gz.sha256",
    "content": "3f56df8e6e534ad179b177f00501e703de348547665e96e7bc1db72d3b98e6fb *third_party/cosmo/2/test_suite_shax.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_shax.com.gz.sha256",
    "content": "997418f17fdb60e15ee2a582db59b8dc717fcb7e0f3f1811faa8016be5238eba *third_party/cosmo/2/test_suite_shax.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_ssl.com.dbg.gz.sha256",
    "content": "630d5953b1ba28c8e670b1e6b235afdb3a87470cfa00514d0e113cda173e1e72 *third_party/cosmo/2/test_suite_ssl.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_ssl.com.gz.sha256",
    "content": "7b8e5b99641eaaea78c96148b9d6dfcd026387db6660cca1dff2dc5d24e3b964 *third_party/cosmo/2/test_suite_ssl.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_timing.com.dbg.gz.sha256",
    "content": "5c8a232d61afb2d649d14c9e1b45e06089383f4ca7e43b7db48881dcad259d83 *third_party/cosmo/2/test_suite_timing.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_timing.com.gz.sha256",
    "content": "b7816b70b64fe1001ff6d016397eb8853d7cd56a93786f1e30b56eff8a0d7e1b *third_party/cosmo/2/test_suite_timing.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_version.com.dbg.gz.sha256",
    "content": "18636ab02cf6e140ea7293fc04c8d996b5639a27c8464af4ad9a6905ad7d34e9 *third_party/cosmo/2/test_suite_version.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_version.com.gz.sha256",
    "content": "88ae6c179987f88c07cde43e01a6fe16adf5154bb2967532dcda8c53bb89adb2 *third_party/cosmo/2/test_suite_version.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_x509parse.com.dbg.gz.sha256",
    "content": "8d834d75c857a7346e20eb6c829ec2aeef4b936ad9b02a4aefcbafd4729790ba *third_party/cosmo/2/test_suite_x509parse.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_x509parse.com.gz.sha256",
    "content": "a028cea72d7d2c8f8817f47ea753ce532e51d3f07a140d559ab337be9fc1e496 *third_party/cosmo/2/test_suite_x509parse.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_x509write.com.dbg.gz.sha256",
    "content": "63a6d1f9bcd6477e9befa6d1e79dce045d9b955dbf4d56709e7b403f057c229d *third_party/cosmo/2/test_suite_x509write.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/test_suite_x509write.com.gz.sha256",
    "content": "c2421fc678e51a0a9cadd4306b4a13edbdb7b63c0d2b305fb7972f27aa415559 *third_party/cosmo/2/test_suite_x509write.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tgamma_test.com.dbg.gz.sha256",
    "content": "1b6fc586c3c35d3e749c5350334fc2b1a067e779d38045eb2383befc948aed51 *third_party/cosmo/2/tgamma_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tgamma_test.com.gz.sha256",
    "content": "dd5a46eb7c0013c49dc65dbad0cbc3885541322b33f7f901adc31bc13f71d732 *third_party/cosmo/2/tgamma_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/timevaltofiletime_test.com.dbg.gz.sha256",
    "content": "1912ba360a7a62963c0883213a48cd339297e7881bd6a168cb29c9cf5e449ccd *third_party/cosmo/2/timevaltofiletime_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/timevaltofiletime_test.com.gz.sha256",
    "content": "fd566c2a22bfd87fc969e6107d040abd1b62e7e346946464a37e26a3d28a975e *third_party/cosmo/2/timevaltofiletime_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tkill_test.com.dbg.gz.sha256",
    "content": "cd6f2498e6550da6a9fed5cf999a74080adb2e826b6885fec33342ddd223ce9b *third_party/cosmo/2/tkill_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tkill_test.com.gz.sha256",
    "content": "bca5e12542e3e75e8f638a2c712eb3b74da55304bcfdb22ceb1f7b4d6990f379 *third_party/cosmo/2/tkill_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tls_test.com.dbg.gz.sha256",
    "content": "f5b260a658f9af9e169571b10de0f99ab83e1be54d3e1f6803f852a7fd75f6ee *third_party/cosmo/2/tls_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tls_test.com.gz.sha256",
    "content": "695ee274f42353e6b6e16f5c08e96c46ea7ab34372c82df833ccee470ae9e795 *third_party/cosmo/2/tls_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tmpfile_test.com.dbg.gz.sha256",
    "content": "00cb6ccc04fdd65c58055d564d8abb9e4b2546d932b6f77a607b9a0fe2e156db *third_party/cosmo/2/tmpfile_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tmpfile_test.com.gz.sha256",
    "content": "9ad581ea7e7942a8bead4de0d53eca1058e7df64172ee21d5a0ebb793084d040 *third_party/cosmo/2/tmpfile_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tokenbucket_test.com.dbg.gz.sha256",
    "content": "bacb2f4117b167e6eab4e005cd3db43908d1657547135db99dc5f9df0587540b *third_party/cosmo/2/tokenbucket_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tokenbucket_test.com.gz.sha256",
    "content": "f332239aa78b436e538c076c8198adc09fbcf575b6c38ae849a480a6de5b0d4c *third_party/cosmo/2/tokenbucket_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/towupper_test.com.dbg.gz.sha256",
    "content": "dc2c37fcb03824a1a6f8e36b4551779827bd819a80eef83548f8518e644d784c *third_party/cosmo/2/towupper_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/towupper_test.com.gz.sha256",
    "content": "a83d18f56db13e2409214b536a2f4156c1a91734736cc46a86c95329addbe779 *third_party/cosmo/2/towupper_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tpenc_test.com.dbg.gz.sha256",
    "content": "83cf663f5d22841ca1e14193d9a0cf6e9c49621ab145232f931f4cab540dcfc9 *third_party/cosmo/2/tpenc_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tpenc_test.com.gz.sha256",
    "content": "e25363afa322de025d549222d99579e932dbcb106a0792bb1702ed5a50137329 *third_party/cosmo/2/tpenc_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tprecode16to8_test.com.dbg.gz.sha256",
    "content": "2a77d3e20bba860c4dcb38f488cabe2aae39246184bf3f154a28b8c7cca5fe79 *third_party/cosmo/2/tprecode16to8_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tprecode16to8_test.com.gz.sha256",
    "content": "4e63f2d25029bce0051d3b1d84cb6b76b3c692c8bf8f0f4e130210af2daf48b2 *third_party/cosmo/2/tprecode16to8_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tprecode8to16_test.com.dbg.gz.sha256",
    "content": "e3f2f4df80d9d6e32c60654abb509164269bdde4a2b7409026e0e8b7a337c8d3 *third_party/cosmo/2/tprecode8to16_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/tprecode8to16_test.com.gz.sha256",
    "content": "27b4cdd3fe71061bec52ab61105f2a338dc68ad61169c0bcb44aeabd2ec38dcc *third_party/cosmo/2/tprecode8to16_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/trunc_test.com.dbg.gz.sha256",
    "content": "b5407aca1f459deb5c7724209d5abf0ac9fe25eef17efdf3c46d8acd2b12c29e *third_party/cosmo/2/trunc_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/trunc_test.com.gz.sha256",
    "content": "039bf561776a6f964d78060be3a003dd26bfb6c58da707a1ac6aa79dbdf3096e *third_party/cosmo/2/trunc_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ttymove_test.com.dbg.gz.sha256",
    "content": "1b65f82a176f70a29008c08e3a32bcf74f2d5b5980024036a6ee0e94b4abe55d *third_party/cosmo/2/ttymove_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ttymove_test.com.gz.sha256",
    "content": "2d20e82c2b90a32e93acb94cade8162fdb44cc49e22b233d8e92866cf3ca07d2 *third_party/cosmo/2/ttymove_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ttyraster_test.com.dbg.gz.sha256",
    "content": "e3123ede3b785e36523ece448dc4fe2279693827bd953e3431ef5bac7ecc9be8 *third_party/cosmo/2/ttyraster_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ttyraster_test.com.gz.sha256",
    "content": "42c3d7c6778fae09bead0556dc8f26fb557831cbac5d70dabeb9f620e430bd3c *third_party/cosmo/2/ttyraster_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/uleb128_test.com.dbg.gz.sha256",
    "content": "fd7f33d8e187c236ab17991ee473839dec44409dc58e0521d1877597534108ba *third_party/cosmo/2/uleb128_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/uleb128_test.com.gz.sha256",
    "content": "72ad186035a0b1994e77748e8ecedba2d893877fed81bd1156cd99dd8e05037c *third_party/cosmo/2/uleb128_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/uleb64_test.com.dbg.gz.sha256",
    "content": "44ab6af3ad420f722fa3685647271a5a384135bf11c44254ba71c22ac395c05e *third_party/cosmo/2/uleb64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/uleb64_test.com.gz.sha256",
    "content": "3559bc8e932573db19e336298aa105f0467c535175023aad04de7b7c97a40136 *third_party/cosmo/2/uleb64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/unchunk_test.com.dbg.gz.sha256",
    "content": "a58f3e665fdb001ef2b3aa97a693694769b990a99f33a896b6f1eb9c2c657a80 *third_party/cosmo/2/unchunk_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/unchunk_test.com.gz.sha256",
    "content": "07f16d7ece1d0d66801c990ef92011c39a10a08e4d07fa62f377d22679c277f5 *third_party/cosmo/2/unchunk_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/underlong_test.com.dbg.gz.sha256",
    "content": "07e66419cd8515dfaf4236997673c6d948d4b258c8d42c3774ec1e2c8866f8e9 *third_party/cosmo/2/underlong_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/underlong_test.com.gz.sha256",
    "content": "53ff56228de731f47bc9b1a0291a82b3ee70363a920043374c4be46089563309 *third_party/cosmo/2/underlong_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ungetc_test.com.dbg.gz.sha256",
    "content": "47ea3dcac3d176deb6c8766c46d326eaf6bf6025594ba312820b40a1bbaa2ada *third_party/cosmo/2/ungetc_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ungetc_test.com.gz.sha256",
    "content": "3d19b5e80d553926923fd473f590e8be2304f1add6c1aeda71bb28fd915ac46a *third_party/cosmo/2/ungetc_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/unlinkat_test.com.dbg.gz.sha256",
    "content": "81dfa3a2ff04f43c7fcd3ffeec74ec82dc10791354f93c4e89c75cb02c37c37d *third_party/cosmo/2/unlinkat_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/unlinkat_test.com.gz.sha256",
    "content": "d4416f72722cc9a16fb645901bd18d8d7fe9d9cf781df78b3f8b6f82dfbcde9a *third_party/cosmo/2/unlinkat_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/unveil_test.com.dbg.gz.sha256",
    "content": "e1f61f13e36128c709b6642e28b0ef049f4bf2d6c0dfc1494104286a59e77d98 *third_party/cosmo/2/unveil_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/unveil_test.com.gz.sha256",
    "content": "9c1e881df86827a03c52b8a845c7462a6ee43605d1dcebdb3507bf30f75c3789 *third_party/cosmo/2/unveil_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/utf16to32_test.com.dbg.gz.sha256",
    "content": "2ba8ee0411f8b58475b689fe9ceb8e8292601c86235d3e80ca46d6b105180c26 *third_party/cosmo/2/utf16to32_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/utf16to32_test.com.gz.sha256",
    "content": "0ebc15cd47f3dd0b410dbe82fbfe3e0ad5eb72d9578aac5e24ec969997d1e095 *third_party/cosmo/2/utf16to32_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/utf16to8_test.com.dbg.gz.sha256",
    "content": "cb0f288cfbb19b19632f324cedc865de78a34fadae2478a8f77eabcbb72f630e *third_party/cosmo/2/utf16to8_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/utf16to8_test.com.gz.sha256",
    "content": "50f5208329824169f178169ae6b4423fe2940c9f1ab6b2d92db41fb4b4911c44 *third_party/cosmo/2/utf16to8_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/utf8to16_test.com.dbg.gz.sha256",
    "content": "a0382141e77e92bc0ce0284bf5675ebe5b03f11f45d34007c19707dbc61e3148 *third_party/cosmo/2/utf8to16_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/utf8to16_test.com.gz.sha256",
    "content": "c6ca3c9c6ae0dd0b2669d8ff1e64a919aa4b9e1d30556eadca4da378695f04d9 *third_party/cosmo/2/utf8to16_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/utf8to32_test.com.dbg.gz.sha256",
    "content": "50153631c8f89da7aff695c15caf365270d2aef02efec83ddf848cd79f8ef75d *third_party/cosmo/2/utf8to32_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/utf8to32_test.com.gz.sha256",
    "content": "5d685a8917c31f2537779c5cffa3203de83134a6d010781d1111c1fc4454f50d *third_party/cosmo/2/utf8to32_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/vappendf_test.com.dbg.gz.sha256",
    "content": "d533d5c3568a97a5e42ff83752fbb794425fbe21f480ed1579c2e73b0ed424ec *third_party/cosmo/2/vappendf_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/vappendf_test.com.gz.sha256",
    "content": "e7a7bde5d0b83adaaed7487ae0eaf0ac52f6eee5767d40a1d3bd4da8e54eec94 *third_party/cosmo/2/vappendf_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/vfork_test.com.dbg.gz.sha256",
    "content": "c770dabf6b912964d96efd6f17b9b12667d07957707da51a0b84d7c00849d213 *third_party/cosmo/2/vfork_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/vfork_test.com.gz.sha256",
    "content": "6e172163551d58dbfde9599c0a0a55c83e4ad2e454cb394782cfb0607e51e3d1 *third_party/cosmo/2/vfork_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/visualizecontrolcodes_test.com.dbg.gz.sha256",
    "content": "b5ffdd4a4fd7a4dea093bd79a4a125ea4a1b8463c18cd1a50659aec804abb53f *third_party/cosmo/2/visualizecontrolcodes_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/visualizecontrolcodes_test.com.gz.sha256",
    "content": "ce8bfd7d65e92b52fbf7503c8770b432e91ac9e6779a3a95c1defdf3125556ab *third_party/cosmo/2/visualizecontrolcodes_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/wait_test.com.dbg.gz.sha256",
    "content": "201feb4fd3d58eb83ebf812b33a5e2f00cacad7e49fdd5a59658c8f47e3d83d9 *third_party/cosmo/2/wait_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/wait_test.com.gz.sha256",
    "content": "936f8c6c4de9600e8a502f4d6476ca52b1ea08397c79ca38bfc249ff36d8d6a1 *third_party/cosmo/2/wait_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/wcsrchr_test.com.dbg.gz.sha256",
    "content": "9adc19fce6a309ba7c1b022bd24c9ae7beea134bfd321e07e6cb5918692ac5fd *third_party/cosmo/2/wcsrchr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/wcsrchr_test.com.gz.sha256",
    "content": "6b49c698d4d9413ef34c3c5d2adc0ab5fb517f6c7948d09bc2bbb4b70086e663 *third_party/cosmo/2/wcsrchr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/wcwidth_test.com.dbg.gz.sha256",
    "content": "663cf6df3e51fd16e64e8f25e931169f5e045b8f0a1ca3e1e9008542dbbe1a3c *third_party/cosmo/2/wcwidth_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/wcwidth_test.com.gz.sha256",
    "content": "668a688432f62cf1da7685ae3ea12a2570cd071ae9442d7af8949724d960f87d *third_party/cosmo/2/wcwidth_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/windex_test.com.dbg.gz.sha256",
    "content": "c00a4de71a0aa3795b63c3b3cea957202a1a28fae1dc3a011767cf9c0bfc120d *third_party/cosmo/2/windex_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/windex_test.com.gz.sha256",
    "content": "521f1e75cca7f961adcf7df843f9b319a2cf00d490bd9bc1f432f5e4d7bd82ae *third_party/cosmo/2/windex_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/wmemrchr_test.com.dbg.gz.sha256",
    "content": "4ba81018fc32b1a6059befc53a198f30e178686bf59bfa46b959533dff04d834 *third_party/cosmo/2/wmemrchr_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/wmemrchr_test.com.gz.sha256",
    "content": "0ac4aa8efc300a03d0df5180371dba5219c6eb7e57daa714fb8fb1a1d9eec5ac *third_party/cosmo/2/wmemrchr_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/write_test.com.dbg.gz.sha256",
    "content": "4307db7fbd1fb6591c3d0d538b6ef4bb3c70e75054d8aaa300c46d9f3fb2a269 *third_party/cosmo/2/write_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/write_test.com.gz.sha256",
    "content": "cd55393d4feb2f8552c62f0c9046f58f6f59641da04b3ac65bbec5c44d596a99 *third_party/cosmo/2/write_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/wut_test.com.dbg.gz.sha256",
    "content": "74785e7da5a5304bb13baeb1a01754c01cadc62447788e271d2c7bac5bfdaacc *third_party/cosmo/2/wut_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/wut_test.com.gz.sha256",
    "content": "d1229f490c74fad405047f34a3fb7a9a7bb9195418dbadb1e118b485a7fda8d7 *third_party/cosmo/2/wut_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_binary_test.com.dbg.gz.sha256",
    "content": "3aed3fd84d2ac5f9c7e07085fe05969cb89e83b7aaec8010f58449a211408d27 *third_party/cosmo/2/x86ild_popular_binary_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_binary_test.com.gz.sha256",
    "content": "403f155bdc4a1d6cdf272aa797e3583db0c0e1064c4947912d96dbe88fcd03fd *third_party/cosmo/2/x86ild_popular_binary_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_cmov_test.com.dbg.gz.sha256",
    "content": "59172e35f0f04d5fe74f555531ac424728fd955d19fdaa3142bd6b5a309c5298 *third_party/cosmo/2/x86ild_popular_cmov_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_cmov_test.com.gz.sha256",
    "content": "6960c4c5f5919415987174dd6c4d707ac68f626c8ac8c9b1cd5b034d3af4e3c9 *third_party/cosmo/2/x86ild_popular_cmov_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_i186_test.com.dbg.gz.sha256",
    "content": "d321ccf3fab3caca8d71055510fc2c8fe8c20abe879f4d4e153c298f37156ae4 *third_party/cosmo/2/x86ild_popular_i186_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_i186_test.com.gz.sha256",
    "content": "a55ed616cde3b0131cbb31c51bfac39fe5aac636ed4b8e0f06807e75790f8589 *third_party/cosmo/2/x86ild_popular_i186_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_i386_test.com.dbg.gz.sha256",
    "content": "470d2e34faa02b74a784b5daf8be33efc001582d7b28279bab11f732e4ef5587 *third_party/cosmo/2/x86ild_popular_i386_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_i386_test.com.gz.sha256",
    "content": "4f5f60fad01d9520dd4fea9e7f90b47466b549ffd74c27cb310b618e9dbff767 *third_party/cosmo/2/x86ild_popular_i386_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_i86_2_test.com.dbg.gz.sha256",
    "content": "da1491258fdf8b1f341cd27ff0b3b03fc9e502b63f7ee4b06c72b084440e9c71 *third_party/cosmo/2/x86ild_popular_i86_2_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_i86_2_test.com.gz.sha256",
    "content": "b6b7142752599028107e2bcfe09ff5d96bef48cfd6e00c36749be9c7af243984 *third_party/cosmo/2/x86ild_popular_i86_2_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_i86_test.com.dbg.gz.sha256",
    "content": "f9a3c7cdb4704384a4d1721cdac7f3a33ed316dde4845d9a15347af3d0d4b335 *third_party/cosmo/2/x86ild_popular_i86_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_i86_test.com.gz.sha256",
    "content": "cedb5794ab14720249952fad9e8e33fb994f906ae82112d60aa5a771a617a17b *third_party/cosmo/2/x86ild_popular_i86_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_logical_test.com.dbg.gz.sha256",
    "content": "31b61a8d2484313011c5afe36a8ff6b54680e6d0a2787ae55c1d23954ead86f0 *third_party/cosmo/2/x86ild_popular_logical_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_logical_test.com.gz.sha256",
    "content": "0669bf20adac429d308918ff0cb1511a6ff4b6a7b68e570f084504f0214b3228 *third_party/cosmo/2/x86ild_popular_logical_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_misc_test.com.dbg.gz.sha256",
    "content": "3560d9eddc281105a446e2314eb47701275b53d2567cb71b3908e7f027967830 *third_party/cosmo/2/x86ild_popular_misc_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_popular_misc_test.com.gz.sha256",
    "content": "2c22c4288d85ed52bb36331eb662b01cd6ca3fbdda1b23544a92fd310af22290 *third_party/cosmo/2/x86ild_popular_misc_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_test.com.dbg.gz.sha256",
    "content": "7cf9c5fbbd3a0794a7ccd236e2e5c611c25c3af9401ea5d284482cacdeeb09aa *third_party/cosmo/2/x86ild_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_test.com.gz.sha256",
    "content": "a1d1c63884fd17d5568c59c6d4665889196f73e09b796b22eb4440382a3c3f62 *third_party/cosmo/2/x86ild_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_widenop_test.com.dbg.gz.sha256",
    "content": "21139b14268e5176dccfc2b665e3774448510080f226af0495972c0717525319 *third_party/cosmo/2/x86ild_widenop_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/x86ild_widenop_test.com.gz.sha256",
    "content": "fe52c7bbfebbff769803a3bb29da4f72fe9b3f46c8e7600c20870cbbacc0c372 *third_party/cosmo/2/x86ild_widenop_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xasprintf_test.com.dbg.gz.sha256",
    "content": "d923f4af4447cbad70fe467cb802cbc471ad55f4b4ccdefd8aede8539ad3a525 *third_party/cosmo/2/xasprintf_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xasprintf_test.com.gz.sha256",
    "content": "219e3e17929f4588ee7b5f57b8df2e06d4bb2052d184af244e820c0bde8a8cfe *third_party/cosmo/2/xasprintf_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xfixpath_test.com.dbg.gz.sha256",
    "content": "1dc6eeb24596455a96b9ae6b223c4772713fa40533e42fd94157f3e5154a5219 *third_party/cosmo/2/xfixpath_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xfixpath_test.com.gz.sha256",
    "content": "5b112114c873294e5b6a8d1f86cedcd4296a5965f8a1aadc84e22c39a809fa72 *third_party/cosmo/2/xfixpath_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xjoinpaths_test.com.dbg.gz.sha256",
    "content": "b0fef3f6717e7bcd5373f9ae357fc87a96b24c83ef003d5e76ba87029ca3fc40 *third_party/cosmo/2/xjoinpaths_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xjoinpaths_test.com.gz.sha256",
    "content": "7846eed399d0b8d04f999c80b4a72c7e3392de700d657bb984e3468b19488037 *third_party/cosmo/2/xjoinpaths_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xlaterrno_test.com.dbg.gz.sha256",
    "content": "4bb5edfd06081fa1a55cf65ff1e9da054629ac3e1e95596b150bcae96a8e8a92 *third_party/cosmo/2/xlaterrno_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xlaterrno_test.com.gz.sha256",
    "content": "c1e6a6366ed4fd5517154bfac96f8251694151dbbe2cbd4f8978255b407ada17 *third_party/cosmo/2/xlaterrno_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xslurp_test.com.dbg.gz.sha256",
    "content": "26558eeb04fbef59eb443f01b712da27d318c08040f09cbe641a620e886e8641 *third_party/cosmo/2/xslurp_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xslurp_test.com.gz.sha256",
    "content": "b3795004d6ca354e31046fbea86e5429e38b47cb037af2d96fdd1257622259ab *third_party/cosmo/2/xslurp_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xstrcat_test.com.dbg.gz.sha256",
    "content": "dbf09670f259bebd3587433f47ae886b77800e3ccb9264624a7224412e8f15c0 *third_party/cosmo/2/xstrcat_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/xstrcat_test.com.gz.sha256",
    "content": "6c2cbef7b693cc80c4d110081c844bb39afcbd89163b2e2a59f6b4dab3184126 *third_party/cosmo/2/xstrcat_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ycbcr2rgb2_test.com.dbg.gz.sha256",
    "content": "5f04d38fb47cec33c4608b108f0d7aa4fc09e202d8b82b9d0026d79e16a51cd6 *third_party/cosmo/2/ycbcr2rgb2_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/ycbcr2rgb2_test.com.gz.sha256",
    "content": "435a51434a0b48cb8a7e65ba6178efad77412f149bb77ec2d03acb63a09d660d *third_party/cosmo/2/ycbcr2rgb2_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/2/zleb64_test.com.dbg.gz.sha256",
    "content": "8ba8873c4b190f3dd113a336b6a89b567d60263e1a3a48a85aa22154693a39fc *third_party/cosmo/2/zleb64_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/2/zleb64_test.com.gz.sha256",
    "content": "aa8159a3dea1b1c9bf8fe552d81f2444367e9be0f5695f8759d7845813a42d5b *third_party/cosmo/2/zleb64_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/3/sqlite_test.com.dbg.gz.sha256",
    "content": "70b4ee4307743a80dc09efe6eae9d157b25fd0281d40393b5c030216d23c8179 *third_party/cosmo/3/sqlite_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/3/sqlite_test.com.gz.sha256",
    "content": "e55a9f5146ab68c658c7ebc3b60dbe9c92dcba40fbb091bc332be1337e1734b1 *third_party/cosmo/3/sqlite_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/4/dtoa_test.com.dbg.gz.sha256",
    "content": "5cf3cd60c45255ecc226dcdc368a688c66cfb69b47a3165c9aa4c277370f07df *third_party/cosmo/4/dtoa_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/4/dtoa_test.com.gz.sha256",
    "content": "02d94cc824a11db7f0e2f8c4517e2f05284dfe981ece0a2b2ea51de73b05d8df *third_party/cosmo/4/dtoa_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/4/writev_test.com.dbg.gz.sha256",
    "content": "7831aca9eff86dcbe76bd517d401097b9fa5cd8e57161478b4e0bf308c6eab5a *third_party/cosmo/4/writev_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/4/writev_test.com.gz.sha256",
    "content": "4c85486b04e1b50b58715afe544cecbf35ad2e40a5f1987383026ea1e6a1ba6a *third_party/cosmo/4/writev_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/5/pipe_test.com.dbg.gz.sha256",
    "content": "53c1954479cb53b9f020fde8c1b056ffbfa0067e9538f12f5ce73a8a95b20290 *third_party/cosmo/5/pipe_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/5/pipe_test.com.gz.sha256",
    "content": "9aa7d5b7a9c5ce3b487a92ec8ab81d90f36ed8b3c80e0ac60c57bcd50eff4f9f *third_party/cosmo/5/pipe_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/5/sigaction_test.com.dbg.gz.sha256",
    "content": "79f804fce956d13bf35cca5d7f3aa6cffc85bcd2e324bba00c6c70f86b0cd949 *third_party/cosmo/5/sigaction_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/5/sigaction_test.com.gz.sha256",
    "content": "0e4f327d3b22bd05d2c418eaaf7f1f5799f8014135fc0a1fda1eda52fae81ac5 *third_party/cosmo/5/sigaction_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/5/unix_test.com.dbg.gz.sha256",
    "content": "699146f4bed6416e91ffd213b254ec223862da0722f999a15f3d2c4ab82ed3d0 *third_party/cosmo/5/unix_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/5/unix_test.com.gz.sha256",
    "content": "69fb7f47c553600f417e364d97c7d2ae7e7ae4474db30a23437dacef2358e0b0 *third_party/cosmo/5/unix_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/7/munmap_test.com.dbg.gz.sha256",
    "content": "62c4375a79ca6826bdcf1c82125a5e40857a03d6371cc054e8f1f1cf32069cd5 *third_party/cosmo/7/munmap_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/7/munmap_test.com.gz.sha256",
    "content": "216def82234c8a7641cca6b0b3f5e08cfd5c2e5bf172136d94e6a295875445df *third_party/cosmo/7/munmap_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/7/utimensat_test.com.dbg.gz.sha256",
    "content": "b7bdbc50e324f4830b78bb5b48d0179e02420ab2b66c28699c8958b9e985c037 *third_party/cosmo/7/utimensat_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/7/utimensat_test.com.gz.sha256",
    "content": "f594da2ceb9997e50a14a1f39ba2927a292b40aae762a71f5b68eb091d2aa06f *third_party/cosmo/7/utimensat_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/8/ftruncate_test.com.dbg.gz.sha256",
    "content": "daf10d74b893612404b51e2d672311604c683070ca3fdb6510941e450c31eeb0 *third_party/cosmo/8/ftruncate_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/8/ftruncate_test.com.gz.sha256",
    "content": "e1e43ab58345eeca0f02ff6ae7814221d7cba39153fc2982a08e292925847211 *third_party/cosmo/8/ftruncate_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/8/intrin_test.com.dbg.gz.sha256",
    "content": "9b6e74924cb619aac4c1e4a775c610b3739260034a35580f2d3f3d8d80ea28ac *third_party/cosmo/8/intrin_test.com.dbg.gz\n"
  },
  {
    "path": "third_party/cosmo/8/intrin_test.com.gz.sha256",
    "content": "127622ee2fe636c4b491e524e4b4082f144ce7eeb5dd5ec896f78f4f86063249 *third_party/cosmo/8/intrin_test.com.gz\n"
  },
  {
    "path": "third_party/cosmo/cosmo.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\n.PRECIOUS: third_party/cosmo/%.gz\nthird_party/cosmo/%.gz: third_party/cosmo/%.gz.sha256 o/tool/sha256sum\n\tcurl -so $@ https://justine.storage.googleapis.com/cosmotests/$(subst third_party/cosmo/,,$@)\n\to/tool/sha256sum -c $<\n\n.PRECIOUS: third_party/cosmo/%.com.dbg\nthird_party/cosmo/%.com.dbg: third_party/cosmo/%.com.dbg.gz\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\n.PRECIOUS: third_party/cosmo/%.com\nthird_party/cosmo/%.com: third_party/cosmo/%.com.gz\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/$(MODE)/third_party/cosmo/%.com.ok:\t\t\t\t\t\t\t\t\\\n\t\tthird_party/cosmo/%.com\t\t\t\t\t\t\t\t\\\n\t\tthird_party/cosmo/%.com.dbg\t\t\t\t\t\t\t\\\n\t\to/$(MODE)/blink/blink $(VM)\n\t@mkdir -p $(@D)\n\to/$(MODE)/blink/blink $<\n\t@touch $@\n\nCOSMO_TESTS =\t\t\t\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/8/intrin_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/lockscale_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/palignr_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pmulhrsw_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/mulaw_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/nanosleep_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/clock_nanosleep_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/palandprintf_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pshuf_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/popcnt_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/kprintf_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/memmem_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/memcmp_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/memory_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/memrchr_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/parsecidr_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/parsecontentlength_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/parseforwarded_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/parsehoststxt_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/parsehttpdatetime_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/parsehttpmessage_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/parsehttprange_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/parseip_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/parseresolvconf_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/parseurl_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pascalifydnsname_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pcmpstr_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pingpong_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/prototxt_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/rand64_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/qsort_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/regex_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/renameat_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/atoi_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/resolvehostsreverse_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/resolvehoststxt_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/reverse_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/rgb2ansi_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/rngset_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/round_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/roundup2log_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/roundup2pow_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sad16x8n_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/scalevolume_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/secp384r1_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/putenv_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/note_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/mu_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/servicestxt_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/setitimer_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/setlocale_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sincos_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sinh_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sizetol_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sleb128_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/snprintf_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/alu_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/bsu_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/divmul_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/test_suite_ecp.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/dll_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/asmdown_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/asin_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/atan2_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/argon2_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/counter_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pthread_detach_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pthread_mutex_lock_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pthread_mutex_lock2_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pthread_spin_lock_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/cescapec_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/clock_gettime_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/cas_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/bilinearscale_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/access_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/a64l_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/_timespec_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/zleb64_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/xslurp_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/chdir_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/mkdir_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/unlinkat_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/makedirs_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/dirstream_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/bitscan_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/commandv_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/closefrom_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/ecvt_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/division_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/test_suite_aes.cbc.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/test_suite_cipher.gcm.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/test_suite_ctr_drbg.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/test_suite_entropy.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/test_suite_mpi.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/test_suite_md.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/crc32_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/crc32c_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/crc32z_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sigsetjmp_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/escapehtml_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/escapeurlparam_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/escapejsstringliteral_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/erf_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/encodebase64_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/fabs_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/fgets_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/fileexists_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/floor_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/fmemopen_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/fmt_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/fputc_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/gamma_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/tgamma_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/gclongjmp_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/getcwd_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/gz_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/ilogb_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/imaxdiv_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/inv3_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/iso8601_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/itsatrap_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/mu_starvation_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/open_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/stat_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/stackrwx_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/clone_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/cv_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/4/writev_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/3/sqlite_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sched_yield_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pwrite_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/read_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pread_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/preadv_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/nsync_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/mt19937_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/modrm_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/measureentropy_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/malloc_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/ftell_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/fseeko_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/fputs_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/5/pipe_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/arena_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/acos_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/getintegercoefficients8_test.com.ok\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/atan_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/bextra_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/cbrt_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/clock_getres_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/copysign_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/cos_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/cosh_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/complex_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/countbits_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/cv_wait_example_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/expm1_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/fgetln_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/getcontext_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/getenv_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/8/ftruncate_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/tmpfile_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/select_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/7/utimensat_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/readlinkat_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/signal_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/tkill_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/getdelim_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/getgroups_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/dup_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sem_timedwait_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/lockipc_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/socket_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/5/unix_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/daemon_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/execve_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sigpending_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/fork_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/setsockopt_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sigsuspend_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/lock2_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/lock_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/5/sigaction_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pthread_create_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/pthread_exit_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/readansi_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sendrecvmsg_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/lseek_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/mmap_test.com.ok\n\n# munmap_test triggers SIGSEGV on purpose, making it fail on asan\n# TODO(jart): Make this work on asan\nifneq ($(MODE), asan)\nCOSMO_TESTS += o/$(MODE)/third_party/cosmo/7/munmap_test.com.ok\nendif\n\n# write_test is broken on Cygwin due to RLIMIT_FSIZE\n# TODO(jart): Why do the other ones flake on Cygwin?\nifneq ($(HOST_OS), Cygwin)\nCOSMO_TESTS +=\t\t\t\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/4/dtoa_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/write_test.com.ok\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/once_test.com.ok\nendif\n\no/$(MODE)/third_party/cosmo: $(COSMO_TESTS)\n\t@mkdir -p $(@D)\n\t@touch $@\n\nPROBLEMATIC_TESTS =\t\t\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sem_open_test.com.ok\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sigprocmask_test.com.ok\n\nDARWIN_PROBLEMATIC_TESTS =\t\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/sched_getaffinity_test.com.ok\t\t\t\t\\\n\to/$(MODE)/third_party/cosmo/2/backtrace_test.com.ok\n\no/$(MODE)/third_party/cosmo/emulates:\t\t\t\t\t\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/8/intrin_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/palandprintf_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/divmul_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/test_suite_ecp.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/lockscale_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/palignr_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/pmulhrsw_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/pshuf_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/alu_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/bsu_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/pthread_mutex_lock2_test.com.emulates\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/pthread_mutex_lock_test.com.emulates\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/pthread_spin_lock_test.com.emulates\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/sincos_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/round_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/kprintf_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/snprintf_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/once_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/mu_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/note_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/counter_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/dll_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/secp384r1_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/parsehttpmessage_test.com.emulates\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/parseurl_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/parseip_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/parsehttprange_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/pcmpstr_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/rand64_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/cescapec_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/clock_gettime_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/cas_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/bilinearscale_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/access_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/a64l_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/_timespec_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/zleb64_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/xslurp_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/chdir_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/mkdir_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/unlinkat_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/makedirs_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/dirstream_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/bitscan_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/commandv_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/closefrom_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/ecvt_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/division_test.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/test_suite_aes.cbc.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/test_suite_cipher.gcm.com.emulates\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/test_suite_ctr_drbg.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/test_suite_entropy.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/test_suite_md.com.emulates\t\t\\\n\t\to/$(MODE)/aarch64/third_party/cosmo/2/execve_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/mips64el/third_party/cosmo/8/intrin_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/mips64el/third_party/cosmo/2/palandprintf_test.com.emulates\t\t\\\n\t\to/$(MODE)/mips64el/third_party/cosmo/2/divmul_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/mips64el/third_party/cosmo/2/lockscale_test.com.emulates\t\t\\\n\t\to/$(MODE)/mips64el/third_party/cosmo/2/palignr_test.com.emulates\t\t\\\n\t\to/$(MODE)/mips64el/third_party/cosmo/2/pmulhrsw_test.com.emulates\t\t\\\n\t\to/$(MODE)/mips64el/third_party/cosmo/2/pshuf_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/mips64el/third_party/cosmo/2/pthread_mutex_lock2_test.com.emulates\t\\\n\t\to/$(MODE)/mips64el/third_party/cosmo/2/pthread_mutex_lock_test.com.emulates\t\\\n\t\to/$(MODE)/mips64el/third_party/cosmo/2/pthread_spin_lock_test.com.emulates\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/8/intrin_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/palandprintf_test.com.emulates\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/divmul_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/lockscale_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/palignr_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/pmulhrsw_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/pshuf_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/pthread_mutex_lock2_test.com.emulates\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/pthread_mutex_lock_test.com.emulates\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/pthread_spin_lock_test.com.emulates\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/sincos_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/round_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/kprintf_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/snprintf_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/once_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/note_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/counter_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/dll_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/secp384r1_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/parsehttpmessage_test.com.emulates\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/parseurl_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/parseip_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/parsehttprange_test.com.emulates\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/pcmpstr_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/rand64_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/cescapec_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/clock_gettime_test.com.emulates\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/cas_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/bilinearscale_test.com.emulates\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/access_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/a64l_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/_timespec_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/zleb64_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/xslurp_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/chdir_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/mkdir_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/unlinkat_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/makedirs_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/dirstream_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/bitscan_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/commandv_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/closefrom_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/ecvt_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/division_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/test_suite_aes.cbc.com.emulates\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/test_suite_cipher.gcm.com.emulates\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/test_suite_ctr_drbg.com.emulates\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/test_suite_entropy.com.emulates\t\t\\\n\t\to/$(MODE)/s390x/third_party/cosmo/2/test_suite_md.com.emulates\t\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/8/intrin_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/palandprintf_test.com.emulates\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/divmul_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/lockscale_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/palignr_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/pmulhrsw_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/pshuf_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/pthread_mutex_lock2_test.com.emulates\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/pthread_mutex_lock_test.com.emulates\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/pthread_spin_lock_test.com.emulates\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/sincos_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/round_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/kprintf_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/snprintf_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/once_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/note_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/counter_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/dll_test.com.emulates\t\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/secp384r1_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/parsehttpmessage_test.com.emulates\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/parseurl_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/parseip_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/parsehttprange_test.com.emulates\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/pcmpstr_test.com.emulates\t\t\\\n\t\to/$(MODE)/powerpc64le/third_party/cosmo/2/rand64_test.com.emulates\n\t@mkdir -p $(@D)\n\t@touch $@\n"
  },
  {
    "path": "third_party/elks/README",
    "content": "DESCRIPTION\n\n  ELKS distribution images\n\nORIGIN\n\n  fd1440.img\n    ELKS v0.6.0 floppy image\n    https://github.com/jbruchon/elks\n    Built using blink16.config\n    GPL v2 License\n"
  },
  {
    "path": "third_party/freedos/README",
    "content": "DESCRIPTION\n\n  FreeDOS distribution images\n\nORIGIN\n\n  freedos13.img\n    FreeDOS v1.3 floppy image\n    https://www.freedos.org/download/\n    FD13-FloppyEdition.zip\n    GPL v2 License\n"
  },
  {
    "path": "third_party/gameoflife/README.md",
    "content": "# Game Of Life\n\nThis is an implementation of Conway's game of life that runs in x86_64\nbare metal freestanding environment.\n\n### Origin\n\n<https://github.com/glitzflitz/gameoflife/blob/ac17b5987f845f242bc7c9f8f4aea38e8a98f92f/gameoflife.bin>\n\n### Author\n\n[Amey Narkhede](https://github.com/glitzflitz)\n\n### License\n\nGPL v2.0\n"
  },
  {
    "path": "third_party/games/README",
    "content": "DESCRIPTION\n\n  Various boot sector games\n\nORIGIN\n\n  basic.bin\n    BootBASIC\n    https://github.com/nanochess/bootBASIC/basic.img\n    BSD-2-Clause License\n\n  fbird.bin\n    F-Bird\n    https://github.com/nanochess/fbird\n\n  ntetros.bin\n    TetrOS\n    https://github.com/daniel-e/tetros/tree/master/tetros.img\n    MIT License\n"
  },
  {
    "path": "third_party/gcc/2/x86_64-linux-musl__mips64-linux-musl__g++-9.4.0.tar.xz.sha256",
    "content": "bc9b58b9e466a7cb32acaf09cc8af482667a6539ea5f91d2b846a04d67328077 *third_party/gcc/2/x86_64-linux-musl__mips64-linux-musl__g++-9.4.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/2/x86_64-linux-musl__powerpc64le-linux-musl__g++-9.2.0.tar.xz.sha256",
    "content": "fcd0a7d73d441451ac7aee9231b515bc571a895603391f8f92099c9a41090676 *third_party/gcc/2/x86_64-linux-musl__powerpc64le-linux-musl__g++-9.2.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/gcc.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nthird_party/gcc/%.xz: third_party/gcc/%.xz.sha256 o/tool/sha256sum\n\tcurl -so $@ https://justine.storage.googleapis.com/compilers/$(subst third_party/gcc/,,$@)\n\to/tool/sha256sum -c $<\n\no/$(MODE)/i486/%.o: %.c o/third_party/gcc/i486/bin/i486-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/i486/bin/i486-linux-musl-gcc -static -Werror $(filter-out -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/i486/%.o: %.s o/third_party/gcc/i486/bin/i486-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/i486/bin/i486-linux-musl-as -o $@ $<\n\no/$(MODE)/i486/%.o: %.S o/third_party/gcc/i486/bin/i486-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/i486/bin/i486-linux-musl-gcc $(CPPFLAGS) $(CPPFLAGS_STATIC) -c -o $@ $<\n\no/$(MODE)/x86_64/%.o: %.c o/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc -static -Werror $(filter-out -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/x86_64/%.o: %.s o/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/x86_64/bin/x86_64-linux-musl-as -o $@ $<\n\no/$(MODE)/x86_64/%.o: %.S o/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc $(CPPFLAGS) $(CPPFLAGS_STATIC) -c -o $@ $<\n\no/$(MODE)/x86_64-gcc48/%.o: %.c o/third_party/gcc/x86_64-gcc48/bin/x86_64-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/x86_64-gcc48/bin/x86_64-linux-musl-gcc -static -Werror $(filter-out -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/x86_64-gcc48/%.o: %.S o/third_party/gcc/x86_64-gcc48/bin/x86_64-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/x86_64-gcc48/bin/x86_64-linux-musl-gcc $(CPPFLAGS) $(CPPFLAGS_STATIC) -c -o $@ $<\n\no/$(MODE)/x86_64-gcc49/%.o: %.c o/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc -static -Werror $(filter-out -fcf-protection=%,$(CFLAGS)) -Wno-unused-value $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/x86_64-gcc49/%.o: %.S o/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc $(CPPFLAGS) $(CPPFLAGS_STATIC) -c -o $@ $<\n\no/$(MODE)/m68k/%.o: %.c o/third_party/gcc/m68k/bin/m68k-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/m68k/bin/m68k-linux-musl-gcc -static -Werror $(filter-out -mtune=generic -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/arm/%.o: %.c o/third_party/gcc/arm/bin/arm-linux-musleabi-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/arm/bin/arm-linux-musleabi-gcc -static -Werror $(filter-out -mtune=generic -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/aarch64/%.o: %.c o/third_party/gcc/aarch64/bin/aarch64-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/aarch64/bin/aarch64-linux-musl-gcc -static -Werror $(filter-out -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/riscv64/%.o: %.c o/third_party/gcc/riscv64/bin/riscv64-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/riscv64/bin/riscv64-linux-musl-gcc -static -Werror $(filter-out -mtune=generic -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/mips/%.o: %.c o/third_party/gcc/mips/bin/mips-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/mips/bin/mips-linux-musl-gcc -static -Werror $(filter-out -mtune=generic -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/mipsel/%.o: %.c o/third_party/gcc/mipsel/bin/mipsel-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/mipsel/bin/mipsel-linux-musl-gcc -static -Werror $(filter-out -mtune=generic -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/mips64/%.o: %.c o/third_party/gcc/mips64/bin/mips64-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/mips64/bin/mips64-linux-musl-gcc -static -Werror $(filter-out -mtune=generic -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/mips64el/%.o: %.c o/third_party/gcc/mips64el/bin/mips64el-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/mips64el/bin/mips64el-linux-musl-gcc -static -Werror $(filter-out -mtune=generic -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/s390x/%.o: %.c o/third_party/gcc/s390x/bin/s390x-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/s390x/bin/s390x-linux-musl-gcc -static -Werror $(filter-out -mtune=generic -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/microblaze/%.o: %.c o/third_party/gcc/microblaze/bin/microblaze-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/microblaze/bin/microblaze-linux-musl-gcc -static -Werror $(filter-out -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/powerpc/%.o: %.c o/third_party/gcc/powerpc/bin/powerpc-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/powerpc/bin/powerpc-linux-musl-gcc -static -Werror $(filter-out -mtune=generic -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/$(MODE)/powerpc64le/%.o: %.c o/third_party/gcc/powerpc64le/bin/powerpc64le-linux-musl-gcc $(VM)\n\t@mkdir -p $(@D)\n\t$(VM) o/third_party/gcc/powerpc64le/bin/powerpc64le-linux-musl-gcc -static -Werror $(filter-out -mtune=generic -fcf-protection=%,$(CFLAGS)) $(CPPFLAGS) $(CPPFLAGS_STATIC) $(TARGET_ARCH) -c -o $@ $<\n\no/third_party/gcc/i486/bin/i486-linux-musl-gcc:\t\t\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__i486-linux-musl__g++-7.2.0.tar.xz\n\tmkdir -p o/third_party/gcc/i486\n\ttar -C o/third_party/gcc/i486 -xJf $<\n\ttouch $@\n\no/third_party/gcc/m68k/bin/m68k-linux-musl-gcc:\t\t\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__m68k-linux-musl__gcc-5.3.0.tar.xz\n\tmkdir -p o/third_party/gcc/m68k\n\ttar -C o/third_party/gcc/m68k -xJf $<\n\ttouch $@\n\no/third_party/gcc/x86_64/bin/x86_64-linux-musl-gcc:\t\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__x86_64-linux-musl__g++-7.2.0.tar.xz\n\tmkdir -p o/third_party/gcc/x86_64\n\ttar -C o/third_party/gcc/x86_64 -xJf $<\n\ttouch $@\n\no/third_party/gcc/x86_64-gcc48/bin/x86_64-linux-musl-gcc:\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__x86_64-linux-musl__gcc-4.8.5.tar.xz\n\tmkdir -p o/third_party/gcc/x86_64-gcc48\n\ttar -C o/third_party/gcc/x86_64-gcc48 -xJf $<\n\ttouch $@\n\no/third_party/gcc/x86_64-gcc49/bin/x86_64-linux-musl-gcc:\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__x86_64-linux-musl__g++-4.9.4.tar.xz\n\tmkdir -p o/third_party/gcc/x86_64-gcc49\n\ttar -C o/third_party/gcc/x86_64-gcc49 -xJf $<\n\ttouch $@\n\no/third_party/gcc/arm/bin/arm-linux-musleabi-gcc:\t\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__arm-linux-musleabi__g++-7.2.0.tar.xz\n\tmkdir -p o/third_party/gcc/arm\n\ttar -C o/third_party/gcc/arm -xJf $<\n\ttouch $@\n\no/third_party/gcc/aarch64/bin/aarch64-linux-musl-gcc:\t\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__aarch64-linux-musl__g++-7.2.0.tar.xz\n\tmkdir -p o/third_party/gcc/aarch64\n\ttar -C o/third_party/gcc/aarch64 -xJf $<\n\ttouch $@\n\no/third_party/gcc/riscv64/bin/riscv64-linux-musl-gcc:\t\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__riscv64-linux-musl__gcc-9.2.0.tar.xz\n\tmkdir -p o/third_party/gcc/riscv64\n\ttar -C o/third_party/gcc/riscv64 -xJf $<\n\ttouch $@\n\no/third_party/gcc/mips/bin/mips-linux-musl-gcc:\t\t\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__mips-linux-musl__g++-7.2.0.tar.xz\n\tmkdir -p o/third_party/gcc/mips\n\ttar -C o/third_party/gcc/mips -xJf $<\n\ttouch $@\n\no/third_party/gcc/mipsel/bin/mipsel-linux-musl-gcc:\t\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__mipsel-linux-musl__g++-9.2.0.tar.xz\n\tmkdir -p o/third_party/gcc/mipsel\n\ttar -C o/third_party/gcc/mipsel -xJf $<\n\ttouch $@\n\no/third_party/gcc/mips64/bin/mips64-linux-musl-gcc:\t\t\\\n\t\tthird_party/gcc/2/x86_64-linux-musl__mips64-linux-musl__g++-9.4.0.tar.xz\n\tmkdir -p o/third_party/gcc/mips64\n\ttar -C o/third_party/gcc/mips64 -xJf $<\n\ttouch $@\n\no/third_party/gcc/mips64el/bin/mips64el-linux-musl-gcc:\t\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__mips64el-linux-musl__gcc-5.3.0.tar.xz\n\tmkdir -p o/third_party/gcc/mips64el\n\ttar -C o/third_party/gcc/mips64el -xJf $<\n\ttouch $@\n\no/third_party/gcc/s390x/bin/s390x-linux-musl-gcc:\t\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__s390x-linux-musl__g++-7.2.0.tar.xz\n\tmkdir -p o/third_party/gcc/s390x\n\ttar -C o/third_party/gcc/s390x -xJf $<\n\ttouch $@\n\no/third_party/gcc/microblaze/bin/microblaze-linux-musl-gcc:\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__microblaze-linux-musl__g++-7.2.0.tar.xz\n\tmkdir -p o/third_party/gcc/microblaze\n\ttar -C o/third_party/gcc/microblaze -xJf $<\n\ttouch $@\n\no/third_party/gcc/powerpc/bin/powerpc-linux-musl-gcc:\t\t\\\n\t\tthird_party/gcc/x86_64-linux-musl__powerpc-linux-musl__g++-7.2.0.tar.xz\n\tmkdir -p o/third_party/gcc/powerpc\n\ttar -C o/third_party/gcc/powerpc -xJf $<\n\ttouch $@\n\no/third_party/gcc/powerpc64le/bin/powerpc64le-linux-musl-gcc:\t\\\n\t\tthird_party/gcc/2/x86_64-linux-musl__powerpc64le-linux-musl__g++-9.2.0.tar.xz\n\tmkdir -p o/third_party/gcc/powerpc64le\n\ttar -C o/third_party/gcc/powerpc64le -xJf $<\n\ttouch $@\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__aarch64-linux-musl__g++-7.2.0.tar.xz.sha256",
    "content": "45add9649925052c42ad5dfe4234658e520f16aa365dfb27ccb4af4e4bb1bfe4 *third_party/gcc/x86_64-linux-musl__aarch64-linux-musl__g++-7.2.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__arm-linux-musleabi__g++-7.2.0.tar.xz.sha256",
    "content": "9c753bee6c8dce961607bcdb507944b332d5d20a4b063de31acc519c2f5178de *third_party/gcc/x86_64-linux-musl__arm-linux-musleabi__g++-7.2.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__i486-linux-musl__g++-7.2.0.tar.xz.sha256",
    "content": "95a30473064b3bdd0cd01249c6075691b4690646d491feaccc075415f8093129 *third_party/gcc/x86_64-linux-musl__i486-linux-musl__g++-7.2.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__m68k-linux-musl__gcc-5.3.0.tar.xz.sha256",
    "content": "c77795ed7b415411f92f74fa461ddff89809c8854a661bad6e2513117c613361 *third_party/gcc/x86_64-linux-musl__m68k-linux-musl__gcc-5.3.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__microblaze-linux-musl__g++-7.2.0.tar.xz.sha256",
    "content": "9cf57f5c8cb54550898cb395d8936124a99502770fbc080904b4bb4914993231 *third_party/gcc/x86_64-linux-musl__microblaze-linux-musl__g++-7.2.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__mips-linux-musl__g++-7.2.0.tar.xz.sha256",
    "content": "ed53952cd68d5330ff3fb976488235901c380df6047ecadc99487b725b337dd1 *third_party/gcc/x86_64-linux-musl__mips-linux-musl__g++-7.2.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__mips64el-linux-musl__gcc-5.3.0.tar.xz.sha256",
    "content": "525dbdd0d12005f9c37c27fb34374e4a37cc71ac85d6760853ba8c3b088051d2 *third_party/gcc/x86_64-linux-musl__mips64el-linux-musl__gcc-5.3.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__mipsel-linux-musl__g++-9.2.0.tar.xz.sha256",
    "content": "3284617b33dc2ea43b32b07a393dba0d74ac48c30aa11c585cf06ee82070b420 *third_party/gcc/x86_64-linux-musl__mipsel-linux-musl__g++-9.2.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__powerpc-linux-musl__g++-7.2.0.tar.xz.sha256",
    "content": "7b0c9baf87eac2329fe4b83d18a53a3eb537c8d91a627404db39e7e697c5ec10 *third_party/gcc/x86_64-linux-musl__powerpc-linux-musl__g++-7.2.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__riscv64-linux-musl__gcc-9.2.0.tar.xz.sha256",
    "content": "93dbe95dd459fe7be6a2e37f6cdcc8c27b0458762a2257dccdb23b263a869a93 *third_party/gcc/x86_64-linux-musl__riscv64-linux-musl__gcc-9.2.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__s390x-linux-musl__g++-7.2.0.tar.xz.sha256",
    "content": "8f2ca5c7917d699d075359c2be8bbc758e596f5085f1c15a80656e646398d4cf *third_party/gcc/x86_64-linux-musl__s390x-linux-musl__g++-7.2.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__x86_64-linux-musl__g++-4.9.4.tar.xz.sha256",
    "content": "6600f139ec0caeb6d27aad87ebc7347e60c85d224779fcb8901528d12972a51d *third_party/gcc/x86_64-linux-musl__x86_64-linux-musl__g++-4.9.4.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__x86_64-linux-musl__g++-7.2.0.tar.xz.sha256",
    "content": "4a2a724c5ea3ca44423578dbb62c1e3bf729090fd0185490f9ce861c65a56b1b *third_party/gcc/x86_64-linux-musl__x86_64-linux-musl__g++-7.2.0.tar.xz\n"
  },
  {
    "path": "third_party/gcc/x86_64-linux-musl__x86_64-linux-musl__gcc-4.8.5.tar.xz.sha256",
    "content": "95ca17d949180404d70df436dde698bd2d8148f1e7d3d08461b4f5b2be0a1c7e *third_party/gcc/x86_64-linux-musl__x86_64-linux-musl__gcc-4.8.5.tar.xz\n"
  },
  {
    "path": "third_party/libc-test/README.md",
    "content": "# Libc Test Project\n\nThis folder downloads prebuilt binaries from the [Libc Test\nProject](https://github.com/jart/libc-test). This is Musl Libc's test\nsuite collection.\n\n## Origin\n\ngit://repo.or.cz/libc-test\n\n## Changes\n\nSee link above to our GitHub fork.\n\n## Build\n\nThe binaries were compiled on Alpine Linux using:\n\n```\nexport CC=\"cc -fno-omit-frame-pointer -Wl,-z,common-page-size=65536,-z,max-page-size=65536\"\nmake -j16\nmake install\n```\n\n## Deploy\n\nOur operations team them uses [deploy-libc-test](deploy-libc-test) to\ndeploy individual test programs to Google Cloud Storage once they've\nbeen confirmed to work.\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/argv.elf.gz.sha256",
    "content": "6c5a7e17d7af78fd9b8ee71d305fce179320a2623989276f8333f27194e6b76c *third_party/libc-test/bin/2/functional/argv.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/basename.elf.gz.sha256",
    "content": "a00ed4d780761f1041385200e8acc0baabd3273362643c5e721112975bfb3c8a *third_party/libc-test/bin/2/functional/basename.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/clocale_mbfuncs.elf.gz.sha256",
    "content": "0457a1757b9f7bf0be9e3cbf41aacabbb8bd58f1a17d7925add122490142b9e7 *third_party/libc-test/bin/2/functional/clocale_mbfuncs.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/clock_gettime.elf.gz.sha256",
    "content": "c0e91258cc020dd0adb4c368da14838c5af9b522064218b99d57fd9013f019b1 *third_party/libc-test/bin/2/functional/clock_gettime.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/crypt.elf.gz.sha256",
    "content": "dca6b8da2612fe55172f7d1c2559cbb58a2695ffa2c3cc6b4d453d21a333ff19 *third_party/libc-test/bin/2/functional/crypt.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/dirname.elf.gz.sha256",
    "content": "64de17f04659bc20a98bf3578b92d90a8bc0ce98cd114e985f3bc20025e652b6 *third_party/libc-test/bin/2/functional/dirname.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/env.elf.gz.sha256",
    "content": "e5e3fa8cb2176e6783c7119ba5b3ea31872ac338f7e39134694845b3c24ea4e3 *third_party/libc-test/bin/2/functional/env.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/fcntl.elf.gz.sha256",
    "content": "ebf27102a931d647b56a603f3241da59296fdb8222533be6f4c1a377ea805d63 *third_party/libc-test/bin/2/functional/fcntl.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/fdopen.elf.gz.sha256",
    "content": "5699f34f8519b84bd03cd02dc280bd8da2ba239cf317eccbcfaa92305bf8a79c *third_party/libc-test/bin/2/functional/fdopen.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/fnmatch.elf.gz.sha256",
    "content": "f8919500315400ce85eb830b6860e748a4872108862b6122734593a46ecf326a *third_party/libc-test/bin/2/functional/fnmatch.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/fscanf.elf.gz.sha256",
    "content": "959963623ef55dc72029e7df67a3dab3c26119e3839ebf843d47569a4fa81765 *third_party/libc-test/bin/2/functional/fscanf.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/fwscanf.elf.gz.sha256",
    "content": "f496349f5171a0ac824412c88ad7f58806f47975ea690a139650e452e29bd92e *third_party/libc-test/bin/2/functional/fwscanf.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/iconv_open.elf.gz.sha256",
    "content": "96fae862e16fdb02684b09b3d8ae3372abb60e70aebea0fb2dd2362f4b737ae7 *third_party/libc-test/bin/2/functional/iconv_open.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/mbc.elf.gz.sha256",
    "content": "dec082f97e78e5447df8a9069ef5f84509c28721d87654a4c03842dc8ca5ae5d *third_party/libc-test/bin/2/functional/mbc.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/memstream.elf.gz.sha256",
    "content": "abc0b42a97e465a503327039c6a963e503041cfb1ca7cafe05f1ed28f65bfc5a *third_party/libc-test/bin/2/functional/memstream.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/pthread_cancel-points.elf.gz.sha256",
    "content": "e6f495cf1f257ed8588f9aea2d81c1927ee0394385771bd66c0b9d3d05c125b0 *third_party/libc-test/bin/2/functional/pthread_cancel-points.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/pthread_cancel.elf.gz.sha256",
    "content": "20bd0d8d4ffa58c1a0912da924de106174c9d00e17e4cd06f3033bc4bf3a2a45 *third_party/libc-test/bin/2/functional/pthread_cancel.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/pthread_cond.elf.gz.sha256",
    "content": "51c08c63dc3f1a7b6663ee4f7ad01702185d980e5449a681befae5b71a9b809b *third_party/libc-test/bin/2/functional/pthread_cond.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/pthread_mutex.elf.gz.sha256",
    "content": "646203ae83655c57ed8b72eb2b47457be819e0f813c63d02ad6d91979c0cc423 *third_party/libc-test/bin/2/functional/pthread_mutex.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/pthread_tsd.elf.gz.sha256",
    "content": "980691eb0b4eb278137e752892efdc4496cbfbd3e7b77227cd10777afc22aa44 *third_party/libc-test/bin/2/functional/pthread_tsd.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/qsort.elf.gz.sha256",
    "content": "5eaf028fa92bea5647d9f74811be55f328c249405045bd4a92177e3a72dd8de8 *third_party/libc-test/bin/2/functional/qsort.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/random.elf.gz.sha256",
    "content": "68b34859732fd21a2d73a3084c39fd62639b23c66fb069c3576757e3582f538a *third_party/libc-test/bin/2/functional/random.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/search_hsearch.elf.gz.sha256",
    "content": "f65d4b916cac73ffc74e093994de4b86b8688bb1c1435aeba3981a7c26fd48d6 *third_party/libc-test/bin/2/functional/search_hsearch.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/search_insque.elf.gz.sha256",
    "content": "79f5963c4e322467e6663428af4413575c6d0d3cdec9584671a6d1d168657b50 *third_party/libc-test/bin/2/functional/search_insque.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/search_lsearch.elf.gz.sha256",
    "content": "757a267713893091aa8784caef4f410d9ce2655cd07e93a86c6c9c90864159c1 *third_party/libc-test/bin/2/functional/search_lsearch.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/search_tsearch.elf.gz.sha256",
    "content": "69fa6e0c216874dd8172251b3ad664cff4b025545561cb00e0fb2c48441b048f *third_party/libc-test/bin/2/functional/search_tsearch.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/sem_init.elf.gz.sha256",
    "content": "f3987edea50357959e8c4d9326ee15a4953123250584559dec640083b4ee1bed *third_party/libc-test/bin/2/functional/sem_init.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/sem_open.elf.gz.sha256",
    "content": "1ce184ab97f54cfd52d4d259488cd4f37d1c760a702d6c757ceaf4d7bd1db36f *third_party/libc-test/bin/2/functional/sem_open.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/setjmp.elf.gz.sha256",
    "content": "049f333318ab5b40e8465e35d6fd3ea552dbf77ea668e6cbf5a0c87ecdebbb70 *third_party/libc-test/bin/2/functional/setjmp.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/socket.elf.gz.sha256",
    "content": "bef73da4846c25331810f54213b70aae597971f877691899b7657bfb8dbadc8a *third_party/libc-test/bin/2/functional/socket.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/sscanf_long.elf.gz.sha256",
    "content": "d3a352eb2edd90bfe225d7f06d497657e73eaef17295722a84706e912cb6ba49 *third_party/libc-test/bin/2/functional/sscanf_long.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/stat.elf.gz.sha256",
    "content": "a5df0a73371db51a102ef88a15b62e0b76a7e90291d4cf9356c4d6c67de53a19 *third_party/libc-test/bin/2/functional/stat.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/strftime.elf.gz.sha256",
    "content": "678036969e9b5eecdaf818b580e3d5659543bcdaa41bb4378aff2876a8a2cba4 *third_party/libc-test/bin/2/functional/strftime.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/string.elf.gz.sha256",
    "content": "fd2e3f30bcdf3e04299d882791c2ea7b5dfea61f1c9970ecaaca96c247b58cf6 *third_party/libc-test/bin/2/functional/string.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/string_memcpy.elf.gz.sha256",
    "content": "25934595671d7fe461d8046f777a2b8eea6f1a05629b30e294fbf2e514149310 *third_party/libc-test/bin/2/functional/string_memcpy.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/string_memmem.elf.gz.sha256",
    "content": "7772d83252eabad720e912aa0d3208555372ed5c253f313c569275e35e899d85 *third_party/libc-test/bin/2/functional/string_memmem.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/string_memset.elf.gz.sha256",
    "content": "47b47d0502330d07dda57024ab0be280aa5852e764875264970f878681eaea09 *third_party/libc-test/bin/2/functional/string_memset.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/string_strchr.elf.gz.sha256",
    "content": "fd12334206de0d277c886c1c2ca0d9b714cce4755e54c08604d7ff8100447843 *third_party/libc-test/bin/2/functional/string_strchr.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/string_strcspn.elf.gz.sha256",
    "content": "25f2f22ae5c022b580896dd85a722cccfc5eebfe377934e16a07135db3e88628 *third_party/libc-test/bin/2/functional/string_strcspn.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/string_strstr.elf.gz.sha256",
    "content": "582bb348defae513655f5b7c96495e94540a174fbe232ad66d6b42e4a8b85f26 *third_party/libc-test/bin/2/functional/string_strstr.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/strtol.elf.gz.sha256",
    "content": "2362e726cdde6bfb6afb2efb71d9fdfc49fb47e72a7c4675b48b2dfdd9248c94 *third_party/libc-test/bin/2/functional/strtol.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/strtold.elf.gz.sha256",
    "content": "23a660648a7fb03137f4acde79f7229337c0aff7393db1a52fea2c2b8967a997 *third_party/libc-test/bin/2/functional/strtold.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/tgmath.elf.gz.sha256",
    "content": "a9b9d8cb498f0478f4e939f2905237a0b8b64d944a230bd433e450a3faee4ecf *third_party/libc-test/bin/2/functional/tgmath.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/time.elf.gz.sha256",
    "content": "7c6222d2465f37c2f95fa11228c7231d0fe85ba5ac91682455be9bcaaaa09253 *third_party/libc-test/bin/2/functional/time.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/tls_init.elf.gz.sha256",
    "content": "3ca0bfbb56e648dac86e8384ba00c2117be1ebdffa21acb3c6c2697c9f6591e4 *third_party/libc-test/bin/2/functional/tls_init.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/tls_local_exec.elf.gz.sha256",
    "content": "335fb181e774df65290380e59c51e5f8491b2ed9e08a223a42384bf57d80ada2 *third_party/libc-test/bin/2/functional/tls_local_exec.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/udiv.elf.gz.sha256",
    "content": "226b3fc4ac17f0daf251439afd639d7e1b381f6236793ee2edaa52eefc94223a *third_party/libc-test/bin/2/functional/udiv.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/ungetc.elf.gz.sha256",
    "content": "f495d373482c40db966007987b3854e084236cebc3c5185733110702ad9d388b *third_party/libc-test/bin/2/functional/ungetc.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/utime.elf.gz.sha256",
    "content": "e2b5ce5eccb7ad57e07de1921f8d5b020375231e1f08a0645700eced562f7037 *third_party/libc-test/bin/2/functional/utime.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/vfork.elf.gz.sha256",
    "content": "e25a623cf465fa0bd7a0bb3dec87b1b14e7a81b56699dffb50edf45548f02988 *third_party/libc-test/bin/2/functional/vfork.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/wcsstr.elf.gz.sha256",
    "content": "1b7a90e7d974b1384fffbedacbf10c2c7c54cf797e7bef9a259fcfb549ac066c *third_party/libc-test/bin/2/functional/wcsstr.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/functional/wcstol.elf.gz.sha256",
    "content": "d75905be54d2c85e2f641ec5fc1486626aba039e8255faa8c476bf953f66ec1f *third_party/libc-test/bin/2/functional/wcstol.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/dn_expand-empty.elf.gz.sha256",
    "content": "f0819d2f3a1bf79b4082342bbbdebbffcf3d9615047c423dfb2fb618fdc7a642 *third_party/libc-test/bin/2/regression/dn_expand-empty.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/dn_expand-ptr-0.elf.gz.sha256",
    "content": "41bdc93b527d4f63828683ccc6807b1acc417232492dc143e0743c505b666c67 *third_party/libc-test/bin/2/regression/dn_expand-ptr-0.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/execle-env.elf.gz.sha256",
    "content": "f254059cb0bb06f78a31299dbecf82cd961ae9684e5e7708edec2d0669b8ef16 *third_party/libc-test/bin/2/regression/execle-env.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/fflush-exit.elf.gz.sha256",
    "content": "9a0b7eda63084a38e3722c4aeb78e6d46d85b32a5200a1b79d4accbc498a9b0f *third_party/libc-test/bin/2/regression/fflush-exit.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/fgets-eof.elf.gz.sha256",
    "content": "0a033d91b434a27d16f6523a89e6be24e3deadacb89bd8e7704700f3ec8b67a8 *third_party/libc-test/bin/2/regression/fgets-eof.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/fgetwc-buffering.elf.gz.sha256",
    "content": "8e8553581c7890e3dccc20eb0a59f946a42e1d46469caf762b0f6fba28436a2a *third_party/libc-test/bin/2/regression/fgetwc-buffering.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/flockfile-list.elf.gz.sha256",
    "content": "de2082e40e3ca8af5f9be0208f86af779ef0b3eb24adb2d88b6a36ac8640f7ff *third_party/libc-test/bin/2/regression/flockfile-list.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/ftello-unflushed-append.elf.gz.sha256",
    "content": "2fee13891f893b27e9b8641429344b6afba4dea2d9b845b733696ac7c9c2215b *third_party/libc-test/bin/2/regression/ftello-unflushed-append.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/getpwnam_r-crash.elf.gz.sha256",
    "content": "c5f2de6784ada2ab93640072fbed132971baac6897bf7cff50e061a6143efb4b *third_party/libc-test/bin/2/regression/getpwnam_r-crash.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/getpwnam_r-errno.elf.gz.sha256",
    "content": "5a51a1c0fd16f3d49b1ffc0dec10722ecae0bfa2ad23de4b80d66d516e6cd55c *third_party/libc-test/bin/2/regression/getpwnam_r-errno.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/iconv-roundtrips.elf.gz.sha256",
    "content": "5f6f2107960f0d7b92f89223d02642bf6c14387cad5e0054774f12e0359efead *third_party/libc-test/bin/2/regression/iconv-roundtrips.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/inet_ntop-v4mapped.elf.gz.sha256",
    "content": "9ed0c856f7c76d661619c166dc0289264fe50dbf3894f81594ec5649e7e3b4d6 *third_party/libc-test/bin/2/regression/inet_ntop-v4mapped.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/inet_pton-empty-last-field.elf.gz.sha256",
    "content": "559e8450cd471d2742cc6bb6ed17948d928926cc62d7c4a1610f5f216533cb1f *third_party/libc-test/bin/2/regression/inet_pton-empty-last-field.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/iswspace-null.elf.gz.sha256",
    "content": "9ed15e2b7eb96be50a9e28af4c337c48162c58be0c1d60c1adc494e405405650 *third_party/libc-test/bin/2/regression/iswspace-null.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/lrand48-signextend.elf.gz.sha256",
    "content": "7683f60a0926cdf1e62022b25cc71f953090d9fa83611705a8aed5b47c699893 *third_party/libc-test/bin/2/regression/lrand48-signextend.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/lseek-large.elf.gz.sha256",
    "content": "afaaa04480d004248b25972f160d0c2043593b13a862c45711fe268534c9a6fd *third_party/libc-test/bin/2/regression/lseek-large.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/malloc-0.elf.gz.sha256",
    "content": "811abdd56712150a8550cf915bd66f1f2782b162f385183837304fe90895ca16 *third_party/libc-test/bin/2/regression/malloc-0.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/mbsrtowcs-overflow.elf.gz.sha256",
    "content": "237436f0233aa1f78b8970ba4af19057e581f3909cbd611bf26b245e73f39a73 *third_party/libc-test/bin/2/regression/mbsrtowcs-overflow.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/memmem-oob-read.elf.gz.sha256",
    "content": "4bab0a1e9f7fe847cefc9d62f46c9f7c4051da321d55cbe469bafd8bd1995ec8 *third_party/libc-test/bin/2/regression/memmem-oob-read.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/memmem-oob.elf.gz.sha256",
    "content": "f5b2811e56d5234ae2d3f71e33bb9a8be329760faff910492839b62d5220ae09 *third_party/libc-test/bin/2/regression/memmem-oob.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/mkdtemp-failure.elf.gz.sha256",
    "content": "0618bc9c9cc6afcb98d27348a7940252b5e8a60523a30aed4f5523e087f98f02 *third_party/libc-test/bin/2/regression/mkdtemp-failure.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/mkstemp-failure.elf.gz.sha256",
    "content": "f9d8acb73b1a7f9219f968e08e05b9cd722bd063df82d80c44059fb03769cc30 *third_party/libc-test/bin/2/regression/mkstemp-failure.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/printf-fmt-g-round.elf.gz.sha256",
    "content": "f0487cd33925d31db3b626456a68db9a02cfb4d01aa46365317a6e17569dc928 *third_party/libc-test/bin/2/regression/printf-fmt-g-round.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/printf-fmt-g-zeros.elf.gz.sha256",
    "content": "f1da587e88cc8ca5641a1c0fbf9cf06d3cad8e4df9a97803d7d85013a8253d04 *third_party/libc-test/bin/2/regression/printf-fmt-g-zeros.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/printf-fmt-n.elf.gz.sha256",
    "content": "2b6e7fe7033949b0cab05fabe2e37775c347910dc414e1fc0d7aa0b9af21344e *third_party/libc-test/bin/2/regression/printf-fmt-n.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/pthread-robust-detach.elf.gz.sha256",
    "content": "0e5a000295c51cdc5d4a3aa6e0bbe0b9dfc1ff820fb5df52fc724833fc72e5ec *third_party/libc-test/bin/2/regression/pthread-robust-detach.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/pthread_atfork-errno-clobber.elf.gz.sha256",
    "content": "0f13082785457de541bc6148e5aa8160ffbd6286241de4a5d040105203d679db *third_party/libc-test/bin/2/regression/pthread_atfork-errno-clobber.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/pthread_cancel-sem_wait.elf.gz.sha256",
    "content": "3cd44caaeb057aa9c0132683ee26dbef036219178a209d6aa4cdd1f4f20dc329 *third_party/libc-test/bin/2/regression/pthread_cancel-sem_wait.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/pthread_cond-smasher.elf.gz.sha256",
    "content": "3cf6046d677ad3ad2ad5efacd034de73394ccc97e62deb7071e13e35141c075f *third_party/libc-test/bin/2/regression/pthread_cond-smasher.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/pthread_condattr_setclock.elf.gz.sha256",
    "content": "ffc72f4dbda6cf0d87d223ccbb9551a8f6a51040f6ebfd5bb29cd8a6844075a5 *third_party/libc-test/bin/2/regression/pthread_condattr_setclock.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/pthread_exit-cancel.elf.gz.sha256",
    "content": "b3a1633a1fe83ce960f2999924c3373750337efee02149c81d461aca4333aedc *third_party/libc-test/bin/2/regression/pthread_exit-cancel.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/pthread_exit-dtor.elf.gz.sha256",
    "content": "57a69544be84dfad05ade5bef80648cf1cf73463f9632e689b6b71bedb1fb449 *third_party/libc-test/bin/2/regression/pthread_exit-dtor.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/pthread_once-deadlock.elf.gz.sha256",
    "content": "a6b3d9824dd41c72b0098e30e9611dbf5340be0f895549e13f22d304f66bac77 *third_party/libc-test/bin/2/regression/pthread_once-deadlock.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/pthread_rwlock-ebusy.elf.gz.sha256",
    "content": "e92d48948ff8b9d8e7f32c671fa687f32c85fc0c8b8245ac1788e4df2c9b5578 *third_party/libc-test/bin/2/regression/pthread_rwlock-ebusy.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/putenv-doublefree.elf.gz.sha256",
    "content": "26e55fc3293c6301ef6c0dd67b328f0b3eb1a624a5e152581b4d80922835ee27 *third_party/libc-test/bin/2/regression/putenv-doublefree.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/regex-backref-0.elf.gz.sha256",
    "content": "bc507fc045b1c0b3e962521e8420808eff00e617c0347dcf46c5ba256c83b15b *third_party/libc-test/bin/2/regression/regex-backref-0.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/regex-bracket-icase.elf.gz.sha256",
    "content": "4f00208b2bd08a42adfbdc327e6770b56c0528643d6ba52668e6c08e6a7f5254 *third_party/libc-test/bin/2/regression/regex-bracket-icase.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/regex-ere-backref.elf.gz.sha256",
    "content": "4c0e5d57e852a665b945633b3640c1818f98db6b9ae7b74b07a734981b6030dc *third_party/libc-test/bin/2/regression/regex-ere-backref.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/regex-escaped-high-byte.elf.gz.sha256",
    "content": "eb16385515cc44eb076a7b10ddce32e9b2875e81edae83e169a244bd8cc4ed6d *third_party/libc-test/bin/2/regression/regex-escaped-high-byte.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/regex-negated-range.elf.gz.sha256",
    "content": "c11fbc73bd30d7f0ea8929ca218a6f3423c210d6779011745c1ca978d1ae8d80 *third_party/libc-test/bin/2/regression/regex-negated-range.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/regexec-nosub.elf.gz.sha256",
    "content": "3a2bb37a2e96b168cc3affbb46edc40f8e89174b4d2e40fc339c29a73e157c8c *third_party/libc-test/bin/2/regression/regexec-nosub.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/rewind-clear-error.elf.gz.sha256",
    "content": "960454a3ccddfdc63e7749e3ce3cd6d073fc3a3742820a7069e8bc74a6b194b4 *third_party/libc-test/bin/2/regression/rewind-clear-error.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/scanf-bytes-consumed.elf.gz.sha256",
    "content": "d53a42b5de5f2a5240962bb6b17b3366fac5535af6f19d67f0f2e8df746ac2eb *third_party/libc-test/bin/2/regression/scanf-bytes-consumed.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/scanf-match-literal-eof.elf.gz.sha256",
    "content": "61555b752efc3e5a61a55ed8c9d93263dde7207f2e63eb9df39fbc9ef79cb511 *third_party/libc-test/bin/2/regression/scanf-match-literal-eof.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/scanf-nullbyte-char.elf.gz.sha256",
    "content": "95fb33c95e4a50231cc309788373211947fde65883c59a47cf667dbc5a7417a4 *third_party/libc-test/bin/2/regression/scanf-nullbyte-char.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/sem_close-unmap.elf.gz.sha256",
    "content": "1e97328608e42c61c103f097dddb5e2ae6589e2cd9c1f9c1a16a6d131406fa3c *third_party/libc-test/bin/2/regression/sem_close-unmap.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/setvbuf-unget.elf.gz.sha256",
    "content": "84634b459730d00f856f304312387945fc2482a7470473798e3b6fcffad5de19 *third_party/libc-test/bin/2/regression/setvbuf-unget.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/sigaltstack.elf.gz.sha256",
    "content": "2235ba6fc8efa4fbae40e3fdcebf22aa1c270ea9b0872cf000dd1d45835235eb *third_party/libc-test/bin/2/regression/sigaltstack.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/sigprocmask-internal.elf.gz.sha256",
    "content": "c517a479ebc5df9b204602f48a8c88140f0283940744f2354d2ee805f7e4f10c *third_party/libc-test/bin/2/regression/sigprocmask-internal.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/sigreturn.elf.gz.sha256",
    "content": "b276bdffe0ce33abe6afdac2c853cdd39808dc1fb0d77144c79a10dd30a8273b *third_party/libc-test/bin/2/regression/sigreturn.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/sscanf-eof.elf.gz.sha256",
    "content": "4011c8ca943b497cda52e612d456d18f9113916c8ece3d9ea8fd7f80476a9cba *third_party/libc-test/bin/2/regression/sscanf-eof.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/statvfs.elf.gz.sha256",
    "content": "ff8b0d02538c1fd939f64300e541ce35f1e2fdc925df6fbfb049f1387286cdd0 *third_party/libc-test/bin/2/regression/statvfs.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/strverscmp.elf.gz.sha256",
    "content": "296253f0726d1d7db6d7bb9a018eb57bd29812cf38c4720c0e2855cec8c60610 *third_party/libc-test/bin/2/regression/strverscmp.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/syscall-sign-extend.elf.gz.sha256",
    "content": "c19ac2172b64fff6ed7d64488fe20aefd19bc286988a50129a285feef45d1e94 *third_party/libc-test/bin/2/regression/syscall-sign-extend.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/uselocale-0.elf.gz.sha256",
    "content": "8ef0243fd02c5d88dcfe9b29e719bc9dc65589d74fe76febaf1a58200dd335e4 *third_party/libc-test/bin/2/regression/uselocale-0.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/wcsncpy-read-overflow.elf.gz.sha256",
    "content": "0943b5d0ac46ff5738335df6ef445d67b357dcf1db4c73d3658258e7c401c9c7 *third_party/libc-test/bin/2/regression/wcsncpy-read-overflow.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/2/regression/wcsstr-false-negative.elf.gz.sha256",
    "content": "fd9ba0b79b0f49db322dc738058e1deb8e24bd5eecc312ca777eb353cb9f8709 *third_party/libc-test/bin/2/regression/wcsstr-false-negative.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/3/functional/inet_pton.elf.gz.sha256",
    "content": "57968f75356af5a6e11fa8b47e77f48326c70e4bf7a89059ed1c8895fdb4a7b5 *third_party/libc-test/bin/3/functional/inet_pton.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/3/functional/popen.elf.gz.sha256",
    "content": "7e3ee8f410dafcb22279fff06b5d598f2770d1a3d9aac051cc51926bd0f3685c *third_party/libc-test/bin/3/functional/popen.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/3/regression/daemon-failure.elf.gz.sha256",
    "content": "fb5211bc9f10097b986bf284faae7c4c587c2193b99445d702b477f1b4dc4542 *third_party/libc-test/bin/3/regression/daemon-failure.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/3/regression/malloc-oom.elf.gz.sha256",
    "content": "8f9ee23f33eda286c118c97a772ef77a8f0db18d20cd7c1e76d91ec03c28ca99 *third_party/libc-test/bin/3/regression/malloc-oom.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/3/regression/pthread_create-oom.elf.gz.sha256",
    "content": "0e5765f5cfcd2980473980bdf5aadf6dac876f6ee062ae04bab7db03728eef84 *third_party/libc-test/bin/3/regression/pthread_create-oom.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/bin/3/regression/setenv-oom.elf.gz.sha256",
    "content": "0bf7ecb7761b0e6130c0b0e61fbc74e036f16196a9819a617483c940ebf14180 *third_party/libc-test/bin/3/regression/setenv-oom.elf.gz\n"
  },
  {
    "path": "third_party/libc-test/deploy-libc-test",
    "content": "#!/bin/sh\nset -ex\n# e.g. deploy-libc-test regression/scanf-bytes-consumed\n\nT=/mnt/videos/website/justine.lol/libc-test/bin\nL=/home/jart/vendor/libc-test/src\nV=2\nmkdir -p $T/$V\n\nfor f; do\n  if [ ! -f $L/$f.exe ]; then\n    echo \"not found: $L/$f\" >&2\n    exit 1\n  fi\n\n  mkdir -p $T/$V/${f%/*}\n  mkdir -p ~/blink/third_party/libc-test/bin/$V/${f%/*}\n  cp $L/$f.exe $T/$V/$f.elf\n  rm -f $T/$V/$f.elf.gz\n  gzip $T/$V/$f.elf\n  sha256sum -b $T/$V/$f.elf.gz >$T/$V/$f.elf.gz.sha256\n  mkdir -p ~/blink/third_party/libc-test/bin/$V\n  cp $T/$V/$f.elf.gz.sha256 ~/blink/third_party/libc-test/bin/$V/$f.elf.gz.sha256\n\n  sed -i -e 's!/mnt/videos/website/justine.lol/libc-test/bin!third_party/libc-test/bin!' \\\n      ~/blink/third_party/libc-test/bin/$V/$f.elf.gz.sha256\n\n  ssh debian gsutil -m -h Cache-Control:public,max-age=31536000 cp -r -a public-read \\\n      /mnt/videos/website/justine.lol/libc-test/bin/$V/$f.elf.gz \\\n      gs://justine/libc-test/bin/$V/$f.elf.gz\ndone\n\nsyncweb\n"
  },
  {
    "path": "third_party/libc-test/libc-test.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\n.PRECIOUS: third_party/libc-test/%.gz\nthird_party/libc-test/%.gz: third_party/libc-test/%.gz.sha256 o/tool/sha256sum\n\tcurl -so $@ https://justine.storage.googleapis.com/libc-test/$(subst third_party/libc-test/,,$@)\n\to/tool/sha256sum -c $<\n\n.PRECIOUS: third_party/libc-test/bin/%.elf\nthird_party/libc-test/bin/%.elf: third_party/libc-test/bin/%.elf.gz\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/$(MODE)/third_party/libc-test/bin/%.elf.ok:\t\t\t\t\t\t\t\\\n\t\tthird_party/libc-test/bin/%.elf\t\t\t\t\t\t\t\\\n\t\to/lib/ld-musl-x86_64.so.1\t\t\t\t\t\t\t\\\n\t\to/$(MODE)/blink/blink\t\t\t\t\t\t\t\t\\\n\t\to/proc/cpuinfo\t\t\t\t\t\t\t\t\t\\\n\t\to/proc/meminfo\n\t@mkdir -p $(@D)\n\to/$(MODE)/blink/blink $<\n\t@touch $@\n\no/proc/%: third_party/libc-test/%\n\t@mkdir -p $(@D)\n\tcp -f $< $@\n\tchmod +x $@\n\nLIBC_TEST_TESTS =\t\t\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/pthread_cancel.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/strtol.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/crypt.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/string_strstr.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/string_memcpy.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/clock_gettime.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/iconv_open.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/fdopen.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/argv.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/memstream.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/fcntl.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/random.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/mbc.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/search_insque.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/tgmath.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/pthread_tsd.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/socket.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/search_tsearch.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/udiv.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/string.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/basename.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/string_memmem.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/tls_local_exec.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/strftime.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/pthread_cond.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/string_memset.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/wcsstr.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/clocale_mbfuncs.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/setjmp.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/utime.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/env.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/sem_init.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/dirname.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/ungetc.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/wcstol.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/search_lsearch.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/strtold.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/fnmatch.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/fwscanf.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/qsort.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/string_strchr.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/time.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/search_hsearch.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/fscanf.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/sscanf_long.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/string_strcspn.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/printf-fmt-n.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/putenv-doublefree.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/memmem-oob.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/regex-ere-backref.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/iconv-roundtrips.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/malloc-0.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/regex-backref-0.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/regex-negated-range.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/sigreturn.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/rewind-clear-error.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/sigaltstack.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/pthread_condattr_setclock.elf.ok\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/fgets-eof.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/setvbuf-unget.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/ftello-unflushed-append.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/syscall-sign-extend.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/fflush-exit.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/lrand48-signextend.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/pthread_once-deadlock.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/printf-fmt-g-round.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/pthread_exit-cancel.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/pthread_rwlock-ebusy.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/printf-fmt-g-zeros.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/wcsncpy-read-overflow.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/mbsrtowcs-overflow.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/sscanf-eof.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/lseek-large.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/dn_expand-empty.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/inet_pton-empty-last-field.elf.ok\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/strverscmp.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/wcsstr-false-negative.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/pthread_exit-dtor.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/memmem-oob-read.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/regex-bracket-icase.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/iswspace-null.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/regexec-nosub.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/mkdtemp-failure.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/dn_expand-ptr-0.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/getpwnam_r-errno.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/fgetwc-buffering.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/pthread-robust-detach.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/scanf-nullbyte-char.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/flockfile-list.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/inet_ntop-v4mapped.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/regex-escaped-high-byte.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/mkstemp-failure.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/uselocale-0.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/sigprocmask-internal.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/statvfs.elf.ok\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/scanf-match-literal-eof.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/getpwnam_r-crash.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/scanf-bytes-consumed.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/3/regression/pthread_create-oom.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/3/regression/daemon-failure.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/3/functional/inet_pton.elf.ok\n\n# TODO(jart): This needs a longer timeout.\n# o/$(MODE)/third_party/libc-test/bin/2/regression/pthread_cond-smasher.elf.ok\n\nifneq ($(wildcard /dev/shm),)\nifneq ($(HOST_SYSTEM), FreeBSD)\nLIBC_TEST_TESTS +=\t\t\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/sem_open.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/sem_close-unmap.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/regression/pthread_cancel-sem_wait.elf.ok\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/2/functional/pthread_cancel-points.elf.ok\nendif\nendif\n\n# When creating files, Linux sets st_gid to getegid() but Darwin and\n# FreeBSD appear to always sets it to 0 (wheel). This test also just\n# seems to be flaky in general, printing errors like \"st.st_atime<=t\n# failed: 1675987682 > 1675970318\".\n#\n# ifneq ($(HOST_SYSTEM), Darwin)\n# ifneq ($(HOST_SYSTEM), FreeBSD)\n# LIBC_TEST_TESTS += o/$(MODE)/third_party/libc-test/bin/2/functional/stat.elf.ok\n# endif\n# endif\n\n# No RLIMIT_NPROC on Cygwin\nifneq ($(HOST_OS), Cygwin)\nLIBC_TEST_TESTS += o/$(MODE)/third_party/libc-test/bin/2/regression/pthread_atfork-errno-clobber.elf.ok\nendif\n\nifneq ($(HOST_SYSTEM), OpenBSD)\nLIBC_TEST_TESTS +=\t\t\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/3/regression/malloc-oom.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/libc-test/bin/3/regression/setenv-oom.elf.ok\nendif\n\n################################################################################\n# FLAKY TESTS\n\n# This test execve()'s the system /bin/sh. GitHub Actions Linux\n# environment reports \"sh: error while loading shared libraries:\n# libc.so.6: cannot stat shared object: No such file or directory\".\n#\n# o/$(MODE)/third_party/libc-test/bin/2/regression/execle-env.elf.ok\n\n# This test also executes /bin/sh so it's failing on GitHub Actions. It\n# also fails for unexplained reasons on OpenBSD.\n#\n# o/$(MODE)/third_party/libc-test/bin/2/functional/vfork.elf.ok\n\n# These tests work fine but they launch /bin/sh so avoiding adding them\n# to `make check` until we find some way to detect GA environment.\n#\n# o/$(MODE)/third_party/libc-test/bin/3/functional/popen.elf.ok\n# o/$(MODE)/third_party/libc-test/bin/3/functional/spawn.elf.ok\n\n# Fails on GitHub Actions Linux with \"SEGMENTATION FAULT AT ADDRESS 10\"\n# and this hasn't happened in any other environment.\n# https://github.com/jart/blink/actions/runs/4131367559/jobs/7138932392\n#\n# o/$(MODE)/third_party/libc-test/bin/2/functional/tls_init.elf.ok\n\n################################################################################\n\no/$(MODE)/third_party/libc-test: $(LIBC_TEST_TESTS)\n\t@mkdir -p $(@D)\n\t@touch $@\n"
  },
  {
    "path": "third_party/libz/LICENSE",
    "content": "Copyright notice:\n\n (C) 1995-2022 Jean-loup Gailly and Mark Adler\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n\n  Jean-loup Gailly        Mark Adler\n  jloup@gzip.org          madler@alumni.caltech.edu\n"
  },
  {
    "path": "third_party/libz/README.blink",
    "content": "DESCRIPTION\n\n  zlib is a data compression library\n\nORIGIN\n\n  zlib 1.2.13\n  04f42ceca40f73e2978b50e93806c2a18c1281fc\n  https://github.com/madler/zlib\n\nLICENSE\n\n  The Zlib License\n\nLOCAL CHANGES\n\n  - Add comments disabling clang-format\n  - Made #include lines relative to repo root\n"
  },
  {
    "path": "third_party/libz/adler32.c",
    "content": "// clang-format off\n/* adler32.c -- compute the Adler-32 checksum of a data stream\n * Copyright (C) 1995-2011, 2016 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* @(#) $Id$ */\n\n#include \"third_party/libz/zutil.h\"\n\nlocal uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));\n\n#define BASE 65521U     /* largest prime smaller than 65536 */\n#define NMAX 5552\n/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */\n\n#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}\n#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);\n#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);\n#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);\n#define DO16(buf)   DO8(buf,0); DO8(buf,8);\n\n/* use NO_DIVIDE if your processor does not do division in hardware --\n   try it both ways to see which is faster */\n#ifdef NO_DIVIDE\n/* note that this assumes BASE is 65521, where 65536 % 65521 == 15\n   (thank you to John Reiser for pointing this out) */\n#  define CHOP(a) \\\n    do { \\\n        unsigned long tmp = a >> 16; \\\n        a &= 0xffffUL; \\\n        a += (tmp << 4) - tmp; \\\n    } while (0)\n#  define MOD28(a) \\\n    do { \\\n        CHOP(a); \\\n        if (a >= BASE) a -= BASE; \\\n    } while (0)\n#  define MOD(a) \\\n    do { \\\n        CHOP(a); \\\n        MOD28(a); \\\n    } while (0)\n#  define MOD63(a) \\\n    do { /* this assumes a is not negative */ \\\n        z_off64_t tmp = a >> 32; \\\n        a &= 0xffffffffL; \\\n        a += (tmp << 8) - (tmp << 5) + tmp; \\\n        tmp = a >> 16; \\\n        a &= 0xffffL; \\\n        a += (tmp << 4) - tmp; \\\n        tmp = a >> 16; \\\n        a &= 0xffffL; \\\n        a += (tmp << 4) - tmp; \\\n        if (a >= BASE) a -= BASE; \\\n    } while (0)\n#else\n#  define MOD(a) a %= BASE\n#  define MOD28(a) a %= BASE\n#  define MOD63(a) a %= BASE\n#endif\n\n/* ========================================================================= */\nuLong ZEXPORT adler32_z(adler, buf, len)\n    uLong adler;\n    const Bytef *buf;\n    z_size_t len;\n{\n    unsigned long sum2;\n    unsigned n;\n\n    /* split Adler-32 into component sums */\n    sum2 = (adler >> 16) & 0xffff;\n    adler &= 0xffff;\n\n    /* in case user likes doing a byte at a time, keep it fast */\n    if (len == 1) {\n        adler += buf[0];\n        if (adler >= BASE)\n            adler -= BASE;\n        sum2 += adler;\n        if (sum2 >= BASE)\n            sum2 -= BASE;\n        return adler | (sum2 << 16);\n    }\n\n    /* initial Adler-32 value (deferred check for len == 1 speed) */\n    if (buf == Z_NULL)\n        return 1L;\n\n    /* in case short lengths are provided, keep it somewhat fast */\n    if (len < 16) {\n        while (len--) {\n            adler += *buf++;\n            sum2 += adler;\n        }\n        if (adler >= BASE)\n            adler -= BASE;\n        MOD28(sum2);            /* only added so many BASE's */\n        return adler | (sum2 << 16);\n    }\n\n    /* do length NMAX blocks -- requires just one modulo operation */\n    while (len >= NMAX) {\n        len -= NMAX;\n        n = NMAX / 16;          /* NMAX is divisible by 16 */\n        do {\n            DO16(buf);          /* 16 sums unrolled */\n            buf += 16;\n        } while (--n);\n        MOD(adler);\n        MOD(sum2);\n    }\n\n    /* do remaining bytes (less than NMAX, still just one modulo) */\n    if (len) {                  /* avoid modulos if none remaining */\n        while (len >= 16) {\n            len -= 16;\n            DO16(buf);\n            buf += 16;\n        }\n        while (len--) {\n            adler += *buf++;\n            sum2 += adler;\n        }\n        MOD(adler);\n        MOD(sum2);\n    }\n\n    /* return recombined sums */\n    return adler | (sum2 << 16);\n}\n\n/* ========================================================================= */\nuLong ZEXPORT adler32(adler, buf, len)\n    uLong adler;\n    const Bytef *buf;\n    uInt len;\n{\n    return adler32_z(adler, buf, len);\n}\n\n/* ========================================================================= */\nlocal uLong adler32_combine_(adler1, adler2, len2)\n    uLong adler1;\n    uLong adler2;\n    z_off64_t len2;\n{\n    unsigned long sum1;\n    unsigned long sum2;\n    unsigned rem;\n\n    /* for negative len, return invalid adler32 as a clue for debugging */\n    if (len2 < 0)\n        return 0xffffffffUL;\n\n    /* the derivation of this formula is left as an exercise for the reader */\n    MOD63(len2);                /* assumes len2 >= 0 */\n    rem = (unsigned)len2;\n    sum1 = adler1 & 0xffff;\n    sum2 = rem * sum1;\n    MOD(sum2);\n    sum1 += (adler2 & 0xffff) + BASE - 1;\n    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;\n    if (sum1 >= BASE) sum1 -= BASE;\n    if (sum1 >= BASE) sum1 -= BASE;\n    if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);\n    if (sum2 >= BASE) sum2 -= BASE;\n    return sum1 | (sum2 << 16);\n}\n\n/* ========================================================================= */\nuLong ZEXPORT adler32_combine(adler1, adler2, len2)\n    uLong adler1;\n    uLong adler2;\n    z_off_t len2;\n{\n    return adler32_combine_(adler1, adler2, len2);\n}\n\nuLong ZEXPORT adler32_combine64(adler1, adler2, len2)\n    uLong adler1;\n    uLong adler2;\n    z_off64_t len2;\n{\n    return adler32_combine_(adler1, adler2, len2);\n}\n"
  },
  {
    "path": "third_party/libz/compress.c",
    "content": "// clang-format off\n/* compress.c -- compress a memory buffer\n * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* @(#) $Id$ */\n\n#define ZLIB_INTERNAL\n#include \"third_party/libz/zlib.h\"\n\n/* ===========================================================================\n     Compresses the source buffer into the destination buffer. The level\n   parameter has the same meaning as in deflateInit.  sourceLen is the byte\n   length of the source buffer. Upon entry, destLen is the total size of the\n   destination buffer, which must be at least 0.1% larger than sourceLen plus\n   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.\n\n     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_BUF_ERROR if there was not enough room in the output buffer,\n   Z_STREAM_ERROR if the level parameter is invalid.\n*/\nint ZEXPORT compress2(dest, destLen, source, sourceLen, level)\n    Bytef *dest;\n    uLongf *destLen;\n    const Bytef *source;\n    uLong sourceLen;\n    int level;\n{\n    z_stream stream;\n    int err;\n    const uInt max = (uInt)-1;\n    uLong left;\n\n    left = *destLen;\n    *destLen = 0;\n\n    stream.zalloc = (alloc_func)0;\n    stream.zfree = (free_func)0;\n    stream.opaque = (voidpf)0;\n\n    err = deflateInit(&stream, level);\n    if (err != Z_OK) return err;\n\n    stream.next_out = dest;\n    stream.avail_out = 0;\n    stream.next_in = (z_const Bytef *)source;\n    stream.avail_in = 0;\n\n    do {\n        if (stream.avail_out == 0) {\n            stream.avail_out = left > (uLong)max ? max : (uInt)left;\n            left -= stream.avail_out;\n        }\n        if (stream.avail_in == 0) {\n            stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;\n            sourceLen -= stream.avail_in;\n        }\n        err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);\n    } while (err == Z_OK);\n\n    *destLen = stream.total_out;\n    deflateEnd(&stream);\n    return err == Z_STREAM_END ? Z_OK : err;\n}\n\n/* ===========================================================================\n */\nint ZEXPORT compress(dest, destLen, source, sourceLen)\n    Bytef *dest;\n    uLongf *destLen;\n    const Bytef *source;\n    uLong sourceLen;\n{\n    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);\n}\n\n/* ===========================================================================\n     If the default memLevel or windowBits for deflateInit() is changed, then\n   this function needs to be updated.\n */\nuLong ZEXPORT compressBound(sourceLen)\n    uLong sourceLen;\n{\n    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +\n           (sourceLen >> 25) + 13;\n}\n"
  },
  {
    "path": "third_party/libz/crc32.c",
    "content": "// clang-format off\n/* crc32.c -- compute the CRC-32 of a data stream\n * Copyright (C) 1995-2022 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n *\n * This interleaved implementation of a CRC makes use of pipelined multiple\n * arithmetic-logic units, commonly found in modern CPU cores. It is due to\n * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution.\n */\n\n/* @(#) $Id$ */\n\n/*\n  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore\n  protection on the static variables used to control the first-use generation\n  of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should\n  first call get_crc_table() to initialize the tables before allowing more than\n  one thread to use crc32().\n\n  MAKECRCH can be #defined to write out crc32.h. A main() routine is also\n  produced, so that this one source file can be compiled to an executable.\n */\n\n#ifdef MAKECRCH\n#  include <stdio.h>\n#  ifndef DYNAMIC_CRC_TABLE\n#    define DYNAMIC_CRC_TABLE\n#  endif /* !DYNAMIC_CRC_TABLE */\n#endif /* MAKECRCH */\n\n#include \"third_party/libz/zutil.h\"      /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */\n\n /*\n  A CRC of a message is computed on N braids of words in the message, where\n  each word consists of W bytes (4 or 8). If N is 3, for example, then three\n  running sparse CRCs are calculated respectively on each braid, at these\n  indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ...\n  This is done starting at a word boundary, and continues until as many blocks\n  of N * W bytes as are available have been processed. The results are combined\n  into a single CRC at the end. For this code, N must be in the range 1..6 and\n  W must be 4 or 8. The upper limit on N can be increased if desired by adding\n  more #if blocks, extending the patterns apparent in the code. In addition,\n  crc32.h would need to be regenerated, if the maximum N value is increased.\n\n  N and W are chosen empirically by benchmarking the execution time on a given\n  processor. The choices for N and W below were based on testing on Intel Kaby\n  Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64\n  Octeon II processors. The Intel, AMD, and ARM processors were all fastest\n  with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4.\n  They were all tested with either gcc or clang, all using the -O3 optimization\n  level. Your mileage may vary.\n */\n\n/* Define N */\n#ifdef Z_TESTN\n#  define N Z_TESTN\n#else\n#  define N 5\n#endif\n#if N < 1 || N > 6\n#  error N must be in 1..6\n#endif\n\n/*\n  z_crc_t must be at least 32 bits. z_word_t must be at least as long as\n  z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and\n  that bytes are eight bits.\n */\n\n/*\n  Define W and the associated z_word_t type. If W is not defined, then a\n  braided calculation is not used, and the associated tables and code are not\n  compiled.\n */\n#ifdef Z_TESTW\n#  if Z_TESTW-1 != -1\n#    define W Z_TESTW\n#  endif\n#else\n#  ifdef MAKECRCH\n#    define W 8         /* required for MAKECRCH */\n#  else\n#    if defined(__x86_64__) || defined(__aarch64__)\n#      define W 8\n#    else\n#      define W 4\n#    endif\n#  endif\n#endif\n#ifdef W\n#  if W == 8 && defined(Z_U8)\n     typedef Z_U8 z_word_t;\n#  elif defined(Z_U4)\n#    undef W\n#    define W 4\n     typedef Z_U4 z_word_t;\n#  else\n#    undef W\n#  endif\n#endif\n\n/* If available, use the ARM processor CRC32 instruction. */\n#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8\n#  define ARMCRC32\n#endif\n\n/* Local functions. */\nlocal z_crc_t multmodp OF((z_crc_t a, z_crc_t b));\nlocal z_crc_t x2nmodp OF((z_off64_t n, unsigned k));\n\n#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))\n    local z_word_t byte_swap OF((z_word_t word));\n#endif\n\n#if defined(W) && !defined(ARMCRC32)\n    local z_crc_t crc_word OF((z_word_t data));\n    local z_word_t crc_word_big OF((z_word_t data));\n#endif\n\n#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))\n/*\n  Swap the bytes in a z_word_t to convert between little and big endian. Any\n  self-respecting compiler will optimize this to a single machine byte-swap\n  instruction, if one is available. This assumes that word_t is either 32 bits\n  or 64 bits.\n */\nlocal z_word_t byte_swap(word)\n    z_word_t word;\n{\n#  if W == 8\n    return\n        (word & 0xff00000000000000) >> 56 |\n        (word & 0xff000000000000) >> 40 |\n        (word & 0xff0000000000) >> 24 |\n        (word & 0xff00000000) >> 8 |\n        (word & 0xff000000) << 8 |\n        (word & 0xff0000) << 24 |\n        (word & 0xff00) << 40 |\n        (word & 0xff) << 56;\n#  else   /* W == 4 */\n    return\n        (word & 0xff000000) >> 24 |\n        (word & 0xff0000) >> 8 |\n        (word & 0xff00) << 8 |\n        (word & 0xff) << 24;\n#  endif\n}\n#endif\n\n/* CRC polynomial. */\n#define POLY 0xedb88320         /* p(x) reflected, with x^32 implied */\n\n#ifdef DYNAMIC_CRC_TABLE\n\nlocal z_crc_t FAR crc_table[256];\nlocal z_crc_t FAR x2n_table[32];\nlocal void make_crc_table OF((void));\n#ifdef W\n   local z_word_t FAR crc_big_table[256];\n   local z_crc_t FAR crc_braid_table[W][256];\n   local z_word_t FAR crc_braid_big_table[W][256];\n   local void braid OF((z_crc_t [][256], z_word_t [][256], int, int));\n#endif\n#ifdef MAKECRCH\n   local void write_table OF((FILE *, const z_crc_t FAR *, int));\n   local void write_table32hi OF((FILE *, const z_word_t FAR *, int));\n   local void write_table64 OF((FILE *, const z_word_t FAR *, int));\n#endif /* MAKECRCH */\n\n/*\n  Define a once() function depending on the availability of atomics. If this is\n  compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in\n  multiple threads, and if atomics are not available, then get_crc_table() must\n  be called to initialize the tables and must return before any threads are\n  allowed to compute or combine CRCs.\n */\n\n/* Definition of once functionality. */\ntypedef struct once_s once_t;\nlocal void once OF((once_t *, void (*)(void)));\n\n/* Check for the availability of atomics. */\n#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \\\n    !defined(__STDC_NO_ATOMICS__)\n\n#include <stdatomic.h>\n\n/* Structure for once(), which must be initialized with ONCE_INIT. */\nstruct once_s {\n    atomic_flag begun;\n    atomic_int done;\n};\n#define ONCE_INIT {ATOMIC_FLAG_INIT, 0}\n\n/*\n  Run the provided init() function exactly once, even if multiple threads\n  invoke once() at the same time. The state must be a once_t initialized with\n  ONCE_INIT.\n */\nlocal void once(state, init)\n    once_t *state;\n    void (*init)(void);\n{\n    if (!atomic_load(&state->done)) {\n        if (atomic_flag_test_and_set(&state->begun))\n            while (!atomic_load(&state->done))\n                ;\n        else {\n            init();\n            atomic_store(&state->done, 1);\n        }\n    }\n}\n\n#else   /* no atomics */\n\n/* Structure for once(), which must be initialized with ONCE_INIT. */\nstruct once_s {\n    volatile int begun;\n    volatile int done;\n};\n#define ONCE_INIT {0, 0}\n\n/* Test and set. Alas, not atomic, but tries to minimize the period of\n   vulnerability. */\nlocal int test_and_set OF((int volatile *));\nlocal int test_and_set(flag)\n    int volatile *flag;\n{\n    int was;\n\n    was = *flag;\n    *flag = 1;\n    return was;\n}\n\n/* Run the provided init() function once. This is not thread-safe. */\nlocal void once(state, init)\n    once_t *state;\n    void (*init)(void);\n{\n    if (!state->done) {\n        if (test_and_set(&state->begun))\n            while (!state->done)\n                ;\n        else {\n            init();\n            state->done = 1;\n        }\n    }\n}\n\n#endif\n\n/* State for once(). */\nlocal once_t made = ONCE_INIT;\n\n/*\n  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:\n  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.\n\n  Polynomials over GF(2) are represented in binary, one bit per coefficient,\n  with the lowest powers in the most significant bit. Then adding polynomials\n  is just exclusive-or, and multiplying a polynomial by x is a right shift by\n  one. If we call the above polynomial p, and represent a byte as the\n  polynomial q, also with the lowest power in the most significant bit (so the\n  byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p,\n  where a mod b means the remainder after dividing a by b.\n\n  This calculation is done using the shift-register method of multiplying and\n  taking the remainder. The register is initialized to zero, and for each\n  incoming bit, x^32 is added mod p to the register if the bit is a one (where\n  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x\n  (which is shifting right by one and adding x^32 mod p if the bit shifted out\n  is a one). We start with the highest power (least significant bit) of q and\n  repeat for all eight bits of q.\n\n  The table is simply the CRC of all possible eight bit values. This is all the\n  information needed to generate CRCs on data a byte at a time for all\n  combinations of CRC register values and incoming bytes.\n */\n\nlocal void make_crc_table()\n{\n    unsigned i, j, n;\n    z_crc_t p;\n\n    /* initialize the CRC of bytes tables */\n    for (i = 0; i < 256; i++) {\n        p = i;\n        for (j = 0; j < 8; j++)\n            p = p & 1 ? (p >> 1) ^ POLY : p >> 1;\n        crc_table[i] = p;\n#ifdef W\n        crc_big_table[i] = byte_swap(p);\n#endif\n    }\n\n    /* initialize the x^2^n mod p(x) table */\n    p = (z_crc_t)1 << 30;         /* x^1 */\n    x2n_table[0] = p;\n    for (n = 1; n < 32; n++)\n        x2n_table[n] = p = multmodp(p, p);\n\n#ifdef W\n    /* initialize the braiding tables -- needs x2n_table[] */\n    braid(crc_braid_table, crc_braid_big_table, N, W);\n#endif\n\n#ifdef MAKECRCH\n    {\n        /*\n          The crc32.h header file contains tables for both 32-bit and 64-bit\n          z_word_t's, and so requires a 64-bit type be available. In that case,\n          z_word_t must be defined to be 64-bits. This code then also generates\n          and writes out the tables for the case that z_word_t is 32 bits.\n         */\n#if !defined(W) || W != 8\n#  error Need a 64-bit integer type in order to generate crc32.h.\n#endif\n        FILE *out;\n        int k, n;\n        z_crc_t ltl[8][256];\n        z_word_t big[8][256];\n\n        out = fopen(\"crc32.h\", \"w\");\n        if (out == NULL) return;\n\n        /* write out little-endian CRC table to crc32.h */\n        fprintf(out,\n            \"/* crc32.h -- tables for rapid CRC calculation\\n\"\n            \" * Generated automatically by crc32.c\\n */\\n\"\n            \"\\n\"\n            \"local const z_crc_t FAR crc_table[] = {\\n\"\n            \"    \");\n        write_table(out, crc_table, 256);\n        fprintf(out,\n            \"};\\n\");\n\n        /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */\n        fprintf(out,\n            \"\\n\"\n            \"#ifdef W\\n\"\n            \"\\n\"\n            \"#if W == 8\\n\"\n            \"\\n\"\n            \"local const z_word_t FAR crc_big_table[] = {\\n\"\n            \"    \");\n        write_table64(out, crc_big_table, 256);\n        fprintf(out,\n            \"};\\n\");\n\n        /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */\n        fprintf(out,\n            \"\\n\"\n            \"#else /* W == 4 */\\n\"\n            \"\\n\"\n            \"local const z_word_t FAR crc_big_table[] = {\\n\"\n            \"    \");\n        write_table32hi(out, crc_big_table, 256);\n        fprintf(out,\n            \"};\\n\"\n            \"\\n\"\n            \"#endif\\n\");\n\n        /* write out braid tables for each value of N */\n        for (n = 1; n <= 6; n++) {\n            fprintf(out,\n            \"\\n\"\n            \"#if N == %d\\n\", n);\n\n            /* compute braid tables for this N and 64-bit word_t */\n            braid(ltl, big, n, 8);\n\n            /* write out braid tables for 64-bit z_word_t to crc32.h */\n            fprintf(out,\n            \"\\n\"\n            \"#if W == 8\\n\"\n            \"\\n\"\n            \"local const z_crc_t FAR crc_braid_table[][256] = {\\n\");\n            for (k = 0; k < 8; k++) {\n                fprintf(out, \"   {\");\n                write_table(out, ltl[k], 256);\n                fprintf(out, \"}%s\", k < 7 ? \",\\n\" : \"\");\n            }\n            fprintf(out,\n            \"};\\n\"\n            \"\\n\"\n            \"local const z_word_t FAR crc_braid_big_table[][256] = {\\n\");\n            for (k = 0; k < 8; k++) {\n                fprintf(out, \"   {\");\n                write_table64(out, big[k], 256);\n                fprintf(out, \"}%s\", k < 7 ? \",\\n\" : \"\");\n            }\n            fprintf(out,\n            \"};\\n\");\n\n            /* compute braid tables for this N and 32-bit word_t */\n            braid(ltl, big, n, 4);\n\n            /* write out braid tables for 32-bit z_word_t to crc32.h */\n            fprintf(out,\n            \"\\n\"\n            \"#else /* W == 4 */\\n\"\n            \"\\n\"\n            \"local const z_crc_t FAR crc_braid_table[][256] = {\\n\");\n            for (k = 0; k < 4; k++) {\n                fprintf(out, \"   {\");\n                write_table(out, ltl[k], 256);\n                fprintf(out, \"}%s\", k < 3 ? \",\\n\" : \"\");\n            }\n            fprintf(out,\n            \"};\\n\"\n            \"\\n\"\n            \"local const z_word_t FAR crc_braid_big_table[][256] = {\\n\");\n            for (k = 0; k < 4; k++) {\n                fprintf(out, \"   {\");\n                write_table32hi(out, big[k], 256);\n                fprintf(out, \"}%s\", k < 3 ? \",\\n\" : \"\");\n            }\n            fprintf(out,\n            \"};\\n\"\n            \"\\n\"\n            \"#endif\\n\"\n            \"\\n\"\n            \"#endif\\n\");\n        }\n        fprintf(out,\n            \"\\n\"\n            \"#endif\\n\");\n\n        /* write out zeros operator table to crc32.h */\n        fprintf(out,\n            \"\\n\"\n            \"local const z_crc_t FAR x2n_table[] = {\\n\"\n            \"    \");\n        write_table(out, x2n_table, 32);\n        fprintf(out,\n            \"};\\n\");\n        fclose(out);\n    }\n#endif /* MAKECRCH */\n}\n\n#ifdef MAKECRCH\n\n/*\n   Write the 32-bit values in table[0..k-1] to out, five per line in\n   hexadecimal separated by commas.\n */\nlocal void write_table(out, table, k)\n    FILE *out;\n    const z_crc_t FAR *table;\n    int k;\n{\n    int n;\n\n    for (n = 0; n < k; n++)\n        fprintf(out, \"%s0x%08lx%s\", n == 0 || n % 5 ? \"\" : \"    \",\n                (unsigned long)(table[n]),\n                n == k - 1 ? \"\" : (n % 5 == 4 ? \",\\n\" : \", \"));\n}\n\n/*\n   Write the high 32-bits of each value in table[0..k-1] to out, five per line\n   in hexadecimal separated by commas.\n */\nlocal void write_table32hi(out, table, k)\nFILE *out;\nconst z_word_t FAR *table;\nint k;\n{\n    int n;\n\n    for (n = 0; n < k; n++)\n        fprintf(out, \"%s0x%08lx%s\", n == 0 || n % 5 ? \"\" : \"    \",\n                (unsigned long)(table[n] >> 32),\n                n == k - 1 ? \"\" : (n % 5 == 4 ? \",\\n\" : \", \"));\n}\n\n/*\n  Write the 64-bit values in table[0..k-1] to out, three per line in\n  hexadecimal separated by commas. This assumes that if there is a 64-bit\n  type, then there is also a long long integer type, and it is at least 64\n  bits. If not, then the type cast and format string can be adjusted\n  accordingly.\n */\nlocal void write_table64(out, table, k)\n    FILE *out;\n    const z_word_t FAR *table;\n    int k;\n{\n    int n;\n\n    for (n = 0; n < k; n++)\n        fprintf(out, \"%s0x%016llx%s\", n == 0 || n % 3 ? \"\" : \"    \",\n                (unsigned long long)(table[n]),\n                n == k - 1 ? \"\" : (n % 3 == 2 ? \",\\n\" : \", \"));\n}\n\n/* Actually do the deed. */\nint main()\n{\n    make_crc_table();\n    return 0;\n}\n\n#endif /* MAKECRCH */\n\n#ifdef W\n/*\n  Generate the little and big-endian braid tables for the given n and z_word_t\n  size w. Each array must have room for w blocks of 256 elements.\n */\nlocal void braid(ltl, big, n, w)\n    z_crc_t ltl[][256];\n    z_word_t big[][256];\n    int n;\n    int w;\n{\n    int k;\n    z_crc_t i, p, q;\n    for (k = 0; k < w; k++) {\n        p = x2nmodp((n * w + 3 - k) << 3, 0);\n        ltl[k][0] = 0;\n        big[w - 1 - k][0] = 0;\n        for (i = 1; i < 256; i++) {\n            ltl[k][i] = q = multmodp(i << 24, p);\n            big[w - 1 - k][i] = byte_swap(q);\n        }\n    }\n}\n#endif\n\n#else /* !DYNAMIC_CRC_TABLE */\n/* ========================================================================\n * Tables for byte-wise and braided CRC-32 calculations, and a table of powers\n * of x for combining CRC-32s, all made by make_crc_table().\n */\n#include \"third_party/libz/crc32.h\"\n#endif /* DYNAMIC_CRC_TABLE */\n\n/* ========================================================================\n * Routines used for CRC calculation. Some are also required for the table\n * generation above.\n */\n\n/*\n  Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,\n  reflected. For speed, this requires that a not be zero.\n */\nlocal z_crc_t multmodp(a, b)\n    z_crc_t a;\n    z_crc_t b;\n{\n    z_crc_t m, p;\n\n    m = (z_crc_t)1 << 31;\n    p = 0;\n    for (;;) {\n        if (a & m) {\n            p ^= b;\n            if ((a & (m - 1)) == 0)\n                break;\n        }\n        m >>= 1;\n        b = b & 1 ? (b >> 1) ^ POLY : b >> 1;\n    }\n    return p;\n}\n\n/*\n  Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been\n  initialized.\n */\nlocal z_crc_t x2nmodp(n, k)\n    z_off64_t n;\n    unsigned k;\n{\n    z_crc_t p;\n\n    p = (z_crc_t)1 << 31;           /* x^0 == 1 */\n    while (n) {\n        if (n & 1)\n            p = multmodp(x2n_table[k & 31], p);\n        n >>= 1;\n        k++;\n    }\n    return p;\n}\n\n/* =========================================================================\n * This function can be used by asm versions of crc32(), and to force the\n * generation of the CRC tables in a threaded application.\n */\nconst z_crc_t FAR * ZEXPORT get_crc_table()\n{\n#ifdef DYNAMIC_CRC_TABLE\n    once(&made, make_crc_table);\n#endif /* DYNAMIC_CRC_TABLE */\n    return (const z_crc_t FAR *)crc_table;\n}\n\n/* =========================================================================\n * Use ARM machine instructions if available. This will compute the CRC about\n * ten times faster than the braided calculation. This code does not check for\n * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will\n * only be defined if the compilation specifies an ARM processor architecture\n * that has the instructions. For example, compiling with -march=armv8.1-a or\n * -march=armv8-a+crc, or -march=native if the compile machine has the crc32\n * instructions.\n */\n#ifdef ARMCRC32\n\n/*\n   Constants empirically determined to maximize speed. These values are from\n   measurements on a Cortex-A57. Your mileage may vary.\n */\n#define Z_BATCH 3990                /* number of words in a batch */\n#define Z_BATCH_ZEROS 0xa10d3d0c    /* computed from Z_BATCH = 3990 */\n#define Z_BATCH_MIN 800             /* fewest words in a final batch */\n\nunsigned long ZEXPORT crc32_z(crc, buf, len)\n    unsigned long crc;\n    const unsigned char FAR *buf;\n    z_size_t len;\n{\n    z_crc_t val;\n    z_word_t crc1, crc2;\n    const z_word_t *word;\n    z_word_t val0, val1, val2;\n    z_size_t last, last2, i;\n    z_size_t num;\n\n    /* Return initial CRC, if requested. */\n    if (buf == Z_NULL) return 0;\n\n#ifdef DYNAMIC_CRC_TABLE\n    once(&made, make_crc_table);\n#endif /* DYNAMIC_CRC_TABLE */\n\n    /* Pre-condition the CRC */\n    crc = (~crc) & 0xffffffff;\n\n    /* Compute the CRC up to a word boundary. */\n    while (len && ((z_size_t)buf & 7) != 0) {\n        len--;\n        val = *buf++;\n        __asm__ volatile(\"crc32b %w0, %w0, %w1\" : \"+r\"(crc) : \"r\"(val));\n    }\n\n    /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */\n    word = (z_word_t const *)buf;\n    num = len >> 3;\n    len &= 7;\n\n    /* Do three interleaved CRCs to realize the throughput of one crc32x\n       instruction per cycle. Each CRC is calculated on Z_BATCH words. The\n       three CRCs are combined into a single CRC after each set of batches. */\n    while (num >= 3 * Z_BATCH) {\n        crc1 = 0;\n        crc2 = 0;\n        for (i = 0; i < Z_BATCH; i++) {\n            val0 = word[i];\n            val1 = word[i + Z_BATCH];\n            val2 = word[i + 2 * Z_BATCH];\n            __asm__ volatile(\"crc32x %w0, %w0, %x1\" : \"+r\"(crc) : \"r\"(val0));\n            __asm__ volatile(\"crc32x %w0, %w0, %x1\" : \"+r\"(crc1) : \"r\"(val1));\n            __asm__ volatile(\"crc32x %w0, %w0, %x1\" : \"+r\"(crc2) : \"r\"(val2));\n        }\n        word += 3 * Z_BATCH;\n        num -= 3 * Z_BATCH;\n        crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1;\n        crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2;\n    }\n\n    /* Do one last smaller batch with the remaining words, if there are enough\n       to pay for the combination of CRCs. */\n    last = num / 3;\n    if (last >= Z_BATCH_MIN) {\n        last2 = last << 1;\n        crc1 = 0;\n        crc2 = 0;\n        for (i = 0; i < last; i++) {\n            val0 = word[i];\n            val1 = word[i + last];\n            val2 = word[i + last2];\n            __asm__ volatile(\"crc32x %w0, %w0, %x1\" : \"+r\"(crc) : \"r\"(val0));\n            __asm__ volatile(\"crc32x %w0, %w0, %x1\" : \"+r\"(crc1) : \"r\"(val1));\n            __asm__ volatile(\"crc32x %w0, %w0, %x1\" : \"+r\"(crc2) : \"r\"(val2));\n        }\n        word += 3 * last;\n        num -= 3 * last;\n        val = x2nmodp(last, 6);\n        crc = multmodp(val, crc) ^ crc1;\n        crc = multmodp(val, crc) ^ crc2;\n    }\n\n    /* Compute the CRC on any remaining words. */\n    for (i = 0; i < num; i++) {\n        val0 = word[i];\n        __asm__ volatile(\"crc32x %w0, %w0, %x1\" : \"+r\"(crc) : \"r\"(val0));\n    }\n    word += num;\n\n    /* Complete the CRC on any remaining bytes. */\n    buf = (const unsigned char FAR *)word;\n    while (len) {\n        len--;\n        val = *buf++;\n        __asm__ volatile(\"crc32b %w0, %w0, %w1\" : \"+r\"(crc) : \"r\"(val));\n    }\n\n    /* Return the CRC, post-conditioned. */\n    return crc ^ 0xffffffff;\n}\n\n#else\n\n#ifdef W\n\n/*\n  Return the CRC of the W bytes in the word_t data, taking the\n  least-significant byte of the word as the first byte of data, without any pre\n  or post conditioning. This is used to combine the CRCs of each braid.\n */\nlocal z_crc_t crc_word(data)\n    z_word_t data;\n{\n    int k;\n    for (k = 0; k < W; k++)\n        data = (data >> 8) ^ crc_table[data & 0xff];\n    return (z_crc_t)data;\n}\n\nlocal z_word_t crc_word_big(data)\n    z_word_t data;\n{\n    int k;\n    for (k = 0; k < W; k++)\n        data = (data << 8) ^\n            crc_big_table[(data >> ((W - 1) << 3)) & 0xff];\n    return data;\n}\n\n#endif\n\n/* ========================================================================= */\nunsigned long ZEXPORT crc32_z(crc, buf, len)\n    unsigned long crc;\n    const unsigned char FAR *buf;\n    z_size_t len;\n{\n    /* Return initial CRC, if requested. */\n    if (buf == Z_NULL) return 0;\n\n#ifdef DYNAMIC_CRC_TABLE\n    once(&made, make_crc_table);\n#endif /* DYNAMIC_CRC_TABLE */\n\n    /* Pre-condition the CRC */\n    crc = (~crc) & 0xffffffff;\n\n#ifdef W\n\n    /* If provided enough bytes, do a braided CRC calculation. */\n    if (len >= N * W + W - 1) {\n        z_size_t blks;\n        z_word_t const *words;\n        unsigned endian;\n        int k;\n\n        /* Compute the CRC up to a z_word_t boundary. */\n        while (len && ((z_size_t)buf & (W - 1)) != 0) {\n            len--;\n            crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];\n        }\n\n        /* Compute the CRC on as many N z_word_t blocks as are available. */\n        blks = len / (N * W);\n        len -= blks * N * W;\n        words = (z_word_t const *)buf;\n\n        /* Do endian check at execution time instead of compile time, since ARM\n           processors can change the endianess at execution time. If the\n           compiler knows what the endianess will be, it can optimize out the\n           check and the unused branch. */\n        endian = 1;\n        if (*(unsigned char *)&endian) {\n            /* Little endian. */\n\n            z_crc_t crc0;\n            z_word_t word0;\n#if N > 1\n            z_crc_t crc1;\n            z_word_t word1;\n#if N > 2\n            z_crc_t crc2;\n            z_word_t word2;\n#if N > 3\n            z_crc_t crc3;\n            z_word_t word3;\n#if N > 4\n            z_crc_t crc4;\n            z_word_t word4;\n#if N > 5\n            z_crc_t crc5;\n            z_word_t word5;\n#endif\n#endif\n#endif\n#endif\n#endif\n\n            /* Initialize the CRC for each braid. */\n            crc0 = crc;\n#if N > 1\n            crc1 = 0;\n#if N > 2\n            crc2 = 0;\n#if N > 3\n            crc3 = 0;\n#if N > 4\n            crc4 = 0;\n#if N > 5\n            crc5 = 0;\n#endif\n#endif\n#endif\n#endif\n#endif\n\n            /*\n              Process the first blks-1 blocks, computing the CRCs on each braid\n              independently.\n             */\n            while (--blks) {\n                /* Load the word for each braid into registers. */\n                word0 = crc0 ^ words[0];\n#if N > 1\n                word1 = crc1 ^ words[1];\n#if N > 2\n                word2 = crc2 ^ words[2];\n#if N > 3\n                word3 = crc3 ^ words[3];\n#if N > 4\n                word4 = crc4 ^ words[4];\n#if N > 5\n                word5 = crc5 ^ words[5];\n#endif\n#endif\n#endif\n#endif\n#endif\n                words += N;\n\n                /* Compute and update the CRC for each word. The loop should\n                   get unrolled. */\n                crc0 = crc_braid_table[0][word0 & 0xff];\n#if N > 1\n                crc1 = crc_braid_table[0][word1 & 0xff];\n#if N > 2\n                crc2 = crc_braid_table[0][word2 & 0xff];\n#if N > 3\n                crc3 = crc_braid_table[0][word3 & 0xff];\n#if N > 4\n                crc4 = crc_braid_table[0][word4 & 0xff];\n#if N > 5\n                crc5 = crc_braid_table[0][word5 & 0xff];\n#endif\n#endif\n#endif\n#endif\n#endif\n                for (k = 1; k < W; k++) {\n                    crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff];\n#if N > 1\n                    crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff];\n#if N > 2\n                    crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff];\n#if N > 3\n                    crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff];\n#if N > 4\n                    crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff];\n#if N > 5\n                    crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff];\n#endif\n#endif\n#endif\n#endif\n#endif\n                }\n            }\n\n            /*\n              Process the last block, combining the CRCs of the N braids at the\n              same time.\n             */\n            crc = crc_word(crc0 ^ words[0]);\n#if N > 1\n            crc = crc_word(crc1 ^ words[1] ^ crc);\n#if N > 2\n            crc = crc_word(crc2 ^ words[2] ^ crc);\n#if N > 3\n            crc = crc_word(crc3 ^ words[3] ^ crc);\n#if N > 4\n            crc = crc_word(crc4 ^ words[4] ^ crc);\n#if N > 5\n            crc = crc_word(crc5 ^ words[5] ^ crc);\n#endif\n#endif\n#endif\n#endif\n#endif\n            words += N;\n        }\n        else {\n            /* Big endian. */\n\n            z_word_t crc0, word0, comb;\n#if N > 1\n            z_word_t crc1, word1;\n#if N > 2\n            z_word_t crc2, word2;\n#if N > 3\n            z_word_t crc3, word3;\n#if N > 4\n            z_word_t crc4, word4;\n#if N > 5\n            z_word_t crc5, word5;\n#endif\n#endif\n#endif\n#endif\n#endif\n\n            /* Initialize the CRC for each braid. */\n            crc0 = byte_swap(crc);\n#if N > 1\n            crc1 = 0;\n#if N > 2\n            crc2 = 0;\n#if N > 3\n            crc3 = 0;\n#if N > 4\n            crc4 = 0;\n#if N > 5\n            crc5 = 0;\n#endif\n#endif\n#endif\n#endif\n#endif\n\n            /*\n              Process the first blks-1 blocks, computing the CRCs on each braid\n              independently.\n             */\n            while (--blks) {\n                /* Load the word for each braid into registers. */\n                word0 = crc0 ^ words[0];\n#if N > 1\n                word1 = crc1 ^ words[1];\n#if N > 2\n                word2 = crc2 ^ words[2];\n#if N > 3\n                word3 = crc3 ^ words[3];\n#if N > 4\n                word4 = crc4 ^ words[4];\n#if N > 5\n                word5 = crc5 ^ words[5];\n#endif\n#endif\n#endif\n#endif\n#endif\n                words += N;\n\n                /* Compute and update the CRC for each word. The loop should\n                   get unrolled. */\n                crc0 = crc_braid_big_table[0][word0 & 0xff];\n#if N > 1\n                crc1 = crc_braid_big_table[0][word1 & 0xff];\n#if N > 2\n                crc2 = crc_braid_big_table[0][word2 & 0xff];\n#if N > 3\n                crc3 = crc_braid_big_table[0][word3 & 0xff];\n#if N > 4\n                crc4 = crc_braid_big_table[0][word4 & 0xff];\n#if N > 5\n                crc5 = crc_braid_big_table[0][word5 & 0xff];\n#endif\n#endif\n#endif\n#endif\n#endif\n                for (k = 1; k < W; k++) {\n                    crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff];\n#if N > 1\n                    crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff];\n#if N > 2\n                    crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff];\n#if N > 3\n                    crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff];\n#if N > 4\n                    crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff];\n#if N > 5\n                    crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff];\n#endif\n#endif\n#endif\n#endif\n#endif\n                }\n            }\n\n            /*\n              Process the last block, combining the CRCs of the N braids at the\n              same time.\n             */\n            comb = crc_word_big(crc0 ^ words[0]);\n#if N > 1\n            comb = crc_word_big(crc1 ^ words[1] ^ comb);\n#if N > 2\n            comb = crc_word_big(crc2 ^ words[2] ^ comb);\n#if N > 3\n            comb = crc_word_big(crc3 ^ words[3] ^ comb);\n#if N > 4\n            comb = crc_word_big(crc4 ^ words[4] ^ comb);\n#if N > 5\n            comb = crc_word_big(crc5 ^ words[5] ^ comb);\n#endif\n#endif\n#endif\n#endif\n#endif\n            words += N;\n            crc = byte_swap(comb);\n        }\n\n        /*\n          Update the pointer to the remaining bytes to process.\n         */\n        buf = (unsigned char const *)words;\n    }\n\n#endif /* W */\n\n    /* Complete the computation of the CRC on any remaining bytes. */\n    while (len >= 8) {\n        len -= 8;\n        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];\n        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];\n        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];\n        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];\n        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];\n        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];\n        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];\n        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];\n    }\n    while (len) {\n        len--;\n        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];\n    }\n\n    /* Return the CRC, post-conditioned. */\n    return crc ^ 0xffffffff;\n}\n\n#endif\n\n/* ========================================================================= */\nunsigned long ZEXPORT crc32(crc, buf, len)\n    unsigned long crc;\n    const unsigned char FAR *buf;\n    uInt len;\n{\n    return crc32_z(crc, buf, len);\n}\n\n/* ========================================================================= */\nuLong ZEXPORT crc32_combine64(crc1, crc2, len2)\n    uLong crc1;\n    uLong crc2;\n    z_off64_t len2;\n{\n#ifdef DYNAMIC_CRC_TABLE\n    once(&made, make_crc_table);\n#endif /* DYNAMIC_CRC_TABLE */\n    return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff);\n}\n\n/* ========================================================================= */\nuLong ZEXPORT crc32_combine(crc1, crc2, len2)\n    uLong crc1;\n    uLong crc2;\n    z_off_t len2;\n{\n    return crc32_combine64(crc1, crc2, (z_off64_t)len2);\n}\n\n/* ========================================================================= */\nuLong ZEXPORT crc32_combine_gen64(len2)\n    z_off64_t len2;\n{\n#ifdef DYNAMIC_CRC_TABLE\n    once(&made, make_crc_table);\n#endif /* DYNAMIC_CRC_TABLE */\n    return x2nmodp(len2, 3);\n}\n\n/* ========================================================================= */\nuLong ZEXPORT crc32_combine_gen(len2)\n    z_off_t len2;\n{\n    return crc32_combine_gen64((z_off64_t)len2);\n}\n\n/* ========================================================================= */\nuLong ZEXPORT crc32_combine_op(crc1, crc2, op)\n    uLong crc1;\n    uLong crc2;\n    uLong op;\n{\n    return multmodp(op, crc1) ^ (crc2 & 0xffffffff);\n}\n"
  },
  {
    "path": "third_party/libz/crc32.h",
    "content": "// clang-format off\n/* crc32.h -- tables for rapid CRC calculation\n * Generated automatically by crc32.c\n */\n\nlocal const z_crc_t FAR crc_table[] = {\n    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,\n    0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,\n    0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,\n    0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,\n    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,\n    0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,\n    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,\n    0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,\n    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,\n    0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,\n    0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,\n    0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\n    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,\n    0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,\n    0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,\n    0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,\n    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,\n    0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,\n    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,\n    0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,\n    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,\n    0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,\n    0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,\n    0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,\n    0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,\n    0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,\n    0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,\n    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,\n    0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,\n    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,\n    0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,\n    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,\n    0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,\n    0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,\n    0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\n    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,\n    0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,\n    0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,\n    0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,\n    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,\n    0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,\n    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,\n    0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,\n    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,\n    0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,\n    0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,\n    0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,\n    0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,\n    0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,\n    0x2d02ef8d};\n\n#ifdef W\n\n#if W == 8\n\nlocal const z_word_t FAR crc_big_table[] = {\n    0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,\n    0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,\n    0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,\n    0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,\n    0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,\n    0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,\n    0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,\n    0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,\n    0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,\n    0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,\n    0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,\n    0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,\n    0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,\n    0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,\n    0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,\n    0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,\n    0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,\n    0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,\n    0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,\n    0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,\n    0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,\n    0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,\n    0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,\n    0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,\n    0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,\n    0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,\n    0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,\n    0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,\n    0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,\n    0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,\n    0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,\n    0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,\n    0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,\n    0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,\n    0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,\n    0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,\n    0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,\n    0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,\n    0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,\n    0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,\n    0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,\n    0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,\n    0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,\n    0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,\n    0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,\n    0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,\n    0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,\n    0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,\n    0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,\n    0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,\n    0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,\n    0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,\n    0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,\n    0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,\n    0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,\n    0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,\n    0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,\n    0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,\n    0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,\n    0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,\n    0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,\n    0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,\n    0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,\n    0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,\n    0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,\n    0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,\n    0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,\n    0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,\n    0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,\n    0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,\n    0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,\n    0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,\n    0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,\n    0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,\n    0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,\n    0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,\n    0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,\n    0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,\n    0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,\n    0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,\n    0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,\n    0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,\n    0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,\n    0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,\n    0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,\n    0x8def022d00000000};\n\n#else /* W == 4 */\n\nlocal const z_word_t FAR crc_big_table[] = {\n    0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,\n    0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,\n    0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,\n    0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,\n    0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,\n    0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,\n    0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,\n    0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,\n    0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,\n    0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,\n    0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,\n    0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,\n    0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,\n    0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,\n    0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,\n    0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,\n    0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,\n    0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,\n    0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,\n    0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,\n    0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,\n    0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,\n    0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,\n    0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,\n    0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,\n    0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,\n    0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,\n    0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,\n    0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,\n    0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,\n    0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,\n    0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,\n    0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,\n    0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,\n    0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,\n    0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,\n    0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,\n    0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,\n    0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,\n    0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,\n    0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,\n    0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,\n    0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,\n    0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,\n    0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,\n    0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,\n    0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,\n    0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,\n    0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,\n    0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,\n    0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,\n    0x8def022d};\n\n#endif\n\n#if N == 1\n\n#if W == 8\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,\n    0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,\n    0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,\n    0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,\n    0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,\n    0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,\n    0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,\n    0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,\n    0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,\n    0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,\n    0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,\n    0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,\n    0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,\n    0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,\n    0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,\n    0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,\n    0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,\n    0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,\n    0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,\n    0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,\n    0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,\n    0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,\n    0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,\n    0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,\n    0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,\n    0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,\n    0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,\n    0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,\n    0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,\n    0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,\n    0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,\n    0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,\n    0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,\n    0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,\n    0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,\n    0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,\n    0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,\n    0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,\n    0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,\n    0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,\n    0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,\n    0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,\n    0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,\n    0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,\n    0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,\n    0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,\n    0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,\n    0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,\n    0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,\n    0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,\n    0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,\n    0x264b06e6},\n   {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,\n    0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,\n    0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,\n    0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,\n    0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,\n    0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,\n    0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,\n    0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,\n    0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,\n    0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,\n    0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,\n    0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,\n    0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,\n    0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,\n    0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,\n    0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,\n    0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,\n    0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,\n    0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,\n    0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,\n    0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,\n    0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,\n    0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,\n    0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,\n    0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,\n    0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,\n    0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,\n    0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,\n    0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,\n    0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,\n    0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,\n    0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,\n    0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,\n    0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,\n    0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,\n    0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,\n    0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,\n    0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,\n    0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,\n    0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,\n    0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,\n    0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,\n    0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,\n    0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,\n    0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,\n    0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,\n    0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,\n    0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,\n    0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,\n    0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,\n    0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,\n    0x92364a30},\n   {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,\n    0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,\n    0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,\n    0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,\n    0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,\n    0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,\n    0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,\n    0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,\n    0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,\n    0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,\n    0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,\n    0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,\n    0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,\n    0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,\n    0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,\n    0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,\n    0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,\n    0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,\n    0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,\n    0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,\n    0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,\n    0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,\n    0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,\n    0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,\n    0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,\n    0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,\n    0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,\n    0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,\n    0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,\n    0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,\n    0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,\n    0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,\n    0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,\n    0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,\n    0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,\n    0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,\n    0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,\n    0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,\n    0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,\n    0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,\n    0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,\n    0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,\n    0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,\n    0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,\n    0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,\n    0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,\n    0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,\n    0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,\n    0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,\n    0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,\n    0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,\n    0xe4c4abcc},\n   {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,\n    0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,\n    0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,\n    0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,\n    0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,\n    0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,\n    0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,\n    0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,\n    0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,\n    0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,\n    0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,\n    0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,\n    0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,\n    0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,\n    0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,\n    0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,\n    0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,\n    0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,\n    0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,\n    0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,\n    0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,\n    0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,\n    0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,\n    0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,\n    0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,\n    0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,\n    0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,\n    0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,\n    0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,\n    0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,\n    0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,\n    0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,\n    0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,\n    0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,\n    0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,\n    0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,\n    0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,\n    0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,\n    0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,\n    0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,\n    0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,\n    0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,\n    0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,\n    0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,\n    0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,\n    0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,\n    0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,\n    0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,\n    0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,\n    0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,\n    0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,\n    0xca64c78c},\n   {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,\n    0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,\n    0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,\n    0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,\n    0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,\n    0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,\n    0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,\n    0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,\n    0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,\n    0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,\n    0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,\n    0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,\n    0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,\n    0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,\n    0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,\n    0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,\n    0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,\n    0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,\n    0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,\n    0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,\n    0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,\n    0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,\n    0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,\n    0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,\n    0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,\n    0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,\n    0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,\n    0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,\n    0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,\n    0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,\n    0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,\n    0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,\n    0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,\n    0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,\n    0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,\n    0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,\n    0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,\n    0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,\n    0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,\n    0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,\n    0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,\n    0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,\n    0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,\n    0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,\n    0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,\n    0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,\n    0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,\n    0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,\n    0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,\n    0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,\n    0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,\n    0xde0506f1},\n   {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,\n    0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,\n    0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,\n    0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,\n    0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,\n    0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,\n    0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,\n    0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,\n    0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,\n    0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,\n    0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,\n    0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,\n    0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,\n    0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,\n    0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,\n    0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,\n    0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,\n    0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,\n    0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,\n    0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,\n    0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,\n    0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,\n    0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,\n    0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,\n    0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,\n    0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,\n    0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,\n    0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,\n    0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,\n    0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,\n    0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,\n    0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,\n    0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,\n    0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,\n    0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,\n    0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,\n    0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,\n    0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,\n    0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,\n    0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,\n    0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,\n    0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,\n    0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,\n    0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,\n    0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,\n    0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,\n    0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,\n    0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,\n    0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,\n    0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,\n    0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,\n    0xbe9834ed},\n   {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,\n    0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,\n    0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,\n    0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,\n    0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,\n    0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,\n    0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,\n    0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,\n    0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,\n    0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,\n    0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,\n    0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,\n    0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,\n    0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,\n    0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,\n    0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,\n    0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,\n    0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,\n    0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,\n    0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,\n    0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,\n    0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,\n    0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,\n    0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,\n    0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,\n    0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,\n    0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,\n    0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,\n    0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,\n    0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,\n    0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,\n    0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,\n    0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,\n    0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,\n    0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,\n    0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,\n    0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,\n    0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,\n    0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,\n    0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,\n    0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,\n    0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,\n    0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,\n    0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,\n    0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,\n    0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,\n    0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,\n    0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,\n    0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,\n    0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,\n    0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,\n    0x9324fd72},\n   {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,\n    0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,\n    0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,\n    0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,\n    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,\n    0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,\n    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,\n    0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,\n    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,\n    0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,\n    0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,\n    0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\n    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,\n    0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,\n    0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,\n    0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,\n    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,\n    0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,\n    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,\n    0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,\n    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,\n    0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,\n    0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,\n    0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,\n    0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,\n    0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,\n    0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,\n    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,\n    0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,\n    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,\n    0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,\n    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,\n    0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,\n    0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,\n    0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\n    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,\n    0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,\n    0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,\n    0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,\n    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,\n    0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,\n    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,\n    0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,\n    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,\n    0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,\n    0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,\n    0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,\n    0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,\n    0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,\n    0x2d02ef8d}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,\n    0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,\n    0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,\n    0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,\n    0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,\n    0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,\n    0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,\n    0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,\n    0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,\n    0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,\n    0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,\n    0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,\n    0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,\n    0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,\n    0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,\n    0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,\n    0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,\n    0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,\n    0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,\n    0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,\n    0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,\n    0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,\n    0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,\n    0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,\n    0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,\n    0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,\n    0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,\n    0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,\n    0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,\n    0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,\n    0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,\n    0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,\n    0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,\n    0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,\n    0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,\n    0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,\n    0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,\n    0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,\n    0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,\n    0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,\n    0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,\n    0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,\n    0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,\n    0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,\n    0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,\n    0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,\n    0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,\n    0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,\n    0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,\n    0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,\n    0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,\n    0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,\n    0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,\n    0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,\n    0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,\n    0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,\n    0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,\n    0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,\n    0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,\n    0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,\n    0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,\n    0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,\n    0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,\n    0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,\n    0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,\n    0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,\n    0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,\n    0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,\n    0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,\n    0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,\n    0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,\n    0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,\n    0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,\n    0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,\n    0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,\n    0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,\n    0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,\n    0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,\n    0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,\n    0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,\n    0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,\n    0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,\n    0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,\n    0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,\n    0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,\n    0x8def022d00000000},\n   {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000,\n    0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000,\n    0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000,\n    0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000,\n    0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000,\n    0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000,\n    0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000,\n    0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000,\n    0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000,\n    0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000,\n    0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000,\n    0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000,\n    0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000,\n    0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000,\n    0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000,\n    0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000,\n    0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000,\n    0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000,\n    0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000,\n    0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000,\n    0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000,\n    0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000,\n    0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000,\n    0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000,\n    0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000,\n    0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000,\n    0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000,\n    0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000,\n    0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000,\n    0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000,\n    0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000,\n    0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000,\n    0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000,\n    0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000,\n    0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000,\n    0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000,\n    0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000,\n    0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000,\n    0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000,\n    0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000,\n    0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000,\n    0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000,\n    0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000,\n    0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000,\n    0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000,\n    0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000,\n    0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000,\n    0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000,\n    0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000,\n    0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000,\n    0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000,\n    0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000,\n    0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000,\n    0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000,\n    0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000,\n    0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000,\n    0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000,\n    0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000,\n    0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000,\n    0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000,\n    0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000,\n    0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000,\n    0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000,\n    0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000,\n    0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000,\n    0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000,\n    0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000,\n    0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000,\n    0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000,\n    0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000,\n    0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000,\n    0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000,\n    0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000,\n    0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000,\n    0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000,\n    0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000,\n    0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000,\n    0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000,\n    0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000,\n    0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000,\n    0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000,\n    0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000,\n    0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000,\n    0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000,\n    0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000,\n    0x72fd249300000000},\n   {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000,\n    0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000,\n    0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000,\n    0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000,\n    0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000,\n    0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000,\n    0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000,\n    0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000,\n    0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000,\n    0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000,\n    0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000,\n    0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000,\n    0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000,\n    0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000,\n    0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000,\n    0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000,\n    0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000,\n    0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000,\n    0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000,\n    0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000,\n    0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000,\n    0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000,\n    0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000,\n    0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000,\n    0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000,\n    0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000,\n    0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000,\n    0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000,\n    0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000,\n    0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000,\n    0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000,\n    0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000,\n    0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000,\n    0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000,\n    0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000,\n    0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000,\n    0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000,\n    0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000,\n    0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000,\n    0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000,\n    0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000,\n    0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000,\n    0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000,\n    0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000,\n    0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000,\n    0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000,\n    0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000,\n    0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000,\n    0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000,\n    0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000,\n    0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000,\n    0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000,\n    0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000,\n    0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000,\n    0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000,\n    0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000,\n    0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000,\n    0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000,\n    0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000,\n    0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000,\n    0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000,\n    0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000,\n    0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000,\n    0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000,\n    0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000,\n    0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000,\n    0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000,\n    0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000,\n    0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000,\n    0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000,\n    0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000,\n    0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000,\n    0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000,\n    0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000,\n    0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000,\n    0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000,\n    0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000,\n    0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000,\n    0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000,\n    0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000,\n    0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000,\n    0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000,\n    0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000,\n    0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000,\n    0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000,\n    0xed3498be00000000},\n   {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000,\n    0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000,\n    0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000,\n    0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000,\n    0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000,\n    0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000,\n    0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000,\n    0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000,\n    0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000,\n    0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000,\n    0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000,\n    0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000,\n    0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000,\n    0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000,\n    0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000,\n    0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000,\n    0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000,\n    0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000,\n    0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000,\n    0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000,\n    0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000,\n    0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000,\n    0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000,\n    0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000,\n    0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000,\n    0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000,\n    0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000,\n    0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000,\n    0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000,\n    0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000,\n    0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000,\n    0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000,\n    0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000,\n    0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000,\n    0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000,\n    0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000,\n    0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000,\n    0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000,\n    0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000,\n    0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000,\n    0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000,\n    0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000,\n    0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000,\n    0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000,\n    0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000,\n    0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000,\n    0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000,\n    0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000,\n    0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000,\n    0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000,\n    0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000,\n    0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000,\n    0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000,\n    0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000,\n    0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000,\n    0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000,\n    0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000,\n    0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000,\n    0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000,\n    0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000,\n    0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000,\n    0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000,\n    0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000,\n    0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000,\n    0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000,\n    0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000,\n    0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000,\n    0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000,\n    0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000,\n    0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000,\n    0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000,\n    0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000,\n    0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000,\n    0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000,\n    0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000,\n    0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000,\n    0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000,\n    0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000,\n    0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000,\n    0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000,\n    0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000,\n    0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000,\n    0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000,\n    0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000,\n    0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000,\n    0xf10605de00000000},\n   {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000,\n    0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000,\n    0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000,\n    0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000,\n    0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000,\n    0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000,\n    0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000,\n    0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000,\n    0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000,\n    0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000,\n    0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000,\n    0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000,\n    0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000,\n    0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000,\n    0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000,\n    0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000,\n    0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000,\n    0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000,\n    0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000,\n    0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000,\n    0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000,\n    0x572f712300000000, 0x4958f35800000000, 0xf971936500000000,\n    0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000,\n    0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000,\n    0x8813836800000000, 0x383ae35500000000, 0xe840431200000000,\n    0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000,\n    0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000,\n    0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000,\n    0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000,\n    0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000,\n    0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000,\n    0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000,\n    0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000,\n    0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000,\n    0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000,\n    0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000,\n    0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000,\n    0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000,\n    0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000,\n    0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000,\n    0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000,\n    0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000,\n    0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000,\n    0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000,\n    0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000,\n    0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000,\n    0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000,\n    0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000,\n    0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000,\n    0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000,\n    0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000,\n    0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000,\n    0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000,\n    0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000,\n    0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000,\n    0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000,\n    0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000,\n    0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000,\n    0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000,\n    0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000,\n    0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000,\n    0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000,\n    0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000,\n    0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000,\n    0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000,\n    0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000,\n    0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000,\n    0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000,\n    0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000,\n    0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000,\n    0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000,\n    0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000,\n    0x983485b900000000, 0x281de58400000000, 0xf86745c300000000,\n    0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000,\n    0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000,\n    0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000,\n    0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000,\n    0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000,\n    0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000,\n    0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000,\n    0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000,\n    0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000,\n    0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000,\n    0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000,\n    0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000,\n    0x8cc764ca00000000},\n   {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000,\n    0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000,\n    0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000,\n    0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000,\n    0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000,\n    0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000,\n    0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000,\n    0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000,\n    0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000,\n    0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000,\n    0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000,\n    0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000,\n    0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000,\n    0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000,\n    0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000,\n    0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000,\n    0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000,\n    0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000,\n    0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000,\n    0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000,\n    0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000,\n    0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000,\n    0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000,\n    0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000,\n    0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000,\n    0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000,\n    0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000,\n    0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000,\n    0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000,\n    0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000,\n    0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000,\n    0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000,\n    0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000,\n    0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000,\n    0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000,\n    0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000,\n    0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000,\n    0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000,\n    0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000,\n    0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000,\n    0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000,\n    0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000,\n    0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000,\n    0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000,\n    0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000,\n    0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000,\n    0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000,\n    0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000,\n    0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000,\n    0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000,\n    0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000,\n    0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000,\n    0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000,\n    0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000,\n    0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000,\n    0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000,\n    0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000,\n    0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000,\n    0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000,\n    0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000,\n    0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000,\n    0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000,\n    0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000,\n    0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000,\n    0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000,\n    0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000,\n    0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000,\n    0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000,\n    0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000,\n    0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000,\n    0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000,\n    0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000,\n    0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000,\n    0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000,\n    0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000,\n    0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000,\n    0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000,\n    0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000,\n    0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000,\n    0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000,\n    0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000,\n    0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000,\n    0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000,\n    0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000,\n    0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000,\n    0xccabc4e400000000},\n   {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000,\n    0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000,\n    0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000,\n    0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000,\n    0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000,\n    0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000,\n    0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000,\n    0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000,\n    0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000,\n    0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000,\n    0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000,\n    0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000,\n    0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000,\n    0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000,\n    0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000,\n    0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000,\n    0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000,\n    0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000,\n    0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000,\n    0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000,\n    0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000,\n    0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000,\n    0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000,\n    0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000,\n    0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000,\n    0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000,\n    0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000,\n    0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000,\n    0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000,\n    0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000,\n    0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000,\n    0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000,\n    0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000,\n    0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000,\n    0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000,\n    0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000,\n    0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000,\n    0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000,\n    0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000,\n    0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000,\n    0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000,\n    0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000,\n    0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000,\n    0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000,\n    0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000,\n    0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000,\n    0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000,\n    0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000,\n    0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000,\n    0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000,\n    0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000,\n    0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000,\n    0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000,\n    0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000,\n    0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000,\n    0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000,\n    0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000,\n    0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000,\n    0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000,\n    0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000,\n    0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000,\n    0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000,\n    0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000,\n    0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000,\n    0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000,\n    0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000,\n    0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000,\n    0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000,\n    0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000,\n    0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000,\n    0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000,\n    0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000,\n    0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000,\n    0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000,\n    0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000,\n    0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000,\n    0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000,\n    0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000,\n    0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000,\n    0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000,\n    0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000,\n    0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000,\n    0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000,\n    0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000,\n    0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000,\n    0x304a369200000000},\n   {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000,\n    0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000,\n    0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000,\n    0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000,\n    0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000,\n    0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000,\n    0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000,\n    0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000,\n    0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000,\n    0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000,\n    0x1923316900000000, 0x87239ba500000000, 0x566276f900000000,\n    0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000,\n    0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000,\n    0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000,\n    0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000,\n    0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000,\n    0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000,\n    0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000,\n    0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000,\n    0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000,\n    0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000,\n    0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000,\n    0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000,\n    0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000,\n    0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000,\n    0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000,\n    0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000,\n    0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000,\n    0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000,\n    0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000,\n    0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000,\n    0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000,\n    0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000,\n    0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000,\n    0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000,\n    0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000,\n    0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000,\n    0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000,\n    0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000,\n    0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000,\n    0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000,\n    0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000,\n    0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000,\n    0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000,\n    0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000,\n    0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000,\n    0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000,\n    0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000,\n    0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000,\n    0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000,\n    0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000,\n    0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000,\n    0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000,\n    0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000,\n    0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000,\n    0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000,\n    0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000,\n    0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000,\n    0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000,\n    0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000,\n    0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000,\n    0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000,\n    0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000,\n    0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000,\n    0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000,\n    0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000,\n    0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000,\n    0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000,\n    0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000,\n    0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000,\n    0x6171384400000000, 0xff71928800000000, 0xe678578200000000,\n    0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000,\n    0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000,\n    0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000,\n    0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000,\n    0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000,\n    0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000,\n    0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000,\n    0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000,\n    0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000,\n    0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000,\n    0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000,\n    0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000,\n    0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000,\n    0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000,\n    0xe6064b2600000000}};\n\n#else /* W == 4 */\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,\n    0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,\n    0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,\n    0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,\n    0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,\n    0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,\n    0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,\n    0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,\n    0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,\n    0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,\n    0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,\n    0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,\n    0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,\n    0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,\n    0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,\n    0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,\n    0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,\n    0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,\n    0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,\n    0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,\n    0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,\n    0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,\n    0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,\n    0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,\n    0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,\n    0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,\n    0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,\n    0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,\n    0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,\n    0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,\n    0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,\n    0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,\n    0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,\n    0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,\n    0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,\n    0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,\n    0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,\n    0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,\n    0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,\n    0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,\n    0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,\n    0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,\n    0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,\n    0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,\n    0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,\n    0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,\n    0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,\n    0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,\n    0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,\n    0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,\n    0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,\n    0xde0506f1},\n   {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,\n    0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,\n    0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,\n    0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,\n    0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,\n    0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,\n    0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,\n    0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,\n    0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,\n    0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,\n    0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,\n    0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,\n    0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,\n    0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,\n    0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,\n    0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,\n    0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,\n    0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,\n    0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,\n    0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,\n    0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,\n    0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,\n    0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,\n    0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,\n    0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,\n    0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,\n    0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,\n    0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,\n    0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,\n    0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,\n    0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,\n    0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,\n    0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,\n    0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,\n    0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,\n    0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,\n    0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,\n    0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,\n    0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,\n    0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,\n    0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,\n    0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,\n    0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,\n    0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,\n    0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,\n    0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,\n    0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,\n    0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,\n    0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,\n    0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,\n    0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,\n    0xbe9834ed},\n   {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,\n    0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,\n    0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,\n    0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,\n    0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,\n    0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,\n    0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,\n    0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,\n    0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,\n    0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,\n    0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,\n    0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,\n    0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,\n    0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,\n    0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,\n    0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,\n    0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,\n    0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,\n    0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,\n    0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,\n    0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,\n    0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,\n    0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,\n    0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,\n    0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,\n    0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,\n    0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,\n    0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,\n    0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,\n    0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,\n    0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,\n    0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,\n    0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,\n    0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,\n    0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,\n    0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,\n    0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,\n    0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,\n    0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,\n    0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,\n    0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,\n    0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,\n    0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,\n    0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,\n    0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,\n    0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,\n    0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,\n    0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,\n    0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,\n    0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,\n    0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,\n    0x9324fd72},\n   {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,\n    0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,\n    0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,\n    0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,\n    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,\n    0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,\n    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,\n    0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,\n    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,\n    0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,\n    0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,\n    0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\n    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,\n    0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,\n    0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,\n    0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,\n    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,\n    0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,\n    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,\n    0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,\n    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,\n    0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,\n    0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,\n    0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,\n    0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,\n    0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,\n    0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,\n    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,\n    0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,\n    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,\n    0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,\n    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,\n    0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,\n    0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,\n    0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\n    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,\n    0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,\n    0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,\n    0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,\n    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,\n    0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,\n    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,\n    0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,\n    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,\n    0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,\n    0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,\n    0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,\n    0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,\n    0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,\n    0x2d02ef8d}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,\n    0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,\n    0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,\n    0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,\n    0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,\n    0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,\n    0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,\n    0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,\n    0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,\n    0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,\n    0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,\n    0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,\n    0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,\n    0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,\n    0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,\n    0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,\n    0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,\n    0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,\n    0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,\n    0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,\n    0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,\n    0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,\n    0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,\n    0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,\n    0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,\n    0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,\n    0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,\n    0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,\n    0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,\n    0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,\n    0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,\n    0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,\n    0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,\n    0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,\n    0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,\n    0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,\n    0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,\n    0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,\n    0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,\n    0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,\n    0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,\n    0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,\n    0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,\n    0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,\n    0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,\n    0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,\n    0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,\n    0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,\n    0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,\n    0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,\n    0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,\n    0x8def022d},\n   {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64,\n    0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1,\n    0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e,\n    0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61,\n    0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82,\n    0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff,\n    0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7,\n    0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da,\n    0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139,\n    0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6,\n    0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89,\n    0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c,\n    0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0,\n    0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d,\n    0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a,\n    0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177,\n    0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de,\n    0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b,\n    0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824,\n    0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e,\n    0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad,\n    0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0,\n    0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d,\n    0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60,\n    0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83,\n    0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822,\n    0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d,\n    0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8,\n    0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171,\n    0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c,\n    0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b,\n    0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6,\n    0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca,\n    0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f,\n    0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430,\n    0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf,\n    0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c,\n    0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51,\n    0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9,\n    0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84,\n    0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67,\n    0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398,\n    0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7,\n    0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62,\n    0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e,\n    0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923,\n    0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4,\n    0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9,\n    0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070,\n    0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5,\n    0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a,\n    0x72fd2493},\n   {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907,\n    0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f,\n    0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a,\n    0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e,\n    0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512,\n    0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14,\n    0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b,\n    0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d,\n    0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731,\n    0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925,\n    0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620,\n    0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28,\n    0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70,\n    0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176,\n    0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d,\n    0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b,\n    0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b,\n    0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63,\n    0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266,\n    0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a,\n    0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446,\n    0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40,\n    0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557,\n    0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51,\n    0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d,\n    0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0,\n    0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5,\n    0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed,\n    0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd,\n    0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb,\n    0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0,\n    0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6,\n    0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de,\n    0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6,\n    0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3,\n    0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7,\n    0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb,\n    0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd,\n    0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92,\n    0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094,\n    0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598,\n    0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c,\n    0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489,\n    0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81,\n    0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9,\n    0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af,\n    0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4,\n    0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2,\n    0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2,\n    0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba,\n    0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf,\n    0xed3498be},\n   {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f,\n    0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d,\n    0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0,\n    0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42,\n    0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95,\n    0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2,\n    0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a,\n    0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d,\n    0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea,\n    0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748,\n    0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5,\n    0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27,\n    0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b,\n    0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac,\n    0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4,\n    0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3,\n    0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44,\n    0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6,\n    0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b,\n    0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329,\n    0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe,\n    0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9,\n    0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1,\n    0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6,\n    0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921,\n    0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555,\n    0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8,\n    0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a,\n    0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd,\n    0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a,\n    0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2,\n    0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5,\n    0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2,\n    0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330,\n    0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad,\n    0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f,\n    0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8,\n    0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef,\n    0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc,\n    0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb,\n    0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c,\n    0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e,\n    0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03,\n    0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1,\n    0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6,\n    0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1,\n    0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9,\n    0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e,\n    0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409,\n    0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb,\n    0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966,\n    0xf10605de}};\n\n#endif\n\n#endif\n\n#if N == 2\n\n#if W == 8\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,\n    0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,\n    0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,\n    0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,\n    0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,\n    0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,\n    0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,\n    0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,\n    0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,\n    0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,\n    0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,\n    0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,\n    0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,\n    0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,\n    0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,\n    0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,\n    0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,\n    0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,\n    0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,\n    0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,\n    0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,\n    0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,\n    0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,\n    0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,\n    0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,\n    0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,\n    0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,\n    0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,\n    0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,\n    0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,\n    0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,\n    0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,\n    0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,\n    0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,\n    0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,\n    0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,\n    0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,\n    0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,\n    0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,\n    0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,\n    0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,\n    0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,\n    0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,\n    0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,\n    0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,\n    0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,\n    0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,\n    0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,\n    0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,\n    0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,\n    0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,\n    0x0d7139d7},\n   {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,\n    0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,\n    0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,\n    0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,\n    0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,\n    0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,\n    0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,\n    0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,\n    0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,\n    0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,\n    0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,\n    0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,\n    0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,\n    0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,\n    0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,\n    0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,\n    0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,\n    0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,\n    0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,\n    0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,\n    0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,\n    0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,\n    0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,\n    0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,\n    0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,\n    0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,\n    0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,\n    0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,\n    0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,\n    0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,\n    0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,\n    0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,\n    0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,\n    0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,\n    0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,\n    0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,\n    0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,\n    0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,\n    0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,\n    0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,\n    0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,\n    0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,\n    0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,\n    0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,\n    0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,\n    0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,\n    0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,\n    0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,\n    0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,\n    0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,\n    0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,\n    0x1c53e98a},\n   {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,\n    0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,\n    0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,\n    0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,\n    0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,\n    0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,\n    0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,\n    0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,\n    0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,\n    0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,\n    0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,\n    0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,\n    0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,\n    0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,\n    0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,\n    0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,\n    0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,\n    0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,\n    0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,\n    0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,\n    0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,\n    0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,\n    0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,\n    0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,\n    0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,\n    0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,\n    0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,\n    0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,\n    0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,\n    0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,\n    0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,\n    0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,\n    0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,\n    0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,\n    0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,\n    0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,\n    0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,\n    0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,\n    0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,\n    0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,\n    0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,\n    0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,\n    0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,\n    0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,\n    0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,\n    0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,\n    0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,\n    0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,\n    0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,\n    0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,\n    0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,\n    0x3f88e851},\n   {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,\n    0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,\n    0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,\n    0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,\n    0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,\n    0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,\n    0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,\n    0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,\n    0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,\n    0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,\n    0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,\n    0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,\n    0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,\n    0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,\n    0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,\n    0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,\n    0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,\n    0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,\n    0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,\n    0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,\n    0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,\n    0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,\n    0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,\n    0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,\n    0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,\n    0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,\n    0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,\n    0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,\n    0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,\n    0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,\n    0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,\n    0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,\n    0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,\n    0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,\n    0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,\n    0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,\n    0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,\n    0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,\n    0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,\n    0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,\n    0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,\n    0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,\n    0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,\n    0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,\n    0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,\n    0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,\n    0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,\n    0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,\n    0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,\n    0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,\n    0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,\n    0x3dee8ca6},\n   {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,\n    0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,\n    0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,\n    0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,\n    0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,\n    0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,\n    0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,\n    0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,\n    0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,\n    0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,\n    0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,\n    0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,\n    0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,\n    0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,\n    0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,\n    0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,\n    0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,\n    0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,\n    0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,\n    0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,\n    0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,\n    0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,\n    0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,\n    0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,\n    0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,\n    0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,\n    0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,\n    0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,\n    0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,\n    0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,\n    0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,\n    0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,\n    0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,\n    0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,\n    0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,\n    0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,\n    0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,\n    0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,\n    0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,\n    0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,\n    0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,\n    0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,\n    0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,\n    0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,\n    0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,\n    0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,\n    0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,\n    0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,\n    0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,\n    0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,\n    0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,\n    0x36197165},\n   {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,\n    0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,\n    0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,\n    0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,\n    0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,\n    0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,\n    0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,\n    0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,\n    0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,\n    0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,\n    0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,\n    0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,\n    0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,\n    0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,\n    0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,\n    0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,\n    0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,\n    0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,\n    0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,\n    0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,\n    0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,\n    0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,\n    0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,\n    0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,\n    0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,\n    0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,\n    0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,\n    0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,\n    0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,\n    0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,\n    0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,\n    0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,\n    0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,\n    0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,\n    0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,\n    0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,\n    0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,\n    0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,\n    0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,\n    0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,\n    0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,\n    0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,\n    0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,\n    0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,\n    0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,\n    0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,\n    0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,\n    0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,\n    0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,\n    0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,\n    0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,\n    0x1a3b93aa},\n   {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,\n    0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,\n    0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,\n    0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,\n    0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,\n    0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,\n    0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,\n    0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,\n    0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,\n    0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,\n    0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,\n    0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,\n    0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,\n    0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,\n    0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,\n    0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,\n    0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,\n    0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,\n    0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,\n    0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,\n    0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,\n    0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,\n    0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,\n    0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,\n    0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,\n    0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,\n    0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,\n    0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,\n    0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,\n    0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,\n    0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,\n    0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,\n    0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,\n    0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,\n    0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,\n    0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,\n    0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,\n    0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,\n    0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,\n    0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,\n    0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,\n    0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,\n    0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,\n    0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,\n    0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,\n    0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,\n    0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,\n    0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,\n    0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,\n    0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,\n    0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,\n    0xe147d714},\n   {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,\n    0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,\n    0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,\n    0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,\n    0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,\n    0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,\n    0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,\n    0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,\n    0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,\n    0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,\n    0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,\n    0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,\n    0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,\n    0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,\n    0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,\n    0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,\n    0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,\n    0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,\n    0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,\n    0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,\n    0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,\n    0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,\n    0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,\n    0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,\n    0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,\n    0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,\n    0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,\n    0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,\n    0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,\n    0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,\n    0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,\n    0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,\n    0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,\n    0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,\n    0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,\n    0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,\n    0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,\n    0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,\n    0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,\n    0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,\n    0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,\n    0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,\n    0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,\n    0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,\n    0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,\n    0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,\n    0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,\n    0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,\n    0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,\n    0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,\n    0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,\n    0x494f0c4b}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000,\n    0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000,\n    0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000,\n    0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000,\n    0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000,\n    0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000,\n    0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000,\n    0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000,\n    0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000,\n    0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000,\n    0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000,\n    0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000,\n    0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000,\n    0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000,\n    0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000,\n    0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000,\n    0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000,\n    0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000,\n    0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000,\n    0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000,\n    0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000,\n    0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000,\n    0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000,\n    0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000,\n    0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000,\n    0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000,\n    0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000,\n    0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000,\n    0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000,\n    0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000,\n    0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000,\n    0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000,\n    0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000,\n    0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000,\n    0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000,\n    0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000,\n    0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000,\n    0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000,\n    0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000,\n    0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000,\n    0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000,\n    0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000,\n    0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000,\n    0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000,\n    0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000,\n    0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000,\n    0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000,\n    0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000,\n    0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000,\n    0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000,\n    0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000,\n    0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000,\n    0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000,\n    0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000,\n    0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000,\n    0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000,\n    0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000,\n    0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000,\n    0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000,\n    0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000,\n    0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000,\n    0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000,\n    0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000,\n    0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000,\n    0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000,\n    0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000,\n    0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000,\n    0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000,\n    0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000,\n    0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000,\n    0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000,\n    0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000,\n    0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000,\n    0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000,\n    0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000,\n    0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000,\n    0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000,\n    0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000,\n    0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000,\n    0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000,\n    0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000,\n    0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000,\n    0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000,\n    0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000,\n    0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000,\n    0x4b0c4f4900000000},\n   {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000,\n    0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000,\n    0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000,\n    0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000,\n    0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000,\n    0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000,\n    0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000,\n    0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000,\n    0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000,\n    0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000,\n    0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000,\n    0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000,\n    0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000,\n    0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000,\n    0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000,\n    0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000,\n    0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000,\n    0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000,\n    0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000,\n    0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000,\n    0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000,\n    0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000,\n    0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000,\n    0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000,\n    0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000,\n    0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000,\n    0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000,\n    0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000,\n    0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000,\n    0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000,\n    0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000,\n    0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000,\n    0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000,\n    0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000,\n    0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000,\n    0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000,\n    0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000,\n    0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000,\n    0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000,\n    0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000,\n    0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000,\n    0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000,\n    0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000,\n    0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000,\n    0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000,\n    0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000,\n    0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000,\n    0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000,\n    0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000,\n    0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000,\n    0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000,\n    0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000,\n    0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000,\n    0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000,\n    0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000,\n    0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000,\n    0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000,\n    0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000,\n    0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000,\n    0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000,\n    0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000,\n    0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000,\n    0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000,\n    0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000,\n    0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000,\n    0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000,\n    0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000,\n    0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000,\n    0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000,\n    0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000,\n    0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000,\n    0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000,\n    0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000,\n    0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000,\n    0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000,\n    0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000,\n    0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000,\n    0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000,\n    0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000,\n    0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000,\n    0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000,\n    0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000,\n    0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000,\n    0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000,\n    0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000,\n    0x14d747e100000000},\n   {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000,\n    0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000,\n    0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000,\n    0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000,\n    0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000,\n    0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000,\n    0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000,\n    0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000,\n    0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000,\n    0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000,\n    0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000,\n    0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000,\n    0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000,\n    0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000,\n    0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000,\n    0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000,\n    0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000,\n    0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000,\n    0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000,\n    0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000,\n    0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000,\n    0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000,\n    0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000,\n    0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000,\n    0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000,\n    0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000,\n    0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000,\n    0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000,\n    0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000,\n    0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000,\n    0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000,\n    0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000,\n    0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000,\n    0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000,\n    0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000,\n    0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000,\n    0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000,\n    0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000,\n    0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000,\n    0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000,\n    0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000,\n    0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000,\n    0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000,\n    0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000,\n    0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000,\n    0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000,\n    0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000,\n    0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000,\n    0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000,\n    0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000,\n    0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000,\n    0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000,\n    0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000,\n    0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000,\n    0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000,\n    0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000,\n    0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000,\n    0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000,\n    0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000,\n    0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000,\n    0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000,\n    0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000,\n    0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000,\n    0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000,\n    0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000,\n    0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000,\n    0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000,\n    0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000,\n    0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000,\n    0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000,\n    0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000,\n    0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000,\n    0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000,\n    0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000,\n    0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000,\n    0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000,\n    0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000,\n    0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000,\n    0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000,\n    0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000,\n    0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000,\n    0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000,\n    0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000,\n    0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000,\n    0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000,\n    0xaa933b1a00000000},\n   {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000,\n    0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000,\n    0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000,\n    0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000,\n    0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000,\n    0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000,\n    0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000,\n    0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000,\n    0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000,\n    0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000,\n    0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000,\n    0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000,\n    0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000,\n    0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000,\n    0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000,\n    0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000,\n    0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000,\n    0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000,\n    0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000,\n    0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000,\n    0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000,\n    0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000,\n    0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000,\n    0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000,\n    0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000,\n    0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000,\n    0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000,\n    0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000,\n    0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000,\n    0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000,\n    0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000,\n    0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000,\n    0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000,\n    0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000,\n    0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000,\n    0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000,\n    0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000,\n    0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000,\n    0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000,\n    0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000,\n    0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000,\n    0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000,\n    0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000,\n    0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000,\n    0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000,\n    0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000,\n    0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000,\n    0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000,\n    0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000,\n    0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000,\n    0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000,\n    0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000,\n    0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000,\n    0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000,\n    0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000,\n    0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000,\n    0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000,\n    0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000,\n    0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000,\n    0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000,\n    0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000,\n    0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000,\n    0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000,\n    0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000,\n    0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000,\n    0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000,\n    0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000,\n    0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000,\n    0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000,\n    0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000,\n    0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000,\n    0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000,\n    0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000,\n    0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000,\n    0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000,\n    0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000,\n    0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000,\n    0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000,\n    0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000,\n    0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000,\n    0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000,\n    0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000,\n    0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000,\n    0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000,\n    0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000,\n    0x6571193600000000},\n   {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000,\n    0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000,\n    0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000,\n    0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000,\n    0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000,\n    0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000,\n    0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000,\n    0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000,\n    0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000,\n    0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000,\n    0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000,\n    0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000,\n    0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000,\n    0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000,\n    0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000,\n    0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000,\n    0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000,\n    0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000,\n    0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000,\n    0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000,\n    0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000,\n    0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000,\n    0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000,\n    0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000,\n    0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000,\n    0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000,\n    0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000,\n    0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000,\n    0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000,\n    0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000,\n    0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000,\n    0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000,\n    0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000,\n    0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000,\n    0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000,\n    0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000,\n    0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000,\n    0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000,\n    0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000,\n    0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000,\n    0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000,\n    0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000,\n    0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000,\n    0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000,\n    0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000,\n    0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000,\n    0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000,\n    0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000,\n    0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000,\n    0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000,\n    0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000,\n    0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000,\n    0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000,\n    0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000,\n    0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000,\n    0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000,\n    0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000,\n    0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000,\n    0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000,\n    0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000,\n    0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000,\n    0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000,\n    0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000,\n    0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000,\n    0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000,\n    0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000,\n    0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000,\n    0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000,\n    0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000,\n    0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000,\n    0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000,\n    0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000,\n    0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000,\n    0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000,\n    0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000,\n    0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000,\n    0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000,\n    0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000,\n    0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000,\n    0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000,\n    0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000,\n    0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000,\n    0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000,\n    0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000,\n    0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000,\n    0xa68cee3d00000000},\n   {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000,\n    0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000,\n    0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000,\n    0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000,\n    0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000,\n    0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000,\n    0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000,\n    0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000,\n    0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000,\n    0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000,\n    0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000,\n    0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000,\n    0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000,\n    0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000,\n    0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000,\n    0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000,\n    0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000,\n    0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000,\n    0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000,\n    0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000,\n    0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000,\n    0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000,\n    0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000,\n    0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000,\n    0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000,\n    0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000,\n    0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000,\n    0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000,\n    0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000,\n    0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000,\n    0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000,\n    0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000,\n    0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000,\n    0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000,\n    0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000,\n    0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000,\n    0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000,\n    0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000,\n    0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000,\n    0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000,\n    0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000,\n    0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000,\n    0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000,\n    0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000,\n    0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000,\n    0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000,\n    0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000,\n    0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000,\n    0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000,\n    0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000,\n    0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000,\n    0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000,\n    0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000,\n    0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000,\n    0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000,\n    0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000,\n    0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000,\n    0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000,\n    0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000,\n    0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000,\n    0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000,\n    0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000,\n    0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000,\n    0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000,\n    0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000,\n    0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000,\n    0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000,\n    0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000,\n    0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000,\n    0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000,\n    0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000,\n    0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000,\n    0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000,\n    0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000,\n    0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000,\n    0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000,\n    0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000,\n    0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000,\n    0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000,\n    0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000,\n    0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000,\n    0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000,\n    0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000,\n    0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000,\n    0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000,\n    0x51e8883f00000000},\n   {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000,\n    0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000,\n    0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000,\n    0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000,\n    0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000,\n    0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000,\n    0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000,\n    0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000,\n    0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000,\n    0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000,\n    0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000,\n    0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000,\n    0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000,\n    0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000,\n    0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000,\n    0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000,\n    0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000,\n    0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000,\n    0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000,\n    0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000,\n    0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000,\n    0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000,\n    0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000,\n    0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000,\n    0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000,\n    0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000,\n    0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000,\n    0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000,\n    0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000,\n    0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000,\n    0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000,\n    0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000,\n    0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000,\n    0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000,\n    0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000,\n    0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000,\n    0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000,\n    0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000,\n    0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000,\n    0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000,\n    0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000,\n    0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000,\n    0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000,\n    0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000,\n    0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000,\n    0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000,\n    0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000,\n    0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000,\n    0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000,\n    0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000,\n    0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000,\n    0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000,\n    0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000,\n    0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000,\n    0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000,\n    0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000,\n    0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000,\n    0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000,\n    0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000,\n    0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000,\n    0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000,\n    0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000,\n    0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000,\n    0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000,\n    0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000,\n    0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000,\n    0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000,\n    0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000,\n    0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000,\n    0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000,\n    0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000,\n    0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000,\n    0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000,\n    0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000,\n    0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000,\n    0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000,\n    0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000,\n    0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000,\n    0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000,\n    0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000,\n    0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000,\n    0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000,\n    0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000,\n    0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000,\n    0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000,\n    0x8ae9531c00000000},\n   {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000,\n    0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000,\n    0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000,\n    0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000,\n    0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000,\n    0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000,\n    0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000,\n    0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000,\n    0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000,\n    0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000,\n    0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000,\n    0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000,\n    0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000,\n    0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000,\n    0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000,\n    0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000,\n    0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000,\n    0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000,\n    0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000,\n    0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000,\n    0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000,\n    0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000,\n    0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000,\n    0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000,\n    0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000,\n    0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000,\n    0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000,\n    0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000,\n    0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000,\n    0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000,\n    0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000,\n    0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000,\n    0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000,\n    0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000,\n    0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000,\n    0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000,\n    0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000,\n    0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000,\n    0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000,\n    0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000,\n    0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000,\n    0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000,\n    0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000,\n    0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000,\n    0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000,\n    0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000,\n    0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000,\n    0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000,\n    0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000,\n    0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000,\n    0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000,\n    0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000,\n    0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000,\n    0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000,\n    0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000,\n    0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000,\n    0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000,\n    0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000,\n    0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000,\n    0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000,\n    0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000,\n    0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000,\n    0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000,\n    0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000,\n    0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000,\n    0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000,\n    0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000,\n    0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000,\n    0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000,\n    0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000,\n    0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000,\n    0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000,\n    0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000,\n    0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000,\n    0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000,\n    0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000,\n    0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000,\n    0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000,\n    0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000,\n    0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000,\n    0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000,\n    0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000,\n    0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000,\n    0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000,\n    0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000,\n    0xd739710d00000000}};\n\n#else /* W == 4 */\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,\n    0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,\n    0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,\n    0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,\n    0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,\n    0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,\n    0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,\n    0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,\n    0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,\n    0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,\n    0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,\n    0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,\n    0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,\n    0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,\n    0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,\n    0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,\n    0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,\n    0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,\n    0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,\n    0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,\n    0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,\n    0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,\n    0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,\n    0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,\n    0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,\n    0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,\n    0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,\n    0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,\n    0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,\n    0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,\n    0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,\n    0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,\n    0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,\n    0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,\n    0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,\n    0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,\n    0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,\n    0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,\n    0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,\n    0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,\n    0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,\n    0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,\n    0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,\n    0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,\n    0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,\n    0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,\n    0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,\n    0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,\n    0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,\n    0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,\n    0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,\n    0x264b06e6},\n   {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,\n    0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,\n    0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,\n    0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,\n    0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,\n    0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,\n    0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,\n    0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,\n    0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,\n    0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,\n    0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,\n    0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,\n    0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,\n    0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,\n    0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,\n    0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,\n    0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,\n    0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,\n    0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,\n    0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,\n    0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,\n    0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,\n    0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,\n    0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,\n    0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,\n    0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,\n    0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,\n    0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,\n    0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,\n    0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,\n    0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,\n    0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,\n    0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,\n    0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,\n    0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,\n    0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,\n    0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,\n    0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,\n    0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,\n    0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,\n    0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,\n    0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,\n    0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,\n    0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,\n    0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,\n    0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,\n    0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,\n    0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,\n    0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,\n    0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,\n    0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,\n    0x92364a30},\n   {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,\n    0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,\n    0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,\n    0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,\n    0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,\n    0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,\n    0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,\n    0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,\n    0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,\n    0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,\n    0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,\n    0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,\n    0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,\n    0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,\n    0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,\n    0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,\n    0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,\n    0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,\n    0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,\n    0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,\n    0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,\n    0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,\n    0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,\n    0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,\n    0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,\n    0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,\n    0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,\n    0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,\n    0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,\n    0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,\n    0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,\n    0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,\n    0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,\n    0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,\n    0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,\n    0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,\n    0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,\n    0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,\n    0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,\n    0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,\n    0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,\n    0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,\n    0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,\n    0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,\n    0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,\n    0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,\n    0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,\n    0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,\n    0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,\n    0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,\n    0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,\n    0xe4c4abcc},\n   {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,\n    0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,\n    0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,\n    0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,\n    0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,\n    0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,\n    0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,\n    0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,\n    0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,\n    0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,\n    0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,\n    0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,\n    0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,\n    0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,\n    0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,\n    0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,\n    0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,\n    0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,\n    0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,\n    0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,\n    0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,\n    0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,\n    0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,\n    0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,\n    0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,\n    0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,\n    0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,\n    0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,\n    0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,\n    0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,\n    0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,\n    0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,\n    0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,\n    0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,\n    0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,\n    0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,\n    0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,\n    0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,\n    0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,\n    0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,\n    0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,\n    0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,\n    0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,\n    0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,\n    0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,\n    0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,\n    0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,\n    0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,\n    0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,\n    0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,\n    0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,\n    0xca64c78c}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5,\n    0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d,\n    0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf,\n    0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027,\n    0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050,\n    0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098,\n    0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb,\n    0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173,\n    0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104,\n    0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c,\n    0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e,\n    0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6,\n    0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358,\n    0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390,\n    0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312,\n    0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da,\n    0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd,\n    0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335,\n    0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387,\n    0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de,\n    0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9,\n    0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261,\n    0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283,\n    0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b,\n    0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c,\n    0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c,\n    0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e,\n    0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6,\n    0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1,\n    0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619,\n    0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b,\n    0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653,\n    0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785,\n    0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d,\n    0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf,\n    0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757,\n    0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720,\n    0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8,\n    0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593,\n    0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b,\n    0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c,\n    0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4,\n    0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506,\n    0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe,\n    0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428,\n    0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0,\n    0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462,\n    0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa,\n    0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd,\n    0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445,\n    0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7,\n    0x8cc764ca},\n   {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b,\n    0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27,\n    0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a,\n    0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285,\n    0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef,\n    0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf,\n    0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a,\n    0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a,\n    0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70,\n    0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf,\n    0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2,\n    0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e,\n    0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f,\n    0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f,\n    0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae,\n    0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe,\n    0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97,\n    0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b,\n    0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436,\n    0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e,\n    0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4,\n    0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4,\n    0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46,\n    0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716,\n    0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c,\n    0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5,\n    0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8,\n    0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774,\n    0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d,\n    0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d,\n    0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc,\n    0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec,\n    0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82,\n    0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e,\n    0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623,\n    0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c,\n    0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6,\n    0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6,\n    0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c,\n    0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c,\n    0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66,\n    0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9,\n    0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4,\n    0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978,\n    0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416,\n    0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946,\n    0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7,\n    0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7,\n    0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e,\n    0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32,\n    0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f,\n    0xccabc4e4},\n   {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4,\n    0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895,\n    0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50,\n    0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656,\n    0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154,\n    0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906,\n    0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258,\n    0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a,\n    0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08,\n    0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e,\n    0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb,\n    0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa,\n    0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44,\n    0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316,\n    0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0,\n    0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2,\n    0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7,\n    0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6,\n    0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73,\n    0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba,\n    0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8,\n    0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea,\n    0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b,\n    0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29,\n    0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b,\n    0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e,\n    0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb,\n    0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a,\n    0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef,\n    0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd,\n    0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b,\n    0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019,\n    0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3,\n    0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2,\n    0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417,\n    0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11,\n    0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13,\n    0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241,\n    0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b,\n    0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09,\n    0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b,\n    0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d,\n    0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8,\n    0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9,\n    0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003,\n    0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851,\n    0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7,\n    0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5,\n    0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190,\n    0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1,\n    0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134,\n    0x304a3692},\n   {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84,\n    0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f,\n    0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15,\n    0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2,\n    0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf,\n    0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7,\n    0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb,\n    0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3,\n    0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae,\n    0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749,\n    0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243,\n    0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8,\n    0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29,\n    0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61,\n    0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8,\n    0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0,\n    0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1,\n    0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a,\n    0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40,\n    0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e,\n    0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03,\n    0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b,\n    0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee,\n    0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6,\n    0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb,\n    0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f,\n    0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495,\n    0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e,\n    0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f,\n    0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067,\n    0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be,\n    0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6,\n    0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e,\n    0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5,\n    0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf,\n    0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958,\n    0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305,\n    0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d,\n    0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338,\n    0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370,\n    0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d,\n    0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca,\n    0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0,\n    0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b,\n    0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083,\n    0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb,\n    0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012,\n    0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a,\n    0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b,\n    0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0,\n    0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea,\n    0xe6064b26}};\n\n#endif\n\n#endif\n\n#if N == 3\n\n#if W == 8\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,\n    0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,\n    0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,\n    0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,\n    0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,\n    0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,\n    0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,\n    0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,\n    0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,\n    0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,\n    0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,\n    0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,\n    0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,\n    0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,\n    0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,\n    0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,\n    0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,\n    0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,\n    0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,\n    0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,\n    0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,\n    0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,\n    0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,\n    0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,\n    0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,\n    0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,\n    0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,\n    0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,\n    0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,\n    0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,\n    0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,\n    0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,\n    0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,\n    0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,\n    0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,\n    0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,\n    0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,\n    0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,\n    0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,\n    0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,\n    0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,\n    0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,\n    0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,\n    0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,\n    0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,\n    0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,\n    0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,\n    0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,\n    0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,\n    0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,\n    0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,\n    0x09cd8551},\n   {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,\n    0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,\n    0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,\n    0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,\n    0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,\n    0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,\n    0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,\n    0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,\n    0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,\n    0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,\n    0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,\n    0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,\n    0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,\n    0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,\n    0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,\n    0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,\n    0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,\n    0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,\n    0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,\n    0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,\n    0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,\n    0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,\n    0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,\n    0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,\n    0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,\n    0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,\n    0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,\n    0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,\n    0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,\n    0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,\n    0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,\n    0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,\n    0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,\n    0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,\n    0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,\n    0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,\n    0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,\n    0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,\n    0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,\n    0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,\n    0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,\n    0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,\n    0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,\n    0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,\n    0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,\n    0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,\n    0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,\n    0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,\n    0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,\n    0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,\n    0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,\n    0x7bc97a0c},\n   {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,\n    0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,\n    0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,\n    0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,\n    0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,\n    0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,\n    0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,\n    0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,\n    0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,\n    0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,\n    0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,\n    0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,\n    0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,\n    0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,\n    0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,\n    0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,\n    0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,\n    0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,\n    0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,\n    0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,\n    0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,\n    0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,\n    0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,\n    0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,\n    0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,\n    0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,\n    0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,\n    0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,\n    0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,\n    0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,\n    0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,\n    0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,\n    0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,\n    0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,\n    0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,\n    0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,\n    0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,\n    0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,\n    0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,\n    0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,\n    0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,\n    0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,\n    0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,\n    0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,\n    0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,\n    0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,\n    0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,\n    0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,\n    0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,\n    0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,\n    0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,\n    0x7851a2ca},\n   {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,\n    0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,\n    0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,\n    0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,\n    0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,\n    0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,\n    0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,\n    0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,\n    0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,\n    0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,\n    0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,\n    0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,\n    0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,\n    0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,\n    0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,\n    0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,\n    0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,\n    0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,\n    0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,\n    0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,\n    0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,\n    0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,\n    0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,\n    0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,\n    0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,\n    0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,\n    0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,\n    0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,\n    0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,\n    0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,\n    0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,\n    0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,\n    0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,\n    0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,\n    0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,\n    0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,\n    0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,\n    0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,\n    0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,\n    0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,\n    0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,\n    0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,\n    0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,\n    0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,\n    0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,\n    0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,\n    0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,\n    0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,\n    0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,\n    0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,\n    0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,\n    0x566b6848},\n   {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,\n    0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,\n    0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,\n    0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,\n    0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,\n    0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,\n    0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,\n    0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,\n    0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,\n    0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,\n    0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,\n    0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,\n    0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,\n    0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,\n    0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,\n    0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,\n    0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,\n    0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,\n    0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,\n    0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,\n    0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,\n    0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,\n    0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,\n    0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,\n    0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,\n    0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,\n    0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,\n    0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,\n    0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,\n    0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,\n    0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,\n    0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,\n    0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,\n    0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,\n    0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,\n    0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,\n    0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,\n    0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,\n    0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,\n    0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,\n    0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,\n    0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,\n    0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,\n    0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,\n    0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,\n    0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,\n    0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,\n    0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,\n    0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,\n    0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,\n    0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,\n    0xd8ac6b35},\n   {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,\n    0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,\n    0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,\n    0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,\n    0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,\n    0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,\n    0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,\n    0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,\n    0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,\n    0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,\n    0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,\n    0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,\n    0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,\n    0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,\n    0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,\n    0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,\n    0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,\n    0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,\n    0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,\n    0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,\n    0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,\n    0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,\n    0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,\n    0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,\n    0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,\n    0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,\n    0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,\n    0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,\n    0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,\n    0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,\n    0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,\n    0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,\n    0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,\n    0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,\n    0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,\n    0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,\n    0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,\n    0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,\n    0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,\n    0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,\n    0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,\n    0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,\n    0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,\n    0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,\n    0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,\n    0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,\n    0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,\n    0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,\n    0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,\n    0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,\n    0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,\n    0xa140efa8},\n   {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,\n    0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,\n    0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,\n    0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,\n    0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,\n    0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,\n    0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,\n    0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,\n    0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,\n    0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,\n    0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,\n    0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,\n    0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,\n    0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,\n    0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,\n    0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,\n    0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,\n    0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,\n    0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,\n    0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,\n    0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,\n    0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,\n    0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,\n    0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,\n    0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,\n    0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,\n    0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,\n    0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,\n    0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,\n    0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,\n    0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,\n    0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,\n    0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,\n    0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,\n    0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,\n    0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,\n    0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,\n    0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,\n    0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,\n    0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,\n    0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,\n    0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,\n    0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,\n    0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,\n    0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,\n    0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,\n    0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,\n    0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,\n    0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,\n    0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,\n    0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,\n    0x917cd6a1},\n   {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,\n    0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,\n    0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,\n    0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,\n    0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,\n    0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,\n    0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,\n    0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,\n    0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,\n    0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,\n    0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,\n    0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,\n    0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,\n    0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,\n    0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,\n    0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,\n    0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,\n    0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,\n    0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,\n    0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,\n    0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,\n    0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,\n    0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,\n    0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,\n    0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,\n    0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,\n    0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,\n    0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,\n    0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,\n    0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,\n    0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,\n    0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,\n    0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,\n    0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,\n    0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,\n    0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,\n    0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,\n    0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,\n    0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,\n    0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,\n    0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,\n    0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,\n    0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,\n    0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,\n    0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,\n    0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,\n    0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,\n    0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,\n    0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,\n    0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,\n    0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,\n    0x18ba364e}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000,\n    0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000,\n    0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000,\n    0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000,\n    0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000,\n    0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000,\n    0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000,\n    0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000,\n    0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000,\n    0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000,\n    0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000,\n    0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000,\n    0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000,\n    0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000,\n    0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000,\n    0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000,\n    0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000,\n    0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000,\n    0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000,\n    0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000,\n    0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000,\n    0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000,\n    0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000,\n    0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000,\n    0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000,\n    0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000,\n    0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000,\n    0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000,\n    0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000,\n    0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000,\n    0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000,\n    0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000,\n    0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000,\n    0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000,\n    0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000,\n    0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000,\n    0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000,\n    0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000,\n    0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000,\n    0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000,\n    0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000,\n    0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000,\n    0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000,\n    0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000,\n    0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000,\n    0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000,\n    0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000,\n    0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000,\n    0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000,\n    0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000,\n    0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000,\n    0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000,\n    0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000,\n    0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000,\n    0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000,\n    0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000,\n    0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000,\n    0x08eda52100000000, 0x4391370100000000, 0x005a918600000000,\n    0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000,\n    0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000,\n    0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000,\n    0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000,\n    0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000,\n    0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000,\n    0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000,\n    0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000,\n    0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000,\n    0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000,\n    0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000,\n    0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000,\n    0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000,\n    0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000,\n    0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000,\n    0x7b23114500000000, 0x305f836500000000, 0x739425e200000000,\n    0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000,\n    0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000,\n    0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000,\n    0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000,\n    0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000,\n    0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000,\n    0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000,\n    0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000,\n    0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000,\n    0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000,\n    0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000,\n    0x4e36ba1800000000},\n   {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000,\n    0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000,\n    0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000,\n    0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000,\n    0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000,\n    0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000,\n    0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000,\n    0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000,\n    0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000,\n    0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000,\n    0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000,\n    0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000,\n    0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000,\n    0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000,\n    0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000,\n    0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000,\n    0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000,\n    0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000,\n    0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000,\n    0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000,\n    0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000,\n    0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000,\n    0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000,\n    0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000,\n    0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000,\n    0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000,\n    0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000,\n    0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000,\n    0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000,\n    0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000,\n    0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000,\n    0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000,\n    0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000,\n    0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000,\n    0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000,\n    0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000,\n    0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000,\n    0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000,\n    0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000,\n    0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000,\n    0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000,\n    0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000,\n    0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000,\n    0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000,\n    0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000,\n    0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000,\n    0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000,\n    0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000,\n    0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000,\n    0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000,\n    0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000,\n    0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000,\n    0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000,\n    0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000,\n    0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000,\n    0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000,\n    0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000,\n    0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000,\n    0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000,\n    0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000,\n    0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000,\n    0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000,\n    0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000,\n    0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000,\n    0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000,\n    0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000,\n    0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000,\n    0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000,\n    0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000,\n    0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000,\n    0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000,\n    0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000,\n    0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000,\n    0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000,\n    0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000,\n    0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000,\n    0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000,\n    0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000,\n    0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000,\n    0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000,\n    0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000,\n    0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000,\n    0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000,\n    0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000,\n    0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000,\n    0xa1d67c9100000000},\n   {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000,\n    0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000,\n    0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000,\n    0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000,\n    0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000,\n    0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000,\n    0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000,\n    0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000,\n    0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000,\n    0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000,\n    0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000,\n    0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000,\n    0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000,\n    0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000,\n    0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000,\n    0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000,\n    0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000,\n    0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000,\n    0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000,\n    0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000,\n    0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000,\n    0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000,\n    0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000,\n    0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000,\n    0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000,\n    0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000,\n    0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000,\n    0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000,\n    0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000,\n    0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000,\n    0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000,\n    0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000,\n    0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000,\n    0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000,\n    0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000,\n    0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000,\n    0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000,\n    0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000,\n    0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000,\n    0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000,\n    0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000,\n    0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000,\n    0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000,\n    0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000,\n    0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000,\n    0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000,\n    0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000,\n    0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000,\n    0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000,\n    0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000,\n    0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000,\n    0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000,\n    0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000,\n    0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000,\n    0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000,\n    0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000,\n    0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000,\n    0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000,\n    0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000,\n    0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000,\n    0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000,\n    0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000,\n    0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000,\n    0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000,\n    0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000,\n    0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000,\n    0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000,\n    0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000,\n    0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000,\n    0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000,\n    0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000,\n    0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000,\n    0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000,\n    0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000,\n    0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000,\n    0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000,\n    0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000,\n    0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000,\n    0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000,\n    0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000,\n    0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000,\n    0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000,\n    0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000,\n    0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000,\n    0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000,\n    0xa8ef40a100000000},\n   {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000,\n    0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000,\n    0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000,\n    0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000,\n    0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000,\n    0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000,\n    0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000,\n    0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000,\n    0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000,\n    0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000,\n    0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000,\n    0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000,\n    0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000,\n    0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000,\n    0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000,\n    0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000,\n    0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000,\n    0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000,\n    0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000,\n    0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000,\n    0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000,\n    0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000,\n    0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000,\n    0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000,\n    0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000,\n    0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000,\n    0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000,\n    0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000,\n    0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000,\n    0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000,\n    0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000,\n    0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000,\n    0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000,\n    0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000,\n    0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000,\n    0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000,\n    0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000,\n    0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000,\n    0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000,\n    0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000,\n    0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000,\n    0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000,\n    0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000,\n    0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000,\n    0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000,\n    0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000,\n    0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000,\n    0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000,\n    0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000,\n    0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000,\n    0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000,\n    0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000,\n    0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000,\n    0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000,\n    0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000,\n    0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000,\n    0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000,\n    0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000,\n    0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000,\n    0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000,\n    0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000,\n    0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000,\n    0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000,\n    0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000,\n    0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000,\n    0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000,\n    0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000,\n    0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000,\n    0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000,\n    0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000,\n    0x933d017400000000, 0xd506661100000000, 0x46a022f000000000,\n    0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000,\n    0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000,\n    0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000,\n    0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000,\n    0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000,\n    0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000,\n    0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000,\n    0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000,\n    0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000,\n    0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000,\n    0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000,\n    0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000,\n    0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000,\n    0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000,\n    0x356bacd800000000},\n   {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000,\n    0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000,\n    0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000,\n    0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000,\n    0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000,\n    0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000,\n    0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000,\n    0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000,\n    0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000,\n    0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000,\n    0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000,\n    0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000,\n    0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000,\n    0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000,\n    0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000,\n    0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000,\n    0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000,\n    0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000,\n    0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000,\n    0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000,\n    0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000,\n    0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000,\n    0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000,\n    0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000,\n    0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000,\n    0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000,\n    0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000,\n    0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000,\n    0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000,\n    0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000,\n    0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000,\n    0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000,\n    0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000,\n    0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000,\n    0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000,\n    0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000,\n    0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000,\n    0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000,\n    0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000,\n    0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000,\n    0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000,\n    0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000,\n    0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000,\n    0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000,\n    0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000,\n    0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000,\n    0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000,\n    0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000,\n    0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000,\n    0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000,\n    0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000,\n    0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000,\n    0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000,\n    0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000,\n    0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000,\n    0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000,\n    0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000,\n    0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000,\n    0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000,\n    0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000,\n    0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000,\n    0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000,\n    0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000,\n    0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000,\n    0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000,\n    0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000,\n    0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000,\n    0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000,\n    0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000,\n    0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000,\n    0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000,\n    0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000,\n    0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000,\n    0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000,\n    0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000,\n    0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000,\n    0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000,\n    0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000,\n    0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000,\n    0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000,\n    0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000,\n    0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000,\n    0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000,\n    0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000,\n    0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000,\n    0x48686b5600000000},\n   {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000,\n    0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000,\n    0x805af17200000000, 0x403ed96500000000, 0x002643b900000000,\n    0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000,\n    0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000,\n    0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000,\n    0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000,\n    0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000,\n    0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000,\n    0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000,\n    0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000,\n    0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000,\n    0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000,\n    0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000,\n    0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000,\n    0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000,\n    0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000,\n    0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000,\n    0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000,\n    0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000,\n    0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000,\n    0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000,\n    0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000,\n    0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000,\n    0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000,\n    0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000,\n    0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000,\n    0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000,\n    0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000,\n    0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000,\n    0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000,\n    0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000,\n    0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000,\n    0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000,\n    0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000,\n    0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000,\n    0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000,\n    0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000,\n    0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000,\n    0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000,\n    0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000,\n    0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000,\n    0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000,\n    0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000,\n    0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000,\n    0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000,\n    0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000,\n    0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000,\n    0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000,\n    0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000,\n    0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000,\n    0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000,\n    0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000,\n    0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000,\n    0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000,\n    0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000,\n    0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000,\n    0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000,\n    0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000,\n    0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000,\n    0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000,\n    0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000,\n    0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000,\n    0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000,\n    0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000,\n    0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000,\n    0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000,\n    0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000,\n    0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000,\n    0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000,\n    0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000,\n    0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000,\n    0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000,\n    0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000,\n    0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000,\n    0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000,\n    0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000,\n    0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000,\n    0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000,\n    0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000,\n    0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000,\n    0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000,\n    0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000,\n    0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000,\n    0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000,\n    0xcaa2517800000000},\n   {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000,\n    0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000,\n    0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000,\n    0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000,\n    0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000,\n    0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000,\n    0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000,\n    0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000,\n    0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000,\n    0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000,\n    0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000,\n    0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000,\n    0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000,\n    0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000,\n    0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000,\n    0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000,\n    0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000,\n    0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000,\n    0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000,\n    0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000,\n    0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000,\n    0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000,\n    0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000,\n    0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000,\n    0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000,\n    0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000,\n    0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000,\n    0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000,\n    0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000,\n    0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000,\n    0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000,\n    0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000,\n    0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000,\n    0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000,\n    0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000,\n    0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000,\n    0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000,\n    0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000,\n    0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000,\n    0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000,\n    0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000,\n    0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000,\n    0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000,\n    0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000,\n    0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000,\n    0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000,\n    0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000,\n    0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000,\n    0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000,\n    0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000,\n    0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000,\n    0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000,\n    0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000,\n    0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000,\n    0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000,\n    0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000,\n    0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000,\n    0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000,\n    0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000,\n    0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000,\n    0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000,\n    0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000,\n    0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000,\n    0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000,\n    0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000,\n    0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000,\n    0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000,\n    0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000,\n    0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000,\n    0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000,\n    0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000,\n    0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000,\n    0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000,\n    0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000,\n    0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000,\n    0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000,\n    0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000,\n    0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000,\n    0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000,\n    0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000,\n    0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000,\n    0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000,\n    0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000,\n    0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000,\n    0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000,\n    0x0c7ac97b00000000},\n   {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000,\n    0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000,\n    0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000,\n    0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000,\n    0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000,\n    0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000,\n    0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000,\n    0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000,\n    0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000,\n    0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000,\n    0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000,\n    0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000,\n    0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000,\n    0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000,\n    0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000,\n    0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000,\n    0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000,\n    0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000,\n    0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000,\n    0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000,\n    0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000,\n    0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000,\n    0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000,\n    0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000,\n    0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000,\n    0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000,\n    0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000,\n    0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000,\n    0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000,\n    0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000,\n    0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000,\n    0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000,\n    0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000,\n    0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000,\n    0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000,\n    0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000,\n    0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000,\n    0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000,\n    0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000,\n    0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000,\n    0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000,\n    0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000,\n    0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000,\n    0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000,\n    0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000,\n    0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000,\n    0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000,\n    0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000,\n    0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000,\n    0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000,\n    0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000,\n    0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000,\n    0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000,\n    0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000,\n    0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000,\n    0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000,\n    0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000,\n    0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000,\n    0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000,\n    0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000,\n    0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000,\n    0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000,\n    0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000,\n    0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000,\n    0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000,\n    0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000,\n    0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000,\n    0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000,\n    0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000,\n    0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000,\n    0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000,\n    0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000,\n    0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000,\n    0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000,\n    0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000,\n    0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000,\n    0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000,\n    0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000,\n    0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000,\n    0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000,\n    0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000,\n    0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000,\n    0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000,\n    0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000,\n    0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000,\n    0x5185cd0900000000}};\n\n#else /* W == 4 */\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,\n    0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,\n    0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,\n    0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,\n    0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,\n    0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,\n    0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,\n    0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,\n    0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,\n    0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,\n    0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,\n    0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,\n    0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,\n    0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,\n    0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,\n    0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,\n    0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,\n    0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,\n    0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,\n    0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,\n    0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,\n    0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,\n    0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,\n    0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,\n    0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,\n    0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,\n    0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,\n    0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,\n    0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,\n    0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,\n    0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,\n    0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,\n    0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,\n    0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,\n    0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,\n    0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,\n    0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,\n    0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,\n    0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,\n    0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,\n    0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,\n    0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,\n    0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,\n    0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,\n    0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,\n    0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,\n    0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,\n    0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,\n    0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,\n    0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,\n    0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,\n    0x36197165},\n   {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,\n    0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,\n    0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,\n    0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,\n    0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,\n    0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,\n    0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,\n    0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,\n    0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,\n    0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,\n    0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,\n    0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,\n    0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,\n    0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,\n    0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,\n    0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,\n    0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,\n    0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,\n    0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,\n    0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,\n    0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,\n    0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,\n    0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,\n    0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,\n    0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,\n    0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,\n    0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,\n    0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,\n    0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,\n    0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,\n    0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,\n    0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,\n    0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,\n    0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,\n    0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,\n    0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,\n    0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,\n    0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,\n    0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,\n    0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,\n    0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,\n    0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,\n    0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,\n    0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,\n    0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,\n    0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,\n    0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,\n    0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,\n    0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,\n    0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,\n    0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,\n    0x1a3b93aa},\n   {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,\n    0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,\n    0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,\n    0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,\n    0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,\n    0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,\n    0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,\n    0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,\n    0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,\n    0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,\n    0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,\n    0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,\n    0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,\n    0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,\n    0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,\n    0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,\n    0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,\n    0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,\n    0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,\n    0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,\n    0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,\n    0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,\n    0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,\n    0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,\n    0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,\n    0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,\n    0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,\n    0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,\n    0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,\n    0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,\n    0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,\n    0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,\n    0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,\n    0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,\n    0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,\n    0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,\n    0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,\n    0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,\n    0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,\n    0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,\n    0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,\n    0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,\n    0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,\n    0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,\n    0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,\n    0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,\n    0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,\n    0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,\n    0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,\n    0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,\n    0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,\n    0xe147d714},\n   {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,\n    0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,\n    0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,\n    0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,\n    0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,\n    0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,\n    0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,\n    0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,\n    0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,\n    0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,\n    0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,\n    0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,\n    0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,\n    0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,\n    0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,\n    0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,\n    0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,\n    0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,\n    0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,\n    0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,\n    0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,\n    0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,\n    0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,\n    0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,\n    0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,\n    0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,\n    0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,\n    0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,\n    0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,\n    0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,\n    0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,\n    0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,\n    0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,\n    0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,\n    0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,\n    0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,\n    0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,\n    0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,\n    0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,\n    0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,\n    0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,\n    0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,\n    0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,\n    0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,\n    0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,\n    0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,\n    0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,\n    0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,\n    0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,\n    0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,\n    0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,\n    0x494f0c4b}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d,\n    0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac,\n    0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8,\n    0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95,\n    0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817,\n    0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d,\n    0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac,\n    0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6,\n    0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564,\n    0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39,\n    0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d,\n    0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac,\n    0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de,\n    0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594,\n    0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b,\n    0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01,\n    0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f,\n    0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de,\n    0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba,\n    0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65,\n    0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7,\n    0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad,\n    0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de,\n    0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294,\n    0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716,\n    0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71,\n    0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15,\n    0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4,\n    0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca,\n    0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280,\n    0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f,\n    0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15,\n    0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9,\n    0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748,\n    0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c,\n    0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971,\n    0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3,\n    0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9,\n    0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196,\n    0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc,\n    0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e,\n    0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03,\n    0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67,\n    0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296,\n    0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a,\n    0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170,\n    0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af,\n    0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5,\n    0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb,\n    0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a,\n    0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e,\n    0x4b0c4f49},\n   {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09,\n    0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc,\n    0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e,\n    0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc,\n    0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934,\n    0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2,\n    0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b,\n    0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad,\n    0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155,\n    0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187,\n    0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65,\n    0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390,\n    0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e,\n    0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378,\n    0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889,\n    0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f,\n    0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0,\n    0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145,\n    0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7,\n    0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a,\n    0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2,\n    0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924,\n    0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2,\n    0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514,\n    0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec,\n    0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709,\n    0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb,\n    0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e,\n    0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1,\n    0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227,\n    0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6,\n    0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030,\n    0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0,\n    0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55,\n    0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7,\n    0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165,\n    0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d,\n    0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b,\n    0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c,\n    0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a,\n    0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362,\n    0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0,\n    0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52,\n    0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7,\n    0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237,\n    0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1,\n    0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020,\n    0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6,\n    0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719,\n    0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec,\n    0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e,\n    0x14d747e1},\n   {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0,\n    0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b,\n    0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652,\n    0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437,\n    0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514,\n    0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265,\n    0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de,\n    0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af,\n    0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c,\n    0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9,\n    0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0,\n    0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b,\n    0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6,\n    0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7,\n    0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734,\n    0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045,\n    0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8,\n    0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303,\n    0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a,\n    0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9,\n    0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea,\n    0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b,\n    0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6,\n    0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7,\n    0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4,\n    0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6,\n    0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f,\n    0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054,\n    0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9,\n    0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8,\n    0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b,\n    0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a,\n    0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441,\n    0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a,\n    0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3,\n    0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6,\n    0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5,\n    0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94,\n    0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9,\n    0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288,\n    0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab,\n    0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce,\n    0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7,\n    0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c,\n    0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527,\n    0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256,\n    0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5,\n    0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4,\n    0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39,\n    0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2,\n    0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db,\n    0xaa933b1a},\n   {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603,\n    0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d,\n    0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9,\n    0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b,\n    0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a,\n    0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792,\n    0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4,\n    0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c,\n    0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d,\n    0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f,\n    0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb,\n    0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65,\n    0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330,\n    0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8,\n    0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da,\n    0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742,\n    0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f,\n    0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1,\n    0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5,\n    0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f,\n    0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e,\n    0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6,\n    0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8,\n    0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250,\n    0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021,\n    0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb,\n    0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f,\n    0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511,\n    0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c,\n    0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4,\n    0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886,\n    0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e,\n    0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b,\n    0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5,\n    0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791,\n    0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003,\n    0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272,\n    0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea,\n    0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc,\n    0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24,\n    0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55,\n    0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7,\n    0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3,\n    0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d,\n    0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548,\n    0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0,\n    0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2,\n    0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a,\n    0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47,\n    0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9,\n    0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad,\n    0x65711936}};\n\n#endif\n\n#endif\n\n#if N == 4\n\n#if W == 8\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a,\n    0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe,\n    0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b,\n    0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656,\n    0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd,\n    0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d,\n    0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7,\n    0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47,\n    0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac,\n    0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691,\n    0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404,\n    0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0,\n    0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4,\n    0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424,\n    0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5,\n    0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65,\n    0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67,\n    0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3,\n    0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626,\n    0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9,\n    0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222,\n    0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2,\n    0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a,\n    0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a,\n    0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1,\n    0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2,\n    0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077,\n    0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3,\n    0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1,\n    0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621,\n    0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0,\n    0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60,\n    0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0,\n    0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64,\n    0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1,\n    0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc,\n    0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027,\n    0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7,\n    0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9,\n    0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79,\n    0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292,\n    0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af,\n    0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a,\n    0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee,\n    0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e,\n    0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe,\n    0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f,\n    0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff,\n    0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd,\n    0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29,\n    0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc,\n    0xe3c45916},\n   {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344,\n    0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59,\n    0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e,\n    0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463,\n    0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98,\n    0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d,\n    0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3,\n    0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656,\n    0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad,\n    0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0,\n    0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397,\n    0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a,\n    0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2,\n    0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357,\n    0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8,\n    0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d,\n    0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696,\n    0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b,\n    0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc,\n    0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0,\n    0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b,\n    0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be,\n    0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811,\n    0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384,\n    0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f,\n    0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955,\n    0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362,\n    0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f,\n    0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94,\n    0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701,\n    0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe,\n    0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b,\n    0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1,\n    0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc,\n    0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b,\n    0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986,\n    0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d,\n    0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8,\n    0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4,\n    0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371,\n    0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a,\n    0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87,\n    0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0,\n    0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad,\n    0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527,\n    0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2,\n    0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d,\n    0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998,\n    0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73,\n    0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e,\n    0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59,\n    0xa7520488},\n   {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20,\n    0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09,\n    0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431,\n    0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a,\n    0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203,\n    0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b,\n    0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14,\n    0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c,\n    0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25,\n    0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e,\n    0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36,\n    0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f,\n    0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649,\n    0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961,\n    0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58,\n    0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170,\n    0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b,\n    0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742,\n    0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a,\n    0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55,\n    0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c,\n    0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64,\n    0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f,\n    0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77,\n    0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e,\n    0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a,\n    0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2,\n    0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b,\n    0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090,\n    0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8,\n    0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881,\n    0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9,\n    0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6,\n    0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f,\n    0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7,\n    0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c,\n    0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695,\n    0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd,\n    0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb,\n    0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3,\n    0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa,\n    0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1,\n    0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9,\n    0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0,\n    0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df,\n    0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7,\n    0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace,\n    0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6,\n    0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd,\n    0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4,\n    0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec,\n    0x3522e9e4},\n   {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1,\n    0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86,\n    0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b,\n    0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669,\n    0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7,\n    0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352,\n    0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03,\n    0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6,\n    0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38,\n    0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a,\n    0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7,\n    0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80,\n    0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7,\n    0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522,\n    0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d,\n    0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8,\n    0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103,\n    0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54,\n    0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9,\n    0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0,\n    0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e,\n    0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb,\n    0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1,\n    0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624,\n    0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea,\n    0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a,\n    0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37,\n    0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360,\n    0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab,\n    0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e,\n    0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741,\n    0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4,\n    0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334,\n    0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63,\n    0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de,\n    0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c,\n    0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942,\n    0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7,\n    0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131,\n    0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4,\n    0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a,\n    0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758,\n    0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5,\n    0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2,\n    0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32,\n    0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7,\n    0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8,\n    0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d,\n    0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6,\n    0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1,\n    0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c,\n    0x97411e28},\n   {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474,\n    0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5,\n    0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6,\n    0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7,\n    0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938,\n    0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051,\n    0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a,\n    0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3,\n    0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c,\n    0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d,\n    0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e,\n    0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf,\n    0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740,\n    0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29,\n    0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592,\n    0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb,\n    0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4,\n    0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365,\n    0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036,\n    0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7,\n    0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08,\n    0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561,\n    0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a,\n    0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663,\n    0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac,\n    0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d,\n    0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce,\n    0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f,\n    0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50,\n    0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639,\n    0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82,\n    0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb,\n    0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954,\n    0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5,\n    0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86,\n    0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7,\n    0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418,\n    0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71,\n    0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa,\n    0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93,\n    0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c,\n    0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d,\n    0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e,\n    0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df,\n    0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60,\n    0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309,\n    0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2,\n    0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db,\n    0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4,\n    0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45,\n    0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16,\n    0x93c7a00b},\n   {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45,\n    0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb,\n    0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d,\n    0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696,\n    0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf,\n    0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb,\n    0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028,\n    0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c,\n    0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65,\n    0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be,\n    0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038,\n    0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6,\n    0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15,\n    0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11,\n    0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d,\n    0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19,\n    0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05,\n    0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b,\n    0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d,\n    0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c,\n    0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35,\n    0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31,\n    0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068,\n    0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c,\n    0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25,\n    0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a,\n    0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac,\n    0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22,\n    0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e,\n    0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a,\n    0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36,\n    0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32,\n    0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84,\n    0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a,\n    0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c,\n    0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057,\n    0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e,\n    0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a,\n    0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc,\n    0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8,\n    0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1,\n    0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a,\n    0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec,\n    0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62,\n    0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4,\n    0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0,\n    0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc,\n    0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8,\n    0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4,\n    0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a,\n    0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc,\n    0xce5f968d},\n   {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de,\n    0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b,\n    0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d,\n    0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680,\n    0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4,\n    0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d,\n    0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde,\n    0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97,\n    0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3,\n    0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e,\n    0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678,\n    0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d,\n    0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723,\n    0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a,\n    0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0,\n    0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9,\n    0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85,\n    0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770,\n    0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56,\n    0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a,\n    0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e,\n    0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67,\n    0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785,\n    0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc,\n    0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788,\n    0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90,\n    0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6,\n    0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843,\n    0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f,\n    0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336,\n    0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac,\n    0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5,\n    0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68,\n    0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d,\n    0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb,\n    0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36,\n    0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72,\n    0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b,\n    0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b,\n    0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402,\n    0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446,\n    0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb,\n    0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed,\n    0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418,\n    0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95,\n    0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc,\n    0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946,\n    0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f,\n    0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233,\n    0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6,\n    0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0,\n    0x3e721277},\n   {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb,\n    0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9,\n    0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11,\n    0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d,\n    0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9,\n    0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c,\n    0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881,\n    0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274,\n    0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790,\n    0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc,\n    0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514,\n    0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56,\n    0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9,\n    0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c,\n    0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13,\n    0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6,\n    0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c,\n    0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e,\n    0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386,\n    0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376,\n    0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692,\n    0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67,\n    0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416,\n    0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3,\n    0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07,\n    0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd,\n    0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15,\n    0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457,\n    0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd,\n    0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28,\n    0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337,\n    0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2,\n    0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594,\n    0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6,\n    0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e,\n    0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52,\n    0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6,\n    0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143,\n    0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17,\n    0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2,\n    0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306,\n    0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a,\n    0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182,\n    0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0,\n    0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496,\n    0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63,\n    0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c,\n    0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89,\n    0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903,\n    0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041,\n    0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9,\n    0x1c65ace7}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000,\n    0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000,\n    0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000,\n    0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000,\n    0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000,\n    0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000,\n    0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000,\n    0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000,\n    0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000,\n    0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000,\n    0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000,\n    0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000,\n    0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000,\n    0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000,\n    0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000,\n    0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000,\n    0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000,\n    0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000,\n    0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000,\n    0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000,\n    0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000,\n    0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000,\n    0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000,\n    0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000,\n    0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000,\n    0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000,\n    0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000,\n    0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000,\n    0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000,\n    0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000,\n    0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000,\n    0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000,\n    0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000,\n    0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000,\n    0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000,\n    0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000,\n    0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000,\n    0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000,\n    0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000,\n    0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000,\n    0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000,\n    0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000,\n    0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000,\n    0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000,\n    0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000,\n    0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000,\n    0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000,\n    0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000,\n    0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000,\n    0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000,\n    0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000,\n    0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000,\n    0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000,\n    0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000,\n    0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000,\n    0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000,\n    0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000,\n    0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000,\n    0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000,\n    0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000,\n    0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000,\n    0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000,\n    0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000,\n    0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000,\n    0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000,\n    0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000,\n    0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000,\n    0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000,\n    0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000,\n    0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000,\n    0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000,\n    0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000,\n    0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000,\n    0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000,\n    0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000,\n    0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000,\n    0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000,\n    0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000,\n    0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000,\n    0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000,\n    0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000,\n    0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000,\n    0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000,\n    0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000,\n    0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000,\n    0xe7ac651c00000000},\n   {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000,\n    0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000,\n    0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000,\n    0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000,\n    0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000,\n    0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000,\n    0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000,\n    0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000,\n    0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000,\n    0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000,\n    0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000,\n    0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000,\n    0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000,\n    0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000,\n    0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000,\n    0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000,\n    0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000,\n    0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000,\n    0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000,\n    0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000,\n    0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000,\n    0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000,\n    0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000,\n    0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000,\n    0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000,\n    0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000,\n    0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000,\n    0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000,\n    0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000,\n    0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000,\n    0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000,\n    0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000,\n    0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000,\n    0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000,\n    0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000,\n    0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000,\n    0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000,\n    0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000,\n    0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000,\n    0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000,\n    0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000,\n    0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000,\n    0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000,\n    0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000,\n    0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000,\n    0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000,\n    0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000,\n    0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000,\n    0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000,\n    0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000,\n    0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000,\n    0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000,\n    0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000,\n    0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000,\n    0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000,\n    0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000,\n    0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000,\n    0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000,\n    0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000,\n    0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000,\n    0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000,\n    0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000,\n    0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000,\n    0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000,\n    0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000,\n    0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000,\n    0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000,\n    0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000,\n    0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000,\n    0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000,\n    0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000,\n    0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000,\n    0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000,\n    0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000,\n    0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000,\n    0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000,\n    0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000,\n    0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000,\n    0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000,\n    0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000,\n    0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000,\n    0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000,\n    0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000,\n    0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000,\n    0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000,\n    0x7712723e00000000},\n   {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000,\n    0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000,\n    0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000,\n    0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000,\n    0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000,\n    0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000,\n    0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000,\n    0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000,\n    0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000,\n    0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000,\n    0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000,\n    0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000,\n    0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000,\n    0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000,\n    0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000,\n    0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000,\n    0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000,\n    0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000,\n    0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000,\n    0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000,\n    0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000,\n    0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000,\n    0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000,\n    0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000,\n    0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000,\n    0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000,\n    0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000,\n    0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000,\n    0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000,\n    0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000,\n    0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000,\n    0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000,\n    0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000,\n    0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000,\n    0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000,\n    0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000,\n    0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000,\n    0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000,\n    0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000,\n    0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000,\n    0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000,\n    0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000,\n    0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000,\n    0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000,\n    0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000,\n    0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000,\n    0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000,\n    0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000,\n    0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000,\n    0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000,\n    0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000,\n    0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000,\n    0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000,\n    0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000,\n    0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000,\n    0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000,\n    0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000,\n    0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000,\n    0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000,\n    0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000,\n    0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000,\n    0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000,\n    0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000,\n    0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000,\n    0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000,\n    0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000,\n    0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000,\n    0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000,\n    0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000,\n    0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000,\n    0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000,\n    0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000,\n    0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000,\n    0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000,\n    0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000,\n    0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000,\n    0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000,\n    0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000,\n    0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000,\n    0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000,\n    0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000,\n    0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000,\n    0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000,\n    0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000,\n    0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000,\n    0x8d965fce00000000},\n   {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000,\n    0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000,\n    0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000,\n    0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000,\n    0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000,\n    0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000,\n    0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000,\n    0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000,\n    0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000,\n    0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000,\n    0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000,\n    0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000,\n    0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000,\n    0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000,\n    0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000,\n    0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000,\n    0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000,\n    0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000,\n    0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000,\n    0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000,\n    0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000,\n    0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000,\n    0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000,\n    0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000,\n    0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000,\n    0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000,\n    0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000,\n    0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000,\n    0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000,\n    0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000,\n    0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000,\n    0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000,\n    0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000,\n    0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000,\n    0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000,\n    0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000,\n    0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000,\n    0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000,\n    0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000,\n    0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000,\n    0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000,\n    0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000,\n    0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000,\n    0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000,\n    0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000,\n    0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000,\n    0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000,\n    0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000,\n    0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000,\n    0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000,\n    0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000,\n    0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000,\n    0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000,\n    0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000,\n    0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000,\n    0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000,\n    0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000,\n    0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000,\n    0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000,\n    0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000,\n    0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000,\n    0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000,\n    0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000,\n    0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000,\n    0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000,\n    0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000,\n    0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000,\n    0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000,\n    0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000,\n    0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000,\n    0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000,\n    0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000,\n    0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000,\n    0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000,\n    0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000,\n    0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000,\n    0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000,\n    0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000,\n    0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000,\n    0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000,\n    0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000,\n    0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000,\n    0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000,\n    0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000,\n    0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000,\n    0x0ba0c79300000000},\n   {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000,\n    0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000,\n    0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000,\n    0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000,\n    0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000,\n    0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000,\n    0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000,\n    0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000,\n    0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000,\n    0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000,\n    0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000,\n    0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000,\n    0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000,\n    0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000,\n    0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000,\n    0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000,\n    0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000,\n    0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000,\n    0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000,\n    0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000,\n    0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000,\n    0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000,\n    0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000,\n    0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000,\n    0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000,\n    0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000,\n    0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000,\n    0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000,\n    0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000,\n    0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000,\n    0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000,\n    0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000,\n    0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000,\n    0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000,\n    0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000,\n    0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000,\n    0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000,\n    0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000,\n    0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000,\n    0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000,\n    0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000,\n    0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000,\n    0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000,\n    0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000,\n    0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000,\n    0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000,\n    0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000,\n    0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000,\n    0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000,\n    0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000,\n    0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000,\n    0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000,\n    0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000,\n    0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000,\n    0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000,\n    0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000,\n    0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000,\n    0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000,\n    0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000,\n    0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000,\n    0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000,\n    0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000,\n    0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000,\n    0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000,\n    0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000,\n    0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000,\n    0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000,\n    0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000,\n    0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000,\n    0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000,\n    0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000,\n    0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000,\n    0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000,\n    0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000,\n    0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000,\n    0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000,\n    0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000,\n    0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000,\n    0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000,\n    0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000,\n    0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000,\n    0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000,\n    0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000,\n    0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000,\n    0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000,\n    0x281e419700000000},\n   {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000,\n    0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000,\n    0x304a428900000000, 0x38a922b500000000, 0x011e763800000000,\n    0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000,\n    0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000,\n    0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000,\n    0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000,\n    0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000,\n    0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000,\n    0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000,\n    0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000,\n    0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000,\n    0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000,\n    0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000,\n    0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000,\n    0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000,\n    0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000,\n    0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000,\n    0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000,\n    0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000,\n    0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000,\n    0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000,\n    0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000,\n    0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000,\n    0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000,\n    0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000,\n    0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000,\n    0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000,\n    0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000,\n    0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000,\n    0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000,\n    0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000,\n    0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000,\n    0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000,\n    0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000,\n    0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000,\n    0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000,\n    0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000,\n    0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000,\n    0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000,\n    0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000,\n    0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000,\n    0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000,\n    0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000,\n    0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000,\n    0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000,\n    0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000,\n    0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000,\n    0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000,\n    0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000,\n    0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000,\n    0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000,\n    0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000,\n    0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000,\n    0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000,\n    0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000,\n    0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000,\n    0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000,\n    0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000,\n    0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000,\n    0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000,\n    0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000,\n    0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000,\n    0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000,\n    0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000,\n    0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000,\n    0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000,\n    0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000,\n    0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000,\n    0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000,\n    0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000,\n    0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000,\n    0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000,\n    0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000,\n    0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000,\n    0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000,\n    0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000,\n    0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000,\n    0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000,\n    0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000,\n    0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000,\n    0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000,\n    0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000,\n    0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000,\n    0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000,\n    0xe4e9223500000000},\n   {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000,\n    0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000,\n    0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000,\n    0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000,\n    0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000,\n    0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000,\n    0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000,\n    0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000,\n    0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000,\n    0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000,\n    0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000,\n    0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000,\n    0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000,\n    0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000,\n    0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000,\n    0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000,\n    0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000,\n    0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000,\n    0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000,\n    0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000,\n    0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000,\n    0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000,\n    0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000,\n    0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000,\n    0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000,\n    0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000,\n    0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000,\n    0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000,\n    0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000,\n    0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000,\n    0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000,\n    0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000,\n    0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000,\n    0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000,\n    0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000,\n    0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000,\n    0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000,\n    0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000,\n    0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000,\n    0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000,\n    0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000,\n    0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000,\n    0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000,\n    0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000,\n    0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000,\n    0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000,\n    0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000,\n    0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000,\n    0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000,\n    0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000,\n    0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000,\n    0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000,\n    0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000,\n    0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000,\n    0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000,\n    0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000,\n    0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000,\n    0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000,\n    0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000,\n    0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000,\n    0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000,\n    0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000,\n    0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000,\n    0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000,\n    0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000,\n    0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000,\n    0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000,\n    0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000,\n    0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000,\n    0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000,\n    0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000,\n    0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000,\n    0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000,\n    0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000,\n    0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000,\n    0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000,\n    0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000,\n    0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000,\n    0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000,\n    0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000,\n    0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000,\n    0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000,\n    0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000,\n    0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000,\n    0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000,\n    0x880452a700000000},\n   {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000,\n    0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000,\n    0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000,\n    0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000,\n    0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000,\n    0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000,\n    0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000,\n    0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000,\n    0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000,\n    0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000,\n    0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000,\n    0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000,\n    0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000,\n    0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000,\n    0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000,\n    0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000,\n    0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000,\n    0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000,\n    0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000,\n    0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000,\n    0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000,\n    0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000,\n    0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000,\n    0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000,\n    0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000,\n    0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000,\n    0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000,\n    0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000,\n    0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000,\n    0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000,\n    0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000,\n    0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000,\n    0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000,\n    0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000,\n    0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000,\n    0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000,\n    0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000,\n    0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000,\n    0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000,\n    0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000,\n    0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000,\n    0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000,\n    0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000,\n    0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000,\n    0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000,\n    0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000,\n    0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000,\n    0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000,\n    0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000,\n    0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000,\n    0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000,\n    0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000,\n    0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000,\n    0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000,\n    0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000,\n    0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000,\n    0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000,\n    0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000,\n    0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000,\n    0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000,\n    0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000,\n    0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000,\n    0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000,\n    0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000,\n    0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000,\n    0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000,\n    0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000,\n    0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000,\n    0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000,\n    0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000,\n    0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000,\n    0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000,\n    0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000,\n    0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000,\n    0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000,\n    0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000,\n    0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000,\n    0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000,\n    0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000,\n    0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000,\n    0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000,\n    0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000,\n    0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000,\n    0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000,\n    0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000,\n    0x1659c4e300000000}};\n\n#else /* W == 4 */\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,\n    0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,\n    0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,\n    0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,\n    0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,\n    0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,\n    0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,\n    0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,\n    0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,\n    0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,\n    0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,\n    0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,\n    0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,\n    0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,\n    0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,\n    0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,\n    0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,\n    0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,\n    0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,\n    0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,\n    0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,\n    0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,\n    0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,\n    0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,\n    0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,\n    0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,\n    0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,\n    0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,\n    0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,\n    0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,\n    0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,\n    0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,\n    0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,\n    0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,\n    0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,\n    0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,\n    0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,\n    0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,\n    0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,\n    0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,\n    0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,\n    0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,\n    0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,\n    0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,\n    0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,\n    0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,\n    0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,\n    0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,\n    0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,\n    0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,\n    0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,\n    0x0d7139d7},\n   {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,\n    0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,\n    0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,\n    0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,\n    0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,\n    0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,\n    0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,\n    0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,\n    0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,\n    0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,\n    0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,\n    0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,\n    0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,\n    0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,\n    0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,\n    0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,\n    0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,\n    0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,\n    0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,\n    0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,\n    0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,\n    0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,\n    0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,\n    0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,\n    0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,\n    0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,\n    0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,\n    0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,\n    0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,\n    0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,\n    0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,\n    0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,\n    0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,\n    0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,\n    0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,\n    0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,\n    0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,\n    0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,\n    0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,\n    0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,\n    0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,\n    0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,\n    0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,\n    0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,\n    0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,\n    0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,\n    0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,\n    0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,\n    0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,\n    0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,\n    0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,\n    0x1c53e98a},\n   {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,\n    0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,\n    0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,\n    0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,\n    0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,\n    0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,\n    0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,\n    0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,\n    0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,\n    0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,\n    0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,\n    0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,\n    0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,\n    0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,\n    0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,\n    0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,\n    0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,\n    0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,\n    0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,\n    0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,\n    0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,\n    0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,\n    0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,\n    0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,\n    0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,\n    0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,\n    0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,\n    0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,\n    0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,\n    0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,\n    0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,\n    0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,\n    0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,\n    0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,\n    0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,\n    0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,\n    0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,\n    0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,\n    0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,\n    0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,\n    0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,\n    0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,\n    0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,\n    0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,\n    0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,\n    0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,\n    0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,\n    0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,\n    0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,\n    0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,\n    0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,\n    0x3f88e851},\n   {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,\n    0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,\n    0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,\n    0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,\n    0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,\n    0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,\n    0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,\n    0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,\n    0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,\n    0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,\n    0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,\n    0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,\n    0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,\n    0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,\n    0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,\n    0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,\n    0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,\n    0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,\n    0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,\n    0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,\n    0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,\n    0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,\n    0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,\n    0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,\n    0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,\n    0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,\n    0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,\n    0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,\n    0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,\n    0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,\n    0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,\n    0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,\n    0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,\n    0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,\n    0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,\n    0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,\n    0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,\n    0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,\n    0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,\n    0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,\n    0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,\n    0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,\n    0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,\n    0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,\n    0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,\n    0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,\n    0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,\n    0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,\n    0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,\n    0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,\n    0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,\n    0x3dee8ca6}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0,\n    0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587,\n    0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa,\n    0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09,\n    0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee,\n    0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3,\n    0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3,\n    0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce,\n    0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429,\n    0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda,\n    0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7,\n    0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0,\n    0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd,\n    0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0,\n    0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287,\n    0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a,\n    0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9,\n    0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e,\n    0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3,\n    0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3,\n    0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054,\n    0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49,\n    0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da,\n    0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7,\n    0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20,\n    0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d,\n    0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00,\n    0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347,\n    0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14,\n    0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209,\n    0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e,\n    0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33,\n    0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3,\n    0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194,\n    0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9,\n    0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a,\n    0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd,\n    0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0,\n    0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d,\n    0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460,\n    0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87,\n    0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674,\n    0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509,\n    0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e,\n    0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae,\n    0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3,\n    0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694,\n    0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989,\n    0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da,\n    0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d,\n    0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0,\n    0xa68cee3d},\n   {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19,\n    0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae,\n    0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb,\n    0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a,\n    0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55,\n    0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1,\n    0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c,\n    0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8,\n    0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7,\n    0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936,\n    0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453,\n    0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4,\n    0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941,\n    0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5,\n    0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93,\n    0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17,\n    0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e,\n    0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89,\n    0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec,\n    0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0,\n    0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf,\n    0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b,\n    0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b,\n    0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f,\n    0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0,\n    0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e,\n    0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b,\n    0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc,\n    0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5,\n    0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261,\n    0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637,\n    0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3,\n    0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57,\n    0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0,\n    0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85,\n    0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454,\n    0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b,\n    0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f,\n    0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423,\n    0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7,\n    0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8,\n    0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739,\n    0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c,\n    0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb,\n    0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f,\n    0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b,\n    0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd,\n    0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59,\n    0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070,\n    0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7,\n    0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2,\n    0x51e8883f},\n   {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a,\n    0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276,\n    0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed,\n    0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55,\n    0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b,\n    0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8,\n    0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320,\n    0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413,\n    0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd,\n    0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75,\n    0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee,\n    0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312,\n    0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca,\n    0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9,\n    0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad,\n    0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e,\n    0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504,\n    0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8,\n    0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63,\n    0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353,\n    0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d,\n    0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be,\n    0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae,\n    0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d,\n    0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943,\n    0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7,\n    0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c,\n    0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390,\n    0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a,\n    0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239,\n    0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d,\n    0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e,\n    0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c,\n    0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0,\n    0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b,\n    0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93,\n    0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d,\n    0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e,\n    0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c,\n    0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f,\n    0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1,\n    0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579,\n    0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2,\n    0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e,\n    0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c,\n    0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f,\n    0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b,\n    0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158,\n    0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2,\n    0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e,\n    0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5,\n    0x8ae9531c},\n   {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4,\n    0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd,\n    0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220,\n    0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf,\n    0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495,\n    0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def,\n    0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90,\n    0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea,\n    0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0,\n    0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f,\n    0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2,\n    0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab,\n    0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e,\n    0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754,\n    0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda,\n    0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0,\n    0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c,\n    0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215,\n    0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8,\n    0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910,\n    0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a,\n    0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30,\n    0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658,\n    0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22,\n    0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478,\n    0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2,\n    0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f,\n    0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606,\n    0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba,\n    0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0,\n    0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e,\n    0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034,\n    0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f,\n    0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996,\n    0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b,\n    0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84,\n    0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de,\n    0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4,\n    0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5,\n    0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f,\n    0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5,\n    0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a,\n    0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7,\n    0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce,\n    0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65,\n    0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f,\n    0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91,\n    0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb,\n    0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57,\n    0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e,\n    0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3,\n    0xd739710d}};\n\n#endif\n\n#endif\n\n#if N == 5\n\n#if W == 8\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df,\n    0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8,\n    0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef,\n    0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376,\n    0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201,\n    0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399,\n    0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372,\n    0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea,\n    0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d,\n    0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004,\n    0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353,\n    0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334,\n    0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a,\n    0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2,\n    0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a,\n    0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2,\n    0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b,\n    0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c,\n    0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b,\n    0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f,\n    0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338,\n    0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0,\n    0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6,\n    0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e,\n    0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319,\n    0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3,\n    0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4,\n    0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783,\n    0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a,\n    0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492,\n    0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a,\n    0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2,\n    0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496,\n    0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1,\n    0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6,\n    0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f,\n    0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548,\n    0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0,\n    0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741,\n    0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9,\n    0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae,\n    0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437,\n    0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760,\n    0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707,\n    0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433,\n    0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab,\n    0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703,\n    0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b,\n    0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412,\n    0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475,\n    0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722,\n    0xe9947565},\n   {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5,\n    0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22,\n    0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c,\n    0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed,\n    0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d,\n    0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1,\n    0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e,\n    0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32,\n    0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142,\n    0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93,\n    0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d,\n    0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a,\n    0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58,\n    0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14,\n    0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81,\n    0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd,\n    0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab,\n    0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c,\n    0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72,\n    0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f,\n    0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff,\n    0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3,\n    0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30,\n    0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c,\n    0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c,\n    0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558,\n    0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146,\n    0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581,\n    0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7,\n    0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab,\n    0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e,\n    0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272,\n    0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838,\n    0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff,\n    0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1,\n    0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330,\n    0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840,\n    0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c,\n    0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb,\n    0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7,\n    0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7,\n    0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616,\n    0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208,\n    0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf,\n    0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85,\n    0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9,\n    0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c,\n    0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10,\n    0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76,\n    0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1,\n    0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf,\n    0xf7d05006},\n   {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b,\n    0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774,\n    0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58,\n    0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a,\n    0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb,\n    0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952,\n    0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e,\n    0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7,\n    0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746,\n    0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14,\n    0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338,\n    0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907,\n    0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777,\n    0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de,\n    0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064,\n    0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd,\n    0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951,\n    0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e,\n    0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42,\n    0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b,\n    0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a,\n    0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3,\n    0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904,\n    0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad,\n    0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c,\n    0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d,\n    0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861,\n    0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e,\n    0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2,\n    0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b,\n    0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1,\n    0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78,\n    0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f,\n    0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40,\n    0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c,\n    0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e,\n    0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf,\n    0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166,\n    0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d,\n    0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4,\n    0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805,\n    0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157,\n    0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b,\n    0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644,\n    0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43,\n    0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea,\n    0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850,\n    0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9,\n    0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165,\n    0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a,\n    0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676,\n    0xb2075b94},\n   {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf,\n    0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61,\n    0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be,\n    0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd,\n    0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3,\n    0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063,\n    0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105,\n    0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5,\n    0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb,\n    0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8,\n    0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07,\n    0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9,\n    0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5,\n    0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515,\n    0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4,\n    0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014,\n    0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7,\n    0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269,\n    0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6,\n    0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af,\n    0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1,\n    0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111,\n    0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d,\n    0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad,\n    0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3,\n    0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75,\n    0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa,\n    0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74,\n    0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7,\n    0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477,\n    0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6,\n    0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176,\n    0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af,\n    0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71,\n    0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae,\n    0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd,\n    0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3,\n    0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073,\n    0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0,\n    0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400,\n    0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e,\n    0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d,\n    0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2,\n    0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c,\n    0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5,\n    0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505,\n    0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4,\n    0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004,\n    0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7,\n    0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279,\n    0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6,\n    0xba50bcb9},\n   {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897,\n    0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb,\n    0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2,\n    0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2,\n    0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372,\n    0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70,\n    0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92,\n    0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190,\n    0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40,\n    0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430,\n    0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759,\n    0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75,\n    0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2,\n    0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0,\n    0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7,\n    0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5,\n    0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39,\n    0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215,\n    0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c,\n    0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5,\n    0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625,\n    0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27,\n    0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c,\n    0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e,\n    0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee,\n    0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71,\n    0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18,\n    0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134,\n    0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8,\n    0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba,\n    0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd,\n    0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff,\n    0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a,\n    0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6,\n    0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf,\n    0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf,\n    0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f,\n    0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d,\n    0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d,\n    0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f,\n    0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af,\n    0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df,\n    0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6,\n    0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a,\n    0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef,\n    0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed,\n    0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa,\n    0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8,\n    0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624,\n    0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08,\n    0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861,\n    0x808abcf4},\n   {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2,\n    0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd,\n    0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76,\n    0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52,\n    0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e,\n    0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124,\n    0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147,\n    0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d,\n    0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31,\n    0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15,\n    0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae,\n    0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1,\n    0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d,\n    0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307,\n    0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9,\n    0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3,\n    0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084,\n    0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb,\n    0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850,\n    0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2,\n    0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe,\n    0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94,\n    0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261,\n    0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b,\n    0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917,\n    0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53,\n    0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8,\n    0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787,\n    0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0,\n    0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba,\n    0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404,\n    0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e,\n    0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af,\n    0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0,\n    0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b,\n    0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f,\n    0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543,\n    0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129,\n    0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627,\n    0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d,\n    0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51,\n    0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75,\n    0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce,\n    0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1,\n    0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760,\n    0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a,\n    0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4,\n    0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde,\n    0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089,\n    0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6,\n    0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d,\n    0xefdb3f95},\n   {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8,\n    0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7,\n    0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945,\n    0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9,\n    0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652,\n    0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc,\n    0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a,\n    0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4,\n    0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f,\n    0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3,\n    0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51,\n    0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e,\n    0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c,\n    0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362,\n    0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11,\n    0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff,\n    0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7,\n    0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8,\n    0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a,\n    0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690,\n    0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b,\n    0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5,\n    0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05,\n    0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb,\n    0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740,\n    0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f,\n    0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded,\n    0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2,\n    0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa,\n    0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714,\n    0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67,\n    0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89,\n    0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7,\n    0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8,\n    0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a,\n    0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6,\n    0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d,\n    0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3,\n    0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9,\n    0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57,\n    0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc,\n    0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540,\n    0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2,\n    0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd,\n    0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93,\n    0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d,\n    0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e,\n    0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0,\n    0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8,\n    0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7,\n    0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75,\n    0x0e2fbf43},\n   {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc,\n    0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a,\n    0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3,\n    0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7,\n    0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b,\n    0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154,\n    0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3,\n    0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc,\n    0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330,\n    0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264,\n    0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd,\n    0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b,\n    0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a,\n    0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175,\n    0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275,\n    0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a,\n    0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234,\n    0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2,\n    0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b,\n    0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a,\n    0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6,\n    0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189,\n    0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b,\n    0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204,\n    0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8,\n    0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226,\n    0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff,\n    0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219,\n    0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167,\n    0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258,\n    0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158,\n    0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267,\n    0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c,\n    0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da,\n    0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003,\n    0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157,\n    0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b,\n    0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4,\n    0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179,\n    0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246,\n    0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a,\n    0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de,\n    0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107,\n    0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1,\n    0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba,\n    0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285,\n    0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185,\n    0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba,\n    0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4,\n    0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322,\n    0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb,\n    0xf4377108}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000,\n    0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000,\n    0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000,\n    0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000,\n    0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000,\n    0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000,\n    0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000,\n    0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000,\n    0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000,\n    0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000,\n    0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000,\n    0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000,\n    0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000,\n    0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000,\n    0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000,\n    0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000,\n    0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000,\n    0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000,\n    0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000,\n    0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000,\n    0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000,\n    0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000,\n    0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000,\n    0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000,\n    0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000,\n    0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000,\n    0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000,\n    0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000,\n    0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000,\n    0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000,\n    0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000,\n    0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000,\n    0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000,\n    0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000,\n    0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000,\n    0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000,\n    0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000,\n    0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000,\n    0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000,\n    0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000,\n    0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000,\n    0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000,\n    0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000,\n    0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000,\n    0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000,\n    0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000,\n    0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000,\n    0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000,\n    0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000,\n    0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000,\n    0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000,\n    0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000,\n    0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000,\n    0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000,\n    0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000,\n    0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000,\n    0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000,\n    0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000,\n    0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000,\n    0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000,\n    0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000,\n    0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000,\n    0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000,\n    0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000,\n    0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000,\n    0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000,\n    0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000,\n    0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000,\n    0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000,\n    0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000,\n    0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000,\n    0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000,\n    0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000,\n    0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000,\n    0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000,\n    0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000,\n    0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000,\n    0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000,\n    0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000,\n    0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000,\n    0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000,\n    0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000,\n    0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000,\n    0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000,\n    0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000,\n    0x087137f400000000},\n   {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000,\n    0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000,\n    0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000,\n    0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000,\n    0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000,\n    0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000,\n    0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000,\n    0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000,\n    0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000,\n    0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000,\n    0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000,\n    0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000,\n    0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000,\n    0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000,\n    0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000,\n    0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000,\n    0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000,\n    0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000,\n    0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000,\n    0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000,\n    0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000,\n    0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000,\n    0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000,\n    0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000,\n    0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000,\n    0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000,\n    0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000,\n    0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000,\n    0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000,\n    0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000,\n    0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000,\n    0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000,\n    0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000,\n    0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000,\n    0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000,\n    0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000,\n    0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000,\n    0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000,\n    0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000,\n    0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000,\n    0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000,\n    0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000,\n    0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000,\n    0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000,\n    0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000,\n    0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000,\n    0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000,\n    0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000,\n    0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000,\n    0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000,\n    0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000,\n    0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000,\n    0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000,\n    0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000,\n    0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000,\n    0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000,\n    0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000,\n    0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000,\n    0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000,\n    0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000,\n    0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000,\n    0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000,\n    0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000,\n    0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000,\n    0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000,\n    0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000,\n    0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000,\n    0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000,\n    0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000,\n    0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000,\n    0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000,\n    0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000,\n    0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000,\n    0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000,\n    0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000,\n    0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000,\n    0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000,\n    0x1129fad400000000, 0x621116d400000000, 0x544094f000000000,\n    0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000,\n    0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000,\n    0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000,\n    0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000,\n    0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000,\n    0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000,\n    0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000,\n    0x43bf2f0e00000000},\n   {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000,\n    0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000,\n    0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000,\n    0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000,\n    0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000,\n    0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000,\n    0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000,\n    0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000,\n    0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000,\n    0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000,\n    0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000,\n    0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000,\n    0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000,\n    0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000,\n    0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000,\n    0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000,\n    0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000,\n    0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000,\n    0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000,\n    0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000,\n    0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000,\n    0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000,\n    0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000,\n    0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000,\n    0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000,\n    0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000,\n    0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000,\n    0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000,\n    0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000,\n    0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000,\n    0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000,\n    0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000,\n    0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000,\n    0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000,\n    0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000,\n    0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000,\n    0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000,\n    0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000,\n    0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000,\n    0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000,\n    0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000,\n    0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000,\n    0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000,\n    0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000,\n    0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000,\n    0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000,\n    0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000,\n    0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000,\n    0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000,\n    0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000,\n    0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000,\n    0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000,\n    0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000,\n    0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000,\n    0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000,\n    0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000,\n    0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000,\n    0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000,\n    0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000,\n    0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000,\n    0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000,\n    0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000,\n    0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000,\n    0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000,\n    0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000,\n    0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000,\n    0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000,\n    0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000,\n    0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000,\n    0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000,\n    0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000,\n    0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000,\n    0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000,\n    0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000,\n    0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000,\n    0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000,\n    0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000,\n    0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000,\n    0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000,\n    0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000,\n    0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000,\n    0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000,\n    0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000,\n    0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000,\n    0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000,\n    0x953fdbef00000000},\n   {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000,\n    0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000,\n    0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000,\n    0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000,\n    0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000,\n    0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000,\n    0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000,\n    0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000,\n    0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000,\n    0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000,\n    0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000,\n    0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000,\n    0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000,\n    0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000,\n    0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000,\n    0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000,\n    0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000,\n    0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000,\n    0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000,\n    0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000,\n    0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000,\n    0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000,\n    0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000,\n    0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000,\n    0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000,\n    0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000,\n    0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000,\n    0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000,\n    0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000,\n    0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000,\n    0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000,\n    0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000,\n    0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000,\n    0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000,\n    0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000,\n    0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000,\n    0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000,\n    0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000,\n    0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000,\n    0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000,\n    0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000,\n    0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000,\n    0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000,\n    0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000,\n    0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000,\n    0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000,\n    0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000,\n    0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000,\n    0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000,\n    0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000,\n    0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000,\n    0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000,\n    0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000,\n    0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000,\n    0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000,\n    0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000,\n    0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000,\n    0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000,\n    0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000,\n    0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000,\n    0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000,\n    0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000,\n    0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000,\n    0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000,\n    0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000,\n    0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000,\n    0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000,\n    0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000,\n    0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000,\n    0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000,\n    0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000,\n    0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000,\n    0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000,\n    0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000,\n    0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000,\n    0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000,\n    0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000,\n    0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000,\n    0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000,\n    0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000,\n    0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000,\n    0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000,\n    0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000,\n    0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000,\n    0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000,\n    0xf4bc8a8000000000},\n   {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000,\n    0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000,\n    0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000,\n    0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000,\n    0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000,\n    0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000,\n    0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000,\n    0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000,\n    0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000,\n    0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000,\n    0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000,\n    0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000,\n    0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000,\n    0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000,\n    0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000,\n    0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000,\n    0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000,\n    0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000,\n    0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000,\n    0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000,\n    0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000,\n    0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000,\n    0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000,\n    0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000,\n    0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000,\n    0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000,\n    0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000,\n    0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000,\n    0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000,\n    0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000,\n    0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000,\n    0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000,\n    0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000,\n    0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000,\n    0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000,\n    0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000,\n    0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000,\n    0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000,\n    0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000,\n    0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000,\n    0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000,\n    0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000,\n    0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000,\n    0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000,\n    0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000,\n    0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000,\n    0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000,\n    0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000,\n    0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000,\n    0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000,\n    0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000,\n    0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000,\n    0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000,\n    0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000,\n    0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000,\n    0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000,\n    0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000,\n    0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000,\n    0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000,\n    0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000,\n    0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000,\n    0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000,\n    0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000,\n    0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000,\n    0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000,\n    0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000,\n    0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000,\n    0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000,\n    0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000,\n    0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000,\n    0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000,\n    0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000,\n    0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000,\n    0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000,\n    0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000,\n    0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000,\n    0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000,\n    0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000,\n    0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000,\n    0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000,\n    0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000,\n    0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000,\n    0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000,\n    0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000,\n    0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000,\n    0xb9bc50ba00000000},\n   {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000,\n    0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000,\n    0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000,\n    0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000,\n    0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000,\n    0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000,\n    0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000,\n    0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000,\n    0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000,\n    0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000,\n    0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000,\n    0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000,\n    0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000,\n    0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000,\n    0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000,\n    0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000,\n    0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000,\n    0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000,\n    0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000,\n    0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000,\n    0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000,\n    0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000,\n    0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000,\n    0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000,\n    0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000,\n    0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000,\n    0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000,\n    0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000,\n    0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000,\n    0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000,\n    0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000,\n    0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000,\n    0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000,\n    0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000,\n    0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000,\n    0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000,\n    0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000,\n    0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000,\n    0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000,\n    0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000,\n    0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000,\n    0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000,\n    0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000,\n    0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000,\n    0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000,\n    0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000,\n    0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000,\n    0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000,\n    0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000,\n    0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000,\n    0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000,\n    0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000,\n    0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000,\n    0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000,\n    0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000,\n    0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000,\n    0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000,\n    0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000,\n    0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000,\n    0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000,\n    0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000,\n    0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000,\n    0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000,\n    0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000,\n    0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000,\n    0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000,\n    0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000,\n    0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000,\n    0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000,\n    0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000,\n    0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000,\n    0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000,\n    0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000,\n    0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000,\n    0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000,\n    0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000,\n    0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000,\n    0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000,\n    0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000,\n    0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000,\n    0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000,\n    0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000,\n    0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000,\n    0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000,\n    0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000,\n    0x945b07b200000000},\n   {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000,\n    0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000,\n    0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000,\n    0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000,\n    0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000,\n    0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000,\n    0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000,\n    0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000,\n    0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000,\n    0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000,\n    0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000,\n    0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000,\n    0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000,\n    0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000,\n    0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000,\n    0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000,\n    0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000,\n    0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000,\n    0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000,\n    0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000,\n    0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000,\n    0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000,\n    0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000,\n    0x149f066100000000, 0xef839db200000000, 0x468814fc00000000,\n    0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000,\n    0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000,\n    0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000,\n    0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000,\n    0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000,\n    0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000,\n    0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000,\n    0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000,\n    0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000,\n    0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000,\n    0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000,\n    0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000,\n    0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000,\n    0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000,\n    0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000,\n    0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000,\n    0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000,\n    0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000,\n    0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000,\n    0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000,\n    0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000,\n    0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000,\n    0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000,\n    0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000,\n    0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000,\n    0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000,\n    0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000,\n    0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000,\n    0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000,\n    0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000,\n    0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000,\n    0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000,\n    0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000,\n    0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000,\n    0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000,\n    0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000,\n    0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000,\n    0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000,\n    0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000,\n    0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000,\n    0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000,\n    0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000,\n    0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000,\n    0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000,\n    0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000,\n    0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000,\n    0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000,\n    0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000,\n    0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000,\n    0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000,\n    0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000,\n    0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000,\n    0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000,\n    0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000,\n    0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000,\n    0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000,\n    0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000,\n    0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000,\n    0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000,\n    0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000,\n    0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000,\n    0x0650d0f700000000},\n   {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000,\n    0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000,\n    0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000,\n    0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000,\n    0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000,\n    0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000,\n    0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000,\n    0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000,\n    0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000,\n    0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000,\n    0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000,\n    0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000,\n    0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000,\n    0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000,\n    0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000,\n    0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000,\n    0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000,\n    0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000,\n    0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000,\n    0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000,\n    0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000,\n    0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000,\n    0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000,\n    0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000,\n    0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000,\n    0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000,\n    0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000,\n    0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000,\n    0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000,\n    0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000,\n    0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000,\n    0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000,\n    0xc702c15700000000, 0x809085f800000000, 0x082039d200000000,\n    0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000,\n    0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000,\n    0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000,\n    0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000,\n    0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000,\n    0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000,\n    0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000,\n    0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000,\n    0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000,\n    0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000,\n    0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000,\n    0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000,\n    0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000,\n    0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000,\n    0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000,\n    0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000,\n    0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000,\n    0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000,\n    0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000,\n    0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000,\n    0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000,\n    0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000,\n    0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000,\n    0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000,\n    0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000,\n    0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000,\n    0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000,\n    0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000,\n    0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000,\n    0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000,\n    0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000,\n    0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000,\n    0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000,\n    0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000,\n    0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000,\n    0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000,\n    0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000,\n    0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000,\n    0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000,\n    0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000,\n    0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000,\n    0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000,\n    0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000,\n    0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000,\n    0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000,\n    0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000,\n    0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000,\n    0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000,\n    0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000,\n    0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000,\n    0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000,\n    0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000,\n    0x657594e900000000}};\n\n#else /* W == 4 */\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,\n    0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,\n    0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,\n    0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,\n    0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,\n    0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,\n    0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,\n    0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,\n    0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,\n    0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,\n    0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,\n    0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,\n    0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,\n    0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,\n    0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,\n    0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,\n    0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,\n    0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,\n    0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,\n    0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,\n    0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,\n    0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,\n    0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,\n    0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,\n    0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,\n    0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,\n    0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,\n    0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,\n    0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,\n    0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,\n    0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,\n    0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,\n    0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,\n    0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,\n    0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,\n    0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,\n    0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,\n    0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,\n    0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,\n    0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,\n    0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,\n    0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,\n    0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,\n    0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,\n    0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,\n    0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,\n    0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,\n    0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,\n    0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,\n    0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,\n    0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,\n    0xd8ac6b35},\n   {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,\n    0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,\n    0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,\n    0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,\n    0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,\n    0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,\n    0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,\n    0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,\n    0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,\n    0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,\n    0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,\n    0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,\n    0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,\n    0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,\n    0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,\n    0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,\n    0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,\n    0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,\n    0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,\n    0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,\n    0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,\n    0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,\n    0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,\n    0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,\n    0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,\n    0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,\n    0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,\n    0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,\n    0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,\n    0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,\n    0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,\n    0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,\n    0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,\n    0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,\n    0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,\n    0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,\n    0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,\n    0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,\n    0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,\n    0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,\n    0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,\n    0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,\n    0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,\n    0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,\n    0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,\n    0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,\n    0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,\n    0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,\n    0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,\n    0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,\n    0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,\n    0xa140efa8},\n   {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,\n    0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,\n    0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,\n    0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,\n    0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,\n    0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,\n    0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,\n    0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,\n    0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,\n    0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,\n    0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,\n    0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,\n    0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,\n    0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,\n    0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,\n    0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,\n    0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,\n    0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,\n    0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,\n    0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,\n    0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,\n    0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,\n    0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,\n    0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,\n    0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,\n    0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,\n    0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,\n    0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,\n    0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,\n    0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,\n    0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,\n    0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,\n    0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,\n    0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,\n    0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,\n    0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,\n    0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,\n    0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,\n    0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,\n    0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,\n    0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,\n    0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,\n    0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,\n    0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,\n    0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,\n    0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,\n    0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,\n    0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,\n    0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,\n    0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,\n    0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,\n    0x917cd6a1},\n   {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,\n    0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,\n    0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,\n    0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,\n    0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,\n    0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,\n    0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,\n    0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,\n    0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,\n    0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,\n    0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,\n    0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,\n    0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,\n    0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,\n    0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,\n    0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,\n    0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,\n    0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,\n    0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,\n    0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,\n    0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,\n    0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,\n    0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,\n    0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,\n    0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,\n    0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,\n    0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,\n    0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,\n    0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,\n    0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,\n    0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,\n    0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,\n    0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,\n    0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,\n    0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,\n    0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,\n    0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,\n    0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,\n    0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,\n    0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,\n    0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,\n    0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,\n    0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,\n    0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,\n    0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,\n    0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,\n    0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,\n    0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,\n    0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,\n    0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,\n    0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,\n    0x18ba364e}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873,\n    0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661,\n    0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441,\n    0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44,\n    0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1,\n    0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05,\n    0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa,\n    0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e,\n    0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb,\n    0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be,\n    0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e,\n    0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c,\n    0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d,\n    0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9,\n    0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f,\n    0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b,\n    0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39,\n    0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b,\n    0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b,\n    0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20,\n    0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595,\n    0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61,\n    0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0,\n    0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644,\n    0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1,\n    0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d,\n    0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d,\n    0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f,\n    0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad,\n    0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359,\n    0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f,\n    0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b,\n    0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7,\n    0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5,\n    0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5,\n    0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0,\n    0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65,\n    0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091,\n    0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633,\n    0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7,\n    0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272,\n    0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77,\n    0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57,\n    0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145,\n    0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9,\n    0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d,\n    0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb,\n    0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f,\n    0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad,\n    0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf,\n    0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f,\n    0x4e36ba18},\n   {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b,\n    0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8,\n    0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19,\n    0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4,\n    0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239,\n    0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd,\n    0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258,\n    0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc,\n    0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41,\n    0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c,\n    0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d,\n    0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e,\n    0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba,\n    0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e,\n    0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8,\n    0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c,\n    0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f,\n    0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c,\n    0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d,\n    0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d,\n    0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0,\n    0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014,\n    0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc,\n    0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628,\n    0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5,\n    0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941,\n    0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0,\n    0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53,\n    0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880,\n    0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264,\n    0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92,\n    0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776,\n    0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8,\n    0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b,\n    0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea,\n    0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837,\n    0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca,\n    0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e,\n    0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211,\n    0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5,\n    0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08,\n    0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5,\n    0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934,\n    0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7,\n    0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049,\n    0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad,\n    0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b,\n    0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf,\n    0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c,\n    0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f,\n    0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e,\n    0xa1d67c91},\n   {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9,\n    0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de,\n    0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94,\n    0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0,\n    0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a,\n    0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924,\n    0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052,\n    0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c,\n    0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6,\n    0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2,\n    0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8,\n    0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f,\n    0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d,\n    0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273,\n    0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30,\n    0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e,\n    0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7,\n    0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980,\n    0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca,\n    0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8,\n    0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62,\n    0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c,\n    0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c,\n    0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032,\n    0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798,\n    0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d,\n    0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07,\n    0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630,\n    0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389,\n    0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7,\n    0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4,\n    0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca,\n    0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55,\n    0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662,\n    0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828,\n    0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c,\n    0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6,\n    0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98,\n    0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3,\n    0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d,\n    0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037,\n    0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913,\n    0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759,\n    0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e,\n    0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1,\n    0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf,\n    0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c,\n    0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2,\n    0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b,\n    0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c,\n    0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276,\n    0xa8ef40a1},\n   {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e,\n    0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8,\n    0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819,\n    0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f,\n    0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d,\n    0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756,\n    0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0,\n    0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb,\n    0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9,\n    0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f,\n    0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e,\n    0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8,\n    0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835,\n    0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e,\n    0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62,\n    0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749,\n    0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b,\n    0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d,\n    0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc,\n    0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80,\n    0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2,\n    0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599,\n    0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05,\n    0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e,\n    0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c,\n    0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e,\n    0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef,\n    0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359,\n    0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b,\n    0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0,\n    0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc,\n    0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7,\n    0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f,\n    0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189,\n    0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568,\n    0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e,\n    0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c,\n    0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27,\n    0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794,\n    0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf,\n    0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d,\n    0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db,\n    0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a,\n    0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c,\n    0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544,\n    0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f,\n    0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013,\n    0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38,\n    0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea,\n    0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c,\n    0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd,\n    0x356bacd8}};\n\n#endif\n\n#endif\n\n#if N == 6\n\n#if W == 8\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370,\n    0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d,\n    0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69,\n    0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426,\n    0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3,\n    0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f,\n    0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c,\n    0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490,\n    0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155,\n    0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a,\n    0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e,\n    0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603,\n    0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349,\n    0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5,\n    0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50,\n    0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc,\n    0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b,\n    0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76,\n    0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862,\n    0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9,\n    0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c,\n    0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0,\n    0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937,\n    0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b,\n    0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e,\n    0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e,\n    0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a,\n    0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357,\n    0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0,\n    0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c,\n    0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9,\n    0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165,\n    0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766,\n    0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b,\n    0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f,\n    0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030,\n    0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5,\n    0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59,\n    0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63,\n    0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf,\n    0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a,\n    0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845,\n    0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51,\n    0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c,\n    0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f,\n    0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3,\n    0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46,\n    0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea,\n    0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d,\n    0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60,\n    0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74,\n    0x8568a0a8},\n   {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5,\n    0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf,\n    0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5,\n    0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba,\n    0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf,\n    0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f,\n    0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0,\n    0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450,\n    0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55,\n    0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a,\n    0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620,\n    0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a,\n    0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454,\n    0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4,\n    0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534,\n    0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584,\n    0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694,\n    0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e,\n    0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4,\n    0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1,\n    0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4,\n    0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164,\n    0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1,\n    0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911,\n    0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314,\n    0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c,\n    0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6,\n    0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec,\n    0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc,\n    0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c,\n    0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c,\n    0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c,\n    0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716,\n    0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c,\n    0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676,\n    0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879,\n    0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c,\n    0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc,\n    0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77,\n    0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7,\n    0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2,\n    0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd,\n    0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7,\n    0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad,\n    0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897,\n    0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827,\n    0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7,\n    0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947,\n    0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57,\n    0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d,\n    0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37,\n    0x0d907052},\n   {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d,\n    0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89,\n    0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31,\n    0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81,\n    0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e,\n    0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0,\n    0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f,\n    0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291,\n    0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e,\n    0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e,\n    0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936,\n    0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2,\n    0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13,\n    0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d,\n    0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f,\n    0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1,\n    0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a,\n    0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae,\n    0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516,\n    0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f,\n    0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20,\n    0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe,\n    0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28,\n    0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6,\n    0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419,\n    0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5,\n    0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d,\n    0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889,\n    0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412,\n    0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c,\n    0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e,\n    0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0,\n    0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02,\n    0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986,\n    0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e,\n    0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e,\n    0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221,\n    0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf,\n    0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913,\n    0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d,\n    0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622,\n    0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592,\n    0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a,\n    0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae,\n    0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c,\n    0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82,\n    0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20,\n    0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe,\n    0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025,\n    0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1,\n    0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719,\n    0xfd1a6c8a},\n   {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3,\n    0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb,\n    0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d,\n    0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb,\n    0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9,\n    0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156,\n    0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045,\n    0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa,\n    0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8,\n    0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e,\n    0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8,\n    0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0,\n    0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38,\n    0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87,\n    0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46,\n    0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9,\n    0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585,\n    0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d,\n    0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb,\n    0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531,\n    0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03,\n    0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc,\n    0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33,\n    0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c,\n    0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be,\n    0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d,\n    0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b,\n    0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303,\n    0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f,\n    0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0,\n    0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801,\n    0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe,\n    0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e,\n    0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346,\n    0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620,\n    0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776,\n    0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844,\n    0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb,\n    0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0,\n    0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f,\n    0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d,\n    0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b,\n    0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d,\n    0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75,\n    0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795,\n    0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a,\n    0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb,\n    0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354,\n    0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28,\n    0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30,\n    0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856,\n    0x7895f01a},\n   {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188,\n    0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33,\n    0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d,\n    0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445,\n    0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2,\n    0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058,\n    0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43,\n    0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9,\n    0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e,\n    0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06,\n    0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228,\n    0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93,\n    0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e,\n    0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4,\n    0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b,\n    0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371,\n    0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265,\n    0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede,\n    0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0,\n    0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f,\n    0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8,\n    0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32,\n    0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae,\n    0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544,\n    0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3,\n    0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f,\n    0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911,\n    0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa,\n    0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be,\n    0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54,\n    0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b,\n    0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1,\n    0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652,\n    0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9,\n    0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7,\n    0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f,\n    0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68,\n    0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782,\n    0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797,\n    0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d,\n    0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a,\n    0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2,\n    0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc,\n    0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647,\n    0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4,\n    0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e,\n    0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41,\n    0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab,\n    0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf,\n    0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904,\n    0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a,\n    0x9239b848},\n   {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad,\n    0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0,\n    0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40,\n    0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b,\n    0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d,\n    0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b,\n    0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb,\n    0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d,\n    0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b,\n    0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0,\n    0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840,\n    0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d,\n    0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b,\n    0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d,\n    0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6,\n    0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0,\n    0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580,\n    0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd,\n    0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d,\n    0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b,\n    0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d,\n    0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b,\n    0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6,\n    0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0,\n    0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6,\n    0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c,\n    0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c,\n    0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461,\n    0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841,\n    0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317,\n    0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac,\n    0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa,\n    0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7,\n    0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba,\n    0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a,\n    0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161,\n    0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777,\n    0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21,\n    0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a,\n    0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc,\n    0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da,\n    0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1,\n    0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01,\n    0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c,\n    0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241,\n    0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917,\n    0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac,\n    0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa,\n    0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da,\n    0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397,\n    0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537,\n    0xeb36d3cc},\n   {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b,\n    0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059,\n    0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251,\n    0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d,\n    0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9,\n    0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c,\n    0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41,\n    0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4,\n    0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10,\n    0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c,\n    0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54,\n    0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476,\n    0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8,\n    0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d,\n    0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92,\n    0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307,\n    0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad,\n    0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f,\n    0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87,\n    0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17,\n    0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3,\n    0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46,\n    0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197,\n    0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02,\n    0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6,\n    0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e,\n    0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96,\n    0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4,\n    0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e,\n    0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b,\n    0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934,\n    0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1,\n    0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7,\n    0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5,\n    0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd,\n    0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1,\n    0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475,\n    0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0,\n    0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155,\n    0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0,\n    0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304,\n    0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348,\n    0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140,\n    0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862,\n    0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14,\n    0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181,\n    0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e,\n    0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab,\n    0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01,\n    0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523,\n    0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b,\n    0x38e5f3c5},\n   {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06,\n    0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad,\n    0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509,\n    0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba,\n    0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414,\n    0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3,\n    0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733,\n    0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994,\n    0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a,\n    0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889,\n    0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d,\n    0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386,\n    0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621,\n    0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886,\n    0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e,\n    0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389,\n    0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f,\n    0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294,\n    0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30,\n    0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3,\n    0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d,\n    0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba,\n    0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a,\n    0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad,\n    0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03,\n    0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2,\n    0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306,\n    0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad,\n    0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b,\n    0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc,\n    0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914,\n    0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3,\n    0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435,\n    0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e,\n    0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a,\n    0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589,\n    0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27,\n    0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080,\n    0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21,\n    0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586,\n    0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28,\n    0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b,\n    0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f,\n    0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94,\n    0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12,\n    0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5,\n    0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d,\n    0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba,\n    0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c,\n    0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7,\n    0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103,\n    0x3d3101a2}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000,\n    0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000,\n    0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000,\n    0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000,\n    0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000,\n    0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000,\n    0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000,\n    0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000,\n    0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000,\n    0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000,\n    0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000,\n    0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000,\n    0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000,\n    0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000,\n    0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000,\n    0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000,\n    0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000,\n    0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000,\n    0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000,\n    0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000,\n    0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000,\n    0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000,\n    0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000,\n    0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000,\n    0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000,\n    0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000,\n    0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000,\n    0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000,\n    0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000,\n    0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000,\n    0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000,\n    0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000,\n    0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000,\n    0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000,\n    0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000,\n    0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000,\n    0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000,\n    0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000,\n    0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000,\n    0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000,\n    0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000,\n    0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000,\n    0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000,\n    0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000,\n    0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000,\n    0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000,\n    0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000,\n    0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000,\n    0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000,\n    0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000,\n    0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000,\n    0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000,\n    0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000,\n    0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000,\n    0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000,\n    0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000,\n    0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000,\n    0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000,\n    0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000,\n    0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000,\n    0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000,\n    0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000,\n    0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000,\n    0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000,\n    0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000,\n    0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000,\n    0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000,\n    0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000,\n    0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000,\n    0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000,\n    0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000,\n    0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000,\n    0x3688267d00000000, 0x9718319500000000, 0x35af787600000000,\n    0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000,\n    0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000,\n    0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000,\n    0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000,\n    0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000,\n    0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000,\n    0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000,\n    0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000,\n    0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000,\n    0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000,\n    0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000,\n    0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000,\n    0xa201313d00000000},\n   {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000,\n    0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000,\n    0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000,\n    0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000,\n    0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000,\n    0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000,\n    0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000,\n    0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000,\n    0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000,\n    0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000,\n    0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000,\n    0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000,\n    0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000,\n    0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000,\n    0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000,\n    0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000,\n    0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000,\n    0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000,\n    0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000,\n    0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000,\n    0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000,\n    0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000,\n    0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000,\n    0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000,\n    0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000,\n    0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000,\n    0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000,\n    0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000,\n    0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000,\n    0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000,\n    0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000,\n    0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000,\n    0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000,\n    0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000,\n    0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000,\n    0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000,\n    0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000,\n    0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000,\n    0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000,\n    0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000,\n    0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000,\n    0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000,\n    0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000,\n    0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000,\n    0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000,\n    0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000,\n    0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000,\n    0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000,\n    0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000,\n    0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000,\n    0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000,\n    0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000,\n    0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000,\n    0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000,\n    0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000,\n    0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000,\n    0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000,\n    0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000,\n    0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000,\n    0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000,\n    0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000,\n    0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000,\n    0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000,\n    0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000,\n    0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000,\n    0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000,\n    0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000,\n    0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000,\n    0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000,\n    0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000,\n    0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000,\n    0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000,\n    0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000,\n    0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000,\n    0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000,\n    0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000,\n    0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000,\n    0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000,\n    0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000,\n    0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000,\n    0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000,\n    0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000,\n    0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000,\n    0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000,\n    0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000,\n    0xc5f3e53800000000},\n   {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000,\n    0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000,\n    0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000,\n    0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000,\n    0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000,\n    0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000,\n    0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000,\n    0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000,\n    0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000,\n    0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000,\n    0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000,\n    0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000,\n    0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000,\n    0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000,\n    0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000,\n    0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000,\n    0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000,\n    0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000,\n    0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000,\n    0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000,\n    0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000,\n    0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000,\n    0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000,\n    0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000,\n    0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000,\n    0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000,\n    0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000,\n    0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000,\n    0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000,\n    0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000,\n    0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000,\n    0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000,\n    0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000,\n    0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000,\n    0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000,\n    0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000,\n    0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000,\n    0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000,\n    0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000,\n    0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000,\n    0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000,\n    0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000,\n    0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000,\n    0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000,\n    0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000,\n    0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000,\n    0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000,\n    0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000,\n    0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000,\n    0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000,\n    0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000,\n    0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000,\n    0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000,\n    0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000,\n    0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000,\n    0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000,\n    0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000,\n    0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000,\n    0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000,\n    0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000,\n    0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000,\n    0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000,\n    0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000,\n    0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000,\n    0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000,\n    0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000,\n    0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000,\n    0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000,\n    0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000,\n    0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000,\n    0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000,\n    0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000,\n    0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000,\n    0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000,\n    0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000,\n    0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000,\n    0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000,\n    0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000,\n    0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000,\n    0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000,\n    0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000,\n    0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000,\n    0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000,\n    0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000,\n    0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000,\n    0xccd336eb00000000},\n   {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000,\n    0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000,\n    0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000,\n    0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000,\n    0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000,\n    0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000,\n    0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000,\n    0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000,\n    0xb249204500000000, 0xd071086f00000000, 0x7639701100000000,\n    0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000,\n    0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000,\n    0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000,\n    0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000,\n    0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000,\n    0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000,\n    0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000,\n    0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000,\n    0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000,\n    0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000,\n    0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000,\n    0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000,\n    0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000,\n    0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000,\n    0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000,\n    0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000,\n    0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000,\n    0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000,\n    0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000,\n    0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000,\n    0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000,\n    0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000,\n    0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000,\n    0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000,\n    0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000,\n    0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000,\n    0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000,\n    0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000,\n    0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000,\n    0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000,\n    0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000,\n    0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000,\n    0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000,\n    0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000,\n    0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000,\n    0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000,\n    0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000,\n    0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000,\n    0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000,\n    0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000,\n    0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000,\n    0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000,\n    0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000,\n    0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000,\n    0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000,\n    0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000,\n    0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000,\n    0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000,\n    0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000,\n    0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000,\n    0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000,\n    0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000,\n    0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000,\n    0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000,\n    0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000,\n    0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000,\n    0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000,\n    0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000,\n    0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000,\n    0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000,\n    0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000,\n    0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000,\n    0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000,\n    0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000,\n    0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000,\n    0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000,\n    0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000,\n    0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000,\n    0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000,\n    0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000,\n    0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000,\n    0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000,\n    0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000,\n    0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000,\n    0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000,\n    0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000,\n    0x48b8399200000000},\n   {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000,\n    0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000,\n    0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000,\n    0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000,\n    0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000,\n    0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000,\n    0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000,\n    0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000,\n    0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000,\n    0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000,\n    0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000,\n    0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000,\n    0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000,\n    0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000,\n    0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000,\n    0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000,\n    0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000,\n    0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000,\n    0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000,\n    0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000,\n    0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000,\n    0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000,\n    0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000,\n    0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000,\n    0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000,\n    0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000,\n    0xb521428400000000, 0xf909d42700000000, 0x762efede00000000,\n    0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000,\n    0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000,\n    0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000,\n    0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000,\n    0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000,\n    0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000,\n    0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000,\n    0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000,\n    0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000,\n    0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000,\n    0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000,\n    0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000,\n    0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000,\n    0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000,\n    0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000,\n    0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000,\n    0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000,\n    0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000,\n    0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000,\n    0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000,\n    0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000,\n    0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000,\n    0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000,\n    0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000,\n    0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000,\n    0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000,\n    0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000,\n    0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000,\n    0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000,\n    0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000,\n    0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000,\n    0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000,\n    0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000,\n    0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000,\n    0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000,\n    0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000,\n    0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000,\n    0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000,\n    0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000,\n    0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000,\n    0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000,\n    0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000,\n    0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000,\n    0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000,\n    0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000,\n    0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000,\n    0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000,\n    0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000,\n    0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000,\n    0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000,\n    0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000,\n    0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000,\n    0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000,\n    0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000,\n    0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000,\n    0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000,\n    0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000,\n    0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000,\n    0x1af0957800000000},\n   {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000,\n    0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000,\n    0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000,\n    0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000,\n    0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000,\n    0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000,\n    0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000,\n    0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000,\n    0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000,\n    0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000,\n    0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000,\n    0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000,\n    0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000,\n    0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000,\n    0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000,\n    0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000,\n    0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000,\n    0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000,\n    0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000,\n    0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000,\n    0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000,\n    0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000,\n    0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000,\n    0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000,\n    0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000,\n    0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000,\n    0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000,\n    0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000,\n    0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000,\n    0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000,\n    0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000,\n    0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000,\n    0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000,\n    0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000,\n    0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000,\n    0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000,\n    0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000,\n    0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000,\n    0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000,\n    0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000,\n    0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000,\n    0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000,\n    0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000,\n    0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000,\n    0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000,\n    0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000,\n    0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000,\n    0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000,\n    0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000,\n    0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000,\n    0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000,\n    0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000,\n    0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000,\n    0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000,\n    0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000,\n    0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000,\n    0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000,\n    0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000,\n    0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000,\n    0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000,\n    0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000,\n    0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000,\n    0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000,\n    0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000,\n    0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000,\n    0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000,\n    0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000,\n    0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000,\n    0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000,\n    0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000,\n    0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000,\n    0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000,\n    0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000,\n    0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000,\n    0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000,\n    0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000,\n    0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000,\n    0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000,\n    0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000,\n    0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000,\n    0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000,\n    0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000,\n    0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000,\n    0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000,\n    0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000,\n    0x8a6c1afd00000000},\n   {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000,\n    0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000,\n    0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000,\n    0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000,\n    0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000,\n    0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000,\n    0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000,\n    0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000,\n    0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000,\n    0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000,\n    0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000,\n    0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000,\n    0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000,\n    0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000,\n    0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000,\n    0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000,\n    0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000,\n    0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000,\n    0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000,\n    0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000,\n    0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000,\n    0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000,\n    0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000,\n    0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000,\n    0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000,\n    0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000,\n    0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000,\n    0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000,\n    0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000,\n    0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000,\n    0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000,\n    0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000,\n    0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000,\n    0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000,\n    0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000,\n    0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000,\n    0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000,\n    0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000,\n    0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000,\n    0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000,\n    0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000,\n    0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000,\n    0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000,\n    0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000,\n    0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000,\n    0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000,\n    0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000,\n    0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000,\n    0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000,\n    0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000,\n    0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000,\n    0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000,\n    0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000,\n    0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000,\n    0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000,\n    0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000,\n    0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000,\n    0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000,\n    0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000,\n    0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000,\n    0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000,\n    0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000,\n    0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000,\n    0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000,\n    0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000,\n    0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000,\n    0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000,\n    0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000,\n    0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000,\n    0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000,\n    0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000,\n    0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000,\n    0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000,\n    0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000,\n    0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000,\n    0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000,\n    0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000,\n    0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000,\n    0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000,\n    0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000,\n    0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000,\n    0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000,\n    0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000,\n    0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000,\n    0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000,\n    0x5270900d00000000},\n   {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000,\n    0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000,\n    0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000,\n    0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000,\n    0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000,\n    0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000,\n    0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000,\n    0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000,\n    0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000,\n    0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000,\n    0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000,\n    0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000,\n    0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000,\n    0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000,\n    0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000,\n    0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000,\n    0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000,\n    0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000,\n    0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000,\n    0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000,\n    0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000,\n    0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000,\n    0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000,\n    0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000,\n    0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000,\n    0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000,\n    0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000,\n    0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000,\n    0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000,\n    0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000,\n    0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000,\n    0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000,\n    0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000,\n    0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000,\n    0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000,\n    0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000,\n    0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000,\n    0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000,\n    0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000,\n    0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000,\n    0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000,\n    0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000,\n    0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000,\n    0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000,\n    0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000,\n    0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000,\n    0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000,\n    0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000,\n    0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000,\n    0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000,\n    0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000,\n    0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000,\n    0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000,\n    0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000,\n    0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000,\n    0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000,\n    0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000,\n    0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000,\n    0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000,\n    0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000,\n    0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000,\n    0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000,\n    0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000,\n    0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000,\n    0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000,\n    0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000,\n    0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000,\n    0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000,\n    0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000,\n    0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000,\n    0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000,\n    0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000,\n    0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000,\n    0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000,\n    0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000,\n    0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000,\n    0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000,\n    0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000,\n    0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000,\n    0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000,\n    0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000,\n    0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000,\n    0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000,\n    0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000,\n    0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000,\n    0xa8a0688500000000}};\n\n#else /* W == 4 */\n\nlocal const z_crc_t FAR crc_braid_table[][256] = {\n   {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,\n    0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,\n    0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,\n    0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,\n    0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,\n    0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,\n    0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,\n    0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,\n    0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,\n    0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,\n    0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,\n    0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,\n    0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,\n    0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,\n    0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,\n    0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,\n    0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,\n    0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,\n    0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,\n    0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,\n    0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,\n    0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,\n    0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,\n    0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,\n    0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,\n    0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,\n    0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,\n    0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,\n    0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,\n    0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,\n    0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,\n    0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,\n    0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,\n    0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,\n    0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,\n    0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,\n    0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,\n    0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,\n    0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,\n    0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,\n    0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,\n    0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,\n    0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,\n    0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,\n    0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,\n    0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,\n    0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,\n    0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,\n    0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,\n    0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,\n    0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,\n    0x09cd8551},\n   {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,\n    0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,\n    0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,\n    0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,\n    0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,\n    0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,\n    0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,\n    0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,\n    0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,\n    0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,\n    0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,\n    0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,\n    0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,\n    0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,\n    0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,\n    0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,\n    0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,\n    0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,\n    0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,\n    0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,\n    0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,\n    0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,\n    0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,\n    0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,\n    0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,\n    0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,\n    0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,\n    0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,\n    0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,\n    0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,\n    0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,\n    0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,\n    0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,\n    0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,\n    0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,\n    0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,\n    0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,\n    0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,\n    0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,\n    0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,\n    0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,\n    0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,\n    0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,\n    0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,\n    0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,\n    0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,\n    0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,\n    0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,\n    0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,\n    0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,\n    0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,\n    0x7bc97a0c},\n   {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,\n    0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,\n    0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,\n    0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,\n    0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,\n    0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,\n    0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,\n    0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,\n    0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,\n    0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,\n    0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,\n    0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,\n    0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,\n    0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,\n    0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,\n    0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,\n    0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,\n    0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,\n    0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,\n    0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,\n    0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,\n    0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,\n    0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,\n    0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,\n    0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,\n    0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,\n    0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,\n    0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,\n    0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,\n    0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,\n    0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,\n    0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,\n    0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,\n    0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,\n    0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,\n    0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,\n    0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,\n    0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,\n    0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,\n    0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,\n    0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,\n    0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,\n    0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,\n    0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,\n    0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,\n    0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,\n    0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,\n    0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,\n    0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,\n    0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,\n    0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,\n    0x7851a2ca},\n   {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,\n    0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,\n    0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,\n    0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,\n    0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,\n    0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,\n    0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,\n    0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,\n    0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,\n    0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,\n    0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,\n    0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,\n    0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,\n    0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,\n    0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,\n    0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,\n    0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,\n    0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,\n    0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,\n    0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,\n    0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,\n    0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,\n    0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,\n    0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,\n    0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,\n    0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,\n    0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,\n    0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,\n    0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,\n    0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,\n    0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,\n    0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,\n    0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,\n    0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,\n    0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,\n    0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,\n    0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,\n    0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,\n    0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,\n    0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,\n    0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,\n    0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,\n    0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,\n    0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,\n    0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,\n    0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,\n    0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,\n    0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,\n    0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,\n    0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,\n    0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,\n    0x566b6848}};\n\nlocal const z_word_t FAR crc_braid_big_table[][256] = {\n   {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912,\n    0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba,\n    0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3,\n    0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30,\n    0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e,\n    0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3,\n    0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73,\n    0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe,\n    0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0,\n    0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643,\n    0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a,\n    0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082,\n    0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4,\n    0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279,\n    0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735,\n    0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8,\n    0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad,\n    0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05,\n    0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c,\n    0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718,\n    0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46,\n    0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb,\n    0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc,\n    0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41,\n    0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f,\n    0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad,\n    0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4,\n    0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c,\n    0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779,\n    0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4,\n    0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8,\n    0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235,\n    0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7,\n    0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f,\n    0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476,\n    0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195,\n    0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb,\n    0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46,\n    0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622,\n    0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af,\n    0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1,\n    0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12,\n    0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b,\n    0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3,\n    0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51,\n    0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc,\n    0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90,\n    0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d,\n    0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708,\n    0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0,\n    0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9,\n    0x48686b56},\n   {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c,\n    0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae,\n    0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb,\n    0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90,\n    0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410,\n    0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b,\n    0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6,\n    0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed,\n    0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d,\n    0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036,\n    0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953,\n    0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1,\n    0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca,\n    0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781,\n    0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d,\n    0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416,\n    0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f,\n    0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd,\n    0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8,\n    0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b,\n    0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb,\n    0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0,\n    0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5,\n    0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e,\n    0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e,\n    0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558,\n    0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d,\n    0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf,\n    0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6,\n    0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad,\n    0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971,\n    0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a,\n    0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b,\n    0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969,\n    0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c,\n    0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57,\n    0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7,\n    0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c,\n    0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab,\n    0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0,\n    0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160,\n    0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b,\n    0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e,\n    0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac,\n    0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d,\n    0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546,\n    0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a,\n    0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1,\n    0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8,\n    0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a,\n    0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f,\n    0xcaa25178},\n   {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00,\n    0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b,\n    0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed,\n    0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777,\n    0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01,\n    0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a,\n    0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef,\n    0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74,\n    0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002,\n    0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498,\n    0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee,\n    0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75,\n    0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05,\n    0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e,\n    0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8,\n    0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73,\n    0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404,\n    0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f,\n    0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9,\n    0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71,\n    0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607,\n    0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c,\n    0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb,\n    0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470,\n    0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806,\n    0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790,\n    0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6,\n    0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d,\n    0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a,\n    0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991,\n    0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7,\n    0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c,\n    0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09,\n    0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92,\n    0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4,\n    0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e,\n    0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08,\n    0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593,\n    0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3,\n    0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778,\n    0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e,\n    0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94,\n    0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2,\n    0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079,\n    0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c,\n    0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497,\n    0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1,\n    0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a,\n    0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d,\n    0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396,\n    0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0,\n    0x0c7ac97b},\n   {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669,\n    0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853,\n    0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062,\n    0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527,\n    0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad,\n    0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545,\n    0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27,\n    0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf,\n    0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45,\n    0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800,\n    0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031,\n    0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b,\n    0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26,\n    0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce,\n    0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d,\n    0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5,\n    0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130,\n    0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a,\n    0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b,\n    0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480,\n    0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a,\n    0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2,\n    0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e,\n    0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996,\n    0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c,\n    0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc,\n    0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd,\n    0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7,\n    0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232,\n    0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da,\n    0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439,\n    0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1,\n    0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da,\n    0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0,\n    0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1,\n    0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94,\n    0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e,\n    0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6,\n    0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2,\n    0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a,\n    0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0,\n    0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95,\n    0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4,\n    0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e,\n    0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395,\n    0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d,\n    0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e,\n    0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676,\n    0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83,\n    0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9,\n    0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888,\n    0x5185cd09}};\n\n#endif\n\n#endif\n\n#endif\n\nlocal const z_crc_t FAR x2n_table[] = {\n    0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000,\n    0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467,\n    0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0,\n    0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169,\n    0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37,\n    0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a,\n    0xc40ba6d0, 0xc4e22c3c};\n"
  },
  {
    "path": "third_party/libz/deflate.c",
    "content": "// clang-format off\n/* deflate.c -- compress data using the deflation algorithm\n * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/*\n *  ALGORITHM\n *\n *      The \"deflation\" process depends on being able to identify portions\n *      of the input text which are identical to earlier input (within a\n *      sliding window trailing behind the input currently being processed).\n *\n *      The most straightforward technique turns out to be the fastest for\n *      most input files: try all possible matches and select the longest.\n *      The key feature of this algorithm is that insertions into the string\n *      dictionary are very simple and thus fast, and deletions are avoided\n *      completely. Insertions are performed at each input character, whereas\n *      string matches are performed only when the previous match ends. So it\n *      is preferable to spend more time in matches to allow very fast string\n *      insertions and avoid deletions. The matching algorithm for small\n *      strings is inspired from that of Rabin & Karp. A brute force approach\n *      is used to find longer strings when a small match has been found.\n *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze\n *      (by Leonid Broukhis).\n *         A previous version of this file used a more sophisticated algorithm\n *      (by Fiala and Greene) which is guaranteed to run in linear amortized\n *      time, but has a larger average cost, uses more memory and is patented.\n *      However the F&G algorithm may be faster for some highly redundant\n *      files if the parameter max_chain_length (described below) is too large.\n *\n *  ACKNOWLEDGEMENTS\n *\n *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and\n *      I found it in 'freeze' written by Leonid Broukhis.\n *      Thanks to many people for bug reports and testing.\n *\n *  REFERENCES\n *\n *      Deutsch, L.P.,\"DEFLATE Compressed Data Format Specification\".\n *      Available in http://tools.ietf.org/html/rfc1951\n *\n *      A description of the Rabin and Karp algorithm is given in the book\n *         \"Algorithms\" by R. Sedgewick, Addison-Wesley, p252.\n *\n *      Fiala,E.R., and Greene,D.H.\n *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595\n *\n */\n\n/* @(#) $Id$ */\n\n#include \"third_party/libz/deflate.h\"\n\nconst char deflate_copyright[] =\n   \" deflate 1.2.13 Copyright 1995-2022 Jean-loup Gailly and Mark Adler \";\n/*\n  If you use the zlib library in a product, an acknowledgment is welcome\n  in the documentation of your product. If for some reason you cannot\n  include such an acknowledgment, I would appreciate that you keep this\n  copyright string in the executable of your product.\n */\n\n/* ===========================================================================\n *  Function prototypes.\n */\ntypedef enum {\n    need_more,      /* block not completed, need more input or more output */\n    block_done,     /* block flush performed */\n    finish_started, /* finish started, need only more output at next deflate */\n    finish_done     /* finish done, accept no more input or output */\n} block_state;\n\ntypedef block_state (*compress_func) OF((deflate_state *s, int flush));\n/* Compression function. Returns the block state after the call. */\n\nlocal int deflateStateCheck      OF((z_streamp strm));\nlocal void slide_hash     OF((deflate_state *s));\nlocal void fill_window    OF((deflate_state *s));\nlocal block_state deflate_stored OF((deflate_state *s, int flush));\nlocal block_state deflate_fast   OF((deflate_state *s, int flush));\n#ifndef FASTEST\nlocal block_state deflate_slow   OF((deflate_state *s, int flush));\n#endif\nlocal block_state deflate_rle    OF((deflate_state *s, int flush));\nlocal block_state deflate_huff   OF((deflate_state *s, int flush));\nlocal void lm_init        OF((deflate_state *s));\nlocal void putShortMSB    OF((deflate_state *s, uInt b));\nlocal void flush_pending  OF((z_streamp strm));\nlocal unsigned read_buf   OF((z_streamp strm, Bytef *buf, unsigned size));\nlocal uInt longest_match  OF((deflate_state *s, IPos cur_match));\n\n#ifdef ZLIB_DEBUG\nlocal  void check_match OF((deflate_state *s, IPos start, IPos match,\n                            int length));\n#endif\n\n/* ===========================================================================\n * Local data\n */\n\n#define NIL 0\n/* Tail of hash chains */\n\n#ifndef TOO_FAR\n#  define TOO_FAR 4096\n#endif\n/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */\n\n/* Values for max_lazy_match, good_match and max_chain_length, depending on\n * the desired pack level (0..9). The values given below have been tuned to\n * exclude worst case performance for pathological files. Better values may be\n * found for specific files.\n */\ntypedef struct config_s {\n   ush good_length; /* reduce lazy search above this match length */\n   ush max_lazy;    /* do not perform lazy search above this match length */\n   ush nice_length; /* quit search above this match length */\n   ush max_chain;\n   compress_func func;\n} config;\n\n#ifdef FASTEST\nlocal const config configuration_table[2] = {\n/*      good lazy nice chain */\n/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */\n/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* max speed, no lazy matches */\n#else\nlocal const config configuration_table[10] = {\n/*      good lazy nice chain */\n/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */\n/* 1 */ {4,    4,  8,    4, deflate_fast}, /* max speed, no lazy matches */\n/* 2 */ {4,    5, 16,    8, deflate_fast},\n/* 3 */ {4,    6, 32,   32, deflate_fast},\n\n/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */\n/* 5 */ {8,   16, 32,   32, deflate_slow},\n/* 6 */ {8,   16, 128, 128, deflate_slow},\n/* 7 */ {8,   32, 128, 256, deflate_slow},\n/* 8 */ {32, 128, 258, 1024, deflate_slow},\n/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */\n#endif\n\n/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4\n * For deflate_fast() (levels <= 3) good is ignored and lazy has a different\n * meaning.\n */\n\n/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */\n#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0))\n\n/* ===========================================================================\n * Update a hash value with the given input byte\n * IN  assertion: all calls to UPDATE_HASH are made with consecutive input\n *    characters, so that a running hash key can be computed from the previous\n *    key instead of complete recalculation each time.\n */\n#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask)\n\n\n/* ===========================================================================\n * Insert string str in the dictionary and set match_head to the previous head\n * of the hash chain (the most recent string with same hash key). Return\n * the previous length of the hash chain.\n * If this file is compiled with -DFASTEST, the compression level is forced\n * to 1, and no hash chains are maintained.\n * IN  assertion: all calls to INSERT_STRING are made with consecutive input\n *    characters and the first MIN_MATCH bytes of str are valid (except for\n *    the last MIN_MATCH-1 bytes of the input file).\n */\n#ifdef FASTEST\n#define INSERT_STRING(s, str, match_head) \\\n   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \\\n    match_head = s->head[s->ins_h], \\\n    s->head[s->ins_h] = (Pos)(str))\n#else\n#define INSERT_STRING(s, str, match_head) \\\n   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \\\n    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \\\n    s->head[s->ins_h] = (Pos)(str))\n#endif\n\n/* ===========================================================================\n * Initialize the hash table (avoiding 64K overflow for 16 bit systems).\n * prev[] will be initialized on the fly.\n */\n#define CLEAR_HASH(s) \\\n    do { \\\n        s->head[s->hash_size - 1] = NIL; \\\n        zmemzero((Bytef *)s->head, \\\n                 (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \\\n    } while (0)\n\n/* ===========================================================================\n * Slide the hash table when sliding the window down (could be avoided with 32\n * bit values at the expense of memory usage). We slide even when level == 0 to\n * keep the hash table consistent if we switch back to level > 0 later.\n */\nlocal void slide_hash(s)\n    deflate_state *s;\n{\n    unsigned n, m;\n    Posf *p;\n    uInt wsize = s->w_size;\n\n    n = s->hash_size;\n    p = &s->head[n];\n    do {\n        m = *--p;\n        *p = (Pos)(m >= wsize ? m - wsize : NIL);\n    } while (--n);\n    n = wsize;\n#ifndef FASTEST\n    p = &s->prev[n];\n    do {\n        m = *--p;\n        *p = (Pos)(m >= wsize ? m - wsize : NIL);\n        /* If n is not on any hash chain, prev[n] is garbage but\n         * its value will never be used.\n         */\n    } while (--n);\n#endif\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateInit_(strm, level, version, stream_size)\n    z_streamp strm;\n    int level;\n    const char *version;\n    int stream_size;\n{\n    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,\n                         Z_DEFAULT_STRATEGY, version, stream_size);\n    /* To do: ignore strm->next_in if we use it as window */\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,\n                  version, stream_size)\n    z_streamp strm;\n    int  level;\n    int  method;\n    int  windowBits;\n    int  memLevel;\n    int  strategy;\n    const char *version;\n    int stream_size;\n{\n    deflate_state *s;\n    int wrap = 1;\n    static const char my_version[] = ZLIB_VERSION;\n\n    if (version == Z_NULL || version[0] != my_version[0] ||\n        stream_size != sizeof(z_stream)) {\n        return Z_VERSION_ERROR;\n    }\n    if (strm == Z_NULL) return Z_STREAM_ERROR;\n\n    strm->msg = Z_NULL;\n    if (strm->zalloc == (alloc_func)0) {\n#ifdef Z_SOLO\n        return Z_STREAM_ERROR;\n#else\n        strm->zalloc = zcalloc;\n        strm->opaque = (voidpf)0;\n#endif\n    }\n    if (strm->zfree == (free_func)0)\n#ifdef Z_SOLO\n        return Z_STREAM_ERROR;\n#else\n        strm->zfree = zcfree;\n#endif\n\n#ifdef FASTEST\n    if (level != 0) level = 1;\n#else\n    if (level == Z_DEFAULT_COMPRESSION) level = 6;\n#endif\n\n    if (windowBits < 0) { /* suppress zlib wrapper */\n        wrap = 0;\n        if (windowBits < -15)\n            return Z_STREAM_ERROR;\n        windowBits = -windowBits;\n    }\n#ifdef GZIP\n    else if (windowBits > 15) {\n        wrap = 2;       /* write gzip wrapper instead */\n        windowBits -= 16;\n    }\n#endif\n    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||\n        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||\n        strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) {\n        return Z_STREAM_ERROR;\n    }\n    if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */\n    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));\n    if (s == Z_NULL) return Z_MEM_ERROR;\n    strm->state = (struct internal_state FAR *)s;\n    s->strm = strm;\n    s->status = INIT_STATE;     /* to pass state test in deflateReset() */\n\n    s->wrap = wrap;\n    s->gzhead = Z_NULL;\n    s->w_bits = (uInt)windowBits;\n    s->w_size = 1 << s->w_bits;\n    s->w_mask = s->w_size - 1;\n\n    s->hash_bits = (uInt)memLevel + 7;\n    s->hash_size = 1 << s->hash_bits;\n    s->hash_mask = s->hash_size - 1;\n    s->hash_shift =  ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH);\n\n    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));\n    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));\n    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));\n\n    s->high_water = 0;      /* nothing written to s->window yet */\n\n    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */\n\n    /* We overlay pending_buf and sym_buf. This works since the average size\n     * for length/distance pairs over any compressed block is assured to be 31\n     * bits or less.\n     *\n     * Analysis: The longest fixed codes are a length code of 8 bits plus 5\n     * extra bits, for lengths 131 to 257. The longest fixed distance codes are\n     * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest\n     * possible fixed-codes length/distance pair is then 31 bits total.\n     *\n     * sym_buf starts one-fourth of the way into pending_buf. So there are\n     * three bytes in sym_buf for every four bytes in pending_buf. Each symbol\n     * in sym_buf is three bytes -- two for the distance and one for the\n     * literal/length. As each symbol is consumed, the pointer to the next\n     * sym_buf value to read moves forward three bytes. From that symbol, up to\n     * 31 bits are written to pending_buf. The closest the written pending_buf\n     * bits gets to the next sym_buf symbol to read is just before the last\n     * code is written. At that time, 31*(n - 2) bits have been written, just\n     * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at\n     * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1\n     * symbols are written.) The closest the writing gets to what is unread is\n     * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and\n     * can range from 128 to 32768.\n     *\n     * Therefore, at a minimum, there are 142 bits of space between what is\n     * written and what is read in the overlain buffers, so the symbols cannot\n     * be overwritten by the compressed data. That space is actually 139 bits,\n     * due to the three-bit fixed-code block header.\n     *\n     * That covers the case where either Z_FIXED is specified, forcing fixed\n     * codes, or when the use of fixed codes is chosen, because that choice\n     * results in a smaller compressed block than dynamic codes. That latter\n     * condition then assures that the above analysis also covers all dynamic\n     * blocks. A dynamic-code block will only be chosen to be emitted if it has\n     * fewer bits than a fixed-code block would for the same set of symbols.\n     * Therefore its average symbol length is assured to be less than 31. So\n     * the compressed data for a dynamic block also cannot overwrite the\n     * symbols from which it is being constructed.\n     */\n\n    s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);\n    s->pending_buf_size = (ulg)s->lit_bufsize * 4;\n\n    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||\n        s->pending_buf == Z_NULL) {\n        s->status = FINISH_STATE;\n        strm->msg = ERR_MSG(Z_MEM_ERROR);\n        deflateEnd (strm);\n        return Z_MEM_ERROR;\n    }\n    s->sym_buf = s->pending_buf + s->lit_bufsize;\n    s->sym_end = (s->lit_bufsize - 1) * 3;\n    /* We avoid equality with lit_bufsize*3 because of wraparound at 64K\n     * on 16 bit machines and because stored blocks are restricted to\n     * 64K-1 bytes.\n     */\n\n    s->level = level;\n    s->strategy = strategy;\n    s->method = (Byte)method;\n\n    return deflateReset(strm);\n}\n\n/* =========================================================================\n * Check for a valid deflate stream state. Return 0 if ok, 1 if not.\n */\nlocal int deflateStateCheck(strm)\n    z_streamp strm;\n{\n    deflate_state *s;\n    if (strm == Z_NULL ||\n        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)\n        return 1;\n    s = strm->state;\n    if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE &&\n#ifdef GZIP\n                                           s->status != GZIP_STATE &&\n#endif\n                                           s->status != EXTRA_STATE &&\n                                           s->status != NAME_STATE &&\n                                           s->status != COMMENT_STATE &&\n                                           s->status != HCRC_STATE &&\n                                           s->status != BUSY_STATE &&\n                                           s->status != FINISH_STATE))\n        return 1;\n    return 0;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateSetDictionary(strm, dictionary, dictLength)\n    z_streamp strm;\n    const Bytef *dictionary;\n    uInt  dictLength;\n{\n    deflate_state *s;\n    uInt str, n;\n    int wrap;\n    unsigned avail;\n    z_const unsigned char *next;\n\n    if (deflateStateCheck(strm) || dictionary == Z_NULL)\n        return Z_STREAM_ERROR;\n    s = strm->state;\n    wrap = s->wrap;\n    if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)\n        return Z_STREAM_ERROR;\n\n    /* when using zlib wrappers, compute Adler-32 for provided dictionary */\n    if (wrap == 1)\n        strm->adler = adler32(strm->adler, dictionary, dictLength);\n    s->wrap = 0;                    /* avoid computing Adler-32 in read_buf */\n\n    /* if dictionary would fill window, just replace the history */\n    if (dictLength >= s->w_size) {\n        if (wrap == 0) {            /* already empty otherwise */\n            CLEAR_HASH(s);\n            s->strstart = 0;\n            s->block_start = 0L;\n            s->insert = 0;\n        }\n        dictionary += dictLength - s->w_size;  /* use the tail */\n        dictLength = s->w_size;\n    }\n\n    /* insert dictionary into window and hash */\n    avail = strm->avail_in;\n    next = strm->next_in;\n    strm->avail_in = dictLength;\n    strm->next_in = (z_const Bytef *)dictionary;\n    fill_window(s);\n    while (s->lookahead >= MIN_MATCH) {\n        str = s->strstart;\n        n = s->lookahead - (MIN_MATCH-1);\n        do {\n            UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);\n#ifndef FASTEST\n            s->prev[str & s->w_mask] = s->head[s->ins_h];\n#endif\n            s->head[s->ins_h] = (Pos)str;\n            str++;\n        } while (--n);\n        s->strstart = str;\n        s->lookahead = MIN_MATCH-1;\n        fill_window(s);\n    }\n    s->strstart += s->lookahead;\n    s->block_start = (long)s->strstart;\n    s->insert = s->lookahead;\n    s->lookahead = 0;\n    s->match_length = s->prev_length = MIN_MATCH-1;\n    s->match_available = 0;\n    strm->next_in = next;\n    strm->avail_in = avail;\n    s->wrap = wrap;\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateGetDictionary(strm, dictionary, dictLength)\n    z_streamp strm;\n    Bytef *dictionary;\n    uInt  *dictLength;\n{\n    deflate_state *s;\n    uInt len;\n\n    if (deflateStateCheck(strm))\n        return Z_STREAM_ERROR;\n    s = strm->state;\n    len = s->strstart + s->lookahead;\n    if (len > s->w_size)\n        len = s->w_size;\n    if (dictionary != Z_NULL && len)\n        zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len);\n    if (dictLength != Z_NULL)\n        *dictLength = len;\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateResetKeep(strm)\n    z_streamp strm;\n{\n    deflate_state *s;\n\n    if (deflateStateCheck(strm)) {\n        return Z_STREAM_ERROR;\n    }\n\n    strm->total_in = strm->total_out = 0;\n    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */\n    strm->data_type = Z_UNKNOWN;\n\n    s = (deflate_state *)strm->state;\n    s->pending = 0;\n    s->pending_out = s->pending_buf;\n\n    if (s->wrap < 0) {\n        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */\n    }\n    s->status =\n#ifdef GZIP\n        s->wrap == 2 ? GZIP_STATE :\n#endif\n        INIT_STATE;\n    strm->adler =\n#ifdef GZIP\n        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :\n#endif\n        adler32(0L, Z_NULL, 0);\n    s->last_flush = -2;\n\n    _tr_init(s);\n\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateReset(strm)\n    z_streamp strm;\n{\n    int ret;\n\n    ret = deflateResetKeep(strm);\n    if (ret == Z_OK)\n        lm_init(strm->state);\n    return ret;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateSetHeader(strm, head)\n    z_streamp strm;\n    gz_headerp head;\n{\n    if (deflateStateCheck(strm) || strm->state->wrap != 2)\n        return Z_STREAM_ERROR;\n    strm->state->gzhead = head;\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflatePending(strm, pending, bits)\n    unsigned *pending;\n    int *bits;\n    z_streamp strm;\n{\n    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;\n    if (pending != Z_NULL)\n        *pending = strm->state->pending;\n    if (bits != Z_NULL)\n        *bits = strm->state->bi_valid;\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflatePrime(strm, bits, value)\n    z_streamp strm;\n    int bits;\n    int value;\n{\n    deflate_state *s;\n    int put;\n\n    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;\n    s = strm->state;\n    if (bits < 0 || bits > 16 ||\n        s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))\n        return Z_BUF_ERROR;\n    do {\n        put = Buf_size - s->bi_valid;\n        if (put > bits)\n            put = bits;\n        s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);\n        s->bi_valid += put;\n        _tr_flush_bits(s);\n        value >>= put;\n        bits -= put;\n    } while (bits);\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateParams(strm, level, strategy)\n    z_streamp strm;\n    int level;\n    int strategy;\n{\n    deflate_state *s;\n    compress_func func;\n\n    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;\n    s = strm->state;\n\n#ifdef FASTEST\n    if (level != 0) level = 1;\n#else\n    if (level == Z_DEFAULT_COMPRESSION) level = 6;\n#endif\n    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {\n        return Z_STREAM_ERROR;\n    }\n    func = configuration_table[s->level].func;\n\n    if ((strategy != s->strategy || func != configuration_table[level].func) &&\n        s->last_flush != -2) {\n        /* Flush the last buffer: */\n        int err = deflate(strm, Z_BLOCK);\n        if (err == Z_STREAM_ERROR)\n            return err;\n        if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)\n            return Z_BUF_ERROR;\n    }\n    if (s->level != level) {\n        if (s->level == 0 && s->matches != 0) {\n            if (s->matches == 1)\n                slide_hash(s);\n            else\n                CLEAR_HASH(s);\n            s->matches = 0;\n        }\n        s->level = level;\n        s->max_lazy_match   = configuration_table[level].max_lazy;\n        s->good_match       = configuration_table[level].good_length;\n        s->nice_match       = configuration_table[level].nice_length;\n        s->max_chain_length = configuration_table[level].max_chain;\n    }\n    s->strategy = strategy;\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)\n    z_streamp strm;\n    int good_length;\n    int max_lazy;\n    int nice_length;\n    int max_chain;\n{\n    deflate_state *s;\n\n    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;\n    s = strm->state;\n    s->good_match = (uInt)good_length;\n    s->max_lazy_match = (uInt)max_lazy;\n    s->nice_match = nice_length;\n    s->max_chain_length = (uInt)max_chain;\n    return Z_OK;\n}\n\n/* =========================================================================\n * For the default windowBits of 15 and memLevel of 8, this function returns a\n * close to exact, as well as small, upper bound on the compressed size. This\n * is an expansion of ~0.03%, plus a small constant.\n *\n * For any setting other than those defaults for windowBits and memLevel, one\n * of two worst case bounds is returned. This is at most an expansion of ~4% or\n * ~13%, plus a small constant.\n *\n * Both the 0.03% and 4% derive from the overhead of stored blocks. The first\n * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second\n * is for stored blocks of 127 bytes (the worst case memLevel == 1). The\n * expansion results from five bytes of header for each stored block.\n *\n * The larger expansion of 13% results from a window size less than or equal to\n * the symbols buffer size (windowBits <= memLevel + 7). In that case some of\n * the data being compressed may have slid out of the sliding window, impeding\n * a stored block from being emitted. Then the only choice is a fixed or\n * dynamic block, where a fixed block limits the maximum expansion to 9 bits\n * per 8-bit byte, plus 10 bits for every block. The smallest block size for\n * which this can occur is 255 (memLevel == 2).\n *\n * Shifts are used to approximate divisions, for speed.\n */\nuLong ZEXPORT deflateBound(strm, sourceLen)\n    z_streamp strm;\n    uLong sourceLen;\n{\n    deflate_state *s;\n    uLong fixedlen, storelen, wraplen;\n\n    /* upper bound for fixed blocks with 9-bit literals and length 255\n       (memLevel == 2, which is the lowest that may not use stored blocks) --\n       ~13% overhead plus a small constant */\n    fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) +\n               (sourceLen >> 9) + 4;\n\n    /* upper bound for stored blocks with length 127 (memLevel == 1) --\n       ~4% overhead plus a small constant */\n    storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) +\n               (sourceLen >> 11) + 7;\n\n    /* if can't get parameters, return larger bound plus a zlib wrapper */\n    if (deflateStateCheck(strm))\n        return (fixedlen > storelen ? fixedlen : storelen) + 6;\n\n    /* compute wrapper length */\n    s = strm->state;\n    switch (s->wrap) {\n    case 0:                                 /* raw deflate */\n        wraplen = 0;\n        break;\n    case 1:                                 /* zlib wrapper */\n        wraplen = 6 + (s->strstart ? 4 : 0);\n        break;\n#ifdef GZIP\n    case 2:                                 /* gzip wrapper */\n        wraplen = 18;\n        if (s->gzhead != Z_NULL) {          /* user-supplied gzip header */\n            Bytef *str;\n            if (s->gzhead->extra != Z_NULL)\n                wraplen += 2 + s->gzhead->extra_len;\n            str = s->gzhead->name;\n            if (str != Z_NULL)\n                do {\n                    wraplen++;\n                } while (*str++);\n            str = s->gzhead->comment;\n            if (str != Z_NULL)\n                do {\n                    wraplen++;\n                } while (*str++);\n            if (s->gzhead->hcrc)\n                wraplen += 2;\n        }\n        break;\n#endif\n    default:                                /* for compiler happiness */\n        wraplen = 6;\n    }\n\n    /* if not default parameters, return one of the conservative bounds */\n    if (s->w_bits != 15 || s->hash_bits != 8 + 7)\n        return (s->w_bits <= s->hash_bits ? fixedlen : storelen) + wraplen;\n\n    /* default settings: return tight bound for that case -- ~0.03% overhead\n       plus a small constant */\n    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +\n           (sourceLen >> 25) + 13 - 6 + wraplen;\n}\n\n/* =========================================================================\n * Put a short in the pending buffer. The 16-bit value is put in MSB order.\n * IN assertion: the stream state is correct and there is enough room in\n * pending_buf.\n */\nlocal void putShortMSB(s, b)\n    deflate_state *s;\n    uInt b;\n{\n    put_byte(s, (Byte)(b >> 8));\n    put_byte(s, (Byte)(b & 0xff));\n}\n\n/* =========================================================================\n * Flush as much pending output as possible. All deflate() output, except for\n * some deflate_stored() output, goes through this function so some\n * applications may wish to modify it to avoid allocating a large\n * strm->next_out buffer and copying into it. (See also read_buf()).\n */\nlocal void flush_pending(strm)\n    z_streamp strm;\n{\n    unsigned len;\n    deflate_state *s = strm->state;\n\n    _tr_flush_bits(s);\n    len = s->pending;\n    if (len > strm->avail_out) len = strm->avail_out;\n    if (len == 0) return;\n\n    zmemcpy(strm->next_out, s->pending_out, len);\n    strm->next_out  += len;\n    s->pending_out  += len;\n    strm->total_out += len;\n    strm->avail_out -= len;\n    s->pending      -= len;\n    if (s->pending == 0) {\n        s->pending_out = s->pending_buf;\n    }\n}\n\n/* ===========================================================================\n * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1].\n */\n#define HCRC_UPDATE(beg) \\\n    do { \\\n        if (s->gzhead->hcrc && s->pending > (beg)) \\\n            strm->adler = crc32(strm->adler, s->pending_buf + (beg), \\\n                                s->pending - (beg)); \\\n    } while (0)\n\n/* ========================================================================= */\nint ZEXPORT deflate(strm, flush)\n    z_streamp strm;\n    int flush;\n{\n    int old_flush; /* value of flush param for previous deflate call */\n    deflate_state *s;\n\n    if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) {\n        return Z_STREAM_ERROR;\n    }\n    s = strm->state;\n\n    if (strm->next_out == Z_NULL ||\n        (strm->avail_in != 0 && strm->next_in == Z_NULL) ||\n        (s->status == FINISH_STATE && flush != Z_FINISH)) {\n        ERR_RETURN(strm, Z_STREAM_ERROR);\n    }\n    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);\n\n    old_flush = s->last_flush;\n    s->last_flush = flush;\n\n    /* Flush as much pending output as possible */\n    if (s->pending != 0) {\n        flush_pending(strm);\n        if (strm->avail_out == 0) {\n            /* Since avail_out is 0, deflate will be called again with\n             * more output space, but possibly with both pending and\n             * avail_in equal to zero. There won't be anything to do,\n             * but this is not an error situation so make sure we\n             * return OK instead of BUF_ERROR at next call of deflate:\n             */\n            s->last_flush = -1;\n            return Z_OK;\n        }\n\n    /* Make sure there is something to do and avoid duplicate consecutive\n     * flushes. For repeated and useless calls with Z_FINISH, we keep\n     * returning Z_STREAM_END instead of Z_BUF_ERROR.\n     */\n    } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&\n               flush != Z_FINISH) {\n        ERR_RETURN(strm, Z_BUF_ERROR);\n    }\n\n    /* User must not provide more input after the first FINISH: */\n    if (s->status == FINISH_STATE && strm->avail_in != 0) {\n        ERR_RETURN(strm, Z_BUF_ERROR);\n    }\n\n    /* Write the header */\n    if (s->status == INIT_STATE && s->wrap == 0)\n        s->status = BUSY_STATE;\n    if (s->status == INIT_STATE) {\n        /* zlib header */\n        uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8;\n        uInt level_flags;\n\n        if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)\n            level_flags = 0;\n        else if (s->level < 6)\n            level_flags = 1;\n        else if (s->level == 6)\n            level_flags = 2;\n        else\n            level_flags = 3;\n        header |= (level_flags << 6);\n        if (s->strstart != 0) header |= PRESET_DICT;\n        header += 31 - (header % 31);\n\n        putShortMSB(s, header);\n\n        /* Save the adler32 of the preset dictionary: */\n        if (s->strstart != 0) {\n            putShortMSB(s, (uInt)(strm->adler >> 16));\n            putShortMSB(s, (uInt)(strm->adler & 0xffff));\n        }\n        strm->adler = adler32(0L, Z_NULL, 0);\n        s->status = BUSY_STATE;\n\n        /* Compression must start with an empty pending buffer */\n        flush_pending(strm);\n        if (s->pending != 0) {\n            s->last_flush = -1;\n            return Z_OK;\n        }\n    }\n#ifdef GZIP\n    if (s->status == GZIP_STATE) {\n        /* gzip header */\n        strm->adler = crc32(0L, Z_NULL, 0);\n        put_byte(s, 31);\n        put_byte(s, 139);\n        put_byte(s, 8);\n        if (s->gzhead == Z_NULL) {\n            put_byte(s, 0);\n            put_byte(s, 0);\n            put_byte(s, 0);\n            put_byte(s, 0);\n            put_byte(s, 0);\n            put_byte(s, s->level == 9 ? 2 :\n                     (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?\n                      4 : 0));\n            put_byte(s, OS_CODE);\n            s->status = BUSY_STATE;\n\n            /* Compression must start with an empty pending buffer */\n            flush_pending(strm);\n            if (s->pending != 0) {\n                s->last_flush = -1;\n                return Z_OK;\n            }\n        }\n        else {\n            put_byte(s, (s->gzhead->text ? 1 : 0) +\n                     (s->gzhead->hcrc ? 2 : 0) +\n                     (s->gzhead->extra == Z_NULL ? 0 : 4) +\n                     (s->gzhead->name == Z_NULL ? 0 : 8) +\n                     (s->gzhead->comment == Z_NULL ? 0 : 16)\n                     );\n            put_byte(s, (Byte)(s->gzhead->time & 0xff));\n            put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));\n            put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));\n            put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));\n            put_byte(s, s->level == 9 ? 2 :\n                     (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?\n                      4 : 0));\n            put_byte(s, s->gzhead->os & 0xff);\n            if (s->gzhead->extra != Z_NULL) {\n                put_byte(s, s->gzhead->extra_len & 0xff);\n                put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);\n            }\n            if (s->gzhead->hcrc)\n                strm->adler = crc32(strm->adler, s->pending_buf,\n                                    s->pending);\n            s->gzindex = 0;\n            s->status = EXTRA_STATE;\n        }\n    }\n    if (s->status == EXTRA_STATE) {\n        if (s->gzhead->extra != Z_NULL) {\n            ulg beg = s->pending;   /* start of bytes to update crc */\n            uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex;\n            while (s->pending + left > s->pending_buf_size) {\n                uInt copy = s->pending_buf_size - s->pending;\n                zmemcpy(s->pending_buf + s->pending,\n                        s->gzhead->extra + s->gzindex, copy);\n                s->pending = s->pending_buf_size;\n                HCRC_UPDATE(beg);\n                s->gzindex += copy;\n                flush_pending(strm);\n                if (s->pending != 0) {\n                    s->last_flush = -1;\n                    return Z_OK;\n                }\n                beg = 0;\n                left -= copy;\n            }\n            zmemcpy(s->pending_buf + s->pending,\n                    s->gzhead->extra + s->gzindex, left);\n            s->pending += left;\n            HCRC_UPDATE(beg);\n            s->gzindex = 0;\n        }\n        s->status = NAME_STATE;\n    }\n    if (s->status == NAME_STATE) {\n        if (s->gzhead->name != Z_NULL) {\n            ulg beg = s->pending;   /* start of bytes to update crc */\n            int val;\n            do {\n                if (s->pending == s->pending_buf_size) {\n                    HCRC_UPDATE(beg);\n                    flush_pending(strm);\n                    if (s->pending != 0) {\n                        s->last_flush = -1;\n                        return Z_OK;\n                    }\n                    beg = 0;\n                }\n                val = s->gzhead->name[s->gzindex++];\n                put_byte(s, val);\n            } while (val != 0);\n            HCRC_UPDATE(beg);\n            s->gzindex = 0;\n        }\n        s->status = COMMENT_STATE;\n    }\n    if (s->status == COMMENT_STATE) {\n        if (s->gzhead->comment != Z_NULL) {\n            ulg beg = s->pending;   /* start of bytes to update crc */\n            int val;\n            do {\n                if (s->pending == s->pending_buf_size) {\n                    HCRC_UPDATE(beg);\n                    flush_pending(strm);\n                    if (s->pending != 0) {\n                        s->last_flush = -1;\n                        return Z_OK;\n                    }\n                    beg = 0;\n                }\n                val = s->gzhead->comment[s->gzindex++];\n                put_byte(s, val);\n            } while (val != 0);\n            HCRC_UPDATE(beg);\n        }\n        s->status = HCRC_STATE;\n    }\n    if (s->status == HCRC_STATE) {\n        if (s->gzhead->hcrc) {\n            if (s->pending + 2 > s->pending_buf_size) {\n                flush_pending(strm);\n                if (s->pending != 0) {\n                    s->last_flush = -1;\n                    return Z_OK;\n                }\n            }\n            put_byte(s, (Byte)(strm->adler & 0xff));\n            put_byte(s, (Byte)((strm->adler >> 8) & 0xff));\n            strm->adler = crc32(0L, Z_NULL, 0);\n        }\n        s->status = BUSY_STATE;\n\n        /* Compression must start with an empty pending buffer */\n        flush_pending(strm);\n        if (s->pending != 0) {\n            s->last_flush = -1;\n            return Z_OK;\n        }\n    }\n#endif\n\n    /* Start a new block or continue the current one.\n     */\n    if (strm->avail_in != 0 || s->lookahead != 0 ||\n        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {\n        block_state bstate;\n\n        bstate = s->level == 0 ? deflate_stored(s, flush) :\n                 s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :\n                 s->strategy == Z_RLE ? deflate_rle(s, flush) :\n                 (*(configuration_table[s->level].func))(s, flush);\n\n        if (bstate == finish_started || bstate == finish_done) {\n            s->status = FINISH_STATE;\n        }\n        if (bstate == need_more || bstate == finish_started) {\n            if (strm->avail_out == 0) {\n                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */\n            }\n            return Z_OK;\n            /* If flush != Z_NO_FLUSH && avail_out == 0, the next call\n             * of deflate should use the same flush parameter to make sure\n             * that the flush is complete. So we don't have to output an\n             * empty block here, this will be done at next call. This also\n             * ensures that for a very small output buffer, we emit at most\n             * one empty block.\n             */\n        }\n        if (bstate == block_done) {\n            if (flush == Z_PARTIAL_FLUSH) {\n                _tr_align(s);\n            } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */\n                _tr_stored_block(s, (char*)0, 0L, 0);\n                /* For a full flush, this empty block will be recognized\n                 * as a special marker by inflate_sync().\n                 */\n                if (flush == Z_FULL_FLUSH) {\n                    CLEAR_HASH(s);             /* forget history */\n                    if (s->lookahead == 0) {\n                        s->strstart = 0;\n                        s->block_start = 0L;\n                        s->insert = 0;\n                    }\n                }\n            }\n            flush_pending(strm);\n            if (strm->avail_out == 0) {\n              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */\n              return Z_OK;\n            }\n        }\n    }\n\n    if (flush != Z_FINISH) return Z_OK;\n    if (s->wrap <= 0) return Z_STREAM_END;\n\n    /* Write the trailer */\n#ifdef GZIP\n    if (s->wrap == 2) {\n        put_byte(s, (Byte)(strm->adler & 0xff));\n        put_byte(s, (Byte)((strm->adler >> 8) & 0xff));\n        put_byte(s, (Byte)((strm->adler >> 16) & 0xff));\n        put_byte(s, (Byte)((strm->adler >> 24) & 0xff));\n        put_byte(s, (Byte)(strm->total_in & 0xff));\n        put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));\n        put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));\n        put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));\n    }\n    else\n#endif\n    {\n        putShortMSB(s, (uInt)(strm->adler >> 16));\n        putShortMSB(s, (uInt)(strm->adler & 0xffff));\n    }\n    flush_pending(strm);\n    /* If avail_out is zero, the application will call deflate again\n     * to flush the rest.\n     */\n    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */\n    return s->pending != 0 ? Z_OK : Z_STREAM_END;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateEnd(strm)\n    z_streamp strm;\n{\n    int status;\n\n    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;\n\n    status = strm->state->status;\n\n    /* Deallocate in reverse order of allocations: */\n    TRY_FREE(strm, strm->state->pending_buf);\n    TRY_FREE(strm, strm->state->head);\n    TRY_FREE(strm, strm->state->prev);\n    TRY_FREE(strm, strm->state->window);\n\n    ZFREE(strm, strm->state);\n    strm->state = Z_NULL;\n\n    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;\n}\n\n/* =========================================================================\n * Copy the source state to the destination state.\n * To simplify the source, this is not supported for 16-bit MSDOS (which\n * doesn't have enough memory anyway to duplicate compression states).\n */\nint ZEXPORT deflateCopy(dest, source)\n    z_streamp dest;\n    z_streamp source;\n{\n#ifdef MAXSEG_64K\n    return Z_STREAM_ERROR;\n#else\n    deflate_state *ds;\n    deflate_state *ss;\n\n\n    if (deflateStateCheck(source) || dest == Z_NULL) {\n        return Z_STREAM_ERROR;\n    }\n\n    ss = source->state;\n\n    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));\n\n    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));\n    if (ds == Z_NULL) return Z_MEM_ERROR;\n    dest->state = (struct internal_state FAR *) ds;\n    zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));\n    ds->strm = dest;\n\n    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));\n    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));\n    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));\n    ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);\n\n    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||\n        ds->pending_buf == Z_NULL) {\n        deflateEnd (dest);\n        return Z_MEM_ERROR;\n    }\n    /* following zmemcpy do not work for 16-bit MSDOS */\n    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));\n    zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));\n    zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));\n    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);\n\n    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);\n    ds->sym_buf = ds->pending_buf + ds->lit_bufsize;\n\n    ds->l_desc.dyn_tree = ds->dyn_ltree;\n    ds->d_desc.dyn_tree = ds->dyn_dtree;\n    ds->bl_desc.dyn_tree = ds->bl_tree;\n\n    return Z_OK;\n#endif /* MAXSEG_64K */\n}\n\n/* ===========================================================================\n * Read a new buffer from the current input stream, update the adler32\n * and total number of bytes read.  All deflate() input goes through\n * this function so some applications may wish to modify it to avoid\n * allocating a large strm->next_in buffer and copying from it.\n * (See also flush_pending()).\n */\nlocal unsigned read_buf(strm, buf, size)\n    z_streamp strm;\n    Bytef *buf;\n    unsigned size;\n{\n    unsigned len = strm->avail_in;\n\n    if (len > size) len = size;\n    if (len == 0) return 0;\n\n    strm->avail_in  -= len;\n\n    zmemcpy(buf, strm->next_in, len);\n    if (strm->state->wrap == 1) {\n        strm->adler = adler32(strm->adler, buf, len);\n    }\n#ifdef GZIP\n    else if (strm->state->wrap == 2) {\n        strm->adler = crc32(strm->adler, buf, len);\n    }\n#endif\n    strm->next_in  += len;\n    strm->total_in += len;\n\n    return len;\n}\n\n/* ===========================================================================\n * Initialize the \"longest match\" routines for a new zlib stream\n */\nlocal void lm_init(s)\n    deflate_state *s;\n{\n    s->window_size = (ulg)2L*s->w_size;\n\n    CLEAR_HASH(s);\n\n    /* Set the default configuration parameters:\n     */\n    s->max_lazy_match   = configuration_table[s->level].max_lazy;\n    s->good_match       = configuration_table[s->level].good_length;\n    s->nice_match       = configuration_table[s->level].nice_length;\n    s->max_chain_length = configuration_table[s->level].max_chain;\n\n    s->strstart = 0;\n    s->block_start = 0L;\n    s->lookahead = 0;\n    s->insert = 0;\n    s->match_length = s->prev_length = MIN_MATCH-1;\n    s->match_available = 0;\n    s->ins_h = 0;\n}\n\n#ifndef FASTEST\n/* ===========================================================================\n * Set match_start to the longest match starting at the given string and\n * return its length. Matches shorter or equal to prev_length are discarded,\n * in which case the result is equal to prev_length and match_start is\n * garbage.\n * IN assertions: cur_match is the head of the hash chain for the current\n *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n * OUT assertion: the match length is not greater than s->lookahead.\n */\nlocal uInt longest_match(s, cur_match)\n    deflate_state *s;\n    IPos cur_match;                             /* current match */\n{\n    unsigned chain_length = s->max_chain_length;/* max hash chain length */\n    register Bytef *scan = s->window + s->strstart; /* current string */\n    register Bytef *match;                      /* matched string */\n    register int len;                           /* length of current match */\n    int best_len = (int)s->prev_length;         /* best match length so far */\n    int nice_match = s->nice_match;             /* stop if match long enough */\n    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?\n        s->strstart - (IPos)MAX_DIST(s) : NIL;\n    /* Stop when cur_match becomes <= limit. To simplify the code,\n     * we prevent matches with the string of window index 0.\n     */\n    Posf *prev = s->prev;\n    uInt wmask = s->w_mask;\n\n#ifdef UNALIGNED_OK\n    /* Compare two bytes at a time. Note: this is not always beneficial.\n     * Try with and without -DUNALIGNED_OK to check.\n     */\n    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;\n    register ush scan_start = *(ushf*)scan;\n    register ush scan_end   = *(ushf*)(scan + best_len - 1);\n#else\n    register Bytef *strend = s->window + s->strstart + MAX_MATCH;\n    register Byte scan_end1  = scan[best_len - 1];\n    register Byte scan_end   = scan[best_len];\n#endif\n\n    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\n     * It is easy to get rid of this optimization if necessary.\n     */\n    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, \"Code too clever\");\n\n    /* Do not waste too much time if we already have a good match: */\n    if (s->prev_length >= s->good_match) {\n        chain_length >>= 2;\n    }\n    /* Do not look for matches beyond the end of the input. This is necessary\n     * to make deflate deterministic.\n     */\n    if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead;\n\n    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,\n           \"need lookahead\");\n\n    do {\n        Assert(cur_match < s->strstart, \"no future\");\n        match = s->window + cur_match;\n\n        /* Skip to next match if the match length cannot increase\n         * or if the match length is less than 2.  Note that the checks below\n         * for insufficient lookahead only occur occasionally for performance\n         * reasons.  Therefore uninitialized memory will be accessed, and\n         * conditional jumps will be made that depend on those values.\n         * However the length of the match is limited to the lookahead, so\n         * the output of deflate is not affected by the uninitialized values.\n         */\n#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)\n        /* This code assumes sizeof(unsigned short) == 2. Do not use\n         * UNALIGNED_OK if your compiler uses a different size.\n         */\n        if (*(ushf*)(match + best_len - 1) != scan_end ||\n            *(ushf*)match != scan_start) continue;\n\n        /* It is not necessary to compare scan[2] and match[2] since they are\n         * always equal when the other bytes match, given that the hash keys\n         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at\n         * strstart + 3, + 5, up to strstart + 257. We check for insufficient\n         * lookahead only every 4th comparison; the 128th check will be made\n         * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is\n         * necessary to put more guard bytes at the end of the window, or\n         * to check more often for insufficient lookahead.\n         */\n        Assert(scan[2] == match[2], \"scan[2]?\");\n        scan++, match++;\n        do {\n        } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) &&\n                 *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&\n                 *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&\n                 *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&\n                 scan < strend);\n        /* The funny \"do {}\" generates better code on most compilers */\n\n        /* Here, scan <= window + strstart + 257 */\n        Assert(scan <= s->window + (unsigned)(s->window_size - 1),\n               \"wild scan\");\n        if (*scan == *match) scan++;\n\n        len = (MAX_MATCH - 1) - (int)(strend - scan);\n        scan = strend - (MAX_MATCH-1);\n\n#else /* UNALIGNED_OK */\n\n        if (match[best_len]     != scan_end  ||\n            match[best_len - 1] != scan_end1 ||\n            *match              != *scan     ||\n            *++match            != scan[1])      continue;\n\n        /* The check at best_len - 1 can be removed because it will be made\n         * again later. (This heuristic is not always a win.)\n         * It is not necessary to compare scan[2] and match[2] since they\n         * are always equal when the other bytes match, given that\n         * the hash keys are equal and that HASH_BITS >= 8.\n         */\n        scan += 2, match++;\n        Assert(*scan == *match, \"match[2]?\");\n\n        /* We check for insufficient lookahead only every 8th comparison;\n         * the 256th check will be made at strstart + 258.\n         */\n        do {\n        } while (*++scan == *++match && *++scan == *++match &&\n                 *++scan == *++match && *++scan == *++match &&\n                 *++scan == *++match && *++scan == *++match &&\n                 *++scan == *++match && *++scan == *++match &&\n                 scan < strend);\n\n        Assert(scan <= s->window + (unsigned)(s->window_size - 1),\n               \"wild scan\");\n\n        len = MAX_MATCH - (int)(strend - scan);\n        scan = strend - MAX_MATCH;\n\n#endif /* UNALIGNED_OK */\n\n        if (len > best_len) {\n            s->match_start = cur_match;\n            best_len = len;\n            if (len >= nice_match) break;\n#ifdef UNALIGNED_OK\n            scan_end = *(ushf*)(scan + best_len - 1);\n#else\n            scan_end1  = scan[best_len - 1];\n            scan_end   = scan[best_len];\n#endif\n        }\n    } while ((cur_match = prev[cur_match & wmask]) > limit\n             && --chain_length != 0);\n\n    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;\n    return s->lookahead;\n}\n\n#else /* FASTEST */\n\n/* ---------------------------------------------------------------------------\n * Optimized version for FASTEST only\n */\nlocal uInt longest_match(s, cur_match)\n    deflate_state *s;\n    IPos cur_match;                             /* current match */\n{\n    register Bytef *scan = s->window + s->strstart; /* current string */\n    register Bytef *match;                       /* matched string */\n    register int len;                           /* length of current match */\n    register Bytef *strend = s->window + s->strstart + MAX_MATCH;\n\n    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\n     * It is easy to get rid of this optimization if necessary.\n     */\n    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, \"Code too clever\");\n\n    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,\n           \"need lookahead\");\n\n    Assert(cur_match < s->strstart, \"no future\");\n\n    match = s->window + cur_match;\n\n    /* Return failure if the match length is less than 2:\n     */\n    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;\n\n    /* The check at best_len - 1 can be removed because it will be made\n     * again later. (This heuristic is not always a win.)\n     * It is not necessary to compare scan[2] and match[2] since they\n     * are always equal when the other bytes match, given that\n     * the hash keys are equal and that HASH_BITS >= 8.\n     */\n    scan += 2, match += 2;\n    Assert(*scan == *match, \"match[2]?\");\n\n    /* We check for insufficient lookahead only every 8th comparison;\n     * the 256th check will be made at strstart + 258.\n     */\n    do {\n    } while (*++scan == *++match && *++scan == *++match &&\n             *++scan == *++match && *++scan == *++match &&\n             *++scan == *++match && *++scan == *++match &&\n             *++scan == *++match && *++scan == *++match &&\n             scan < strend);\n\n    Assert(scan <= s->window + (unsigned)(s->window_size - 1), \"wild scan\");\n\n    len = MAX_MATCH - (int)(strend - scan);\n\n    if (len < MIN_MATCH) return MIN_MATCH - 1;\n\n    s->match_start = cur_match;\n    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;\n}\n\n#endif /* FASTEST */\n\n#ifdef ZLIB_DEBUG\n\n#define EQUAL 0\n/* result of memcmp for equal strings */\n\n/* ===========================================================================\n * Check that the match at match_start is indeed a match.\n */\nlocal void check_match(s, start, match, length)\n    deflate_state *s;\n    IPos start, match;\n    int length;\n{\n    /* check that the match is indeed a match */\n    if (zmemcmp(s->window + match,\n                s->window + start, length) != EQUAL) {\n        fprintf(stderr, \" start %u, match %u, length %d\\n\",\n                start, match, length);\n        do {\n            fprintf(stderr, \"%c%c\", s->window[match++], s->window[start++]);\n        } while (--length != 0);\n        z_error(\"invalid match\");\n    }\n    if (z_verbose > 1) {\n        fprintf(stderr,\"\\\\[%d,%d]\", start - match, length);\n        do { putc(s->window[start++], stderr); } while (--length != 0);\n    }\n}\n#else\n#  define check_match(s, start, match, length)\n#endif /* ZLIB_DEBUG */\n\n/* ===========================================================================\n * Fill the window when the lookahead becomes insufficient.\n * Updates strstart and lookahead.\n *\n * IN assertion: lookahead < MIN_LOOKAHEAD\n * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD\n *    At least one byte has been read, or avail_in == 0; reads are\n *    performed for at least two bytes (required for the zip translate_eol\n *    option -- not supported here).\n */\nlocal void fill_window(s)\n    deflate_state *s;\n{\n    unsigned n;\n    unsigned more;    /* Amount of free space at the end of the window. */\n    uInt wsize = s->w_size;\n\n    Assert(s->lookahead < MIN_LOOKAHEAD, \"already enough lookahead\");\n\n    do {\n        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);\n\n        /* Deal with !@#$% 64K limit: */\n        if (sizeof(int) <= 2) {\n            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {\n                more = wsize;\n\n            } else if (more == (unsigned)(-1)) {\n                /* Very unlikely, but possible on 16 bit machine if\n                 * strstart == 0 && lookahead == 1 (input done a byte at time)\n                 */\n                more--;\n            }\n        }\n\n        /* If the window is almost full and there is insufficient lookahead,\n         * move the upper half to the lower one to make room in the upper half.\n         */\n        if (s->strstart >= wsize + MAX_DIST(s)) {\n\n            zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more);\n            s->match_start -= wsize;\n            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */\n            s->block_start -= (long) wsize;\n            if (s->insert > s->strstart)\n                s->insert = s->strstart;\n            slide_hash(s);\n            more += wsize;\n        }\n        if (s->strm->avail_in == 0) break;\n\n        /* If there was no sliding:\n         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&\n         *    more == window_size - lookahead - strstart\n         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)\n         * => more >= window_size - 2*WSIZE + 2\n         * In the BIG_MEM or MMAP case (not yet supported),\n         *   window_size == input_size + MIN_LOOKAHEAD  &&\n         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.\n         * Otherwise, window_size == 2*WSIZE so more >= 2.\n         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.\n         */\n        Assert(more >= 2, \"more < 2\");\n\n        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);\n        s->lookahead += n;\n\n        /* Initialize the hash value now that we have some input: */\n        if (s->lookahead + s->insert >= MIN_MATCH) {\n            uInt str = s->strstart - s->insert;\n            s->ins_h = s->window[str];\n            UPDATE_HASH(s, s->ins_h, s->window[str + 1]);\n#if MIN_MATCH != 3\n            Call UPDATE_HASH() MIN_MATCH-3 more times\n#endif\n            while (s->insert) {\n                UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);\n#ifndef FASTEST\n                s->prev[str & s->w_mask] = s->head[s->ins_h];\n#endif\n                s->head[s->ins_h] = (Pos)str;\n                str++;\n                s->insert--;\n                if (s->lookahead + s->insert < MIN_MATCH)\n                    break;\n            }\n        }\n        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,\n         * but this is not important since only literal bytes will be emitted.\n         */\n\n    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);\n\n    /* If the WIN_INIT bytes after the end of the current data have never been\n     * written, then zero those bytes in order to avoid memory check reports of\n     * the use of uninitialized (or uninitialised as Julian writes) bytes by\n     * the longest match routines.  Update the high water mark for the next\n     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match\n     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.\n     */\n    if (s->high_water < s->window_size) {\n        ulg curr = s->strstart + (ulg)(s->lookahead);\n        ulg init;\n\n        if (s->high_water < curr) {\n            /* Previous high water mark below current data -- zero WIN_INIT\n             * bytes or up to end of window, whichever is less.\n             */\n            init = s->window_size - curr;\n            if (init > WIN_INIT)\n                init = WIN_INIT;\n            zmemzero(s->window + curr, (unsigned)init);\n            s->high_water = curr + init;\n        }\n        else if (s->high_water < (ulg)curr + WIN_INIT) {\n            /* High water mark at or above current data, but below current data\n             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up\n             * to end of window, whichever is less.\n             */\n            init = (ulg)curr + WIN_INIT - s->high_water;\n            if (init > s->window_size - s->high_water)\n                init = s->window_size - s->high_water;\n            zmemzero(s->window + s->high_water, (unsigned)init);\n            s->high_water += init;\n        }\n    }\n\n    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,\n           \"not enough room for search\");\n}\n\n/* ===========================================================================\n * Flush the current block, with given end-of-file flag.\n * IN assertion: strstart is set to the end of the current match.\n */\n#define FLUSH_BLOCK_ONLY(s, last) { \\\n   _tr_flush_block(s, (s->block_start >= 0L ? \\\n                   (charf *)&s->window[(unsigned)s->block_start] : \\\n                   (charf *)Z_NULL), \\\n                (ulg)((long)s->strstart - s->block_start), \\\n                (last)); \\\n   s->block_start = s->strstart; \\\n   flush_pending(s->strm); \\\n   Tracev((stderr,\"[FLUSH]\")); \\\n}\n\n/* Same but force premature exit if necessary. */\n#define FLUSH_BLOCK(s, last) { \\\n   FLUSH_BLOCK_ONLY(s, last); \\\n   if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \\\n}\n\n/* Maximum stored block length in deflate format (not including header). */\n#define MAX_STORED 65535\n\n/* Minimum of a and b. */\n#define MIN(a, b) ((a) > (b) ? (b) : (a))\n\n/* ===========================================================================\n * Copy without compression as much as possible from the input stream, return\n * the current block state.\n *\n * In case deflateParams() is used to later switch to a non-zero compression\n * level, s->matches (otherwise unused when storing) keeps track of the number\n * of hash table slides to perform. If s->matches is 1, then one hash table\n * slide will be done when switching. If s->matches is 2, the maximum value\n * allowed here, then the hash table will be cleared, since two or more slides\n * is the same as a clear.\n *\n * deflate_stored() is written to minimize the number of times an input byte is\n * copied. It is most efficient with large input and output buffers, which\n * maximizes the opportunities to have a single copy from next_in to next_out.\n */\nlocal block_state deflate_stored(s, flush)\n    deflate_state *s;\n    int flush;\n{\n    /* Smallest worthy block size when not flushing or finishing. By default\n     * this is 32K. This can be as small as 507 bytes for memLevel == 1. For\n     * large input and output buffers, the stored block size will be larger.\n     */\n    unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size);\n\n    /* Copy as many min_block or larger stored blocks directly to next_out as\n     * possible. If flushing, copy the remaining available input to next_out as\n     * stored blocks, if there is enough space.\n     */\n    unsigned len, left, have, last = 0;\n    unsigned used = s->strm->avail_in;\n    do {\n        /* Set len to the maximum size block that we can copy directly with the\n         * available input data and output space. Set left to how much of that\n         * would be copied from what's left in the window.\n         */\n        len = MAX_STORED;       /* maximum deflate stored block length */\n        have = (s->bi_valid + 42) >> 3;         /* number of header bytes */\n        if (s->strm->avail_out < have)          /* need room for header */\n            break;\n            /* maximum stored block length that will fit in avail_out: */\n        have = s->strm->avail_out - have;\n        left = s->strstart - s->block_start;    /* bytes left in window */\n        if (len > (ulg)left + s->strm->avail_in)\n            len = left + s->strm->avail_in;     /* limit len to the input */\n        if (len > have)\n            len = have;                         /* limit len to the output */\n\n        /* If the stored block would be less than min_block in length, or if\n         * unable to copy all of the available input when flushing, then try\n         * copying to the window and the pending buffer instead. Also don't\n         * write an empty block when flushing -- deflate() does that.\n         */\n        if (len < min_block && ((len == 0 && flush != Z_FINISH) ||\n                                flush == Z_NO_FLUSH ||\n                                len != left + s->strm->avail_in))\n            break;\n\n        /* Make a dummy stored block in pending to get the header bytes,\n         * including any pending bits. This also updates the debugging counts.\n         */\n        last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0;\n        _tr_stored_block(s, (char *)0, 0L, last);\n\n        /* Replace the lengths in the dummy stored block with len. */\n        s->pending_buf[s->pending - 4] = len;\n        s->pending_buf[s->pending - 3] = len >> 8;\n        s->pending_buf[s->pending - 2] = ~len;\n        s->pending_buf[s->pending - 1] = ~len >> 8;\n\n        /* Write the stored block header bytes. */\n        flush_pending(s->strm);\n\n#ifdef ZLIB_DEBUG\n        /* Update debugging counts for the data about to be copied. */\n        s->compressed_len += len << 3;\n        s->bits_sent += len << 3;\n#endif\n\n        /* Copy uncompressed bytes from the window to next_out. */\n        if (left) {\n            if (left > len)\n                left = len;\n            zmemcpy(s->strm->next_out, s->window + s->block_start, left);\n            s->strm->next_out += left;\n            s->strm->avail_out -= left;\n            s->strm->total_out += left;\n            s->block_start += left;\n            len -= left;\n        }\n\n        /* Copy uncompressed bytes directly from next_in to next_out, updating\n         * the check value.\n         */\n        if (len) {\n            read_buf(s->strm, s->strm->next_out, len);\n            s->strm->next_out += len;\n            s->strm->avail_out -= len;\n            s->strm->total_out += len;\n        }\n    } while (last == 0);\n\n    /* Update the sliding window with the last s->w_size bytes of the copied\n     * data, or append all of the copied data to the existing window if less\n     * than s->w_size bytes were copied. Also update the number of bytes to\n     * insert in the hash tables, in the event that deflateParams() switches to\n     * a non-zero compression level.\n     */\n    used -= s->strm->avail_in;      /* number of input bytes directly copied */\n    if (used) {\n        /* If any input was used, then no unused input remains in the window,\n         * therefore s->block_start == s->strstart.\n         */\n        if (used >= s->w_size) {    /* supplant the previous history */\n            s->matches = 2;         /* clear hash */\n            zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);\n            s->strstart = s->w_size;\n            s->insert = s->strstart;\n        }\n        else {\n            if (s->window_size - s->strstart <= used) {\n                /* Slide the window down. */\n                s->strstart -= s->w_size;\n                zmemcpy(s->window, s->window + s->w_size, s->strstart);\n                if (s->matches < 2)\n                    s->matches++;   /* add a pending slide_hash() */\n                if (s->insert > s->strstart)\n                    s->insert = s->strstart;\n            }\n            zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);\n            s->strstart += used;\n            s->insert += MIN(used, s->w_size - s->insert);\n        }\n        s->block_start = s->strstart;\n    }\n    if (s->high_water < s->strstart)\n        s->high_water = s->strstart;\n\n    /* If the last block was written to next_out, then done. */\n    if (last)\n        return finish_done;\n\n    /* If flushing and all input has been consumed, then done. */\n    if (flush != Z_NO_FLUSH && flush != Z_FINISH &&\n        s->strm->avail_in == 0 && (long)s->strstart == s->block_start)\n        return block_done;\n\n    /* Fill the window with any remaining input. */\n    have = s->window_size - s->strstart;\n    if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {\n        /* Slide the window down. */\n        s->block_start -= s->w_size;\n        s->strstart -= s->w_size;\n        zmemcpy(s->window, s->window + s->w_size, s->strstart);\n        if (s->matches < 2)\n            s->matches++;           /* add a pending slide_hash() */\n        have += s->w_size;          /* more space now */\n        if (s->insert > s->strstart)\n            s->insert = s->strstart;\n    }\n    if (have > s->strm->avail_in)\n        have = s->strm->avail_in;\n    if (have) {\n        read_buf(s->strm, s->window + s->strstart, have);\n        s->strstart += have;\n        s->insert += MIN(have, s->w_size - s->insert);\n    }\n    if (s->high_water < s->strstart)\n        s->high_water = s->strstart;\n\n    /* There was not enough avail_out to write a complete worthy or flushed\n     * stored block to next_out. Write a stored block to pending instead, if we\n     * have enough input for a worthy block, or if flushing and there is enough\n     * room for the remaining input as a stored block in the pending buffer.\n     */\n    have = (s->bi_valid + 42) >> 3;         /* number of header bytes */\n        /* maximum stored block length that will fit in pending: */\n    have = MIN(s->pending_buf_size - have, MAX_STORED);\n    min_block = MIN(have, s->w_size);\n    left = s->strstart - s->block_start;\n    if (left >= min_block ||\n        ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH &&\n         s->strm->avail_in == 0 && left <= have)) {\n        len = MIN(left, have);\n        last = flush == Z_FINISH && s->strm->avail_in == 0 &&\n               len == left ? 1 : 0;\n        _tr_stored_block(s, (charf *)s->window + s->block_start, len, last);\n        s->block_start += len;\n        flush_pending(s->strm);\n    }\n\n    /* We've done all we can with the available input and output. */\n    return last ? finish_started : need_more;\n}\n\n/* ===========================================================================\n * Compress as much as possible from the input stream, return the current\n * block state.\n * This function does not perform lazy evaluation of matches and inserts\n * new strings in the dictionary only for unmatched strings or for short\n * matches. It is used only for the fast compression options.\n */\nlocal block_state deflate_fast(s, flush)\n    deflate_state *s;\n    int flush;\n{\n    IPos hash_head;       /* head of the hash chain */\n    int bflush;           /* set if current block must be flushed */\n\n    for (;;) {\n        /* Make sure that we always have enough lookahead, except\n         * at the end of the input file. We need MAX_MATCH bytes\n         * for the next match, plus MIN_MATCH bytes to insert the\n         * string following the next match.\n         */\n        if (s->lookahead < MIN_LOOKAHEAD) {\n            fill_window(s);\n            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {\n                return need_more;\n            }\n            if (s->lookahead == 0) break; /* flush the current block */\n        }\n\n        /* Insert the string window[strstart .. strstart + 2] in the\n         * dictionary, and set hash_head to the head of the hash chain:\n         */\n        hash_head = NIL;\n        if (s->lookahead >= MIN_MATCH) {\n            INSERT_STRING(s, s->strstart, hash_head);\n        }\n\n        /* Find the longest match, discarding those <= prev_length.\n         * At this point we have always match_length < MIN_MATCH\n         */\n        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {\n            /* To simplify the code, we prevent matches with the string\n             * of window index 0 (in particular we have to avoid a match\n             * of the string with itself at the start of the input file).\n             */\n            s->match_length = longest_match (s, hash_head);\n            /* longest_match() sets match_start */\n        }\n        if (s->match_length >= MIN_MATCH) {\n            check_match(s, s->strstart, s->match_start, s->match_length);\n\n            _tr_tally_dist(s, s->strstart - s->match_start,\n                           s->match_length - MIN_MATCH, bflush);\n\n            s->lookahead -= s->match_length;\n\n            /* Insert new strings in the hash table only if the match length\n             * is not too large. This saves time but degrades compression.\n             */\n#ifndef FASTEST\n            if (s->match_length <= s->max_insert_length &&\n                s->lookahead >= MIN_MATCH) {\n                s->match_length--; /* string at strstart already in table */\n                do {\n                    s->strstart++;\n                    INSERT_STRING(s, s->strstart, hash_head);\n                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are\n                     * always MIN_MATCH bytes ahead.\n                     */\n                } while (--s->match_length != 0);\n                s->strstart++;\n            } else\n#endif\n            {\n                s->strstart += s->match_length;\n                s->match_length = 0;\n                s->ins_h = s->window[s->strstart];\n                UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]);\n#if MIN_MATCH != 3\n                Call UPDATE_HASH() MIN_MATCH-3 more times\n#endif\n                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not\n                 * matter since it will be recomputed at next deflate call.\n                 */\n            }\n        } else {\n            /* No match, output a literal byte */\n            Tracevv((stderr,\"%c\", s->window[s->strstart]));\n            _tr_tally_lit(s, s->window[s->strstart], bflush);\n            s->lookahead--;\n            s->strstart++;\n        }\n        if (bflush) FLUSH_BLOCK(s, 0);\n    }\n    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;\n    if (flush == Z_FINISH) {\n        FLUSH_BLOCK(s, 1);\n        return finish_done;\n    }\n    if (s->sym_next)\n        FLUSH_BLOCK(s, 0);\n    return block_done;\n}\n\n#ifndef FASTEST\n/* ===========================================================================\n * Same as above, but achieves better compression. We use a lazy\n * evaluation for matches: a match is finally adopted only if there is\n * no better match at the next window position.\n */\nlocal block_state deflate_slow(s, flush)\n    deflate_state *s;\n    int flush;\n{\n    IPos hash_head;          /* head of hash chain */\n    int bflush;              /* set if current block must be flushed */\n\n    /* Process the input block. */\n    for (;;) {\n        /* Make sure that we always have enough lookahead, except\n         * at the end of the input file. We need MAX_MATCH bytes\n         * for the next match, plus MIN_MATCH bytes to insert the\n         * string following the next match.\n         */\n        if (s->lookahead < MIN_LOOKAHEAD) {\n            fill_window(s);\n            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {\n                return need_more;\n            }\n            if (s->lookahead == 0) break; /* flush the current block */\n        }\n\n        /* Insert the string window[strstart .. strstart + 2] in the\n         * dictionary, and set hash_head to the head of the hash chain:\n         */\n        hash_head = NIL;\n        if (s->lookahead >= MIN_MATCH) {\n            INSERT_STRING(s, s->strstart, hash_head);\n        }\n\n        /* Find the longest match, discarding those <= prev_length.\n         */\n        s->prev_length = s->match_length, s->prev_match = s->match_start;\n        s->match_length = MIN_MATCH-1;\n\n        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&\n            s->strstart - hash_head <= MAX_DIST(s)) {\n            /* To simplify the code, we prevent matches with the string\n             * of window index 0 (in particular we have to avoid a match\n             * of the string with itself at the start of the input file).\n             */\n            s->match_length = longest_match (s, hash_head);\n            /* longest_match() sets match_start */\n\n            if (s->match_length <= 5 && (s->strategy == Z_FILTERED\n#if TOO_FAR <= 32767\n                || (s->match_length == MIN_MATCH &&\n                    s->strstart - s->match_start > TOO_FAR)\n#endif\n                )) {\n\n                /* If prev_match is also MIN_MATCH, match_start is garbage\n                 * but we will ignore the current match anyway.\n                 */\n                s->match_length = MIN_MATCH-1;\n            }\n        }\n        /* If there was a match at the previous step and the current\n         * match is not better, output the previous match:\n         */\n        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {\n            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;\n            /* Do not insert strings in hash table beyond this. */\n\n            check_match(s, s->strstart - 1, s->prev_match, s->prev_length);\n\n            _tr_tally_dist(s, s->strstart - 1 - s->prev_match,\n                           s->prev_length - MIN_MATCH, bflush);\n\n            /* Insert in hash table all strings up to the end of the match.\n             * strstart - 1 and strstart are already inserted. If there is not\n             * enough lookahead, the last two strings are not inserted in\n             * the hash table.\n             */\n            s->lookahead -= s->prev_length - 1;\n            s->prev_length -= 2;\n            do {\n                if (++s->strstart <= max_insert) {\n                    INSERT_STRING(s, s->strstart, hash_head);\n                }\n            } while (--s->prev_length != 0);\n            s->match_available = 0;\n            s->match_length = MIN_MATCH-1;\n            s->strstart++;\n\n            if (bflush) FLUSH_BLOCK(s, 0);\n\n        } else if (s->match_available) {\n            /* If there was no match at the previous position, output a\n             * single literal. If there was a match but the current match\n             * is longer, truncate the previous match to a single literal.\n             */\n            Tracevv((stderr,\"%c\", s->window[s->strstart - 1]));\n            _tr_tally_lit(s, s->window[s->strstart - 1], bflush);\n            if (bflush) {\n                FLUSH_BLOCK_ONLY(s, 0);\n            }\n            s->strstart++;\n            s->lookahead--;\n            if (s->strm->avail_out == 0) return need_more;\n        } else {\n            /* There is no previous match to compare with, wait for\n             * the next step to decide.\n             */\n            s->match_available = 1;\n            s->strstart++;\n            s->lookahead--;\n        }\n    }\n    Assert (flush != Z_NO_FLUSH, \"no flush?\");\n    if (s->match_available) {\n        Tracevv((stderr,\"%c\", s->window[s->strstart - 1]));\n        _tr_tally_lit(s, s->window[s->strstart - 1], bflush);\n        s->match_available = 0;\n    }\n    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;\n    if (flush == Z_FINISH) {\n        FLUSH_BLOCK(s, 1);\n        return finish_done;\n    }\n    if (s->sym_next)\n        FLUSH_BLOCK(s, 0);\n    return block_done;\n}\n#endif /* FASTEST */\n\n/* ===========================================================================\n * For Z_RLE, simply look for runs of bytes, generate matches only of distance\n * one.  Do not maintain a hash table.  (It will be regenerated if this run of\n * deflate switches away from Z_RLE.)\n */\nlocal block_state deflate_rle(s, flush)\n    deflate_state *s;\n    int flush;\n{\n    int bflush;             /* set if current block must be flushed */\n    uInt prev;              /* byte at distance one to match */\n    Bytef *scan, *strend;   /* scan goes up to strend for length of run */\n\n    for (;;) {\n        /* Make sure that we always have enough lookahead, except\n         * at the end of the input file. We need MAX_MATCH bytes\n         * for the longest run, plus one for the unrolled loop.\n         */\n        if (s->lookahead <= MAX_MATCH) {\n            fill_window(s);\n            if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {\n                return need_more;\n            }\n            if (s->lookahead == 0) break; /* flush the current block */\n        }\n\n        /* See how many times the previous byte repeats */\n        s->match_length = 0;\n        if (s->lookahead >= MIN_MATCH && s->strstart > 0) {\n            scan = s->window + s->strstart - 1;\n            prev = *scan;\n            if (prev == *++scan && prev == *++scan && prev == *++scan) {\n                strend = s->window + s->strstart + MAX_MATCH;\n                do {\n                } while (prev == *++scan && prev == *++scan &&\n                         prev == *++scan && prev == *++scan &&\n                         prev == *++scan && prev == *++scan &&\n                         prev == *++scan && prev == *++scan &&\n                         scan < strend);\n                s->match_length = MAX_MATCH - (uInt)(strend - scan);\n                if (s->match_length > s->lookahead)\n                    s->match_length = s->lookahead;\n            }\n            Assert(scan <= s->window + (uInt)(s->window_size - 1),\n                   \"wild scan\");\n        }\n\n        /* Emit match if have run of MIN_MATCH or longer, else emit literal */\n        if (s->match_length >= MIN_MATCH) {\n            check_match(s, s->strstart, s->strstart - 1, s->match_length);\n\n            _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);\n\n            s->lookahead -= s->match_length;\n            s->strstart += s->match_length;\n            s->match_length = 0;\n        } else {\n            /* No match, output a literal byte */\n            Tracevv((stderr,\"%c\", s->window[s->strstart]));\n            _tr_tally_lit(s, s->window[s->strstart], bflush);\n            s->lookahead--;\n            s->strstart++;\n        }\n        if (bflush) FLUSH_BLOCK(s, 0);\n    }\n    s->insert = 0;\n    if (flush == Z_FINISH) {\n        FLUSH_BLOCK(s, 1);\n        return finish_done;\n    }\n    if (s->sym_next)\n        FLUSH_BLOCK(s, 0);\n    return block_done;\n}\n\n/* ===========================================================================\n * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.\n * (It will be regenerated if this run of deflate switches away from Huffman.)\n */\nlocal block_state deflate_huff(s, flush)\n    deflate_state *s;\n    int flush;\n{\n    int bflush;             /* set if current block must be flushed */\n\n    for (;;) {\n        /* Make sure that we have a literal to write. */\n        if (s->lookahead == 0) {\n            fill_window(s);\n            if (s->lookahead == 0) {\n                if (flush == Z_NO_FLUSH)\n                    return need_more;\n                break;      /* flush the current block */\n            }\n        }\n\n        /* Output a literal byte */\n        s->match_length = 0;\n        Tracevv((stderr,\"%c\", s->window[s->strstart]));\n        _tr_tally_lit(s, s->window[s->strstart], bflush);\n        s->lookahead--;\n        s->strstart++;\n        if (bflush) FLUSH_BLOCK(s, 0);\n    }\n    s->insert = 0;\n    if (flush == Z_FINISH) {\n        FLUSH_BLOCK(s, 1);\n        return finish_done;\n    }\n    if (s->sym_next)\n        FLUSH_BLOCK(s, 0);\n    return block_done;\n}\n"
  },
  {
    "path": "third_party/libz/deflate.h",
    "content": "// clang-format off\n/* deflate.h -- internal compression state\n * Copyright (C) 1995-2018 Jean-loup Gailly\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the compression library and is\n   subject to change. Applications should only use zlib.h.\n */\n\n/* @(#) $Id$ */\n\n#ifndef DEFLATE_H\n#define DEFLATE_H\n\n#include \"third_party/libz/zutil.h\"\n\n/* define NO_GZIP when compiling if you want to disable gzip header and\n   trailer creation by deflate().  NO_GZIP would be used to avoid linking in\n   the crc code when it is not needed.  For shared libraries, gzip encoding\n   should be left enabled. */\n#ifndef NO_GZIP\n#  define GZIP\n#endif\n\n/* ===========================================================================\n * Internal compression state.\n */\n\n#define LENGTH_CODES 29\n/* number of length codes, not counting the special END_BLOCK code */\n\n#define LITERALS  256\n/* number of literal bytes 0..255 */\n\n#define L_CODES (LITERALS+1+LENGTH_CODES)\n/* number of Literal or Length codes, including the END_BLOCK code */\n\n#define D_CODES   30\n/* number of distance codes */\n\n#define BL_CODES  19\n/* number of codes used to transfer the bit lengths */\n\n#define HEAP_SIZE (2*L_CODES+1)\n/* maximum heap size */\n\n#define MAX_BITS 15\n/* All codes must not exceed MAX_BITS bits */\n\n#define Buf_size 16\n/* size of bit buffer in bi_buf */\n\n#define INIT_STATE    42    /* zlib header -> BUSY_STATE */\n#ifdef GZIP\n#  define GZIP_STATE  57    /* gzip header -> BUSY_STATE | EXTRA_STATE */\n#endif\n#define EXTRA_STATE   69    /* gzip extra block -> NAME_STATE */\n#define NAME_STATE    73    /* gzip file name -> COMMENT_STATE */\n#define COMMENT_STATE 91    /* gzip comment -> HCRC_STATE */\n#define HCRC_STATE   103    /* gzip header CRC -> BUSY_STATE */\n#define BUSY_STATE   113    /* deflate -> FINISH_STATE */\n#define FINISH_STATE 666    /* stream complete */\n/* Stream status */\n\n\n/* Data structure describing a single value and its code string. */\ntypedef struct ct_data_s {\n    union {\n        ush  freq;       /* frequency count */\n        ush  code;       /* bit string */\n    } fc;\n    union {\n        ush  dad;        /* father node in Huffman tree */\n        ush  len;        /* length of bit string */\n    } dl;\n} FAR ct_data;\n\n#define Freq fc.freq\n#define Code fc.code\n#define Dad  dl.dad\n#define Len  dl.len\n\ntypedef struct static_tree_desc_s  static_tree_desc;\n\ntypedef struct tree_desc_s {\n    ct_data *dyn_tree;           /* the dynamic tree */\n    int     max_code;            /* largest code with non zero frequency */\n    const static_tree_desc *stat_desc;  /* the corresponding static tree */\n} FAR tree_desc;\n\ntypedef ush Pos;\ntypedef Pos FAR Posf;\ntypedef unsigned IPos;\n\n/* A Pos is an index in the character window. We use short instead of int to\n * save space in the various tables. IPos is used only for parameter passing.\n */\n\ntypedef struct internal_state {\n    z_streamp strm;      /* pointer back to this zlib stream */\n    int   status;        /* as the name implies */\n    Bytef *pending_buf;  /* output still pending */\n    ulg   pending_buf_size; /* size of pending_buf */\n    Bytef *pending_out;  /* next pending byte to output to the stream */\n    ulg   pending;       /* nb of bytes in the pending buffer */\n    int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */\n    gz_headerp  gzhead;  /* gzip header information to write */\n    ulg   gzindex;       /* where in extra, name, or comment */\n    Byte  method;        /* can only be DEFLATED */\n    int   last_flush;    /* value of flush param for previous deflate call */\n\n                /* used by deflate.c: */\n\n    uInt  w_size;        /* LZ77 window size (32K by default) */\n    uInt  w_bits;        /* log2(w_size)  (8..16) */\n    uInt  w_mask;        /* w_size - 1 */\n\n    Bytef *window;\n    /* Sliding window. Input bytes are read into the second half of the window,\n     * and move to the first half later to keep a dictionary of at least wSize\n     * bytes. With this organization, matches are limited to a distance of\n     * wSize-MAX_MATCH bytes, but this ensures that IO is always\n     * performed with a length multiple of the block size. Also, it limits\n     * the window size to 64K, which is quite useful on MSDOS.\n     * To do: use the user input buffer as sliding window.\n     */\n\n    ulg window_size;\n    /* Actual size of window: 2*wSize, except when the user input buffer\n     * is directly used as sliding window.\n     */\n\n    Posf *prev;\n    /* Link to older string with same hash index. To limit the size of this\n     * array to 64K, this link is maintained only for the last 32K strings.\n     * An index in this array is thus a window index modulo 32K.\n     */\n\n    Posf *head; /* Heads of the hash chains or NIL. */\n\n    uInt  ins_h;          /* hash index of string to be inserted */\n    uInt  hash_size;      /* number of elements in hash table */\n    uInt  hash_bits;      /* log2(hash_size) */\n    uInt  hash_mask;      /* hash_size-1 */\n\n    uInt  hash_shift;\n    /* Number of bits by which ins_h must be shifted at each input\n     * step. It must be such that after MIN_MATCH steps, the oldest\n     * byte no longer takes part in the hash key, that is:\n     *   hash_shift * MIN_MATCH >= hash_bits\n     */\n\n    long block_start;\n    /* Window position at the beginning of the current output block. Gets\n     * negative when the window is moved backwards.\n     */\n\n    uInt match_length;           /* length of best match */\n    IPos prev_match;             /* previous match */\n    int match_available;         /* set if previous match exists */\n    uInt strstart;               /* start of string to insert */\n    uInt match_start;            /* start of matching string */\n    uInt lookahead;              /* number of valid bytes ahead in window */\n\n    uInt prev_length;\n    /* Length of the best match at previous step. Matches not greater than this\n     * are discarded. This is used in the lazy match evaluation.\n     */\n\n    uInt max_chain_length;\n    /* To speed up deflation, hash chains are never searched beyond this\n     * length.  A higher limit improves compression ratio but degrades the\n     * speed.\n     */\n\n    uInt max_lazy_match;\n    /* Attempt to find a better match only when the current match is strictly\n     * smaller than this value. This mechanism is used only for compression\n     * levels >= 4.\n     */\n#   define max_insert_length  max_lazy_match\n    /* Insert new strings in the hash table only if the match length is not\n     * greater than this length. This saves time but degrades compression.\n     * max_insert_length is used only for compression levels <= 3.\n     */\n\n    int level;    /* compression level (1..9) */\n    int strategy; /* favor or force Huffman coding*/\n\n    uInt good_match;\n    /* Use a faster search when the previous match is longer than this */\n\n    int nice_match; /* Stop searching when current match exceeds this */\n\n                /* used by trees.c: */\n    /* Didn't use ct_data typedef below to suppress compiler warning */\n    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */\n    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */\n    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */\n\n    struct tree_desc_s l_desc;               /* desc. for literal tree */\n    struct tree_desc_s d_desc;               /* desc. for distance tree */\n    struct tree_desc_s bl_desc;              /* desc. for bit length tree */\n\n    ush bl_count[MAX_BITS+1];\n    /* number of codes at each bit length for an optimal tree */\n\n    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */\n    int heap_len;               /* number of elements in the heap */\n    int heap_max;               /* element of largest frequency */\n    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.\n     * The same heap array is used to build all trees.\n     */\n\n    uch depth[2*L_CODES+1];\n    /* Depth of each subtree used as tie breaker for trees of equal frequency\n     */\n\n    uchf *sym_buf;        /* buffer for distances and literals/lengths */\n\n    uInt  lit_bufsize;\n    /* Size of match buffer for literals/lengths.  There are 4 reasons for\n     * limiting lit_bufsize to 64K:\n     *   - frequencies can be kept in 16 bit counters\n     *   - if compression is not successful for the first block, all input\n     *     data is still in the window so we can still emit a stored block even\n     *     when input comes from standard input.  (This can also be done for\n     *     all blocks if lit_bufsize is not greater than 32K.)\n     *   - if compression is not successful for a file smaller than 64K, we can\n     *     even emit a stored file instead of a stored block (saving 5 bytes).\n     *     This is applicable only for zip (not gzip or zlib).\n     *   - creating new Huffman trees less frequently may not provide fast\n     *     adaptation to changes in the input data statistics. (Take for\n     *     example a binary file with poorly compressible code followed by\n     *     a highly compressible string table.) Smaller buffer sizes give\n     *     fast adaptation but have of course the overhead of transmitting\n     *     trees more frequently.\n     *   - I can't count above 4\n     */\n\n    uInt sym_next;      /* running index in sym_buf */\n    uInt sym_end;       /* symbol table full when sym_next reaches this */\n\n    ulg opt_len;        /* bit length of current block with optimal trees */\n    ulg static_len;     /* bit length of current block with static trees */\n    uInt matches;       /* number of string matches in current block */\n    uInt insert;        /* bytes at end of window left to insert */\n\n#ifdef ZLIB_DEBUG\n    ulg compressed_len; /* total bit length of compressed file mod 2^32 */\n    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */\n#endif\n\n    ush bi_buf;\n    /* Output buffer. bits are inserted starting at the bottom (least\n     * significant bits).\n     */\n    int bi_valid;\n    /* Number of valid bits in bi_buf.  All bits above the last valid bit\n     * are always zero.\n     */\n\n    ulg high_water;\n    /* High water mark offset in window for initialized bytes -- bytes above\n     * this are set to zero in order to avoid memory check warnings when\n     * longest match routines access bytes past the input.  This is then\n     * updated to the new high water mark.\n     */\n\n} FAR deflate_state;\n\n/* Output a byte on the stream.\n * IN assertion: there is enough room in pending_buf.\n */\n#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);}\n\n\n#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)\n/* Minimum amount of lookahead, except at the end of the input file.\n * See deflate.c for comments about the MIN_MATCH+1.\n */\n\n#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)\n/* In order to simplify the code, particularly on 16 bit machines, match\n * distances are limited to MAX_DIST instead of WSIZE.\n */\n\n#define WIN_INIT MAX_MATCH\n/* Number of bytes after end of data in window to initialize in order to avoid\n   memory checker errors from longest match routines */\n\n        /* in trees.c */\nvoid ZLIB_INTERNAL _tr_init OF((deflate_state *s));\nint ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));\nvoid ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,\n                        ulg stored_len, int last));\nvoid ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));\nvoid ZLIB_INTERNAL _tr_align OF((deflate_state *s));\nvoid ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,\n                        ulg stored_len, int last));\n\n#define d_code(dist) \\\n   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])\n/* Mapping from a distance to a distance code. dist is the distance - 1 and\n * must not have side effects. _dist_code[256] and _dist_code[257] are never\n * used.\n */\n\n#ifndef ZLIB_DEBUG\n/* Inline versions of _tr_tally for speed: */\n\n#if defined(GEN_TREES_H) || !defined(STDC)\n  extern uch ZLIB_INTERNAL _length_code[];\n  extern uch ZLIB_INTERNAL _dist_code[];\n#else\n  extern const uch ZLIB_INTERNAL _length_code[];\n  extern const uch ZLIB_INTERNAL _dist_code[];\n#endif\n\n# define _tr_tally_lit(s, c, flush) \\\n  { uch cc = (c); \\\n    s->sym_buf[s->sym_next++] = 0; \\\n    s->sym_buf[s->sym_next++] = 0; \\\n    s->sym_buf[s->sym_next++] = cc; \\\n    s->dyn_ltree[cc].Freq++; \\\n    flush = (s->sym_next == s->sym_end); \\\n   }\n# define _tr_tally_dist(s, distance, length, flush) \\\n  { uch len = (uch)(length); \\\n    ush dist = (ush)(distance); \\\n    s->sym_buf[s->sym_next++] = (uch)dist; \\\n    s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \\\n    s->sym_buf[s->sym_next++] = len; \\\n    dist--; \\\n    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \\\n    s->dyn_dtree[d_code(dist)].Freq++; \\\n    flush = (s->sym_next == s->sym_end); \\\n  }\n#else\n# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)\n# define _tr_tally_dist(s, distance, length, flush) \\\n              flush = _tr_tally(s, distance, length)\n#endif\n\n#endif /* DEFLATE_H */\n"
  },
  {
    "path": "third_party/libz/gzclose.c",
    "content": "// clang-format off\n/* gzclose.c -- zlib gzclose() function\n * Copyright (C) 2004, 2010 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n#include \"third_party/libz/gzguts.h\"\n\n/* gzclose() is in a separate file so that it is linked in only if it is used.\n   That way the other gzclose functions can be used instead to avoid linking in\n   unneeded compression or decompression routines. */\nint ZEXPORT gzclose(file)\n    gzFile file;\n{\n#ifndef NO_GZCOMPRESS\n    gz_statep state;\n\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state = (gz_statep)file;\n\n    return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);\n#else\n    return gzclose_r(file);\n#endif\n}\n"
  },
  {
    "path": "third_party/libz/gzguts.h",
    "content": "// clang-format off\n/* gzguts.h -- zlib internal header definitions for gz* operations\n * Copyright (C) 2004-2019 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n#ifdef _LARGEFILE64_SOURCE\n#  ifndef _LARGEFILE_SOURCE\n#    define _LARGEFILE_SOURCE 1\n#  endif\n#  ifdef _FILE_OFFSET_BITS\n#    undef _FILE_OFFSET_BITS\n#  endif\n#endif\n\n#ifdef HAVE_HIDDEN\n#  define ZLIB_INTERNAL __attribute__((visibility (\"hidden\")))\n#else\n#  define ZLIB_INTERNAL\n#endif\n\n#include <stdio.h>\n#include \"third_party/libz/zlib.h\"\n#ifdef STDC\n#  include <string.h>\n#  include <stdlib.h>\n#  include <limits.h>\n#endif\n\n#ifndef _POSIX_SOURCE\n#  define _POSIX_SOURCE\n#endif\n#include <fcntl.h>\n\n#ifdef _WIN32\n#  include <stddef.h>\n#endif\n\n#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)\n#  include <io.h>\n#endif\n\n#if defined(_WIN32)\n#  define WIDECHAR\n#endif\n\n#ifdef WINAPI_FAMILY\n#  define open _open\n#  define read _read\n#  define write _write\n#  define close _close\n#endif\n\n#ifdef NO_DEFLATE       /* for compatibility with old definition */\n#  define NO_GZCOMPRESS\n#endif\n\n#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)\n#  ifndef HAVE_VSNPRINTF\n#    define HAVE_VSNPRINTF\n#  endif\n#endif\n\n#if defined(__CYGWIN__)\n#  ifndef HAVE_VSNPRINTF\n#    define HAVE_VSNPRINTF\n#  endif\n#endif\n\n#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)\n#  ifndef HAVE_VSNPRINTF\n#    define HAVE_VSNPRINTF\n#  endif\n#endif\n\n#ifndef HAVE_VSNPRINTF\n#  ifdef MSDOS\n/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),\n   but for now we just assume it doesn't. */\n#    define NO_vsnprintf\n#  endif\n#  ifdef __TURBOC__\n#    define NO_vsnprintf\n#  endif\n#  ifdef WIN32\n/* In Win32, vsnprintf is available as the \"non-ANSI\" _vsnprintf. */\n#    if !defined(vsnprintf) && !defined(NO_vsnprintf)\n#      if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )\n#         define vsnprintf _vsnprintf\n#      endif\n#    endif\n#  endif\n#  ifdef __SASC\n#    define NO_vsnprintf\n#  endif\n#  ifdef VMS\n#    define NO_vsnprintf\n#  endif\n#  ifdef __OS400__\n#    define NO_vsnprintf\n#  endif\n#  ifdef __MVS__\n#    define NO_vsnprintf\n#  endif\n#endif\n\n/* unlike snprintf (which is required in C99), _snprintf does not guarantee\n   null termination of the result -- however this is only used in gzlib.c where\n   the result is assured to fit in the space provided */\n#if defined(_MSC_VER) && _MSC_VER < 1900\n#  define snprintf _snprintf\n#endif\n\n#ifndef local\n#  define local static\n#endif\n/* since \"static\" is used to mean two completely different things in C, we\n   define \"local\" for the non-static meaning of \"static\", for readability\n   (compile with -Dlocal if your debugger can't find static symbols) */\n\n/* gz* functions always use library allocation functions */\n#ifndef STDC\n  extern voidp  malloc OF((uInt size));\n  extern void   free   OF((voidpf ptr));\n#endif\n\n/* get errno and strerror definition */\n#if defined UNDER_CE\n#  include <windows.h>\n#  define zstrerror() gz_strwinerror((DWORD)GetLastError())\n#else\n#  ifndef NO_STRERROR\n#    include <errno.h>\n#    define zstrerror() strerror(errno)\n#  else\n#    define zstrerror() \"stdio error (consult errno)\"\n#  endif\n#endif\n\n/* provide prototypes for these when building zlib without LFS */\n#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0\n    ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));\n    ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));\n    ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));\n    ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));\n#endif\n\n/* default memLevel */\n#if MAX_MEM_LEVEL >= 8\n#  define DEF_MEM_LEVEL 8\n#else\n#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL\n#endif\n\n/* default i/o buffer size -- double this for output when reading (this and\n   twice this must be able to fit in an unsigned type) */\n#define GZBUFSIZE 8192\n\n/* gzip modes, also provide a little integrity check on the passed structure */\n#define GZ_NONE 0\n#define GZ_READ 7247\n#define GZ_WRITE 31153\n#define GZ_APPEND 1     /* mode set to GZ_WRITE after the file is opened */\n\n/* values for gz_state how */\n#define LOOK 0      /* look for a gzip header */\n#define COPY 1      /* copy input directly */\n#define GZIP 2      /* decompress a gzip stream */\n\n/* internal gzip file state data structure */\ntypedef struct {\n        /* exposed contents for gzgetc() macro */\n    struct gzFile_s x;      /* \"x\" for exposed */\n                            /* x.have: number of bytes available at x.next */\n                            /* x.next: next output data to deliver or write */\n                            /* x.pos: current position in uncompressed data */\n        /* used for both reading and writing */\n    int mode;               /* see gzip modes above */\n    int fd;                 /* file descriptor */\n    char *path;             /* path or fd for error messages */\n    unsigned size;          /* buffer size, zero if not allocated yet */\n    unsigned want;          /* requested buffer size, default is GZBUFSIZE */\n    unsigned char *in;      /* input buffer (double-sized when writing) */\n    unsigned char *out;     /* output buffer (double-sized when reading) */\n    int direct;             /* 0 if processing gzip, 1 if transparent */\n        /* just for reading */\n    int how;                /* 0: get header, 1: copy, 2: decompress */\n    z_off64_t start;        /* where the gzip data started, for rewinding */\n    int eof;                /* true if end of input file reached */\n    int past;               /* true if read requested past end */\n        /* just for writing */\n    int level;              /* compression level */\n    int strategy;           /* compression strategy */\n    int reset;              /* true if a reset is pending after a Z_FINISH */\n        /* seek request */\n    z_off64_t skip;         /* amount to skip (already rewound if backwards) */\n    int seek;               /* true if seek request pending */\n        /* error information */\n    int err;                /* error code */\n    char *msg;              /* error message */\n        /* zlib inflate or deflate stream */\n    z_stream strm;          /* stream structure in-place (not a pointer) */\n} gz_state;\ntypedef gz_state FAR *gz_statep;\n\n/* shared functions */\nvoid ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));\n#if defined UNDER_CE\nchar ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));\n#endif\n\n/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t\n   value -- needed when comparing unsigned to z_off64_t, which is signed\n   (possible z_off64_t types off_t, off64_t, and long are all signed) */\n#ifdef INT_MAX\n#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)\n#else\nunsigned ZLIB_INTERNAL gz_intmax OF((void));\n#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())\n#endif\n"
  },
  {
    "path": "third_party/libz/gzlib.c",
    "content": "// clang-format off\n/* gzlib.c -- zlib functions common to reading and writing gzip files\n * Copyright (C) 2004-2019 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n#include <unistd.h>\n\n#include \"third_party/libz/gzguts.h\"\n\n#if defined(_WIN32) && !defined(__BORLANDC__)\n#  define LSEEK _lseeki64\n#else\n#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0\n#  define LSEEK lseek64\n#else\n#  define LSEEK lseek\n#endif\n#endif\n\n/* Local functions */\nlocal void gz_reset OF((gz_statep));\nlocal gzFile gz_open OF((const void *, int, const char *));\n\n#if defined UNDER_CE\n\n/* Map the Windows error number in ERROR to a locale-dependent error message\n   string and return a pointer to it.  Typically, the values for ERROR come\n   from GetLastError.\n\n   The string pointed to shall not be modified by the application, but may be\n   overwritten by a subsequent call to gz_strwinerror\n\n   The gz_strwinerror function does not change the current setting of\n   GetLastError. */\nchar ZLIB_INTERNAL *gz_strwinerror(error)\n     DWORD error;\n{\n    static char buf[1024];\n\n    wchar_t *msgbuf;\n    DWORD lasterr = GetLastError();\n    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM\n        | FORMAT_MESSAGE_ALLOCATE_BUFFER,\n        NULL,\n        error,\n        0, /* Default language */\n        (LPVOID)&msgbuf,\n        0,\n        NULL);\n    if (chars != 0) {\n        /* If there is an \\r\\n appended, zap it.  */\n        if (chars >= 2\n            && msgbuf[chars - 2] == '\\r' && msgbuf[chars - 1] == '\\n') {\n            chars -= 2;\n            msgbuf[chars] = 0;\n        }\n\n        if (chars > sizeof (buf) - 1) {\n            chars = sizeof (buf) - 1;\n            msgbuf[chars] = 0;\n        }\n\n        wcstombs(buf, msgbuf, chars + 1);\n        LocalFree(msgbuf);\n    }\n    else {\n        sprintf(buf, \"unknown win32 error (%ld)\", error);\n    }\n\n    SetLastError(lasterr);\n    return buf;\n}\n\n#endif /* UNDER_CE */\n\n/* Reset gzip file state */\nlocal void gz_reset(state)\n    gz_statep state;\n{\n    state->x.have = 0;              /* no output data available */\n    if (state->mode == GZ_READ) {   /* for reading ... */\n        state->eof = 0;             /* not at end of file */\n        state->past = 0;            /* have not read past end yet */\n        state->how = LOOK;          /* look for gzip header */\n    }\n    else                            /* for writing ... */\n        state->reset = 0;           /* no deflateReset pending */\n    state->seek = 0;                /* no seek request pending */\n    gz_error(state, Z_OK, NULL);    /* clear error */\n    state->x.pos = 0;               /* no uncompressed data yet */\n    state->strm.avail_in = 0;       /* no input data yet */\n}\n\n/* Open a gzip file either by name or file descriptor. */\nlocal gzFile gz_open(path, fd, mode)\n    const void *path;\n    int fd;\n    const char *mode;\n{\n    gz_statep state;\n    z_size_t len;\n    int oflag;\n#ifdef O_CLOEXEC\n    int cloexec = 0;\n#endif\n#ifdef O_EXCL\n    int exclusive = 0;\n#endif\n\n    /* check input */\n    if (path == NULL)\n        return NULL;\n\n    /* allocate gzFile structure to return */\n    state = (gz_statep)malloc(sizeof(gz_state));\n    if (state == NULL)\n        return NULL;\n    state->size = 0;            /* no buffers allocated yet */\n    state->want = GZBUFSIZE;    /* requested buffer size */\n    state->msg = NULL;          /* no error message yet */\n\n    /* interpret mode */\n    state->mode = GZ_NONE;\n    state->level = Z_DEFAULT_COMPRESSION;\n    state->strategy = Z_DEFAULT_STRATEGY;\n    state->direct = 0;\n    while (*mode) {\n        if (*mode >= '0' && *mode <= '9')\n            state->level = *mode - '0';\n        else\n            switch (*mode) {\n            case 'r':\n                state->mode = GZ_READ;\n                break;\n#ifndef NO_GZCOMPRESS\n            case 'w':\n                state->mode = GZ_WRITE;\n                break;\n            case 'a':\n                state->mode = GZ_APPEND;\n                break;\n#endif\n            case '+':       /* can't read and write at the same time */\n                free(state);\n                return NULL;\n            case 'b':       /* ignore -- will request binary anyway */\n                break;\n#ifdef O_CLOEXEC\n            case 'e':\n                cloexec = 1;\n                break;\n#endif\n#ifdef O_EXCL\n            case 'x':\n                exclusive = 1;\n                break;\n#endif\n            case 'f':\n                state->strategy = Z_FILTERED;\n                break;\n            case 'h':\n                state->strategy = Z_HUFFMAN_ONLY;\n                break;\n            case 'R':\n                state->strategy = Z_RLE;\n                break;\n            case 'F':\n                state->strategy = Z_FIXED;\n                break;\n            case 'T':\n                state->direct = 1;\n                break;\n            default:        /* could consider as an error, but just ignore */\n                ;\n            }\n        mode++;\n    }\n\n    /* must provide an \"r\", \"w\", or \"a\" */\n    if (state->mode == GZ_NONE) {\n        free(state);\n        return NULL;\n    }\n\n    /* can't force transparent read */\n    if (state->mode == GZ_READ) {\n        if (state->direct) {\n            free(state);\n            return NULL;\n        }\n        state->direct = 1;      /* for empty file */\n    }\n\n    /* save the path name for error messages */\n#ifdef WIDECHAR\n    if (fd == -2) {\n        len = wcstombs(NULL, path, 0);\n        if (len == (z_size_t)-1)\n            len = 0;\n    }\n    else\n#endif\n        len = strlen((const char *)path);\n    state->path = (char *)malloc(len + 1);\n    if (state->path == NULL) {\n        free(state);\n        return NULL;\n    }\n#ifdef WIDECHAR\n    if (fd == -2)\n        if (len)\n            wcstombs(state->path, path, len + 1);\n        else\n            *(state->path) = 0;\n    else\n#endif\n#if !defined(NO_snprintf) && !defined(NO_vsnprintf)\n        (void)snprintf(state->path, len + 1, \"%s\", (const char *)path);\n#else\n        strcpy(state->path, path);\n#endif\n\n    /* compute the flags for open() */\n    oflag =\n#ifdef O_LARGEFILE\n        O_LARGEFILE |\n#endif\n#ifdef O_BINARY\n        O_BINARY |\n#endif\n#ifdef O_CLOEXEC\n        (cloexec ? O_CLOEXEC : 0) |\n#endif\n        (state->mode == GZ_READ ?\n         O_RDONLY :\n         (O_WRONLY | O_CREAT |\n#ifdef O_EXCL\n          (exclusive ? O_EXCL : 0) |\n#endif\n          (state->mode == GZ_WRITE ?\n           O_TRUNC :\n           O_APPEND)));\n\n    /* open the file with the appropriate flags (or just use fd) */\n    state->fd = fd > -1 ? fd : (\n#ifdef WIDECHAR\n        fd == -2 ? _wopen(path, oflag, 0666) :\n#endif\n        open((const char *)path, oflag, 0666));\n    if (state->fd == -1) {\n        free(state->path);\n        free(state);\n        return NULL;\n    }\n    if (state->mode == GZ_APPEND) {\n        LSEEK(state->fd, 0, SEEK_END);  /* so gzoffset() is correct */\n        state->mode = GZ_WRITE;         /* simplify later checks */\n    }\n\n    /* save the current position for rewinding (only if reading) */\n    if (state->mode == GZ_READ) {\n        state->start = LSEEK(state->fd, 0, SEEK_CUR);\n        if (state->start == -1) state->start = 0;\n    }\n\n    /* initialize stream */\n    gz_reset(state);\n\n    /* return stream */\n    return (gzFile)state;\n}\n\n/* -- see zlib.h -- */\ngzFile ZEXPORT gzopen(path, mode)\n    const char *path;\n    const char *mode;\n{\n    return gz_open(path, -1, mode);\n}\n\n/* -- see zlib.h -- */\ngzFile ZEXPORT gzopen64(path, mode)\n    const char *path;\n    const char *mode;\n{\n    return gz_open(path, -1, mode);\n}\n\n/* -- see zlib.h -- */\ngzFile ZEXPORT gzdopen(fd, mode)\n    int fd;\n    const char *mode;\n{\n    char *path;         /* identifier for error messages */\n    gzFile gz;\n\n    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)\n        return NULL;\n#if !defined(NO_snprintf) && !defined(NO_vsnprintf)\n    (void)snprintf(path, 7 + 3 * sizeof(int), \"<fd:%d>\", fd);\n#else\n    sprintf(path, \"<fd:%d>\", fd);   /* for debugging */\n#endif\n    gz = gz_open(path, fd, mode);\n    free(path);\n    return gz;\n}\n\n/* -- see zlib.h -- */\n#ifdef WIDECHAR\ngzFile ZEXPORT gzopen_w(path, mode)\n    const wchar_t *path;\n    const char *mode;\n{\n    return gz_open(path, -2, mode);\n}\n#endif\n\n/* -- see zlib.h -- */\nint ZEXPORT gzbuffer(file, size)\n    gzFile file;\n    unsigned size;\n{\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return -1;\n    state = (gz_statep)file;\n    if (state->mode != GZ_READ && state->mode != GZ_WRITE)\n        return -1;\n\n    /* make sure we haven't already allocated memory */\n    if (state->size != 0)\n        return -1;\n\n    /* check and set requested size */\n    if ((size << 1) < size)\n        return -1;              /* need to be able to double it */\n    if (size < 2)\n        size = 2;               /* need two bytes to check magic header */\n    state->want = size;\n    return 0;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzrewind(file)\n    gzFile file;\n{\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state = (gz_statep)file;\n\n    /* check that we're reading and that there's no error */\n    if (state->mode != GZ_READ ||\n            (state->err != Z_OK && state->err != Z_BUF_ERROR))\n        return -1;\n\n    /* back up and start over */\n    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)\n        return -1;\n    gz_reset(state);\n    return 0;\n}\n\n/* -- see zlib.h -- */\nz_off64_t ZEXPORT gzseek64(file, offset, whence)\n    gzFile file;\n    z_off64_t offset;\n    int whence;\n{\n    unsigned n;\n    z_off64_t ret;\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return -1;\n    state = (gz_statep)file;\n    if (state->mode != GZ_READ && state->mode != GZ_WRITE)\n        return -1;\n\n    /* check that there's no error */\n    if (state->err != Z_OK && state->err != Z_BUF_ERROR)\n        return -1;\n\n    /* can only seek from start or relative to current position */\n    if (whence != SEEK_SET && whence != SEEK_CUR)\n        return -1;\n\n    /* normalize offset to a SEEK_CUR specification */\n    if (whence == SEEK_SET)\n        offset -= state->x.pos;\n    else if (state->seek)\n        offset += state->skip;\n    state->seek = 0;\n\n    /* if within raw area while reading, just go there */\n    if (state->mode == GZ_READ && state->how == COPY &&\n            state->x.pos + offset >= 0) {\n        ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);\n        if (ret == -1)\n            return -1;\n        state->x.have = 0;\n        state->eof = 0;\n        state->past = 0;\n        state->seek = 0;\n        gz_error(state, Z_OK, NULL);\n        state->strm.avail_in = 0;\n        state->x.pos += offset;\n        return state->x.pos;\n    }\n\n    /* calculate skip amount, rewinding if needed for back seek when reading */\n    if (offset < 0) {\n        if (state->mode != GZ_READ)         /* writing -- can't go backwards */\n            return -1;\n        offset += state->x.pos;\n        if (offset < 0)                     /* before start of file! */\n            return -1;\n        if (gzrewind(file) == -1)           /* rewind, then skip to offset */\n            return -1;\n    }\n\n    /* if reading, skip what's in output buffer (one less gzgetc() check) */\n    if (state->mode == GZ_READ) {\n        n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?\n            (unsigned)offset : state->x.have;\n        state->x.have -= n;\n        state->x.next += n;\n        state->x.pos += n;\n        offset -= n;\n    }\n\n    /* request skip (if not zero) */\n    if (offset) {\n        state->seek = 1;\n        state->skip = offset;\n    }\n    return state->x.pos + offset;\n}\n\n/* -- see zlib.h -- */\nz_off_t ZEXPORT gzseek(file, offset, whence)\n    gzFile file;\n    z_off_t offset;\n    int whence;\n{\n    z_off64_t ret;\n\n    ret = gzseek64(file, (z_off64_t)offset, whence);\n    return ret == (z_off_t)ret ? (z_off_t)ret : -1;\n}\n\n/* -- see zlib.h -- */\nz_off64_t ZEXPORT gztell64(file)\n    gzFile file;\n{\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return -1;\n    state = (gz_statep)file;\n    if (state->mode != GZ_READ && state->mode != GZ_WRITE)\n        return -1;\n\n    /* return position */\n    return state->x.pos + (state->seek ? state->skip : 0);\n}\n\n/* -- see zlib.h -- */\nz_off_t ZEXPORT gztell(file)\n    gzFile file;\n{\n    z_off64_t ret;\n\n    ret = gztell64(file);\n    return ret == (z_off_t)ret ? (z_off_t)ret : -1;\n}\n\n/* -- see zlib.h -- */\nz_off64_t ZEXPORT gzoffset64(file)\n    gzFile file;\n{\n    z_off64_t offset;\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return -1;\n    state = (gz_statep)file;\n    if (state->mode != GZ_READ && state->mode != GZ_WRITE)\n        return -1;\n\n    /* compute and return effective offset in file */\n    offset = LSEEK(state->fd, 0, SEEK_CUR);\n    if (offset == -1)\n        return -1;\n    if (state->mode == GZ_READ)             /* reading */\n        offset -= state->strm.avail_in;     /* don't count buffered input */\n    return offset;\n}\n\n/* -- see zlib.h -- */\nz_off_t ZEXPORT gzoffset(file)\n    gzFile file;\n{\n    z_off64_t ret;\n\n    ret = gzoffset64(file);\n    return ret == (z_off_t)ret ? (z_off_t)ret : -1;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzeof(file)\n    gzFile file;\n{\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return 0;\n    state = (gz_statep)file;\n    if (state->mode != GZ_READ && state->mode != GZ_WRITE)\n        return 0;\n\n    /* return end-of-file state */\n    return state->mode == GZ_READ ? state->past : 0;\n}\n\n/* -- see zlib.h -- */\nconst char * ZEXPORT gzerror(file, errnum)\n    gzFile file;\n    int *errnum;\n{\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return NULL;\n    state = (gz_statep)file;\n    if (state->mode != GZ_READ && state->mode != GZ_WRITE)\n        return NULL;\n\n    /* return error information */\n    if (errnum != NULL)\n        *errnum = state->err;\n    return state->err == Z_MEM_ERROR ? \"out of memory\" :\n                                       (state->msg == NULL ? \"\" : state->msg);\n}\n\n/* -- see zlib.h -- */\nvoid ZEXPORT gzclearerr(file)\n    gzFile file;\n{\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return;\n    state = (gz_statep)file;\n    if (state->mode != GZ_READ && state->mode != GZ_WRITE)\n        return;\n\n    /* clear error and end-of-file */\n    if (state->mode == GZ_READ) {\n        state->eof = 0;\n        state->past = 0;\n    }\n    gz_error(state, Z_OK, NULL);\n}\n\n/* Create an error message in allocated memory and set state->err and\n   state->msg accordingly.  Free any previous error message already there.  Do\n   not try to free or allocate space if the error is Z_MEM_ERROR (out of\n   memory).  Simply save the error message as a static string.  If there is an\n   allocation failure constructing the error message, then convert the error to\n   out of memory. */\nvoid ZLIB_INTERNAL gz_error(state, err, msg)\n    gz_statep state;\n    int err;\n    const char *msg;\n{\n    /* free previously allocated message and clear */\n    if (state->msg != NULL) {\n        if (state->err != Z_MEM_ERROR)\n            free(state->msg);\n        state->msg = NULL;\n    }\n\n    /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */\n    if (err != Z_OK && err != Z_BUF_ERROR)\n        state->x.have = 0;\n\n    /* set error code, and if no message, then done */\n    state->err = err;\n    if (msg == NULL)\n        return;\n\n    /* for an out of memory error, return literal string when requested */\n    if (err == Z_MEM_ERROR)\n        return;\n\n    /* construct error message with path */\n    if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==\n            NULL) {\n        state->err = Z_MEM_ERROR;\n        return;\n    }\n#if !defined(NO_snprintf) && !defined(NO_vsnprintf)\n    (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,\n                   \"%s%s%s\", state->path, \": \", msg);\n#else\n    strcpy(state->msg, state->path);\n    strcat(state->msg, \": \");\n    strcat(state->msg, msg);\n#endif\n}\n\n#ifndef INT_MAX\n/* portably return maximum value for an int (when limits.h presumed not\n   available) -- we need to do this to cover cases where 2's complement not\n   used, since C standard permits 1's complement and sign-bit representations,\n   otherwise we could just use ((unsigned)-1) >> 1 */\nunsigned ZLIB_INTERNAL gz_intmax()\n{\n    unsigned p, q;\n\n    p = 1;\n    do {\n        q = p;\n        p <<= 1;\n        p++;\n    } while (p > q);\n    return q >> 1;\n}\n#endif\n"
  },
  {
    "path": "third_party/libz/gzread.c",
    "content": "// clang-format off\n/* gzread.c -- zlib functions for reading gzip files\n * Copyright (C) 2004-2017 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n#include <unistd.h>\n\n#include \"third_party/libz/gzguts.h\"\n\n/* Local functions */\nlocal int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));\nlocal int gz_avail OF((gz_statep));\nlocal int gz_look OF((gz_statep));\nlocal int gz_decomp OF((gz_statep));\nlocal int gz_fetch OF((gz_statep));\nlocal int gz_skip OF((gz_statep, z_off64_t));\nlocal z_size_t gz_read OF((gz_statep, voidp, z_size_t));\n\n/* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from\n   state->fd, and update state->eof, state->err, and state->msg as appropriate.\n   This function needs to loop on read(), since read() is not guaranteed to\n   read the number of bytes requested, depending on the type of descriptor. */\nlocal int gz_load(state, buf, len, have)\n    gz_statep state;\n    unsigned char *buf;\n    unsigned len;\n    unsigned *have;\n{\n    int ret;\n    unsigned get, max = ((unsigned)-1 >> 2) + 1;\n\n    *have = 0;\n    do {\n        get = len - *have;\n        if (get > max)\n            get = max;\n        ret = read(state->fd, buf + *have, get);\n        if (ret <= 0)\n            break;\n        *have += (unsigned)ret;\n    } while (*have < len);\n    if (ret < 0) {\n        gz_error(state, Z_ERRNO, zstrerror());\n        return -1;\n    }\n    if (ret == 0)\n        state->eof = 1;\n    return 0;\n}\n\n/* Load up input buffer and set eof flag if last data loaded -- return -1 on\n   error, 0 otherwise.  Note that the eof flag is set when the end of the input\n   file is reached, even though there may be unused data in the buffer.  Once\n   that data has been used, no more attempts will be made to read the file.\n   If strm->avail_in != 0, then the current data is moved to the beginning of\n   the input buffer, and then the remainder of the buffer is loaded with the\n   available data from the input file. */\nlocal int gz_avail(state)\n    gz_statep state;\n{\n    unsigned got;\n    z_streamp strm = &(state->strm);\n\n    if (state->err != Z_OK && state->err != Z_BUF_ERROR)\n        return -1;\n    if (state->eof == 0) {\n        if (strm->avail_in) {       /* copy what's there to the start */\n            unsigned char *p = state->in;\n            unsigned const char *q = strm->next_in;\n            unsigned n = strm->avail_in;\n            do {\n                *p++ = *q++;\n            } while (--n);\n        }\n        if (gz_load(state, state->in + strm->avail_in,\n                    state->size - strm->avail_in, &got) == -1)\n            return -1;\n        strm->avail_in += got;\n        strm->next_in = state->in;\n    }\n    return 0;\n}\n\n/* Look for gzip header, set up for inflate or copy.  state->x.have must be 0.\n   If this is the first time in, allocate required memory.  state->how will be\n   left unchanged if there is no more input data available, will be set to COPY\n   if there is no gzip header and direct copying will be performed, or it will\n   be set to GZIP for decompression.  If direct copying, then leftover input\n   data from the input buffer will be copied to the output buffer.  In that\n   case, all further file reads will be directly to either the output buffer or\n   a user buffer.  If decompressing, the inflate state will be initialized.\n   gz_look() will return 0 on success or -1 on failure. */\nlocal int gz_look(state)\n    gz_statep state;\n{\n    z_streamp strm = &(state->strm);\n\n    /* allocate read buffers and inflate memory */\n    if (state->size == 0) {\n        /* allocate buffers */\n        state->in = (unsigned char *)malloc(state->want);\n        state->out = (unsigned char *)malloc(state->want << 1);\n        if (state->in == NULL || state->out == NULL) {\n            free(state->out);\n            free(state->in);\n            gz_error(state, Z_MEM_ERROR, \"out of memory\");\n            return -1;\n        }\n        state->size = state->want;\n\n        /* allocate inflate memory */\n        state->strm.zalloc = Z_NULL;\n        state->strm.zfree = Z_NULL;\n        state->strm.opaque = Z_NULL;\n        state->strm.avail_in = 0;\n        state->strm.next_in = Z_NULL;\n        if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) {    /* gunzip */\n            free(state->out);\n            free(state->in);\n            state->size = 0;\n            gz_error(state, Z_MEM_ERROR, \"out of memory\");\n            return -1;\n        }\n    }\n\n    /* get at least the magic bytes in the input buffer */\n    if (strm->avail_in < 2) {\n        if (gz_avail(state) == -1)\n            return -1;\n        if (strm->avail_in == 0)\n            return 0;\n    }\n\n    /* look for gzip magic bytes -- if there, do gzip decoding (note: there is\n       a logical dilemma here when considering the case of a partially written\n       gzip file, to wit, if a single 31 byte is written, then we cannot tell\n       whether this is a single-byte file, or just a partially written gzip\n       file -- for here we assume that if a gzip file is being written, then\n       the header will be written in a single operation, so that reading a\n       single byte is sufficient indication that it is not a gzip file) */\n    if (strm->avail_in > 1 &&\n            strm->next_in[0] == 31 && strm->next_in[1] == 139) {\n        inflateReset(strm);\n        state->how = GZIP;\n        state->direct = 0;\n        return 0;\n    }\n\n    /* no gzip header -- if we were decoding gzip before, then this is trailing\n       garbage.  Ignore the trailing garbage and finish. */\n    if (state->direct == 0) {\n        strm->avail_in = 0;\n        state->eof = 1;\n        state->x.have = 0;\n        return 0;\n    }\n\n    /* doing raw i/o, copy any leftover input to output -- this assumes that\n       the output buffer is larger than the input buffer, which also assures\n       space for gzungetc() */\n    state->x.next = state->out;\n    memcpy(state->x.next, strm->next_in, strm->avail_in);\n    state->x.have = strm->avail_in;\n    strm->avail_in = 0;\n    state->how = COPY;\n    state->direct = 1;\n    return 0;\n}\n\n/* Decompress from input to the provided next_out and avail_out in the state.\n   On return, state->x.have and state->x.next point to the just decompressed\n   data.  If the gzip stream completes, state->how is reset to LOOK to look for\n   the next gzip stream or raw data, once state->x.have is depleted.  Returns 0\n   on success, -1 on failure. */\nlocal int gz_decomp(state)\n    gz_statep state;\n{\n    int ret = Z_OK;\n    unsigned had;\n    z_streamp strm = &(state->strm);\n\n    /* fill output buffer up to end of deflate stream */\n    had = strm->avail_out;\n    do {\n        /* get more input for inflate() */\n        if (strm->avail_in == 0 && gz_avail(state) == -1)\n            return -1;\n        if (strm->avail_in == 0) {\n            gz_error(state, Z_BUF_ERROR, \"unexpected end of file\");\n            break;\n        }\n\n        /* decompress and handle errors */\n        ret = inflate(strm, Z_NO_FLUSH);\n        if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {\n            gz_error(state, Z_STREAM_ERROR,\n                     \"internal error: inflate stream corrupt\");\n            return -1;\n        }\n        if (ret == Z_MEM_ERROR) {\n            gz_error(state, Z_MEM_ERROR, \"out of memory\");\n            return -1;\n        }\n        if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */\n            gz_error(state, Z_DATA_ERROR,\n                     strm->msg == NULL ? \"compressed data error\" : strm->msg);\n            return -1;\n        }\n    } while (strm->avail_out && ret != Z_STREAM_END);\n\n    /* update available output */\n    state->x.have = had - strm->avail_out;\n    state->x.next = strm->next_out - state->x.have;\n\n    /* if the gzip stream completed successfully, look for another */\n    if (ret == Z_STREAM_END)\n        state->how = LOOK;\n\n    /* good decompression */\n    return 0;\n}\n\n/* Fetch data and put it in the output buffer.  Assumes state->x.have is 0.\n   Data is either copied from the input file or decompressed from the input\n   file depending on state->how.  If state->how is LOOK, then a gzip header is\n   looked for to determine whether to copy or decompress.  Returns -1 on error,\n   otherwise 0.  gz_fetch() will leave state->how as COPY or GZIP unless the\n   end of the input file has been reached and all data has been processed.  */\nlocal int gz_fetch(state)\n    gz_statep state;\n{\n    z_streamp strm = &(state->strm);\n\n    do {\n        switch(state->how) {\n        case LOOK:      /* -> LOOK, COPY (only if never GZIP), or GZIP */\n            if (gz_look(state) == -1)\n                return -1;\n            if (state->how == LOOK)\n                return 0;\n            break;\n        case COPY:      /* -> COPY */\n            if (gz_load(state, state->out, state->size << 1, &(state->x.have))\n                    == -1)\n                return -1;\n            state->x.next = state->out;\n            return 0;\n        case GZIP:      /* -> GZIP or LOOK (if end of gzip stream) */\n            strm->avail_out = state->size << 1;\n            strm->next_out = state->out;\n            if (gz_decomp(state) == -1)\n                return -1;\n        }\n    } while (state->x.have == 0 && (!state->eof || strm->avail_in));\n    return 0;\n}\n\n/* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */\nlocal int gz_skip(state, len)\n    gz_statep state;\n    z_off64_t len;\n{\n    unsigned n;\n\n    /* skip over len bytes or reach end-of-file, whichever comes first */\n    while (len)\n        /* skip over whatever is in output buffer */\n        if (state->x.have) {\n            n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?\n                (unsigned)len : state->x.have;\n            state->x.have -= n;\n            state->x.next += n;\n            state->x.pos += n;\n            len -= n;\n        }\n\n        /* output buffer empty -- return if we're at the end of the input */\n        else if (state->eof && state->strm.avail_in == 0)\n            break;\n\n        /* need more data to skip -- load up output buffer */\n        else {\n            /* get more output, looking for header if required */\n            if (gz_fetch(state) == -1)\n                return -1;\n        }\n    return 0;\n}\n\n/* Read len bytes into buf from file, or less than len up to the end of the\n   input.  Return the number of bytes read.  If zero is returned, either the\n   end of file was reached, or there was an error.  state->err must be\n   consulted in that case to determine which. */\nlocal z_size_t gz_read(state, buf, len)\n    gz_statep state;\n    voidp buf;\n    z_size_t len;\n{\n    z_size_t got;\n    unsigned n;\n\n    /* if len is zero, avoid unnecessary operations */\n    if (len == 0)\n        return 0;\n\n    /* process a skip request */\n    if (state->seek) {\n        state->seek = 0;\n        if (gz_skip(state, state->skip) == -1)\n            return 0;\n    }\n\n    /* get len bytes to buf, or less than len if at the end */\n    got = 0;\n    do {\n        /* set n to the maximum amount of len that fits in an unsigned int */\n        n = (unsigned)-1;\n        if (n > len)\n            n = (unsigned)len;\n\n        /* first just try copying data from the output buffer */\n        if (state->x.have) {\n            if (state->x.have < n)\n                n = state->x.have;\n            memcpy(buf, state->x.next, n);\n            state->x.next += n;\n            state->x.have -= n;\n        }\n\n        /* output buffer empty -- return if we're at the end of the input */\n        else if (state->eof && state->strm.avail_in == 0) {\n            state->past = 1;        /* tried to read past end */\n            break;\n        }\n\n        /* need output data -- for small len or new stream load up our output\n           buffer */\n        else if (state->how == LOOK || n < (state->size << 1)) {\n            /* get more output, looking for header if required */\n            if (gz_fetch(state) == -1)\n                return 0;\n            continue;       /* no progress yet -- go back to copy above */\n            /* the copy above assures that we will leave with space in the\n               output buffer, allowing at least one gzungetc() to succeed */\n        }\n\n        /* large len -- read directly into user buffer */\n        else if (state->how == COPY) {      /* read directly */\n            if (gz_load(state, (unsigned char *)buf, n, &n) == -1)\n                return 0;\n        }\n\n        /* large len -- decompress directly into user buffer */\n        else {  /* state->how == GZIP */\n            state->strm.avail_out = n;\n            state->strm.next_out = (unsigned char *)buf;\n            if (gz_decomp(state) == -1)\n                return 0;\n            n = state->x.have;\n            state->x.have = 0;\n        }\n\n        /* update progress */\n        len -= n;\n        buf = (char *)buf + n;\n        got += n;\n        state->x.pos += n;\n    } while (len);\n\n    /* return number of bytes read into user buffer */\n    return got;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzread(file, buf, len)\n    gzFile file;\n    voidp buf;\n    unsigned len;\n{\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state = (gz_statep)file;\n\n    /* check that we're reading and that there's no (serious) error */\n    if (state->mode != GZ_READ ||\n            (state->err != Z_OK && state->err != Z_BUF_ERROR))\n        return -1;\n\n    /* since an int is returned, make sure len fits in one, otherwise return\n       with an error (this avoids a flaw in the interface) */\n    if ((int)len < 0) {\n        gz_error(state, Z_STREAM_ERROR, \"request does not fit in an int\");\n        return -1;\n    }\n\n    /* read len or fewer bytes to buf */\n    len = (unsigned)gz_read(state, buf, len);\n\n    /* check for an error */\n    if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)\n        return -1;\n\n    /* return the number of bytes read (this is assured to fit in an int) */\n    return (int)len;\n}\n\n/* -- see zlib.h -- */\nz_size_t ZEXPORT gzfread(buf, size, nitems, file)\n    voidp buf;\n    z_size_t size;\n    z_size_t nitems;\n    gzFile file;\n{\n    z_size_t len;\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return 0;\n    state = (gz_statep)file;\n\n    /* check that we're reading and that there's no (serious) error */\n    if (state->mode != GZ_READ ||\n            (state->err != Z_OK && state->err != Z_BUF_ERROR))\n        return 0;\n\n    /* compute bytes to read -- error on overflow */\n    len = nitems * size;\n    if (size && len / size != nitems) {\n        gz_error(state, Z_STREAM_ERROR, \"request does not fit in a size_t\");\n        return 0;\n    }\n\n    /* read len or fewer bytes to buf, return the number of full items read */\n    return len ? gz_read(state, buf, len) / size : 0;\n}\n\n/* -- see zlib.h -- */\n#ifdef Z_PREFIX_SET\n#  undef z_gzgetc\n#else\n#  undef gzgetc\n#endif\nint ZEXPORT gzgetc(file)\n    gzFile file;\n{\n    unsigned char buf[1];\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state = (gz_statep)file;\n\n    /* check that we're reading and that there's no (serious) error */\n    if (state->mode != GZ_READ ||\n        (state->err != Z_OK && state->err != Z_BUF_ERROR))\n        return -1;\n\n    /* try output buffer (no need to check for skip request) */\n    if (state->x.have) {\n        state->x.have--;\n        state->x.pos++;\n        return *(state->x.next)++;\n    }\n\n    /* nothing there -- try gz_read() */\n    return gz_read(state, buf, 1) < 1 ? -1 : buf[0];\n}\n\nint ZEXPORT gzgetc_(file)\ngzFile file;\n{\n    return gzgetc(file);\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzungetc(c, file)\n    int c;\n    gzFile file;\n{\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state = (gz_statep)file;\n\n    /* check that we're reading and that there's no (serious) error */\n    if (state->mode != GZ_READ ||\n        (state->err != Z_OK && state->err != Z_BUF_ERROR))\n        return -1;\n\n    /* process a skip request */\n    if (state->seek) {\n        state->seek = 0;\n        if (gz_skip(state, state->skip) == -1)\n            return -1;\n    }\n\n    /* can't push EOF */\n    if (c < 0)\n        return -1;\n\n    /* if output buffer empty, put byte at end (allows more pushing) */\n    if (state->x.have == 0) {\n        state->x.have = 1;\n        state->x.next = state->out + (state->size << 1) - 1;\n        state->x.next[0] = (unsigned char)c;\n        state->x.pos--;\n        state->past = 0;\n        return c;\n    }\n\n    /* if no room, give up (must have already done a gzungetc()) */\n    if (state->x.have == (state->size << 1)) {\n        gz_error(state, Z_DATA_ERROR, \"out of room to push characters\");\n        return -1;\n    }\n\n    /* slide output data if needed and insert byte before existing data */\n    if (state->x.next == state->out) {\n        unsigned char *src = state->out + state->x.have;\n        unsigned char *dest = state->out + (state->size << 1);\n        while (src > state->out)\n            *--dest = *--src;\n        state->x.next = dest;\n    }\n    state->x.have++;\n    state->x.next--;\n    state->x.next[0] = (unsigned char)c;\n    state->x.pos--;\n    state->past = 0;\n    return c;\n}\n\n/* -- see zlib.h -- */\nchar * ZEXPORT gzgets(file, buf, len)\n    gzFile file;\n    char *buf;\n    int len;\n{\n    unsigned left, n;\n    char *str;\n    unsigned char *eol;\n    gz_statep state;\n\n    /* check parameters and get internal structure */\n    if (file == NULL || buf == NULL || len < 1)\n        return NULL;\n    state = (gz_statep)file;\n\n    /* check that we're reading and that there's no (serious) error */\n    if (state->mode != GZ_READ ||\n        (state->err != Z_OK && state->err != Z_BUF_ERROR))\n        return NULL;\n\n    /* process a skip request */\n    if (state->seek) {\n        state->seek = 0;\n        if (gz_skip(state, state->skip) == -1)\n            return NULL;\n    }\n\n    /* copy output bytes up to new line or len - 1, whichever comes first --\n       append a terminating zero to the string (we don't check for a zero in\n       the contents, let the user worry about that) */\n    str = buf;\n    left = (unsigned)len - 1;\n    if (left) do {\n        /* assure that something is in the output buffer */\n        if (state->x.have == 0 && gz_fetch(state) == -1)\n            return NULL;                /* error */\n        if (state->x.have == 0) {       /* end of file */\n            state->past = 1;            /* read past end */\n            break;                      /* return what we have */\n        }\n\n        /* look for end-of-line in current output buffer */\n        n = state->x.have > left ? left : state->x.have;\n        eol = (unsigned char *)memchr(state->x.next, '\\n', n);\n        if (eol != NULL)\n            n = (unsigned)(eol - state->x.next) + 1;\n\n        /* copy through end-of-line, or remainder if not found */\n        memcpy(buf, state->x.next, n);\n        state->x.have -= n;\n        state->x.next += n;\n        state->x.pos += n;\n        left -= n;\n        buf += n;\n    } while (left && eol == NULL);\n\n    /* return terminated string, or if nothing, end of file */\n    if (buf == str)\n        return NULL;\n    buf[0] = 0;\n    return str;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzdirect(file)\n    gzFile file;\n{\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return 0;\n    state = (gz_statep)file;\n\n    /* if the state is not known, but we can find out, then do so (this is\n       mainly for right after a gzopen() or gzdopen()) */\n    if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)\n        (void)gz_look(state);\n\n    /* return 1 if transparent, 0 if processing a gzip stream */\n    return state->direct;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzclose_r(file)\n    gzFile file;\n{\n    int ret, err;\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state = (gz_statep)file;\n\n    /* check that we're reading */\n    if (state->mode != GZ_READ)\n        return Z_STREAM_ERROR;\n\n    /* free memory and close file */\n    if (state->size) {\n        inflateEnd(&(state->strm));\n        free(state->out);\n        free(state->in);\n    }\n    err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;\n    gz_error(state, Z_OK, NULL);\n    free(state->path);\n    ret = close(state->fd);\n    free(state);\n    return ret ? Z_ERRNO : err;\n}\n"
  },
  {
    "path": "third_party/libz/gzwrite.c",
    "content": "// clang-format off\n/* gzwrite.c -- zlib functions for writing gzip files\n * Copyright (C) 2004-2019 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n#include <unistd.h>\n\n#include \"third_party/libz/gzguts.h\"\n\n/* Local functions */\nlocal int gz_init OF((gz_statep));\nlocal int gz_comp OF((gz_statep, int));\nlocal int gz_zero OF((gz_statep, z_off64_t));\nlocal z_size_t gz_write OF((gz_statep, voidpc, z_size_t));\n\n/* Initialize state for writing a gzip file.  Mark initialization by setting\n   state->size to non-zero.  Return -1 on a memory allocation failure, or 0 on\n   success. */\nlocal int gz_init(state)\n    gz_statep state;\n{\n    int ret;\n    z_streamp strm = &(state->strm);\n\n    /* allocate input buffer (double size for gzprintf) */\n    state->in = (unsigned char *)malloc(state->want << 1);\n    if (state->in == NULL) {\n        gz_error(state, Z_MEM_ERROR, \"out of memory\");\n        return -1;\n    }\n\n    /* only need output buffer and deflate state if compressing */\n    if (!state->direct) {\n        /* allocate output buffer */\n        state->out = (unsigned char *)malloc(state->want);\n        if (state->out == NULL) {\n            free(state->in);\n            gz_error(state, Z_MEM_ERROR, \"out of memory\");\n            return -1;\n        }\n\n        /* allocate deflate memory, set up for gzip compression */\n        strm->zalloc = Z_NULL;\n        strm->zfree = Z_NULL;\n        strm->opaque = Z_NULL;\n        ret = deflateInit2(strm, state->level, Z_DEFLATED,\n                           MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);\n        if (ret != Z_OK) {\n            free(state->out);\n            free(state->in);\n            gz_error(state, Z_MEM_ERROR, \"out of memory\");\n            return -1;\n        }\n        strm->next_in = NULL;\n    }\n\n    /* mark state as initialized */\n    state->size = state->want;\n\n    /* initialize write buffer if compressing */\n    if (!state->direct) {\n        strm->avail_out = state->size;\n        strm->next_out = state->out;\n        state->x.next = strm->next_out;\n    }\n    return 0;\n}\n\n/* Compress whatever is at avail_in and next_in and write to the output file.\n   Return -1 if there is an error writing to the output file or if gz_init()\n   fails to allocate memory, otherwise 0.  flush is assumed to be a valid\n   deflate() flush value.  If flush is Z_FINISH, then the deflate() state is\n   reset to start a new gzip stream.  If gz->direct is true, then simply write\n   to the output file without compressing, and ignore flush. */\nlocal int gz_comp(state, flush)\n    gz_statep state;\n    int flush;\n{\n    int ret, writ;\n    unsigned have, put, max = ((unsigned)-1 >> 2) + 1;\n    z_streamp strm = &(state->strm);\n\n    /* allocate memory if this is the first time through */\n    if (state->size == 0 && gz_init(state) == -1)\n        return -1;\n\n    /* write directly if requested */\n    if (state->direct) {\n        while (strm->avail_in) {\n            put = strm->avail_in > max ? max : strm->avail_in;\n            writ = write(state->fd, strm->next_in, put);\n            if (writ < 0) {\n                gz_error(state, Z_ERRNO, zstrerror());\n                return -1;\n            }\n            strm->avail_in -= (unsigned)writ;\n            strm->next_in += writ;\n        }\n        return 0;\n    }\n\n    /* check for a pending reset */\n    if (state->reset) {\n        /* don't start a new gzip member unless there is data to write */\n        if (strm->avail_in == 0)\n            return 0;\n        deflateReset(strm);\n        state->reset = 0;\n    }\n\n    /* run deflate() on provided input until it produces no more output */\n    ret = Z_OK;\n    do {\n        /* write out current buffer contents if full, or if flushing, but if\n           doing Z_FINISH then don't write until we get to Z_STREAM_END */\n        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&\n            (flush != Z_FINISH || ret == Z_STREAM_END))) {\n            while (strm->next_out > state->x.next) {\n                put = strm->next_out - state->x.next > (int)max ? max :\n                      (unsigned)(strm->next_out - state->x.next);\n                writ = write(state->fd, state->x.next, put);\n                if (writ < 0) {\n                    gz_error(state, Z_ERRNO, zstrerror());\n                    return -1;\n                }\n                state->x.next += writ;\n            }\n            if (strm->avail_out == 0) {\n                strm->avail_out = state->size;\n                strm->next_out = state->out;\n                state->x.next = state->out;\n            }\n        }\n\n        /* compress */\n        have = strm->avail_out;\n        ret = deflate(strm, flush);\n        if (ret == Z_STREAM_ERROR) {\n            gz_error(state, Z_STREAM_ERROR,\n                      \"internal error: deflate stream corrupt\");\n            return -1;\n        }\n        have -= strm->avail_out;\n    } while (have);\n\n    /* if that completed a deflate stream, allow another to start */\n    if (flush == Z_FINISH)\n        state->reset = 1;\n\n    /* all done, no errors */\n    return 0;\n}\n\n/* Compress len zeros to output.  Return -1 on a write error or memory\n   allocation failure by gz_comp(), or 0 on success. */\nlocal int gz_zero(state, len)\n    gz_statep state;\n    z_off64_t len;\n{\n    int first;\n    unsigned n;\n    z_streamp strm = &(state->strm);\n\n    /* consume whatever's left in the input buffer */\n    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)\n        return -1;\n\n    /* compress len zeros (len guaranteed > 0) */\n    first = 1;\n    while (len) {\n        n = GT_OFF(state->size) || (z_off64_t)state->size > len ?\n            (unsigned)len : state->size;\n        if (first) {\n            memset(state->in, 0, n);\n            first = 0;\n        }\n        strm->avail_in = n;\n        strm->next_in = state->in;\n        state->x.pos += n;\n        if (gz_comp(state, Z_NO_FLUSH) == -1)\n            return -1;\n        len -= n;\n    }\n    return 0;\n}\n\n/* Write len bytes from buf to file.  Return the number of bytes written.  If\n   the returned value is less than len, then there was an error. */\nlocal z_size_t gz_write(state, buf, len)\n    gz_statep state;\n    voidpc buf;\n    z_size_t len;\n{\n    z_size_t put = len;\n\n    /* if len is zero, avoid unnecessary operations */\n    if (len == 0)\n        return 0;\n\n    /* allocate memory if this is the first time through */\n    if (state->size == 0 && gz_init(state) == -1)\n        return 0;\n\n    /* check for seek request */\n    if (state->seek) {\n        state->seek = 0;\n        if (gz_zero(state, state->skip) == -1)\n            return 0;\n    }\n\n    /* for small len, copy to input buffer, otherwise compress directly */\n    if (len < state->size) {\n        /* copy to input buffer, compress when full */\n        do {\n            unsigned have, copy;\n\n            if (state->strm.avail_in == 0)\n                state->strm.next_in = state->in;\n            have = (unsigned)((state->strm.next_in + state->strm.avail_in) -\n                              state->in);\n            copy = state->size - have;\n            if (copy > len)\n                copy = (unsigned)len;\n            memcpy(state->in + have, buf, copy);\n            state->strm.avail_in += copy;\n            state->x.pos += copy;\n            buf = (const char *)buf + copy;\n            len -= copy;\n            if (len && gz_comp(state, Z_NO_FLUSH) == -1)\n                return 0;\n        } while (len);\n    }\n    else {\n        /* consume whatever's left in the input buffer */\n        if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)\n            return 0;\n\n        /* directly compress user buffer to file */\n        state->strm.next_in = (z_const Bytef *)buf;\n        do {\n            unsigned n = (unsigned)-1;\n            if (n > len)\n                n = (unsigned)len;\n            state->strm.avail_in = n;\n            state->x.pos += n;\n            if (gz_comp(state, Z_NO_FLUSH) == -1)\n                return 0;\n            len -= n;\n        } while (len);\n    }\n\n    /* input was all buffered or compressed */\n    return put;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzwrite(file, buf, len)\n    gzFile file;\n    voidpc buf;\n    unsigned len;\n{\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return 0;\n    state = (gz_statep)file;\n\n    /* check that we're writing and that there's no error */\n    if (state->mode != GZ_WRITE || state->err != Z_OK)\n        return 0;\n\n    /* since an int is returned, make sure len fits in one, otherwise return\n       with an error (this avoids a flaw in the interface) */\n    if ((int)len < 0) {\n        gz_error(state, Z_DATA_ERROR, \"requested length does not fit in int\");\n        return 0;\n    }\n\n    /* write len bytes from buf (the return value will fit in an int) */\n    return (int)gz_write(state, buf, len);\n}\n\n/* -- see zlib.h -- */\nz_size_t ZEXPORT gzfwrite(buf, size, nitems, file)\n    voidpc buf;\n    z_size_t size;\n    z_size_t nitems;\n    gzFile file;\n{\n    z_size_t len;\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return 0;\n    state = (gz_statep)file;\n\n    /* check that we're writing and that there's no error */\n    if (state->mode != GZ_WRITE || state->err != Z_OK)\n        return 0;\n\n    /* compute bytes to read -- error on overflow */\n    len = nitems * size;\n    if (size && len / size != nitems) {\n        gz_error(state, Z_STREAM_ERROR, \"request does not fit in a size_t\");\n        return 0;\n    }\n\n    /* write len bytes to buf, return the number of full items written */\n    return len ? gz_write(state, buf, len) / size : 0;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzputc(file, c)\n    gzFile file;\n    int c;\n{\n    unsigned have;\n    unsigned char buf[1];\n    gz_statep state;\n    z_streamp strm;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state = (gz_statep)file;\n    strm = &(state->strm);\n\n    /* check that we're writing and that there's no error */\n    if (state->mode != GZ_WRITE || state->err != Z_OK)\n        return -1;\n\n    /* check for seek request */\n    if (state->seek) {\n        state->seek = 0;\n        if (gz_zero(state, state->skip) == -1)\n            return -1;\n    }\n\n    /* try writing to input buffer for speed (state->size == 0 if buffer not\n       initialized) */\n    if (state->size) {\n        if (strm->avail_in == 0)\n            strm->next_in = state->in;\n        have = (unsigned)((strm->next_in + strm->avail_in) - state->in);\n        if (have < state->size) {\n            state->in[have] = (unsigned char)c;\n            strm->avail_in++;\n            state->x.pos++;\n            return c & 0xff;\n        }\n    }\n\n    /* no room in buffer or not initialized, use gz_write() */\n    buf[0] = (unsigned char)c;\n    if (gz_write(state, buf, 1) != 1)\n        return -1;\n    return c & 0xff;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzputs(file, s)\n    gzFile file;\n    const char *s;\n{\n    z_size_t len, put;\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state = (gz_statep)file;\n\n    /* check that we're writing and that there's no error */\n    if (state->mode != GZ_WRITE || state->err != Z_OK)\n        return -1;\n\n    /* write string */\n    len = strlen(s);\n    if ((int)len < 0 || (unsigned)len != len) {\n        gz_error(state, Z_STREAM_ERROR, \"string length does not fit in int\");\n        return -1;\n    }\n    put = gz_write(state, s, len);\n    return put < len ? -1 : (int)len;\n}\n\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#include <stdarg.h>\n\n/* -- see zlib.h -- */\nint ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)\n{\n    int len;\n    unsigned left;\n    char *next;\n    gz_statep state;\n    z_streamp strm;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state = (gz_statep)file;\n    strm = &(state->strm);\n\n    /* check that we're writing and that there's no error */\n    if (state->mode != GZ_WRITE || state->err != Z_OK)\n        return Z_STREAM_ERROR;\n\n    /* make sure we have some buffer space */\n    if (state->size == 0 && gz_init(state) == -1)\n        return state->err;\n\n    /* check for seek request */\n    if (state->seek) {\n        state->seek = 0;\n        if (gz_zero(state, state->skip) == -1)\n            return state->err;\n    }\n\n    /* do the printf() into the input buffer, put length in len -- the input\n       buffer is double-sized just for this function, so there is guaranteed to\n       be state->size bytes available after the current contents */\n    if (strm->avail_in == 0)\n        strm->next_in = state->in;\n    next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);\n    next[state->size - 1] = 0;\n#ifdef NO_vsnprintf\n#  ifdef HAS_vsprintf_void\n    (void)vsprintf(next, format, va);\n    for (len = 0; len < state->size; len++)\n        if (next[len] == 0) break;\n#  else\n    len = vsprintf(next, format, va);\n#  endif\n#else\n#  ifdef HAS_vsnprintf_void\n    (void)vsnprintf(next, state->size, format, va);\n    len = strlen(next);\n#  else\n    len = vsnprintf(next, state->size, format, va);\n#  endif\n#endif\n\n    /* check that printf() results fit in buffer */\n    if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)\n        return 0;\n\n    /* update buffer and position, compress first half if past that */\n    strm->avail_in += (unsigned)len;\n    state->x.pos += len;\n    if (strm->avail_in >= state->size) {\n        left = strm->avail_in - state->size;\n        strm->avail_in = state->size;\n        if (gz_comp(state, Z_NO_FLUSH) == -1)\n            return state->err;\n        memmove(state->in, state->in + state->size, left);\n        strm->next_in = state->in;\n        strm->avail_in = left;\n    }\n    return len;\n}\n\nint ZEXPORTVA gzprintf(gzFile file, const char *format, ...)\n{\n    va_list va;\n    int ret;\n\n    va_start(va, format);\n    ret = gzvprintf(file, format, va);\n    va_end(va);\n    return ret;\n}\n\n#else /* !STDC && !Z_HAVE_STDARG_H */\n\n/* -- see zlib.h -- */\nint ZEXPORTVA gzprintf(file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,\n                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)\n    gzFile file;\n    const char *format;\n    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,\n        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;\n{\n    unsigned len, left;\n    char *next;\n    gz_statep state;\n    z_streamp strm;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state = (gz_statep)file;\n    strm = &(state->strm);\n\n    /* check that can really pass pointer in ints */\n    if (sizeof(int) != sizeof(void *))\n        return Z_STREAM_ERROR;\n\n    /* check that we're writing and that there's no error */\n    if (state->mode != GZ_WRITE || state->err != Z_OK)\n        return Z_STREAM_ERROR;\n\n    /* make sure we have some buffer space */\n    if (state->size == 0 && gz_init(state) == -1)\n        return state->error;\n\n    /* check for seek request */\n    if (state->seek) {\n        state->seek = 0;\n        if (gz_zero(state, state->skip) == -1)\n            return state->error;\n    }\n\n    /* do the printf() into the input buffer, put length in len -- the input\n       buffer is double-sized just for this function, so there is guaranteed to\n       be state->size bytes available after the current contents */\n    if (strm->avail_in == 0)\n        strm->next_in = state->in;\n    next = (char *)(strm->next_in + strm->avail_in);\n    next[state->size - 1] = 0;\n#ifdef NO_snprintf\n#  ifdef HAS_sprintf_void\n    sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,\n            a13, a14, a15, a16, a17, a18, a19, a20);\n    for (len = 0; len < size; len++)\n        if (next[len] == 0)\n            break;\n#  else\n    len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,\n                  a12, a13, a14, a15, a16, a17, a18, a19, a20);\n#  endif\n#else\n#  ifdef HAS_snprintf_void\n    snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,\n             a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);\n    len = strlen(next);\n#  else\n    len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,\n                   a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);\n#  endif\n#endif\n\n    /* check that printf() results fit in buffer */\n    if (len == 0 || len >= state->size || next[state->size - 1] != 0)\n        return 0;\n\n    /* update buffer and position, compress first half if past that */\n    strm->avail_in += len;\n    state->x.pos += len;\n    if (strm->avail_in >= state->size) {\n        left = strm->avail_in - state->size;\n        strm->avail_in = state->size;\n        if (gz_comp(state, Z_NO_FLUSH) == -1)\n            return state->err;\n        memmove(state->in, state->in + state->size, left);\n        strm->next_in = state->in;\n        strm->avail_in = left;\n    }\n    return (int)len;\n}\n\n#endif\n\n/* -- see zlib.h -- */\nint ZEXPORT gzflush(file, flush)\n    gzFile file;\n    int flush;\n{\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state = (gz_statep)file;\n\n    /* check that we're writing and that there's no error */\n    if (state->mode != GZ_WRITE || state->err != Z_OK)\n        return Z_STREAM_ERROR;\n\n    /* check flush parameter */\n    if (flush < 0 || flush > Z_FINISH)\n        return Z_STREAM_ERROR;\n\n    /* check for seek request */\n    if (state->seek) {\n        state->seek = 0;\n        if (gz_zero(state, state->skip) == -1)\n            return state->err;\n    }\n\n    /* compress remaining data with requested flush */\n    (void)gz_comp(state, flush);\n    return state->err;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzsetparams(file, level, strategy)\n    gzFile file;\n    int level;\n    int strategy;\n{\n    gz_statep state;\n    z_streamp strm;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state = (gz_statep)file;\n    strm = &(state->strm);\n\n    /* check that we're writing and that there's no error */\n    if (state->mode != GZ_WRITE || state->err != Z_OK)\n        return Z_STREAM_ERROR;\n\n    /* if no change is requested, then do nothing */\n    if (level == state->level && strategy == state->strategy)\n        return Z_OK;\n\n    /* check for seek request */\n    if (state->seek) {\n        state->seek = 0;\n        if (gz_zero(state, state->skip) == -1)\n            return state->err;\n    }\n\n    /* change compression parameters for subsequent input */\n    if (state->size) {\n        /* flush previous input with previous parameters before changing */\n        if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)\n            return state->err;\n        deflateParams(strm, level, strategy);\n    }\n    state->level = level;\n    state->strategy = strategy;\n    return Z_OK;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzclose_w(file)\n    gzFile file;\n{\n    int ret = Z_OK;\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state = (gz_statep)file;\n\n    /* check that we're writing */\n    if (state->mode != GZ_WRITE)\n        return Z_STREAM_ERROR;\n\n    /* check for seek request */\n    if (state->seek) {\n        state->seek = 0;\n        if (gz_zero(state, state->skip) == -1)\n            ret = state->err;\n    }\n\n    /* flush, free memory, and close file */\n    if (gz_comp(state, Z_FINISH) == -1)\n        ret = state->err;\n    if (state->size) {\n        if (!state->direct) {\n            (void)deflateEnd(&(state->strm));\n            free(state->out);\n        }\n        free(state->in);\n    }\n    gz_error(state, Z_OK, NULL);\n    free(state->path);\n    if (close(state->fd) == -1)\n        ret = Z_ERRNO;\n    free(state);\n    return ret;\n}\n"
  },
  {
    "path": "third_party/libz/infback.c",
    "content": "// clang-format off\n/* infback.c -- inflate using a call-back interface\n * Copyright (C) 1995-2022 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/*\n   This code is largely copied from inflate.c.  Normally either infback.o or\n   inflate.o would be linked into an application--not both.  The interface\n   with inffast.c is retained so that optimized assembler-coded versions of\n   inflate_fast() can be used with either inflate.c or infback.c.\n */\n\n#include \"third_party/libz/zutil.h\"\n#include \"third_party/libz/inftrees.h\"\n#include \"third_party/libz/inflate.h\"\n#include \"third_party/libz/inffast.h\"\n\n/* function prototypes */\nlocal void fixedtables OF((struct inflate_state FAR *state));\n\n/*\n   strm provides memory allocation functions in zalloc and zfree, or\n   Z_NULL to use the library memory allocation functions.\n\n   windowBits is in the range 8..15, and window is a user-supplied\n   window and output buffer that is 2**windowBits bytes.\n */\nint ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)\nz_streamp strm;\nint windowBits;\nunsigned char FAR *window;\nconst char *version;\nint stream_size;\n{\n    struct inflate_state FAR *state;\n\n    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||\n        stream_size != (int)(sizeof(z_stream)))\n        return Z_VERSION_ERROR;\n    if (strm == Z_NULL || window == Z_NULL ||\n        windowBits < 8 || windowBits > 15)\n        return Z_STREAM_ERROR;\n    strm->msg = Z_NULL;                 /* in case we return an error */\n    if (strm->zalloc == (alloc_func)0) {\n#ifdef Z_SOLO\n        return Z_STREAM_ERROR;\n#else\n        strm->zalloc = zcalloc;\n        strm->opaque = (voidpf)0;\n#endif\n    }\n    if (strm->zfree == (free_func)0)\n#ifdef Z_SOLO\n        return Z_STREAM_ERROR;\n#else\n    strm->zfree = zcfree;\n#endif\n    state = (struct inflate_state FAR *)ZALLOC(strm, 1,\n                                               sizeof(struct inflate_state));\n    if (state == Z_NULL) return Z_MEM_ERROR;\n    Tracev((stderr, \"inflate: allocated\\n\"));\n    strm->state = (struct internal_state FAR *)state;\n    state->dmax = 32768U;\n    state->wbits = (uInt)windowBits;\n    state->wsize = 1U << windowBits;\n    state->window = window;\n    state->wnext = 0;\n    state->whave = 0;\n    state->sane = 1;\n    return Z_OK;\n}\n\n/*\n   Return state with length and distance decoding tables and index sizes set to\n   fixed code decoding.  Normally this returns fixed tables from inffixed.h.\n   If BUILDFIXED is defined, then instead this routine builds the tables the\n   first time it's called, and returns those tables the first time and\n   thereafter.  This reduces the size of the code by about 2K bytes, in\n   exchange for a little execution time.  However, BUILDFIXED should not be\n   used for threaded applications, since the rewriting of the tables and virgin\n   may not be thread-safe.\n */\nlocal void fixedtables(state)\nstruct inflate_state FAR *state;\n{\n#ifdef BUILDFIXED\n    static int virgin = 1;\n    static code *lenfix, *distfix;\n    static code fixed[544];\n\n    /* build fixed huffman tables if first call (may not be thread safe) */\n    if (virgin) {\n        unsigned sym, bits;\n        static code *next;\n\n        /* literal/length table */\n        sym = 0;\n        while (sym < 144) state->lens[sym++] = 8;\n        while (sym < 256) state->lens[sym++] = 9;\n        while (sym < 280) state->lens[sym++] = 7;\n        while (sym < 288) state->lens[sym++] = 8;\n        next = fixed;\n        lenfix = next;\n        bits = 9;\n        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);\n\n        /* distance table */\n        sym = 0;\n        while (sym < 32) state->lens[sym++] = 5;\n        distfix = next;\n        bits = 5;\n        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);\n\n        /* do this just once */\n        virgin = 0;\n    }\n#else /* !BUILDFIXED */\n#   include \"third_party/libz/inffixed.h\"\n#endif /* BUILDFIXED */\n    state->lencode = lenfix;\n    state->lenbits = 9;\n    state->distcode = distfix;\n    state->distbits = 5;\n}\n\n/* Macros for inflateBack(): */\n\n/* Load returned state from inflate_fast() */\n#define LOAD() \\\n    do { \\\n        put = strm->next_out; \\\n        left = strm->avail_out; \\\n        next = strm->next_in; \\\n        have = strm->avail_in; \\\n        hold = state->hold; \\\n        bits = state->bits; \\\n    } while (0)\n\n/* Set state from registers for inflate_fast() */\n#define RESTORE() \\\n    do { \\\n        strm->next_out = put; \\\n        strm->avail_out = left; \\\n        strm->next_in = next; \\\n        strm->avail_in = have; \\\n        state->hold = hold; \\\n        state->bits = bits; \\\n    } while (0)\n\n/* Clear the input bit accumulator */\n#define INITBITS() \\\n    do { \\\n        hold = 0; \\\n        bits = 0; \\\n    } while (0)\n\n/* Assure that some input is available.  If input is requested, but denied,\n   then return a Z_BUF_ERROR from inflateBack(). */\n#define PULL() \\\n    do { \\\n        if (have == 0) { \\\n            have = in(in_desc, &next); \\\n            if (have == 0) { \\\n                next = Z_NULL; \\\n                ret = Z_BUF_ERROR; \\\n                goto inf_leave; \\\n            } \\\n        } \\\n    } while (0)\n\n/* Get a byte of input into the bit accumulator, or return from inflateBack()\n   with an error if there is no input available. */\n#define PULLBYTE() \\\n    do { \\\n        PULL(); \\\n        have--; \\\n        hold += (unsigned long)(*next++) << bits; \\\n        bits += 8; \\\n    } while (0)\n\n/* Assure that there are at least n bits in the bit accumulator.  If there is\n   not enough available input to do that, then return from inflateBack() with\n   an error. */\n#define NEEDBITS(n) \\\n    do { \\\n        while (bits < (unsigned)(n)) \\\n            PULLBYTE(); \\\n    } while (0)\n\n/* Return the low n bits of the bit accumulator (n < 16) */\n#define BITS(n) \\\n    ((unsigned)hold & ((1U << (n)) - 1))\n\n/* Remove n bits from the bit accumulator */\n#define DROPBITS(n) \\\n    do { \\\n        hold >>= (n); \\\n        bits -= (unsigned)(n); \\\n    } while (0)\n\n/* Remove zero to seven bits as needed to go to a byte boundary */\n#define BYTEBITS() \\\n    do { \\\n        hold >>= bits & 7; \\\n        bits -= bits & 7; \\\n    } while (0)\n\n/* Assure that some output space is available, by writing out the window\n   if it's full.  If the write fails, return from inflateBack() with a\n   Z_BUF_ERROR. */\n#define ROOM() \\\n    do { \\\n        if (left == 0) { \\\n            put = state->window; \\\n            left = state->wsize; \\\n            state->whave = left; \\\n            if (out(out_desc, put, left)) { \\\n                ret = Z_BUF_ERROR; \\\n                goto inf_leave; \\\n            } \\\n        } \\\n    } while (0)\n\n/*\n   strm provides the memory allocation functions and window buffer on input,\n   and provides information on the unused input on return.  For Z_DATA_ERROR\n   returns, strm will also provide an error message.\n\n   in() and out() are the call-back input and output functions.  When\n   inflateBack() needs more input, it calls in().  When inflateBack() has\n   filled the window with output, or when it completes with data in the\n   window, it calls out() to write out the data.  The application must not\n   change the provided input until in() is called again or inflateBack()\n   returns.  The application must not change the window/output buffer until\n   inflateBack() returns.\n\n   in() and out() are called with a descriptor parameter provided in the\n   inflateBack() call.  This parameter can be a structure that provides the\n   information required to do the read or write, as well as accumulated\n   information on the input and output such as totals and check values.\n\n   in() should return zero on failure.  out() should return non-zero on\n   failure.  If either in() or out() fails, than inflateBack() returns a\n   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it\n   was in() or out() that caused in the error.  Otherwise,  inflateBack()\n   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format\n   error, or Z_MEM_ERROR if it could not allocate memory for the state.\n   inflateBack() can also return Z_STREAM_ERROR if the input parameters\n   are not correct, i.e. strm is Z_NULL or the state was not initialized.\n */\nint ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)\nz_streamp strm;\nin_func in;\nvoid FAR *in_desc;\nout_func out;\nvoid FAR *out_desc;\n{\n    struct inflate_state FAR *state;\n    z_const unsigned char FAR *next;    /* next input */\n    unsigned char FAR *put;     /* next output */\n    unsigned have, left;        /* available input and output */\n    unsigned long hold;         /* bit buffer */\n    unsigned bits;              /* bits in bit buffer */\n    unsigned copy;              /* number of stored or match bytes to copy */\n    unsigned char FAR *from;    /* where to copy match bytes from */\n    code here;                  /* current decoding table entry */\n    code last;                  /* parent table entry */\n    unsigned len;               /* length to copy for repeats, bits to drop */\n    int ret;                    /* return code */\n    static const unsigned short order[19] = /* permutation of code lengths */\n        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};\n\n    /* Check that the strm exists and that the state was initialized */\n    if (strm == Z_NULL || strm->state == Z_NULL)\n        return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n\n    /* Reset the state */\n    strm->msg = Z_NULL;\n    state->mode = TYPE;\n    state->last = 0;\n    state->whave = 0;\n    next = strm->next_in;\n    have = next != Z_NULL ? strm->avail_in : 0;\n    hold = 0;\n    bits = 0;\n    put = state->window;\n    left = state->wsize;\n\n    /* Inflate until end of block marked as last */\n    for (;;)\n        switch (state->mode) {\n        case TYPE:\n            /* determine and dispatch block type */\n            if (state->last) {\n                BYTEBITS();\n                state->mode = DONE;\n                break;\n            }\n            NEEDBITS(3);\n            state->last = BITS(1);\n            DROPBITS(1);\n            switch (BITS(2)) {\n            case 0:                             /* stored block */\n                Tracev((stderr, \"inflate:     stored block%s\\n\",\n                        state->last ? \" (last)\" : \"\"));\n                state->mode = STORED;\n                break;\n            case 1:                             /* fixed block */\n                fixedtables(state);\n                Tracev((stderr, \"inflate:     fixed codes block%s\\n\",\n                        state->last ? \" (last)\" : \"\"));\n                state->mode = LEN;              /* decode codes */\n                break;\n            case 2:                             /* dynamic block */\n                Tracev((stderr, \"inflate:     dynamic codes block%s\\n\",\n                        state->last ? \" (last)\" : \"\"));\n                state->mode = TABLE;\n                break;\n            case 3:\n                strm->msg = (char *)\"invalid block type\";\n                state->mode = BAD;\n            }\n            DROPBITS(2);\n            break;\n\n        case STORED:\n            /* get and verify stored block length */\n            BYTEBITS();                         /* go to byte boundary */\n            NEEDBITS(32);\n            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {\n                strm->msg = (char *)\"invalid stored block lengths\";\n                state->mode = BAD;\n                break;\n            }\n            state->length = (unsigned)hold & 0xffff;\n            Tracev((stderr, \"inflate:       stored length %u\\n\",\n                    state->length));\n            INITBITS();\n\n            /* copy stored block from input to output */\n            while (state->length != 0) {\n                copy = state->length;\n                PULL();\n                ROOM();\n                if (copy > have) copy = have;\n                if (copy > left) copy = left;\n                zmemcpy(put, next, copy);\n                have -= copy;\n                next += copy;\n                left -= copy;\n                put += copy;\n                state->length -= copy;\n            }\n            Tracev((stderr, \"inflate:       stored end\\n\"));\n            state->mode = TYPE;\n            break;\n\n        case TABLE:\n            /* get dynamic table entries descriptor */\n            NEEDBITS(14);\n            state->nlen = BITS(5) + 257;\n            DROPBITS(5);\n            state->ndist = BITS(5) + 1;\n            DROPBITS(5);\n            state->ncode = BITS(4) + 4;\n            DROPBITS(4);\n#ifndef PKZIP_BUG_WORKAROUND\n            if (state->nlen > 286 || state->ndist > 30) {\n                strm->msg = (char *)\"too many length or distance symbols\";\n                state->mode = BAD;\n                break;\n            }\n#endif\n            Tracev((stderr, \"inflate:       table sizes ok\\n\"));\n\n            /* get code length code lengths (not a typo) */\n            state->have = 0;\n            while (state->have < state->ncode) {\n                NEEDBITS(3);\n                state->lens[order[state->have++]] = (unsigned short)BITS(3);\n                DROPBITS(3);\n            }\n            while (state->have < 19)\n                state->lens[order[state->have++]] = 0;\n            state->next = state->codes;\n            state->lencode = (code const FAR *)(state->next);\n            state->lenbits = 7;\n            ret = inflate_table(CODES, state->lens, 19, &(state->next),\n                                &(state->lenbits), state->work);\n            if (ret) {\n                strm->msg = (char *)\"invalid code lengths set\";\n                state->mode = BAD;\n                break;\n            }\n            Tracev((stderr, \"inflate:       code lengths ok\\n\"));\n\n            /* get length and distance code code lengths */\n            state->have = 0;\n            while (state->have < state->nlen + state->ndist) {\n                for (;;) {\n                    here = state->lencode[BITS(state->lenbits)];\n                    if ((unsigned)(here.bits) <= bits) break;\n                    PULLBYTE();\n                }\n                if (here.val < 16) {\n                    DROPBITS(here.bits);\n                    state->lens[state->have++] = here.val;\n                }\n                else {\n                    if (here.val == 16) {\n                        NEEDBITS(here.bits + 2);\n                        DROPBITS(here.bits);\n                        if (state->have == 0) {\n                            strm->msg = (char *)\"invalid bit length repeat\";\n                            state->mode = BAD;\n                            break;\n                        }\n                        len = (unsigned)(state->lens[state->have - 1]);\n                        copy = 3 + BITS(2);\n                        DROPBITS(2);\n                    }\n                    else if (here.val == 17) {\n                        NEEDBITS(here.bits + 3);\n                        DROPBITS(here.bits);\n                        len = 0;\n                        copy = 3 + BITS(3);\n                        DROPBITS(3);\n                    }\n                    else {\n                        NEEDBITS(here.bits + 7);\n                        DROPBITS(here.bits);\n                        len = 0;\n                        copy = 11 + BITS(7);\n                        DROPBITS(7);\n                    }\n                    if (state->have + copy > state->nlen + state->ndist) {\n                        strm->msg = (char *)\"invalid bit length repeat\";\n                        state->mode = BAD;\n                        break;\n                    }\n                    while (copy--)\n                        state->lens[state->have++] = (unsigned short)len;\n                }\n            }\n\n            /* handle error breaks in while */\n            if (state->mode == BAD) break;\n\n            /* check for end-of-block code (better have one) */\n            if (state->lens[256] == 0) {\n                strm->msg = (char *)\"invalid code -- missing end-of-block\";\n                state->mode = BAD;\n                break;\n            }\n\n            /* build code tables -- note: do not change the lenbits or distbits\n               values here (9 and 6) without reading the comments in inftrees.h\n               concerning the ENOUGH constants, which depend on those values */\n            state->next = state->codes;\n            state->lencode = (code const FAR *)(state->next);\n            state->lenbits = 9;\n            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),\n                                &(state->lenbits), state->work);\n            if (ret) {\n                strm->msg = (char *)\"invalid literal/lengths set\";\n                state->mode = BAD;\n                break;\n            }\n            state->distcode = (code const FAR *)(state->next);\n            state->distbits = 6;\n            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,\n                            &(state->next), &(state->distbits), state->work);\n            if (ret) {\n                strm->msg = (char *)\"invalid distances set\";\n                state->mode = BAD;\n                break;\n            }\n            Tracev((stderr, \"inflate:       codes ok\\n\"));\n            state->mode = LEN;\n                /* fallthrough */\n\n        case LEN:\n            /* use inflate_fast() if we have enough input and output */\n            if (have >= 6 && left >= 258) {\n                RESTORE();\n                if (state->whave < state->wsize)\n                    state->whave = state->wsize - left;\n                inflate_fast(strm, state->wsize);\n                LOAD();\n                break;\n            }\n\n            /* get a literal, length, or end-of-block code */\n            for (;;) {\n                here = state->lencode[BITS(state->lenbits)];\n                if ((unsigned)(here.bits) <= bits) break;\n                PULLBYTE();\n            }\n            if (here.op && (here.op & 0xf0) == 0) {\n                last = here;\n                for (;;) {\n                    here = state->lencode[last.val +\n                            (BITS(last.bits + last.op) >> last.bits)];\n                    if ((unsigned)(last.bits + here.bits) <= bits) break;\n                    PULLBYTE();\n                }\n                DROPBITS(last.bits);\n            }\n            DROPBITS(here.bits);\n            state->length = (unsigned)here.val;\n\n            /* process literal */\n            if (here.op == 0) {\n                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n                        \"inflate:         literal '%c'\\n\" :\n                        \"inflate:         literal 0x%02x\\n\", here.val));\n                ROOM();\n                *put++ = (unsigned char)(state->length);\n                left--;\n                state->mode = LEN;\n                break;\n            }\n\n            /* process end of block */\n            if (here.op & 32) {\n                Tracevv((stderr, \"inflate:         end of block\\n\"));\n                state->mode = TYPE;\n                break;\n            }\n\n            /* invalid code */\n            if (here.op & 64) {\n                strm->msg = (char *)\"invalid literal/length code\";\n                state->mode = BAD;\n                break;\n            }\n\n            /* length code -- get extra bits, if any */\n            state->extra = (unsigned)(here.op) & 15;\n            if (state->extra != 0) {\n                NEEDBITS(state->extra);\n                state->length += BITS(state->extra);\n                DROPBITS(state->extra);\n            }\n            Tracevv((stderr, \"inflate:         length %u\\n\", state->length));\n\n            /* get distance code */\n            for (;;) {\n                here = state->distcode[BITS(state->distbits)];\n                if ((unsigned)(here.bits) <= bits) break;\n                PULLBYTE();\n            }\n            if ((here.op & 0xf0) == 0) {\n                last = here;\n                for (;;) {\n                    here = state->distcode[last.val +\n                            (BITS(last.bits + last.op) >> last.bits)];\n                    if ((unsigned)(last.bits + here.bits) <= bits) break;\n                    PULLBYTE();\n                }\n                DROPBITS(last.bits);\n            }\n            DROPBITS(here.bits);\n            if (here.op & 64) {\n                strm->msg = (char *)\"invalid distance code\";\n                state->mode = BAD;\n                break;\n            }\n            state->offset = (unsigned)here.val;\n\n            /* get distance extra bits, if any */\n            state->extra = (unsigned)(here.op) & 15;\n            if (state->extra != 0) {\n                NEEDBITS(state->extra);\n                state->offset += BITS(state->extra);\n                DROPBITS(state->extra);\n            }\n            if (state->offset > state->wsize - (state->whave < state->wsize ?\n                                                left : 0)) {\n                strm->msg = (char *)\"invalid distance too far back\";\n                state->mode = BAD;\n                break;\n            }\n            Tracevv((stderr, \"inflate:         distance %u\\n\", state->offset));\n\n            /* copy match from window to output */\n            do {\n                ROOM();\n                copy = state->wsize - state->offset;\n                if (copy < left) {\n                    from = put + copy;\n                    copy = left - copy;\n                }\n                else {\n                    from = put - state->offset;\n                    copy = left;\n                }\n                if (copy > state->length) copy = state->length;\n                state->length -= copy;\n                left -= copy;\n                do {\n                    *put++ = *from++;\n                } while (--copy);\n            } while (state->length != 0);\n            break;\n\n        case DONE:\n            /* inflate stream terminated properly */\n            ret = Z_STREAM_END;\n            goto inf_leave;\n\n        case BAD:\n            ret = Z_DATA_ERROR;\n            goto inf_leave;\n\n        default:\n            /* can't happen, but makes compilers happy */\n            ret = Z_STREAM_ERROR;\n            goto inf_leave;\n        }\n\n    /* Write leftover output and return unused input */\n  inf_leave:\n    if (left < state->wsize) {\n        if (out(out_desc, state->window, state->wsize - left) &&\n            ret == Z_STREAM_END)\n            ret = Z_BUF_ERROR;\n    }\n    strm->next_in = next;\n    strm->avail_in = have;\n    return ret;\n}\n\nint ZEXPORT inflateBackEnd(strm)\nz_streamp strm;\n{\n    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)\n        return Z_STREAM_ERROR;\n    ZFREE(strm, strm->state);\n    strm->state = Z_NULL;\n    Tracev((stderr, \"inflate: end\\n\"));\n    return Z_OK;\n}\n"
  },
  {
    "path": "third_party/libz/inffast.c",
    "content": "// clang-format off\n/* inffast.c -- fast decoding\n * Copyright (C) 1995-2017 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n#include \"third_party/libz/zutil.h\"\n#include \"third_party/libz/inftrees.h\"\n#include \"third_party/libz/inflate.h\"\n#include \"third_party/libz/inffast.h\"\n\n#ifdef ASMINF\n#  pragma message(\"Assembler code may have bugs -- use at your own risk\")\n#else\n\n/*\n   Decode literal, length, and distance codes and write out the resulting\n   literal and match bytes until either not enough input or output is\n   available, an end-of-block is encountered, or a data error is encountered.\n   When large enough input and output buffers are supplied to inflate(), for\n   example, a 16K input buffer and a 64K output buffer, more than 95% of the\n   inflate execution time is spent in this routine.\n\n   Entry assumptions:\n\n        state->mode == LEN\n        strm->avail_in >= 6\n        strm->avail_out >= 258\n        start >= strm->avail_out\n        state->bits < 8\n\n   On return, state->mode is one of:\n\n        LEN -- ran out of enough output space or enough available input\n        TYPE -- reached end of block code, inflate() to interpret next block\n        BAD -- error in block data\n\n   Notes:\n\n    - The maximum input bits used by a length/distance pair is 15 bits for the\n      length code, 5 bits for the length extra, 15 bits for the distance code,\n      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.\n      Therefore if strm->avail_in >= 6, then there is enough input to avoid\n      checking for available input while decoding.\n\n    - The maximum bytes that a single length/distance pair can output is 258\n      bytes, which is the maximum length that can be coded.  inflate_fast()\n      requires strm->avail_out >= 258 for each loop to avoid checking for\n      output space.\n */\nvoid ZLIB_INTERNAL inflate_fast(strm, start)\nz_streamp strm;\nunsigned start;         /* inflate()'s starting value for strm->avail_out */\n{\n    struct inflate_state FAR *state;\n    z_const unsigned char FAR *in;      /* local strm->next_in */\n    z_const unsigned char FAR *last;    /* have enough input while in < last */\n    unsigned char FAR *out;     /* local strm->next_out */\n    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */\n    unsigned char FAR *end;     /* while out < end, enough space available */\n#ifdef INFLATE_STRICT\n    unsigned dmax;              /* maximum distance from zlib header */\n#endif\n    unsigned wsize;             /* window size or zero if not using window */\n    unsigned whave;             /* valid bytes in the window */\n    unsigned wnext;             /* window write index */\n    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */\n    unsigned long hold;         /* local strm->hold */\n    unsigned bits;              /* local strm->bits */\n    code const FAR *lcode;      /* local strm->lencode */\n    code const FAR *dcode;      /* local strm->distcode */\n    unsigned lmask;             /* mask for first level of length codes */\n    unsigned dmask;             /* mask for first level of distance codes */\n    code const *here;           /* retrieved table entry */\n    unsigned op;                /* code bits, operation, extra bits, or */\n                                /*  window position, window bytes to copy */\n    unsigned len;               /* match length, unused bytes */\n    unsigned dist;              /* match distance */\n    unsigned char FAR *from;    /* where to copy match from */\n\n    /* copy state to local variables */\n    state = (struct inflate_state FAR *)strm->state;\n    in = strm->next_in;\n    last = in + (strm->avail_in - 5);\n    out = strm->next_out;\n    beg = out - (start - strm->avail_out);\n    end = out + (strm->avail_out - 257);\n#ifdef INFLATE_STRICT\n    dmax = state->dmax;\n#endif\n    wsize = state->wsize;\n    whave = state->whave;\n    wnext = state->wnext;\n    window = state->window;\n    hold = state->hold;\n    bits = state->bits;\n    lcode = state->lencode;\n    dcode = state->distcode;\n    lmask = (1U << state->lenbits) - 1;\n    dmask = (1U << state->distbits) - 1;\n\n    /* decode literals and length/distances until end-of-block or not enough\n       input data or output space */\n    do {\n        if (bits < 15) {\n            hold += (unsigned long)(*in++) << bits;\n            bits += 8;\n            hold += (unsigned long)(*in++) << bits;\n            bits += 8;\n        }\n        here = lcode + (hold & lmask);\n      dolen:\n        op = (unsigned)(here->bits);\n        hold >>= op;\n        bits -= op;\n        op = (unsigned)(here->op);\n        if (op == 0) {                          /* literal */\n            Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?\n                    \"inflate:         literal '%c'\\n\" :\n                    \"inflate:         literal 0x%02x\\n\", here->val));\n            *out++ = (unsigned char)(here->val);\n        }\n        else if (op & 16) {                     /* length base */\n            len = (unsigned)(here->val);\n            op &= 15;                           /* number of extra bits */\n            if (op) {\n                if (bits < op) {\n                    hold += (unsigned long)(*in++) << bits;\n                    bits += 8;\n                }\n                len += (unsigned)hold & ((1U << op) - 1);\n                hold >>= op;\n                bits -= op;\n            }\n            Tracevv((stderr, \"inflate:         length %u\\n\", len));\n            if (bits < 15) {\n                hold += (unsigned long)(*in++) << bits;\n                bits += 8;\n                hold += (unsigned long)(*in++) << bits;\n                bits += 8;\n            }\n            here = dcode + (hold & dmask);\n          dodist:\n            op = (unsigned)(here->bits);\n            hold >>= op;\n            bits -= op;\n            op = (unsigned)(here->op);\n            if (op & 16) {                      /* distance base */\n                dist = (unsigned)(here->val);\n                op &= 15;                       /* number of extra bits */\n                if (bits < op) {\n                    hold += (unsigned long)(*in++) << bits;\n                    bits += 8;\n                    if (bits < op) {\n                        hold += (unsigned long)(*in++) << bits;\n                        bits += 8;\n                    }\n                }\n                dist += (unsigned)hold & ((1U << op) - 1);\n#ifdef INFLATE_STRICT\n                if (dist > dmax) {\n                    strm->msg = (char *)\"invalid distance too far back\";\n                    state->mode = BAD;\n                    break;\n                }\n#endif\n                hold >>= op;\n                bits -= op;\n                Tracevv((stderr, \"inflate:         distance %u\\n\", dist));\n                op = (unsigned)(out - beg);     /* max distance in output */\n                if (dist > op) {                /* see if copy from window */\n                    op = dist - op;             /* distance back in window */\n                    if (op > whave) {\n                        if (state->sane) {\n                            strm->msg =\n                                (char *)\"invalid distance too far back\";\n                            state->mode = BAD;\n                            break;\n                        }\n#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n                        if (len <= op - whave) {\n                            do {\n                                *out++ = 0;\n                            } while (--len);\n                            continue;\n                        }\n                        len -= op - whave;\n                        do {\n                            *out++ = 0;\n                        } while (--op > whave);\n                        if (op == 0) {\n                            from = out - dist;\n                            do {\n                                *out++ = *from++;\n                            } while (--len);\n                            continue;\n                        }\n#endif\n                    }\n                    from = window;\n                    if (wnext == 0) {           /* very common case */\n                        from += wsize - op;\n                        if (op < len) {         /* some from window */\n                            len -= op;\n                            do {\n                                *out++ = *from++;\n                            } while (--op);\n                            from = out - dist;  /* rest from output */\n                        }\n                    }\n                    else if (wnext < op) {      /* wrap around window */\n                        from += wsize + wnext - op;\n                        op -= wnext;\n                        if (op < len) {         /* some from end of window */\n                            len -= op;\n                            do {\n                                *out++ = *from++;\n                            } while (--op);\n                            from = window;\n                            if (wnext < len) {  /* some from start of window */\n                                op = wnext;\n                                len -= op;\n                                do {\n                                    *out++ = *from++;\n                                } while (--op);\n                                from = out - dist;      /* rest from output */\n                            }\n                        }\n                    }\n                    else {                      /* contiguous in window */\n                        from += wnext - op;\n                        if (op < len) {         /* some from window */\n                            len -= op;\n                            do {\n                                *out++ = *from++;\n                            } while (--op);\n                            from = out - dist;  /* rest from output */\n                        }\n                    }\n                    while (len > 2) {\n                        *out++ = *from++;\n                        *out++ = *from++;\n                        *out++ = *from++;\n                        len -= 3;\n                    }\n                    if (len) {\n                        *out++ = *from++;\n                        if (len > 1)\n                            *out++ = *from++;\n                    }\n                }\n                else {\n                    from = out - dist;          /* copy direct from output */\n                    do {                        /* minimum length is three */\n                        *out++ = *from++;\n                        *out++ = *from++;\n                        *out++ = *from++;\n                        len -= 3;\n                    } while (len > 2);\n                    if (len) {\n                        *out++ = *from++;\n                        if (len > 1)\n                            *out++ = *from++;\n                    }\n                }\n            }\n            else if ((op & 64) == 0) {          /* 2nd level distance code */\n                here = dcode + here->val + (hold & ((1U << op) - 1));\n                goto dodist;\n            }\n            else {\n                strm->msg = (char *)\"invalid distance code\";\n                state->mode = BAD;\n                break;\n            }\n        }\n        else if ((op & 64) == 0) {              /* 2nd level length code */\n            here = lcode + here->val + (hold & ((1U << op) - 1));\n            goto dolen;\n        }\n        else if (op & 32) {                     /* end-of-block */\n            Tracevv((stderr, \"inflate:         end of block\\n\"));\n            state->mode = TYPE;\n            break;\n        }\n        else {\n            strm->msg = (char *)\"invalid literal/length code\";\n            state->mode = BAD;\n            break;\n        }\n    } while (in < last && out < end);\n\n    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */\n    len = bits >> 3;\n    in -= len;\n    bits -= len << 3;\n    hold &= (1U << bits) - 1;\n\n    /* update state and return */\n    strm->next_in = in;\n    strm->next_out = out;\n    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));\n    strm->avail_out = (unsigned)(out < end ?\n                                 257 + (end - out) : 257 - (out - end));\n    state->hold = hold;\n    state->bits = bits;\n    return;\n}\n\n/*\n   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):\n   - Using bit fields for code structure\n   - Different op definition to avoid & for extra bits (do & for table bits)\n   - Three separate decoding do-loops for direct, window, and wnext == 0\n   - Special case for distance > 1 copies to do overlapped load and store copy\n   - Explicit branch predictions (based on measured branch probabilities)\n   - Deferring match copy and interspersed it with decoding subsequent codes\n   - Swapping literal/length else\n   - Swapping window/direct else\n   - Larger unrolled copy loops (three is about right)\n   - Moving len -= 3 statement into middle of loop\n */\n\n#endif /* !ASMINF */\n"
  },
  {
    "path": "third_party/libz/inffast.h",
    "content": "// clang-format off\n/* inffast.h -- header to use inffast.c\n * Copyright (C) 1995-2003, 2010 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the compression library and is\n   subject to change. Applications should only use zlib.h.\n */\n\nvoid ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));\n"
  },
  {
    "path": "third_party/libz/inffixed.h",
    "content": "// clang-format off\n    /* inffixed.h -- table for decoding fixed codes\n     * Generated automatically by makefixed().\n     */\n\n    /* WARNING: this file should *not* be used by applications.\n       It is part of the implementation of this library and is\n       subject to change. Applications should only use zlib.h.\n     */\n\n    static const code lenfix[512] = {\n        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},\n        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},\n        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},\n        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},\n        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},\n        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},\n        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},\n        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},\n        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},\n        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},\n        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},\n        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},\n        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},\n        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},\n        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},\n        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},\n        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},\n        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},\n        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},\n        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},\n        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},\n        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},\n        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},\n        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},\n        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},\n        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},\n        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},\n        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},\n        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},\n        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},\n        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},\n        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},\n        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},\n        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},\n        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},\n        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},\n        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},\n        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},\n        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},\n        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},\n        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},\n        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},\n        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},\n        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},\n        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},\n        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},\n        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},\n        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},\n        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},\n        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},\n        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},\n        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},\n        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},\n        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},\n        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},\n        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},\n        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},\n        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},\n        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},\n        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},\n        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},\n        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},\n        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},\n        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},\n        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},\n        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},\n        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},\n        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},\n        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},\n        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},\n        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},\n        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},\n        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},\n        {0,9,255}\n    };\n\n    static const code distfix[32] = {\n        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},\n        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},\n        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},\n        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},\n        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},\n        {22,5,193},{64,5,0}\n    };\n"
  },
  {
    "path": "third_party/libz/inflate.c",
    "content": "// clang-format off\n/* inflate.c -- zlib decompression\n * Copyright (C) 1995-2022 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/*\n * Change history:\n *\n * 1.2.beta0    24 Nov 2002\n * - First version -- complete rewrite of inflate to simplify code, avoid\n *   creation of window when not needed, minimize use of window when it is\n *   needed, make inffast.c even faster, implement gzip decoding, and to\n *   improve code readability and style over the previous zlib inflate code\n *\n * 1.2.beta1    25 Nov 2002\n * - Use pointers for available input and output checking in inffast.c\n * - Remove input and output counters in inffast.c\n * - Change inffast.c entry and loop from avail_in >= 7 to >= 6\n * - Remove unnecessary second byte pull from length extra in inffast.c\n * - Unroll direct copy to three copies per loop in inffast.c\n *\n * 1.2.beta2    4 Dec 2002\n * - Change external routine names to reduce potential conflicts\n * - Correct filename to inffixed.h for fixed tables in inflate.c\n * - Make hbuf[] unsigned char to match parameter type in inflate.c\n * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)\n *   to avoid negation problem on Alphas (64 bit) in inflate.c\n *\n * 1.2.beta3    22 Dec 2002\n * - Add comments on state->bits assertion in inffast.c\n * - Add comments on op field in inftrees.h\n * - Fix bug in reuse of allocated window after inflateReset()\n * - Remove bit fields--back to byte structure for speed\n * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths\n * - Change post-increments to pre-increments in inflate_fast(), PPC biased?\n * - Add compile time option, POSTINC, to use post-increments instead (Intel?)\n * - Make MATCH copy in inflate() much faster for when inflate_fast() not used\n * - Use local copies of stream next and avail values, as well as local bit\n *   buffer and bit count in inflate()--for speed when inflate_fast() not used\n *\n * 1.2.beta4    1 Jan 2003\n * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings\n * - Move a comment on output buffer sizes from inffast.c to inflate.c\n * - Add comments in inffast.c to introduce the inflate_fast() routine\n * - Rearrange window copies in inflate_fast() for speed and simplification\n * - Unroll last copy for window match in inflate_fast()\n * - Use local copies of window variables in inflate_fast() for speed\n * - Pull out common wnext == 0 case for speed in inflate_fast()\n * - Make op and len in inflate_fast() unsigned for consistency\n * - Add FAR to lcode and dcode declarations in inflate_fast()\n * - Simplified bad distance check in inflate_fast()\n * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new\n *   source file infback.c to provide a call-back interface to inflate for\n *   programs like gzip and unzip -- uses window as output buffer to avoid\n *   window copying\n *\n * 1.2.beta5    1 Jan 2003\n * - Improved inflateBack() interface to allow the caller to provide initial\n *   input in strm.\n * - Fixed stored blocks bug in inflateBack()\n *\n * 1.2.beta6    4 Jan 2003\n * - Added comments in inffast.c on effectiveness of POSTINC\n * - Typecasting all around to reduce compiler warnings\n * - Changed loops from while (1) or do {} while (1) to for (;;), again to\n *   make compilers happy\n * - Changed type of window in inflateBackInit() to unsigned char *\n *\n * 1.2.beta7    27 Jan 2003\n * - Changed many types to unsigned or unsigned short to avoid warnings\n * - Added inflateCopy() function\n *\n * 1.2.0        9 Mar 2003\n * - Changed inflateBack() interface to provide separate opaque descriptors\n *   for the in() and out() functions\n * - Changed inflateBack() argument and in_func typedef to swap the length\n *   and buffer address return values for the input function\n * - Check next_in and next_out for Z_NULL on entry to inflate()\n *\n * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.\n */\n\n#include \"third_party/libz/zutil.h\"\n#include \"third_party/libz/inftrees.h\"\n#include \"third_party/libz/inflate.h\"\n#include \"third_party/libz/inffast.h\"\n\n#ifdef MAKEFIXED\n#  ifndef BUILDFIXED\n#    define BUILDFIXED\n#  endif\n#endif\n\n/* function prototypes */\nlocal int inflateStateCheck OF((z_streamp strm));\nlocal void fixedtables OF((struct inflate_state FAR *state));\nlocal int updatewindow OF((z_streamp strm, const unsigned char FAR *end,\n                           unsigned copy));\n#ifdef BUILDFIXED\n   void makefixed OF((void));\n#endif\nlocal unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,\n                              unsigned len));\n\nlocal int inflateStateCheck(strm)\nz_streamp strm;\n{\n    struct inflate_state FAR *state;\n    if (strm == Z_NULL ||\n        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)\n        return 1;\n    state = (struct inflate_state FAR *)strm->state;\n    if (state == Z_NULL || state->strm != strm ||\n        state->mode < HEAD || state->mode > SYNC)\n        return 1;\n    return 0;\n}\n\nint ZEXPORT inflateResetKeep(strm)\nz_streamp strm;\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    strm->total_in = strm->total_out = state->total = 0;\n    strm->msg = Z_NULL;\n    if (state->wrap)        /* to support ill-conceived Java test suite */\n        strm->adler = state->wrap & 1;\n    state->mode = HEAD;\n    state->last = 0;\n    state->havedict = 0;\n    state->flags = -1;\n    state->dmax = 32768U;\n    state->head = Z_NULL;\n    state->hold = 0;\n    state->bits = 0;\n    state->lencode = state->distcode = state->next = state->codes;\n    state->sane = 1;\n    state->back = -1;\n    Tracev((stderr, \"inflate: reset\\n\"));\n    return Z_OK;\n}\n\nint ZEXPORT inflateReset(strm)\nz_streamp strm;\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    state->wsize = 0;\n    state->whave = 0;\n    state->wnext = 0;\n    return inflateResetKeep(strm);\n}\n\nint ZEXPORT inflateReset2(strm, windowBits)\nz_streamp strm;\nint windowBits;\n{\n    int wrap;\n    struct inflate_state FAR *state;\n\n    /* get the state */\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n\n    /* extract wrap request from windowBits parameter */\n    if (windowBits < 0) {\n        if (windowBits < -15)\n            return Z_STREAM_ERROR;\n        wrap = 0;\n        windowBits = -windowBits;\n    }\n    else {\n        wrap = (windowBits >> 4) + 5;\n#ifdef GUNZIP\n        if (windowBits < 48)\n            windowBits &= 15;\n#endif\n    }\n\n    /* set number of window bits, free window if different */\n    if (windowBits && (windowBits < 8 || windowBits > 15))\n        return Z_STREAM_ERROR;\n    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {\n        ZFREE(strm, state->window);\n        state->window = Z_NULL;\n    }\n\n    /* update state and reset the rest of it */\n    state->wrap = wrap;\n    state->wbits = (unsigned)windowBits;\n    return inflateReset(strm);\n}\n\nint ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)\nz_streamp strm;\nint windowBits;\nconst char *version;\nint stream_size;\n{\n    int ret;\n    struct inflate_state FAR *state;\n\n    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||\n        stream_size != (int)(sizeof(z_stream)))\n        return Z_VERSION_ERROR;\n    if (strm == Z_NULL) return Z_STREAM_ERROR;\n    strm->msg = Z_NULL;                 /* in case we return an error */\n    if (strm->zalloc == (alloc_func)0) {\n#ifdef Z_SOLO\n        return Z_STREAM_ERROR;\n#else\n        strm->zalloc = zcalloc;\n        strm->opaque = (voidpf)0;\n#endif\n    }\n    if (strm->zfree == (free_func)0)\n#ifdef Z_SOLO\n        return Z_STREAM_ERROR;\n#else\n        strm->zfree = zcfree;\n#endif\n    state = (struct inflate_state FAR *)\n            ZALLOC(strm, 1, sizeof(struct inflate_state));\n    if (state == Z_NULL) return Z_MEM_ERROR;\n    Tracev((stderr, \"inflate: allocated\\n\"));\n    strm->state = (struct internal_state FAR *)state;\n    state->strm = strm;\n    state->window = Z_NULL;\n    state->mode = HEAD;     /* to pass state test in inflateReset2() */\n    ret = inflateReset2(strm, windowBits);\n    if (ret != Z_OK) {\n        ZFREE(strm, state);\n        strm->state = Z_NULL;\n    }\n    return ret;\n}\n\nint ZEXPORT inflateInit_(strm, version, stream_size)\nz_streamp strm;\nconst char *version;\nint stream_size;\n{\n    return inflateInit2_(strm, DEF_WBITS, version, stream_size);\n}\n\nint ZEXPORT inflatePrime(strm, bits, value)\nz_streamp strm;\nint bits;\nint value;\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if (bits < 0) {\n        state->hold = 0;\n        state->bits = 0;\n        return Z_OK;\n    }\n    if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;\n    value &= (1L << bits) - 1;\n    state->hold += (unsigned)value << state->bits;\n    state->bits += (uInt)bits;\n    return Z_OK;\n}\n\n/*\n   Return state with length and distance decoding tables and index sizes set to\n   fixed code decoding.  Normally this returns fixed tables from inffixed.h.\n   If BUILDFIXED is defined, then instead this routine builds the tables the\n   first time it's called, and returns those tables the first time and\n   thereafter.  This reduces the size of the code by about 2K bytes, in\n   exchange for a little execution time.  However, BUILDFIXED should not be\n   used for threaded applications, since the rewriting of the tables and virgin\n   may not be thread-safe.\n */\nlocal void fixedtables(state)\nstruct inflate_state FAR *state;\n{\n#ifdef BUILDFIXED\n    static int virgin = 1;\n    static code *lenfix, *distfix;\n    static code fixed[544];\n\n    /* build fixed huffman tables if first call (may not be thread safe) */\n    if (virgin) {\n        unsigned sym, bits;\n        static code *next;\n\n        /* literal/length table */\n        sym = 0;\n        while (sym < 144) state->lens[sym++] = 8;\n        while (sym < 256) state->lens[sym++] = 9;\n        while (sym < 280) state->lens[sym++] = 7;\n        while (sym < 288) state->lens[sym++] = 8;\n        next = fixed;\n        lenfix = next;\n        bits = 9;\n        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);\n\n        /* distance table */\n        sym = 0;\n        while (sym < 32) state->lens[sym++] = 5;\n        distfix = next;\n        bits = 5;\n        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);\n\n        /* do this just once */\n        virgin = 0;\n    }\n#else /* !BUILDFIXED */\n#   include \"third_party/libz/inffixed.h\"\n#endif /* BUILDFIXED */\n    state->lencode = lenfix;\n    state->lenbits = 9;\n    state->distcode = distfix;\n    state->distbits = 5;\n}\n\n#ifdef MAKEFIXED\n#include <stdio.h>\n\n/*\n   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also\n   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes\n   those tables to stdout, which would be piped to inffixed.h.  A small program\n   can simply call makefixed to do this:\n\n    void makefixed(void);\n\n    int main(void)\n    {\n        makefixed();\n        return 0;\n    }\n\n   Then that can be linked with zlib built with MAKEFIXED defined and run:\n\n    a.out > inffixed.h\n */\nvoid makefixed()\n{\n    unsigned low, size;\n    struct inflate_state state;\n\n    fixedtables(&state);\n    puts(\"    /* inffixed.h -- table for decoding fixed codes\");\n    puts(\"     * Generated automatically by makefixed().\");\n    puts(\"     */\");\n    puts(\"\");\n    puts(\"    /* WARNING: this file should *not* be used by applications.\");\n    puts(\"       It is part of the implementation of this library and is\");\n    puts(\"       subject to change. Applications should only use zlib.h.\");\n    puts(\"     */\");\n    puts(\"\");\n    size = 1U << 9;\n    printf(\"    static const code lenfix[%u] = {\", size);\n    low = 0;\n    for (;;) {\n        if ((low % 7) == 0) printf(\"\\n        \");\n        printf(\"{%u,%u,%d}\", (low & 127) == 99 ? 64 : state.lencode[low].op,\n               state.lencode[low].bits, state.lencode[low].val);\n        if (++low == size) break;\n        putchar(',');\n    }\n    puts(\"\\n    };\");\n    size = 1U << 5;\n    printf(\"\\n    static const code distfix[%u] = {\", size);\n    low = 0;\n    for (;;) {\n        if ((low % 6) == 0) printf(\"\\n        \");\n        printf(\"{%u,%u,%d}\", state.distcode[low].op, state.distcode[low].bits,\n               state.distcode[low].val);\n        if (++low == size) break;\n        putchar(',');\n    }\n    puts(\"\\n    };\");\n}\n#endif /* MAKEFIXED */\n\n/*\n   Update the window with the last wsize (normally 32K) bytes written before\n   returning.  If window does not exist yet, create it.  This is only called\n   when a window is already in use, or when output has been written during this\n   inflate call, but the end of the deflate stream has not been reached yet.\n   It is also called to create a window for dictionary data when a dictionary\n   is loaded.\n\n   Providing output buffers larger than 32K to inflate() should provide a speed\n   advantage, since only the last 32K of output is copied to the sliding window\n   upon return from inflate(), and since all distances after the first 32K of\n   output will fall in the output data, making match copies simpler and faster.\n   The advantage may be dependent on the size of the processor's data caches.\n */\nlocal int updatewindow(strm, end, copy)\nz_streamp strm;\nconst Bytef *end;\nunsigned copy;\n{\n    struct inflate_state FAR *state;\n    unsigned dist;\n\n    state = (struct inflate_state FAR *)strm->state;\n\n    /* if it hasn't been done already, allocate space for the window */\n    if (state->window == Z_NULL) {\n        state->window = (unsigned char FAR *)\n                        ZALLOC(strm, 1U << state->wbits,\n                               sizeof(unsigned char));\n        if (state->window == Z_NULL) return 1;\n    }\n\n    /* if window not in use yet, initialize */\n    if (state->wsize == 0) {\n        state->wsize = 1U << state->wbits;\n        state->wnext = 0;\n        state->whave = 0;\n    }\n\n    /* copy state->wsize or less output bytes into the circular window */\n    if (copy >= state->wsize) {\n        zmemcpy(state->window, end - state->wsize, state->wsize);\n        state->wnext = 0;\n        state->whave = state->wsize;\n    }\n    else {\n        dist = state->wsize - state->wnext;\n        if (dist > copy) dist = copy;\n        zmemcpy(state->window + state->wnext, end - copy, dist);\n        copy -= dist;\n        if (copy) {\n            zmemcpy(state->window, end - copy, copy);\n            state->wnext = copy;\n            state->whave = state->wsize;\n        }\n        else {\n            state->wnext += dist;\n            if (state->wnext == state->wsize) state->wnext = 0;\n            if (state->whave < state->wsize) state->whave += dist;\n        }\n    }\n    return 0;\n}\n\n/* Macros for inflate(): */\n\n/* check function to use adler32() for zlib or crc32() for gzip */\n#ifdef GUNZIP\n#  define UPDATE_CHECK(check, buf, len) \\\n    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))\n#else\n#  define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)\n#endif\n\n/* check macros for header crc */\n#ifdef GUNZIP\n#  define CRC2(check, word) \\\n    do { \\\n        hbuf[0] = (unsigned char)(word); \\\n        hbuf[1] = (unsigned char)((word) >> 8); \\\n        check = crc32(check, hbuf, 2); \\\n    } while (0)\n\n#  define CRC4(check, word) \\\n    do { \\\n        hbuf[0] = (unsigned char)(word); \\\n        hbuf[1] = (unsigned char)((word) >> 8); \\\n        hbuf[2] = (unsigned char)((word) >> 16); \\\n        hbuf[3] = (unsigned char)((word) >> 24); \\\n        check = crc32(check, hbuf, 4); \\\n    } while (0)\n#endif\n\n/* Load registers with state in inflate() for speed */\n#define LOAD() \\\n    do { \\\n        put = strm->next_out; \\\n        left = strm->avail_out; \\\n        next = strm->next_in; \\\n        have = strm->avail_in; \\\n        hold = state->hold; \\\n        bits = state->bits; \\\n    } while (0)\n\n/* Restore state from registers in inflate() */\n#define RESTORE() \\\n    do { \\\n        strm->next_out = put; \\\n        strm->avail_out = left; \\\n        strm->next_in = next; \\\n        strm->avail_in = have; \\\n        state->hold = hold; \\\n        state->bits = bits; \\\n    } while (0)\n\n/* Clear the input bit accumulator */\n#define INITBITS() \\\n    do { \\\n        hold = 0; \\\n        bits = 0; \\\n    } while (0)\n\n/* Get a byte of input into the bit accumulator, or return from inflate()\n   if there is no input available. */\n#define PULLBYTE() \\\n    do { \\\n        if (have == 0) goto inf_leave; \\\n        have--; \\\n        hold += (unsigned long)(*next++) << bits; \\\n        bits += 8; \\\n    } while (0)\n\n/* Assure that there are at least n bits in the bit accumulator.  If there is\n   not enough available input to do that, then return from inflate(). */\n#define NEEDBITS(n) \\\n    do { \\\n        while (bits < (unsigned)(n)) \\\n            PULLBYTE(); \\\n    } while (0)\n\n/* Return the low n bits of the bit accumulator (n < 16) */\n#define BITS(n) \\\n    ((unsigned)hold & ((1U << (n)) - 1))\n\n/* Remove n bits from the bit accumulator */\n#define DROPBITS(n) \\\n    do { \\\n        hold >>= (n); \\\n        bits -= (unsigned)(n); \\\n    } while (0)\n\n/* Remove zero to seven bits as needed to go to a byte boundary */\n#define BYTEBITS() \\\n    do { \\\n        hold >>= bits & 7; \\\n        bits -= bits & 7; \\\n    } while (0)\n\n/*\n   inflate() uses a state machine to process as much input data and generate as\n   much output data as possible before returning.  The state machine is\n   structured roughly as follows:\n\n    for (;;) switch (state) {\n    ...\n    case STATEn:\n        if (not enough input data or output space to make progress)\n            return;\n        ... make progress ...\n        state = STATEm;\n        break;\n    ...\n    }\n\n   so when inflate() is called again, the same case is attempted again, and\n   if the appropriate resources are provided, the machine proceeds to the\n   next state.  The NEEDBITS() macro is usually the way the state evaluates\n   whether it can proceed or should return.  NEEDBITS() does the return if\n   the requested bits are not available.  The typical use of the BITS macros\n   is:\n\n        NEEDBITS(n);\n        ... do something with BITS(n) ...\n        DROPBITS(n);\n\n   where NEEDBITS(n) either returns from inflate() if there isn't enough\n   input left to load n bits into the accumulator, or it continues.  BITS(n)\n   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops\n   the low n bits off the accumulator.  INITBITS() clears the accumulator\n   and sets the number of available bits to zero.  BYTEBITS() discards just\n   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()\n   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.\n\n   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return\n   if there is no input available.  The decoding of variable length codes uses\n   PULLBYTE() directly in order to pull just enough bytes to decode the next\n   code, and no more.\n\n   Some states loop until they get enough input, making sure that enough\n   state information is maintained to continue the loop where it left off\n   if NEEDBITS() returns in the loop.  For example, want, need, and keep\n   would all have to actually be part of the saved state in case NEEDBITS()\n   returns:\n\n    case STATEw:\n        while (want < need) {\n            NEEDBITS(n);\n            keep[want++] = BITS(n);\n            DROPBITS(n);\n        }\n        state = STATEx;\n    case STATEx:\n\n   As shown above, if the next state is also the next case, then the break\n   is omitted.\n\n   A state may also return if there is not enough output space available to\n   complete that state.  Those states are copying stored data, writing a\n   literal byte, and copying a matching string.\n\n   When returning, a \"goto inf_leave\" is used to update the total counters,\n   update the check value, and determine whether any progress has been made\n   during that inflate() call in order to return the proper return code.\n   Progress is defined as a change in either strm->avail_in or strm->avail_out.\n   When there is a window, goto inf_leave will update the window with the last\n   output written.  If a goto inf_leave occurs in the middle of decompression\n   and there is no window currently, goto inf_leave will create one and copy\n   output to the window for the next call of inflate().\n\n   In this implementation, the flush parameter of inflate() only affects the\n   return code (per zlib.h).  inflate() always writes as much as possible to\n   strm->next_out, given the space available and the provided input--the effect\n   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers\n   the allocation of and copying into a sliding window until necessary, which\n   provides the effect documented in zlib.h for Z_FINISH when the entire input\n   stream available.  So the only thing the flush parameter actually does is:\n   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it\n   will return Z_BUF_ERROR if it has not reached the end of the stream.\n */\n\nint ZEXPORT inflate(strm, flush)\nz_streamp strm;\nint flush;\n{\n    struct inflate_state FAR *state;\n    z_const unsigned char FAR *next;    /* next input */\n    unsigned char FAR *put;     /* next output */\n    unsigned have, left;        /* available input and output */\n    unsigned long hold;         /* bit buffer */\n    unsigned bits;              /* bits in bit buffer */\n    unsigned in, out;           /* save starting available input and output */\n    unsigned copy;              /* number of stored or match bytes to copy */\n    unsigned char FAR *from;    /* where to copy match bytes from */\n    code here;                  /* current decoding table entry */\n    code last;                  /* parent table entry */\n    unsigned len;               /* length to copy for repeats, bits to drop */\n    int ret;                    /* return code */\n#ifdef GUNZIP\n    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */\n#endif\n    static const unsigned short order[19] = /* permutation of code lengths */\n        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};\n\n    if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||\n        (strm->next_in == Z_NULL && strm->avail_in != 0))\n        return Z_STREAM_ERROR;\n\n    state = (struct inflate_state FAR *)strm->state;\n    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */\n    LOAD();\n    in = have;\n    out = left;\n    ret = Z_OK;\n    for (;;)\n        switch (state->mode) {\n        case HEAD:\n            if (state->wrap == 0) {\n                state->mode = TYPEDO;\n                break;\n            }\n            NEEDBITS(16);\n#ifdef GUNZIP\n            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */\n                if (state->wbits == 0)\n                    state->wbits = 15;\n                state->check = crc32(0L, Z_NULL, 0);\n                CRC2(state->check, hold);\n                INITBITS();\n                state->mode = FLAGS;\n                break;\n            }\n            if (state->head != Z_NULL)\n                state->head->done = -1;\n            if (!(state->wrap & 1) ||   /* check if zlib header allowed */\n#else\n            if (\n#endif\n                ((BITS(8) << 8) + (hold >> 8)) % 31) {\n                strm->msg = (char *)\"incorrect header check\";\n                state->mode = BAD;\n                break;\n            }\n            if (BITS(4) != Z_DEFLATED) {\n                strm->msg = (char *)\"unknown compression method\";\n                state->mode = BAD;\n                break;\n            }\n            DROPBITS(4);\n            len = BITS(4) + 8;\n            if (state->wbits == 0)\n                state->wbits = len;\n            if (len > 15 || len > state->wbits) {\n                strm->msg = (char *)\"invalid window size\";\n                state->mode = BAD;\n                break;\n            }\n            state->dmax = 1U << len;\n            state->flags = 0;               /* indicate zlib header */\n            Tracev((stderr, \"inflate:   zlib header ok\\n\"));\n            strm->adler = state->check = adler32(0L, Z_NULL, 0);\n            state->mode = hold & 0x200 ? DICTID : TYPE;\n            INITBITS();\n            break;\n#ifdef GUNZIP\n        case FLAGS:\n            NEEDBITS(16);\n            state->flags = (int)(hold);\n            if ((state->flags & 0xff) != Z_DEFLATED) {\n                strm->msg = (char *)\"unknown compression method\";\n                state->mode = BAD;\n                break;\n            }\n            if (state->flags & 0xe000) {\n                strm->msg = (char *)\"unknown header flags set\";\n                state->mode = BAD;\n                break;\n            }\n            if (state->head != Z_NULL)\n                state->head->text = (int)((hold >> 8) & 1);\n            if ((state->flags & 0x0200) && (state->wrap & 4))\n                CRC2(state->check, hold);\n            INITBITS();\n            state->mode = TIME;\n                /* fallthrough */\n        case TIME:\n            NEEDBITS(32);\n            if (state->head != Z_NULL)\n                state->head->time = hold;\n            if ((state->flags & 0x0200) && (state->wrap & 4))\n                CRC4(state->check, hold);\n            INITBITS();\n            state->mode = OS;\n                /* fallthrough */\n        case OS:\n            NEEDBITS(16);\n            if (state->head != Z_NULL) {\n                state->head->xflags = (int)(hold & 0xff);\n                state->head->os = (int)(hold >> 8);\n            }\n            if ((state->flags & 0x0200) && (state->wrap & 4))\n                CRC2(state->check, hold);\n            INITBITS();\n            state->mode = EXLEN;\n                /* fallthrough */\n        case EXLEN:\n            if (state->flags & 0x0400) {\n                NEEDBITS(16);\n                state->length = (unsigned)(hold);\n                if (state->head != Z_NULL)\n                    state->head->extra_len = (unsigned)hold;\n                if ((state->flags & 0x0200) && (state->wrap & 4))\n                    CRC2(state->check, hold);\n                INITBITS();\n            }\n            else if (state->head != Z_NULL)\n                state->head->extra = Z_NULL;\n            state->mode = EXTRA;\n                /* fallthrough */\n        case EXTRA:\n            if (state->flags & 0x0400) {\n                copy = state->length;\n                if (copy > have) copy = have;\n                if (copy) {\n                    if (state->head != Z_NULL &&\n                        state->head->extra != Z_NULL &&\n                        (len = state->head->extra_len - state->length) <\n                            state->head->extra_max) {\n                        zmemcpy(state->head->extra + len, next,\n                                len + copy > state->head->extra_max ?\n                                state->head->extra_max - len : copy);\n                    }\n                    if ((state->flags & 0x0200) && (state->wrap & 4))\n                        state->check = crc32(state->check, next, copy);\n                    have -= copy;\n                    next += copy;\n                    state->length -= copy;\n                }\n                if (state->length) goto inf_leave;\n            }\n            state->length = 0;\n            state->mode = NAME;\n                /* fallthrough */\n        case NAME:\n            if (state->flags & 0x0800) {\n                if (have == 0) goto inf_leave;\n                copy = 0;\n                do {\n                    len = (unsigned)(next[copy++]);\n                    if (state->head != Z_NULL &&\n                            state->head->name != Z_NULL &&\n                            state->length < state->head->name_max)\n                        state->head->name[state->length++] = (Bytef)len;\n                } while (len && copy < have);\n                if ((state->flags & 0x0200) && (state->wrap & 4))\n                    state->check = crc32(state->check, next, copy);\n                have -= copy;\n                next += copy;\n                if (len) goto inf_leave;\n            }\n            else if (state->head != Z_NULL)\n                state->head->name = Z_NULL;\n            state->length = 0;\n            state->mode = COMMENT;\n                /* fallthrough */\n        case COMMENT:\n            if (state->flags & 0x1000) {\n                if (have == 0) goto inf_leave;\n                copy = 0;\n                do {\n                    len = (unsigned)(next[copy++]);\n                    if (state->head != Z_NULL &&\n                            state->head->comment != Z_NULL &&\n                            state->length < state->head->comm_max)\n                        state->head->comment[state->length++] = (Bytef)len;\n                } while (len && copy < have);\n                if ((state->flags & 0x0200) && (state->wrap & 4))\n                    state->check = crc32(state->check, next, copy);\n                have -= copy;\n                next += copy;\n                if (len) goto inf_leave;\n            }\n            else if (state->head != Z_NULL)\n                state->head->comment = Z_NULL;\n            state->mode = HCRC;\n                /* fallthrough */\n        case HCRC:\n            if (state->flags & 0x0200) {\n                NEEDBITS(16);\n                if ((state->wrap & 4) && hold != (state->check & 0xffff)) {\n                    strm->msg = (char *)\"header crc mismatch\";\n                    state->mode = BAD;\n                    break;\n                }\n                INITBITS();\n            }\n            if (state->head != Z_NULL) {\n                state->head->hcrc = (int)((state->flags >> 9) & 1);\n                state->head->done = 1;\n            }\n            strm->adler = state->check = crc32(0L, Z_NULL, 0);\n            state->mode = TYPE;\n            break;\n#endif\n        case DICTID:\n            NEEDBITS(32);\n            strm->adler = state->check = ZSWAP32(hold);\n            INITBITS();\n            state->mode = DICT;\n                /* fallthrough */\n        case DICT:\n            if (state->havedict == 0) {\n                RESTORE();\n                return Z_NEED_DICT;\n            }\n            strm->adler = state->check = adler32(0L, Z_NULL, 0);\n            state->mode = TYPE;\n                /* fallthrough */\n        case TYPE:\n            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;\n                /* fallthrough */\n        case TYPEDO:\n            if (state->last) {\n                BYTEBITS();\n                state->mode = CHECK;\n                break;\n            }\n            NEEDBITS(3);\n            state->last = BITS(1);\n            DROPBITS(1);\n            switch (BITS(2)) {\n            case 0:                             /* stored block */\n                Tracev((stderr, \"inflate:     stored block%s\\n\",\n                        state->last ? \" (last)\" : \"\"));\n                state->mode = STORED;\n                break;\n            case 1:                             /* fixed block */\n                fixedtables(state);\n                Tracev((stderr, \"inflate:     fixed codes block%s\\n\",\n                        state->last ? \" (last)\" : \"\"));\n                state->mode = LEN_;             /* decode codes */\n                if (flush == Z_TREES) {\n                    DROPBITS(2);\n                    goto inf_leave;\n                }\n                break;\n            case 2:                             /* dynamic block */\n                Tracev((stderr, \"inflate:     dynamic codes block%s\\n\",\n                        state->last ? \" (last)\" : \"\"));\n                state->mode = TABLE;\n                break;\n            case 3:\n                strm->msg = (char *)\"invalid block type\";\n                state->mode = BAD;\n            }\n            DROPBITS(2);\n            break;\n        case STORED:\n            BYTEBITS();                         /* go to byte boundary */\n            NEEDBITS(32);\n            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {\n                strm->msg = (char *)\"invalid stored block lengths\";\n                state->mode = BAD;\n                break;\n            }\n            state->length = (unsigned)hold & 0xffff;\n            Tracev((stderr, \"inflate:       stored length %u\\n\",\n                    state->length));\n            INITBITS();\n            state->mode = COPY_;\n            if (flush == Z_TREES) goto inf_leave;\n                /* fallthrough */\n        case COPY_:\n            state->mode = COPY;\n                /* fallthrough */\n        case COPY:\n            copy = state->length;\n            if (copy) {\n                if (copy > have) copy = have;\n                if (copy > left) copy = left;\n                if (copy == 0) goto inf_leave;\n                zmemcpy(put, next, copy);\n                have -= copy;\n                next += copy;\n                left -= copy;\n                put += copy;\n                state->length -= copy;\n                break;\n            }\n            Tracev((stderr, \"inflate:       stored end\\n\"));\n            state->mode = TYPE;\n            break;\n        case TABLE:\n            NEEDBITS(14);\n            state->nlen = BITS(5) + 257;\n            DROPBITS(5);\n            state->ndist = BITS(5) + 1;\n            DROPBITS(5);\n            state->ncode = BITS(4) + 4;\n            DROPBITS(4);\n#ifndef PKZIP_BUG_WORKAROUND\n            if (state->nlen > 286 || state->ndist > 30) {\n                strm->msg = (char *)\"too many length or distance symbols\";\n                state->mode = BAD;\n                break;\n            }\n#endif\n            Tracev((stderr, \"inflate:       table sizes ok\\n\"));\n            state->have = 0;\n            state->mode = LENLENS;\n                /* fallthrough */\n        case LENLENS:\n            while (state->have < state->ncode) {\n                NEEDBITS(3);\n                state->lens[order[state->have++]] = (unsigned short)BITS(3);\n                DROPBITS(3);\n            }\n            while (state->have < 19)\n                state->lens[order[state->have++]] = 0;\n            state->next = state->codes;\n            state->lencode = (const code FAR *)(state->next);\n            state->lenbits = 7;\n            ret = inflate_table(CODES, state->lens, 19, &(state->next),\n                                &(state->lenbits), state->work);\n            if (ret) {\n                strm->msg = (char *)\"invalid code lengths set\";\n                state->mode = BAD;\n                break;\n            }\n            Tracev((stderr, \"inflate:       code lengths ok\\n\"));\n            state->have = 0;\n            state->mode = CODELENS;\n                /* fallthrough */\n        case CODELENS:\n            while (state->have < state->nlen + state->ndist) {\n                for (;;) {\n                    here = state->lencode[BITS(state->lenbits)];\n                    if ((unsigned)(here.bits) <= bits) break;\n                    PULLBYTE();\n                }\n                if (here.val < 16) {\n                    DROPBITS(here.bits);\n                    state->lens[state->have++] = here.val;\n                }\n                else {\n                    if (here.val == 16) {\n                        NEEDBITS(here.bits + 2);\n                        DROPBITS(here.bits);\n                        if (state->have == 0) {\n                            strm->msg = (char *)\"invalid bit length repeat\";\n                            state->mode = BAD;\n                            break;\n                        }\n                        len = state->lens[state->have - 1];\n                        copy = 3 + BITS(2);\n                        DROPBITS(2);\n                    }\n                    else if (here.val == 17) {\n                        NEEDBITS(here.bits + 3);\n                        DROPBITS(here.bits);\n                        len = 0;\n                        copy = 3 + BITS(3);\n                        DROPBITS(3);\n                    }\n                    else {\n                        NEEDBITS(here.bits + 7);\n                        DROPBITS(here.bits);\n                        len = 0;\n                        copy = 11 + BITS(7);\n                        DROPBITS(7);\n                    }\n                    if (state->have + copy > state->nlen + state->ndist) {\n                        strm->msg = (char *)\"invalid bit length repeat\";\n                        state->mode = BAD;\n                        break;\n                    }\n                    while (copy--)\n                        state->lens[state->have++] = (unsigned short)len;\n                }\n            }\n\n            /* handle error breaks in while */\n            if (state->mode == BAD) break;\n\n            /* check for end-of-block code (better have one) */\n            if (state->lens[256] == 0) {\n                strm->msg = (char *)\"invalid code -- missing end-of-block\";\n                state->mode = BAD;\n                break;\n            }\n\n            /* build code tables -- note: do not change the lenbits or distbits\n               values here (9 and 6) without reading the comments in inftrees.h\n               concerning the ENOUGH constants, which depend on those values */\n            state->next = state->codes;\n            state->lencode = (const code FAR *)(state->next);\n            state->lenbits = 9;\n            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),\n                                &(state->lenbits), state->work);\n            if (ret) {\n                strm->msg = (char *)\"invalid literal/lengths set\";\n                state->mode = BAD;\n                break;\n            }\n            state->distcode = (const code FAR *)(state->next);\n            state->distbits = 6;\n            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,\n                            &(state->next), &(state->distbits), state->work);\n            if (ret) {\n                strm->msg = (char *)\"invalid distances set\";\n                state->mode = BAD;\n                break;\n            }\n            Tracev((stderr, \"inflate:       codes ok\\n\"));\n            state->mode = LEN_;\n            if (flush == Z_TREES) goto inf_leave;\n                /* fallthrough */\n        case LEN_:\n            state->mode = LEN;\n                /* fallthrough */\n        case LEN:\n            if (have >= 6 && left >= 258) {\n                RESTORE();\n                inflate_fast(strm, out);\n                LOAD();\n                if (state->mode == TYPE)\n                    state->back = -1;\n                break;\n            }\n            state->back = 0;\n            for (;;) {\n                here = state->lencode[BITS(state->lenbits)];\n                if ((unsigned)(here.bits) <= bits) break;\n                PULLBYTE();\n            }\n            if (here.op && (here.op & 0xf0) == 0) {\n                last = here;\n                for (;;) {\n                    here = state->lencode[last.val +\n                            (BITS(last.bits + last.op) >> last.bits)];\n                    if ((unsigned)(last.bits + here.bits) <= bits) break;\n                    PULLBYTE();\n                }\n                DROPBITS(last.bits);\n                state->back += last.bits;\n            }\n            DROPBITS(here.bits);\n            state->back += here.bits;\n            state->length = (unsigned)here.val;\n            if ((int)(here.op) == 0) {\n                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n                        \"inflate:         literal '%c'\\n\" :\n                        \"inflate:         literal 0x%02x\\n\", here.val));\n                state->mode = LIT;\n                break;\n            }\n            if (here.op & 32) {\n                Tracevv((stderr, \"inflate:         end of block\\n\"));\n                state->back = -1;\n                state->mode = TYPE;\n                break;\n            }\n            if (here.op & 64) {\n                strm->msg = (char *)\"invalid literal/length code\";\n                state->mode = BAD;\n                break;\n            }\n            state->extra = (unsigned)(here.op) & 15;\n            state->mode = LENEXT;\n                /* fallthrough */\n        case LENEXT:\n            if (state->extra) {\n                NEEDBITS(state->extra);\n                state->length += BITS(state->extra);\n                DROPBITS(state->extra);\n                state->back += state->extra;\n            }\n            Tracevv((stderr, \"inflate:         length %u\\n\", state->length));\n            state->was = state->length;\n            state->mode = DIST;\n                /* fallthrough */\n        case DIST:\n            for (;;) {\n                here = state->distcode[BITS(state->distbits)];\n                if ((unsigned)(here.bits) <= bits) break;\n                PULLBYTE();\n            }\n            if ((here.op & 0xf0) == 0) {\n                last = here;\n                for (;;) {\n                    here = state->distcode[last.val +\n                            (BITS(last.bits + last.op) >> last.bits)];\n                    if ((unsigned)(last.bits + here.bits) <= bits) break;\n                    PULLBYTE();\n                }\n                DROPBITS(last.bits);\n                state->back += last.bits;\n            }\n            DROPBITS(here.bits);\n            state->back += here.bits;\n            if (here.op & 64) {\n                strm->msg = (char *)\"invalid distance code\";\n                state->mode = BAD;\n                break;\n            }\n            state->offset = (unsigned)here.val;\n            state->extra = (unsigned)(here.op) & 15;\n            state->mode = DISTEXT;\n                /* fallthrough */\n        case DISTEXT:\n            if (state->extra) {\n                NEEDBITS(state->extra);\n                state->offset += BITS(state->extra);\n                DROPBITS(state->extra);\n                state->back += state->extra;\n            }\n#ifdef INFLATE_STRICT\n            if (state->offset > state->dmax) {\n                strm->msg = (char *)\"invalid distance too far back\";\n                state->mode = BAD;\n                break;\n            }\n#endif\n            Tracevv((stderr, \"inflate:         distance %u\\n\", state->offset));\n            state->mode = MATCH;\n                /* fallthrough */\n        case MATCH:\n            if (left == 0) goto inf_leave;\n            copy = out - left;\n            if (state->offset > copy) {         /* copy from window */\n                copy = state->offset - copy;\n                if (copy > state->whave) {\n                    if (state->sane) {\n                        strm->msg = (char *)\"invalid distance too far back\";\n                        state->mode = BAD;\n                        break;\n                    }\n#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n                    Trace((stderr, \"inflate.c too far\\n\"));\n                    copy -= state->whave;\n                    if (copy > state->length) copy = state->length;\n                    if (copy > left) copy = left;\n                    left -= copy;\n                    state->length -= copy;\n                    do {\n                        *put++ = 0;\n                    } while (--copy);\n                    if (state->length == 0) state->mode = LEN;\n                    break;\n#endif\n                }\n                if (copy > state->wnext) {\n                    copy -= state->wnext;\n                    from = state->window + (state->wsize - copy);\n                }\n                else\n                    from = state->window + (state->wnext - copy);\n                if (copy > state->length) copy = state->length;\n            }\n            else {                              /* copy from output */\n                from = put - state->offset;\n                copy = state->length;\n            }\n            if (copy > left) copy = left;\n            left -= copy;\n            state->length -= copy;\n            do {\n                *put++ = *from++;\n            } while (--copy);\n            if (state->length == 0) state->mode = LEN;\n            break;\n        case LIT:\n            if (left == 0) goto inf_leave;\n            *put++ = (unsigned char)(state->length);\n            left--;\n            state->mode = LEN;\n            break;\n        case CHECK:\n            if (state->wrap) {\n                NEEDBITS(32);\n                out -= left;\n                strm->total_out += out;\n                state->total += out;\n                if ((state->wrap & 4) && out)\n                    strm->adler = state->check =\n                        UPDATE_CHECK(state->check, put - out, out);\n                out = left;\n                if ((state->wrap & 4) && (\n#ifdef GUNZIP\n                     state->flags ? hold :\n#endif\n                     ZSWAP32(hold)) != state->check) {\n                    strm->msg = (char *)\"incorrect data check\";\n                    state->mode = BAD;\n                    break;\n                }\n                INITBITS();\n                Tracev((stderr, \"inflate:   check matches trailer\\n\"));\n            }\n#ifdef GUNZIP\n            state->mode = LENGTH;\n                /* fallthrough */\n        case LENGTH:\n            if (state->wrap && state->flags) {\n                NEEDBITS(32);\n                if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {\n                    strm->msg = (char *)\"incorrect length check\";\n                    state->mode = BAD;\n                    break;\n                }\n                INITBITS();\n                Tracev((stderr, \"inflate:   length matches trailer\\n\"));\n            }\n#endif\n            state->mode = DONE;\n                /* fallthrough */\n        case DONE:\n            ret = Z_STREAM_END;\n            goto inf_leave;\n        case BAD:\n            ret = Z_DATA_ERROR;\n            goto inf_leave;\n        case MEM:\n            return Z_MEM_ERROR;\n        case SYNC:\n                /* fallthrough */\n        default:\n            return Z_STREAM_ERROR;\n        }\n\n    /*\n       Return from inflate(), updating the total counts and the check value.\n       If there was no progress during the inflate() call, return a buffer\n       error.  Call updatewindow() to create and/or update the window state.\n       Note: a memory error from inflate() is non-recoverable.\n     */\n  inf_leave:\n    RESTORE();\n    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&\n            (state->mode < CHECK || flush != Z_FINISH)))\n        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {\n            state->mode = MEM;\n            return Z_MEM_ERROR;\n        }\n    in -= strm->avail_in;\n    out -= strm->avail_out;\n    strm->total_in += in;\n    strm->total_out += out;\n    state->total += out;\n    if ((state->wrap & 4) && out)\n        strm->adler = state->check =\n            UPDATE_CHECK(state->check, strm->next_out - out, out);\n    strm->data_type = (int)state->bits + (state->last ? 64 : 0) +\n                      (state->mode == TYPE ? 128 : 0) +\n                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);\n    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)\n        ret = Z_BUF_ERROR;\n    return ret;\n}\n\nint ZEXPORT inflateEnd(strm)\nz_streamp strm;\n{\n    struct inflate_state FAR *state;\n    if (inflateStateCheck(strm))\n        return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if (state->window != Z_NULL) ZFREE(strm, state->window);\n    ZFREE(strm, strm->state);\n    strm->state = Z_NULL;\n    Tracev((stderr, \"inflate: end\\n\"));\n    return Z_OK;\n}\n\nint ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)\nz_streamp strm;\nBytef *dictionary;\nuInt *dictLength;\n{\n    struct inflate_state FAR *state;\n\n    /* check state */\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n\n    /* copy dictionary */\n    if (state->whave && dictionary != Z_NULL) {\n        zmemcpy(dictionary, state->window + state->wnext,\n                state->whave - state->wnext);\n        zmemcpy(dictionary + state->whave - state->wnext,\n                state->window, state->wnext);\n    }\n    if (dictLength != Z_NULL)\n        *dictLength = state->whave;\n    return Z_OK;\n}\n\nint ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)\nz_streamp strm;\nconst Bytef *dictionary;\nuInt dictLength;\n{\n    struct inflate_state FAR *state;\n    unsigned long dictid;\n    int ret;\n\n    /* check state */\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if (state->wrap != 0 && state->mode != DICT)\n        return Z_STREAM_ERROR;\n\n    /* check for correct dictionary identifier */\n    if (state->mode == DICT) {\n        dictid = adler32(0L, Z_NULL, 0);\n        dictid = adler32(dictid, dictionary, dictLength);\n        if (dictid != state->check)\n            return Z_DATA_ERROR;\n    }\n\n    /* copy dictionary to window using updatewindow(), which will amend the\n       existing dictionary if appropriate */\n    ret = updatewindow(strm, dictionary + dictLength, dictLength);\n    if (ret) {\n        state->mode = MEM;\n        return Z_MEM_ERROR;\n    }\n    state->havedict = 1;\n    Tracev((stderr, \"inflate:   dictionary set\\n\"));\n    return Z_OK;\n}\n\nint ZEXPORT inflateGetHeader(strm, head)\nz_streamp strm;\ngz_headerp head;\n{\n    struct inflate_state FAR *state;\n\n    /* check state */\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;\n\n    /* save header structure */\n    state->head = head;\n    head->done = 0;\n    return Z_OK;\n}\n\n/*\n   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found\n   or when out of input.  When called, *have is the number of pattern bytes\n   found in order so far, in 0..3.  On return *have is updated to the new\n   state.  If on return *have equals four, then the pattern was found and the\n   return value is how many bytes were read including the last byte of the\n   pattern.  If *have is less than four, then the pattern has not been found\n   yet and the return value is len.  In the latter case, syncsearch() can be\n   called again with more data and the *have state.  *have is initialized to\n   zero for the first call.\n */\nlocal unsigned syncsearch(have, buf, len)\nunsigned FAR *have;\nconst unsigned char FAR *buf;\nunsigned len;\n{\n    unsigned got;\n    unsigned next;\n\n    got = *have;\n    next = 0;\n    while (next < len && got < 4) {\n        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))\n            got++;\n        else if (buf[next])\n            got = 0;\n        else\n            got = 4 - got;\n        next++;\n    }\n    *have = got;\n    return next;\n}\n\nint ZEXPORT inflateSync(strm)\nz_streamp strm;\n{\n    unsigned len;               /* number of bytes to look at or looked at */\n    int flags;                  /* temporary to save header status */\n    unsigned long in, out;      /* temporary to save total_in and total_out */\n    unsigned char buf[4];       /* to restore bit buffer to byte string */\n    struct inflate_state FAR *state;\n\n    /* check parameters */\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;\n\n    /* if first time, start search in bit buffer */\n    if (state->mode != SYNC) {\n        state->mode = SYNC;\n        state->hold <<= state->bits & 7;\n        state->bits -= state->bits & 7;\n        len = 0;\n        while (state->bits >= 8) {\n            buf[len++] = (unsigned char)(state->hold);\n            state->hold >>= 8;\n            state->bits -= 8;\n        }\n        state->have = 0;\n        syncsearch(&(state->have), buf, len);\n    }\n\n    /* search available input */\n    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);\n    strm->avail_in -= len;\n    strm->next_in += len;\n    strm->total_in += len;\n\n    /* return no joy or set up to restart inflate() on a new block */\n    if (state->have != 4) return Z_DATA_ERROR;\n    if (state->flags == -1)\n        state->wrap = 0;    /* if no header yet, treat as raw */\n    else\n        state->wrap &= ~4;  /* no point in computing a check value now */\n    flags = state->flags;\n    in = strm->total_in;  out = strm->total_out;\n    inflateReset(strm);\n    strm->total_in = in;  strm->total_out = out;\n    state->flags = flags;\n    state->mode = TYPE;\n    return Z_OK;\n}\n\n/*\n   Returns true if inflate is currently at the end of a block generated by\n   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP\n   implementation to provide an additional safety check. PPP uses\n   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored\n   block. When decompressing, PPP checks that at the end of input packet,\n   inflate is waiting for these length bytes.\n */\nint ZEXPORT inflateSyncPoint(strm)\nz_streamp strm;\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    return state->mode == STORED && state->bits == 0;\n}\n\nint ZEXPORT inflateCopy(dest, source)\nz_streamp dest;\nz_streamp source;\n{\n    struct inflate_state FAR *state;\n    struct inflate_state FAR *copy;\n    unsigned char FAR *window;\n    unsigned wsize;\n\n    /* check input */\n    if (inflateStateCheck(source) || dest == Z_NULL)\n        return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)source->state;\n\n    /* allocate space */\n    copy = (struct inflate_state FAR *)\n           ZALLOC(source, 1, sizeof(struct inflate_state));\n    if (copy == Z_NULL) return Z_MEM_ERROR;\n    window = Z_NULL;\n    if (state->window != Z_NULL) {\n        window = (unsigned char FAR *)\n                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));\n        if (window == Z_NULL) {\n            ZFREE(source, copy);\n            return Z_MEM_ERROR;\n        }\n    }\n\n    /* copy state */\n    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));\n    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));\n    copy->strm = dest;\n    if (state->lencode >= state->codes &&\n        state->lencode <= state->codes + ENOUGH - 1) {\n        copy->lencode = copy->codes + (state->lencode - state->codes);\n        copy->distcode = copy->codes + (state->distcode - state->codes);\n    }\n    copy->next = copy->codes + (state->next - state->codes);\n    if (window != Z_NULL) {\n        wsize = 1U << state->wbits;\n        zmemcpy(window, state->window, wsize);\n    }\n    copy->window = window;\n    dest->state = (struct internal_state FAR *)copy;\n    return Z_OK;\n}\n\nint ZEXPORT inflateUndermine(strm, subvert)\nz_streamp strm;\nint subvert;\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n    state->sane = !subvert;\n    return Z_OK;\n#else\n    (void)subvert;\n    state->sane = 1;\n    return Z_DATA_ERROR;\n#endif\n}\n\nint ZEXPORT inflateValidate(strm, check)\nz_streamp strm;\nint check;\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if (check && state->wrap)\n        state->wrap |= 4;\n    else\n        state->wrap &= ~4;\n    return Z_OK;\n}\n\nlong ZEXPORT inflateMark(strm)\nz_streamp strm;\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm))\n        return -(1L << 16);\n    state = (struct inflate_state FAR *)strm->state;\n    return (long)(((unsigned long)((long)state->back)) << 16) +\n        (state->mode == COPY ? state->length :\n            (state->mode == MATCH ? state->was - state->length : 0));\n}\n\nunsigned long ZEXPORT inflateCodesUsed(strm)\nz_streamp strm;\n{\n    struct inflate_state FAR *state;\n    if (inflateStateCheck(strm)) return (unsigned long)-1;\n    state = (struct inflate_state FAR *)strm->state;\n    return (unsigned long)(state->next - state->codes);\n}\n"
  },
  {
    "path": "third_party/libz/inflate.h",
    "content": "// clang-format off\n/* inflate.h -- internal inflate state definition\n * Copyright (C) 1995-2019 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the compression library and is\n   subject to change. Applications should only use zlib.h.\n */\n\n/* define NO_GZIP when compiling if you want to disable gzip header and\n   trailer decoding by inflate().  NO_GZIP would be used to avoid linking in\n   the crc code when it is not needed.  For shared libraries, gzip decoding\n   should be left enabled. */\n#ifndef NO_GZIP\n#  define GUNZIP\n#endif\n\n/* Possible inflate modes between inflate() calls */\ntypedef enum {\n    HEAD = 16180,   /* i: waiting for magic header */\n    FLAGS,      /* i: waiting for method and flags (gzip) */\n    TIME,       /* i: waiting for modification time (gzip) */\n    OS,         /* i: waiting for extra flags and operating system (gzip) */\n    EXLEN,      /* i: waiting for extra length (gzip) */\n    EXTRA,      /* i: waiting for extra bytes (gzip) */\n    NAME,       /* i: waiting for end of file name (gzip) */\n    COMMENT,    /* i: waiting for end of comment (gzip) */\n    HCRC,       /* i: waiting for header crc (gzip) */\n    DICTID,     /* i: waiting for dictionary check value */\n    DICT,       /* waiting for inflateSetDictionary() call */\n        TYPE,       /* i: waiting for type bits, including last-flag bit */\n        TYPEDO,     /* i: same, but skip check to exit inflate on new block */\n        STORED,     /* i: waiting for stored size (length and complement) */\n        COPY_,      /* i/o: same as COPY below, but only first time in */\n        COPY,       /* i/o: waiting for input or output to copy stored block */\n        TABLE,      /* i: waiting for dynamic block table lengths */\n        LENLENS,    /* i: waiting for code length code lengths */\n        CODELENS,   /* i: waiting for length/lit and distance code lengths */\n            LEN_,       /* i: same as LEN below, but only first time in */\n            LEN,        /* i: waiting for length/lit/eob code */\n            LENEXT,     /* i: waiting for length extra bits */\n            DIST,       /* i: waiting for distance code */\n            DISTEXT,    /* i: waiting for distance extra bits */\n            MATCH,      /* o: waiting for output space to copy string */\n            LIT,        /* o: waiting for output space to write literal */\n    CHECK,      /* i: waiting for 32-bit check value */\n    LENGTH,     /* i: waiting for 32-bit length (gzip) */\n    DONE,       /* finished check, done -- remain here until reset */\n    BAD,        /* got a data error -- remain here until reset */\n    MEM,        /* got an inflate() memory error -- remain here until reset */\n    SYNC        /* looking for synchronization bytes to restart inflate() */\n} inflate_mode;\n\n/*\n    State transitions between above modes -\n\n    (most modes can go to BAD or MEM on error -- not shown for clarity)\n\n    Process header:\n        HEAD -> (gzip) or (zlib) or (raw)\n        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->\n                  HCRC -> TYPE\n        (zlib) -> DICTID or TYPE\n        DICTID -> DICT -> TYPE\n        (raw) -> TYPEDO\n    Read deflate blocks:\n            TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK\n            STORED -> COPY_ -> COPY -> TYPE\n            TABLE -> LENLENS -> CODELENS -> LEN_\n            LEN_ -> LEN\n    Read deflate codes in fixed or dynamic block:\n                LEN -> LENEXT or LIT or TYPE\n                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN\n                LIT -> LEN\n    Process trailer:\n        CHECK -> LENGTH -> DONE\n */\n\n/* State maintained between inflate() calls -- approximately 7K bytes, not\n   including the allocated sliding window, which is up to 32K bytes. */\nstruct inflate_state {\n    z_streamp strm;             /* pointer back to this zlib stream */\n    inflate_mode mode;          /* current inflate mode */\n    int last;                   /* true if processing last block */\n    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip,\n                                   bit 2 true to validate check value */\n    int havedict;               /* true if dictionary provided */\n    int flags;                  /* gzip header method and flags, 0 if zlib, or\n                                   -1 if raw or no header yet */\n    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */\n    unsigned long check;        /* protected copy of check value */\n    unsigned long total;        /* protected copy of output count */\n    gz_headerp head;            /* where to save gzip header information */\n        /* sliding window */\n    unsigned wbits;             /* log base 2 of requested window size */\n    unsigned wsize;             /* window size or zero if not using window */\n    unsigned whave;             /* valid bytes in the window */\n    unsigned wnext;             /* window write index */\n    unsigned char FAR *window;  /* allocated sliding window, if needed */\n        /* bit accumulator */\n    unsigned long hold;         /* input bit accumulator */\n    unsigned bits;              /* number of bits in \"in\" */\n        /* for string and stored block copying */\n    unsigned length;            /* literal or length of data to copy */\n    unsigned offset;            /* distance back to copy string from */\n        /* for table and code decoding */\n    unsigned extra;             /* extra bits needed */\n        /* fixed and dynamic code tables */\n    code const FAR *lencode;    /* starting table for length/literal codes */\n    code const FAR *distcode;   /* starting table for distance codes */\n    unsigned lenbits;           /* index bits for lencode */\n    unsigned distbits;          /* index bits for distcode */\n        /* dynamic table building */\n    unsigned ncode;             /* number of code length code lengths */\n    unsigned nlen;              /* number of length code lengths */\n    unsigned ndist;             /* number of distance code lengths */\n    unsigned have;              /* number of code lengths in lens[] */\n    code FAR *next;             /* next available space in codes[] */\n    unsigned short lens[320];   /* temporary storage for code lengths */\n    unsigned short work[288];   /* work area for code table building */\n    code codes[ENOUGH];         /* space for code tables */\n    int sane;                   /* if false, allow invalid distance too far */\n    int back;                   /* bits back of last unprocessed length/lit */\n    unsigned was;               /* initial length of match */\n};\n"
  },
  {
    "path": "third_party/libz/inftrees.c",
    "content": "// clang-format off\n/* inftrees.c -- generate Huffman trees for efficient decoding\n * Copyright (C) 1995-2022 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n#include \"third_party/libz/zutil.h\"\n#include \"third_party/libz/inftrees.h\"\n\n#define MAXBITS 15\n\nconst char inflate_copyright[] =\n   \" inflate 1.2.13 Copyright 1995-2022 Mark Adler \";\n/*\n  If you use the zlib library in a product, an acknowledgment is welcome\n  in the documentation of your product. If for some reason you cannot\n  include such an acknowledgment, I would appreciate that you keep this\n  copyright string in the executable of your product.\n */\n\n/*\n   Build a set of tables to decode the provided canonical Huffman code.\n   The code lengths are lens[0..codes-1].  The result starts at *table,\n   whose indices are 0..2^bits-1.  work is a writable array of at least\n   lens shorts, which is used as a work area.  type is the type of code\n   to be generated, CODES, LENS, or DISTS.  On return, zero is success,\n   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table\n   on return points to the next available entry's address.  bits is the\n   requested root table index bits, and on return it is the actual root\n   table index bits.  It will differ if the request is greater than the\n   longest code or if it is less than the shortest code.\n */\nint ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)\ncodetype type;\nunsigned short FAR *lens;\nunsigned codes;\ncode FAR * FAR *table;\nunsigned FAR *bits;\nunsigned short FAR *work;\n{\n    unsigned len;               /* a code's length in bits */\n    unsigned sym;               /* index of code symbols */\n    unsigned min, max;          /* minimum and maximum code lengths */\n    unsigned root;              /* number of index bits for root table */\n    unsigned curr;              /* number of index bits for current table */\n    unsigned drop;              /* code bits to drop for sub-table */\n    int left;                   /* number of prefix codes available */\n    unsigned used;              /* code entries in table used */\n    unsigned huff;              /* Huffman code */\n    unsigned incr;              /* for incrementing code, index */\n    unsigned fill;              /* index for replicating entries */\n    unsigned low;               /* low bits for current root entry */\n    unsigned mask;              /* mask for low root bits */\n    code here;                  /* table entry for duplication */\n    code FAR *next;             /* next available space in table */\n    const unsigned short FAR *base;     /* base value table to use */\n    const unsigned short FAR *extra;    /* extra bits table to use */\n    unsigned match;             /* use base and extra for symbol >= match */\n    unsigned short count[MAXBITS+1];    /* number of codes of each length */\n    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */\n    static const unsigned short lbase[31] = { /* Length codes 257..285 base */\n        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\n        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};\n    static const unsigned short lext[31] = { /* Length codes 257..285 extra */\n        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,\n        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 194, 65};\n    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */\n        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\n        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\n        8193, 12289, 16385, 24577, 0, 0};\n    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */\n        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,\n        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,\n        28, 28, 29, 29, 64, 64};\n\n    /*\n       Process a set of code lengths to create a canonical Huffman code.  The\n       code lengths are lens[0..codes-1].  Each length corresponds to the\n       symbols 0..codes-1.  The Huffman code is generated by first sorting the\n       symbols by length from short to long, and retaining the symbol order\n       for codes with equal lengths.  Then the code starts with all zero bits\n       for the first code of the shortest length, and the codes are integer\n       increments for the same length, and zeros are appended as the length\n       increases.  For the deflate format, these bits are stored backwards\n       from their more natural integer increment ordering, and so when the\n       decoding tables are built in the large loop below, the integer codes\n       are incremented backwards.\n\n       This routine assumes, but does not check, that all of the entries in\n       lens[] are in the range 0..MAXBITS.  The caller must assure this.\n       1..MAXBITS is interpreted as that code length.  zero means that that\n       symbol does not occur in this code.\n\n       The codes are sorted by computing a count of codes for each length,\n       creating from that a table of starting indices for each length in the\n       sorted table, and then entering the symbols in order in the sorted\n       table.  The sorted table is work[], with that space being provided by\n       the caller.\n\n       The length counts are used for other purposes as well, i.e. finding\n       the minimum and maximum length codes, determining if there are any\n       codes at all, checking for a valid set of lengths, and looking ahead\n       at length counts to determine sub-table sizes when building the\n       decoding tables.\n     */\n\n    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */\n    for (len = 0; len <= MAXBITS; len++)\n        count[len] = 0;\n    for (sym = 0; sym < codes; sym++)\n        count[lens[sym]]++;\n\n    /* bound code lengths, force root to be within code lengths */\n    root = *bits;\n    for (max = MAXBITS; max >= 1; max--)\n        if (count[max] != 0) break;\n    if (root > max) root = max;\n    if (max == 0) {                     /* no symbols to code at all */\n        here.op = (unsigned char)64;    /* invalid code marker */\n        here.bits = (unsigned char)1;\n        here.val = (unsigned short)0;\n        *(*table)++ = here;             /* make a table to force an error */\n        *(*table)++ = here;\n        *bits = 1;\n        return 0;     /* no symbols, but wait for decoding to report error */\n    }\n    for (min = 1; min < max; min++)\n        if (count[min] != 0) break;\n    if (root < min) root = min;\n\n    /* check for an over-subscribed or incomplete set of lengths */\n    left = 1;\n    for (len = 1; len <= MAXBITS; len++) {\n        left <<= 1;\n        left -= count[len];\n        if (left < 0) return -1;        /* over-subscribed */\n    }\n    if (left > 0 && (type == CODES || max != 1))\n        return -1;                      /* incomplete set */\n\n    /* generate offsets into symbol table for each length for sorting */\n    offs[1] = 0;\n    for (len = 1; len < MAXBITS; len++)\n        offs[len + 1] = offs[len] + count[len];\n\n    /* sort symbols by length, by symbol order within each length */\n    for (sym = 0; sym < codes; sym++)\n        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;\n\n    /*\n       Create and fill in decoding tables.  In this loop, the table being\n       filled is at next and has curr index bits.  The code being used is huff\n       with length len.  That code is converted to an index by dropping drop\n       bits off of the bottom.  For codes where len is less than drop + curr,\n       those top drop + curr - len bits are incremented through all values to\n       fill the table with replicated entries.\n\n       root is the number of index bits for the root table.  When len exceeds\n       root, sub-tables are created pointed to by the root entry with an index\n       of the low root bits of huff.  This is saved in low to check for when a\n       new sub-table should be started.  drop is zero when the root table is\n       being filled, and drop is root when sub-tables are being filled.\n\n       When a new sub-table is needed, it is necessary to look ahead in the\n       code lengths to determine what size sub-table is needed.  The length\n       counts are used for this, and so count[] is decremented as codes are\n       entered in the tables.\n\n       used keeps track of how many table entries have been allocated from the\n       provided *table space.  It is checked for LENS and DIST tables against\n       the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in\n       the initial root table size constants.  See the comments in inftrees.h\n       for more information.\n\n       sym increments through all symbols, and the loop terminates when\n       all codes of length max, i.e. all codes, have been processed.  This\n       routine permits incomplete codes, so another loop after this one fills\n       in the rest of the decoding tables with invalid code markers.\n     */\n\n    /* set up for code type */\n    switch (type) {\n    case CODES:\n        base = extra = work;    /* dummy value--not used */\n        match = 20;\n        break;\n    case LENS:\n        base = lbase;\n        extra = lext;\n        match = 257;\n        break;\n    default:    /* DISTS */\n        base = dbase;\n        extra = dext;\n        match = 0;\n    }\n\n    /* initialize state for loop */\n    huff = 0;                   /* starting code */\n    sym = 0;                    /* starting code symbol */\n    len = min;                  /* starting code length */\n    next = *table;              /* current table to fill in */\n    curr = root;                /* current table index bits */\n    drop = 0;                   /* current bits to drop from code for index */\n    low = (unsigned)(-1);       /* trigger new sub-table when len > root */\n    used = 1U << root;          /* use root table entries */\n    mask = used - 1;            /* mask for comparing low */\n\n    /* check available table space */\n    if ((type == LENS && used > ENOUGH_LENS) ||\n        (type == DISTS && used > ENOUGH_DISTS))\n        return 1;\n\n    /* process all codes and make table entries */\n    for (;;) {\n        /* create table entry */\n        here.bits = (unsigned char)(len - drop);\n        if (work[sym] + 1U < match) {\n            here.op = (unsigned char)0;\n            here.val = work[sym];\n        }\n        else if (work[sym] >= match) {\n            here.op = (unsigned char)(extra[work[sym] - match]);\n            here.val = base[work[sym] - match];\n        }\n        else {\n            here.op = (unsigned char)(32 + 64);         /* end of block */\n            here.val = 0;\n        }\n\n        /* replicate for those indices with low len bits equal to huff */\n        incr = 1U << (len - drop);\n        fill = 1U << curr;\n        min = fill;                 /* save offset to next table */\n        do {\n            fill -= incr;\n            next[(huff >> drop) + fill] = here;\n        } while (fill != 0);\n\n        /* backwards increment the len-bit code huff */\n        incr = 1U << (len - 1);\n        while (huff & incr)\n            incr >>= 1;\n        if (incr != 0) {\n            huff &= incr - 1;\n            huff += incr;\n        }\n        else\n            huff = 0;\n\n        /* go to next symbol, update count, len */\n        sym++;\n        if (--(count[len]) == 0) {\n            if (len == max) break;\n            len = lens[work[sym]];\n        }\n\n        /* create new sub-table if needed */\n        if (len > root && (huff & mask) != low) {\n            /* if first time, transition to sub-tables */\n            if (drop == 0)\n                drop = root;\n\n            /* increment past last table */\n            next += min;            /* here min is 1 << curr */\n\n            /* determine length of next table */\n            curr = len - drop;\n            left = (int)(1 << curr);\n            while (curr + drop < max) {\n                left -= count[curr + drop];\n                if (left <= 0) break;\n                curr++;\n                left <<= 1;\n            }\n\n            /* check for enough space */\n            used += 1U << curr;\n            if ((type == LENS && used > ENOUGH_LENS) ||\n                (type == DISTS && used > ENOUGH_DISTS))\n                return 1;\n\n            /* point entry in root table to sub-table */\n            low = huff & mask;\n            (*table)[low].op = (unsigned char)curr;\n            (*table)[low].bits = (unsigned char)root;\n            (*table)[low].val = (unsigned short)(next - *table);\n        }\n    }\n\n    /* fill in remaining table entry if code is incomplete (guaranteed to have\n       at most one remaining entry, since if the code is incomplete, the\n       maximum code length that was allowed to get this far is one bit) */\n    if (huff != 0) {\n        here.op = (unsigned char)64;            /* invalid code marker */\n        here.bits = (unsigned char)(len - drop);\n        here.val = (unsigned short)0;\n        next[huff] = here;\n    }\n\n    /* set return parameters */\n    *table += used;\n    *bits = root;\n    return 0;\n}\n"
  },
  {
    "path": "third_party/libz/inftrees.h",
    "content": "// clang-format off\n/* inftrees.h -- header to use inftrees.c\n * Copyright (C) 1995-2005, 2010 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the compression library and is\n   subject to change. Applications should only use zlib.h.\n */\n\n/* Structure for decoding tables.  Each entry provides either the\n   information needed to do the operation requested by the code that\n   indexed that table entry, or it provides a pointer to another\n   table that indexes more bits of the code.  op indicates whether\n   the entry is a pointer to another table, a literal, a length or\n   distance, an end-of-block, or an invalid code.  For a table\n   pointer, the low four bits of op is the number of index bits of\n   that table.  For a length or distance, the low four bits of op\n   is the number of extra bits to get after the code.  bits is\n   the number of bits in this code or part of the code to drop off\n   of the bit buffer.  val is the actual byte to output in the case\n   of a literal, the base length or distance, or the offset from\n   the current table to the next table.  Each entry is four bytes. */\ntypedef struct {\n    unsigned char op;           /* operation, extra bits, table bits */\n    unsigned char bits;         /* bits in this part of the code */\n    unsigned short val;         /* offset in table or code value */\n} code;\n\n/* op values as set by inflate_table():\n    00000000 - literal\n    0000tttt - table link, tttt != 0 is the number of table index bits\n    0001eeee - length or distance, eeee is the number of extra bits\n    01100000 - end of block\n    01000000 - invalid code\n */\n\n/* Maximum size of the dynamic table.  The maximum number of code structures is\n   1444, which is the sum of 852 for literal/length codes and 592 for distance\n   codes.  These values were found by exhaustive searches using the program\n   examples/enough.c found in the zlib distribution.  The arguments to that\n   program are the number of symbols, the initial root table size, and the\n   maximum bit length of a code.  \"enough 286 9 15\" for literal/length codes\n   returns returns 852, and \"enough 30 6 15\" for distance codes returns 592.\n   The initial root table size (9 or 6) is found in the fifth argument of the\n   inflate_table() calls in inflate.c and infback.c.  If the root table size is\n   changed, then these maximum sizes would be need to be recalculated and\n   updated. */\n#define ENOUGH_LENS 852\n#define ENOUGH_DISTS 592\n#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)\n\n/* Type of code to build for inflate_table() */\ntypedef enum {\n    CODES,\n    LENS,\n    DISTS\n} codetype;\n\nint ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,\n                             unsigned codes, code FAR * FAR *table,\n                             unsigned FAR *bits, unsigned short FAR *work));\n"
  },
  {
    "path": "third_party/libz/trees.c",
    "content": "// clang-format off\n/* trees.c -- output deflated data using Huffman coding\n * Copyright (C) 1995-2021 Jean-loup Gailly\n * detect_data_type() function provided freely by Cosmin Truta, 2006\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/*\n *  ALGORITHM\n *\n *      The \"deflation\" process uses several Huffman trees. The more\n *      common source values are represented by shorter bit sequences.\n *\n *      Each code tree is stored in a compressed form which is itself\n * a Huffman encoding of the lengths of all the code strings (in\n * ascending order by source values).  The actual code strings are\n * reconstructed from the lengths in the inflate process, as described\n * in the deflate specification.\n *\n *  REFERENCES\n *\n *      Deutsch, L.P.,\"'Deflate' Compressed Data Format Specification\".\n *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc\n *\n *      Storer, James A.\n *          Data Compression:  Methods and Theory, pp. 49-50.\n *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.\n *\n *      Sedgewick, R.\n *          Algorithms, p290.\n *          Addison-Wesley, 1983. ISBN 0-201-06672-6.\n */\n\n/* @(#) $Id$ */\n\n/* #define GEN_TREES_H */\n\n#include \"third_party/libz/deflate.h\"\n\n#ifdef ZLIB_DEBUG\n#  include <ctype.h>\n#endif\n\n/* ===========================================================================\n * Constants\n */\n\n#define MAX_BL_BITS 7\n/* Bit length codes must not exceed MAX_BL_BITS bits */\n\n#define END_BLOCK 256\n/* end of block literal code */\n\n#define REP_3_6      16\n/* repeat previous bit length 3-6 times (2 bits of repeat count) */\n\n#define REPZ_3_10    17\n/* repeat a zero length 3-10 times  (3 bits of repeat count) */\n\n#define REPZ_11_138  18\n/* repeat a zero length 11-138 times  (7 bits of repeat count) */\n\nlocal const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */\n   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};\n\nlocal const int extra_dbits[D_CODES] /* extra bits for each distance code */\n   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};\n\nlocal const int extra_blbits[BL_CODES]/* extra bits for each bit length code */\n   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};\n\nlocal const uch bl_order[BL_CODES]\n   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};\n/* The lengths of the bit length codes are sent in order of decreasing\n * probability, to avoid transmitting the lengths for unused bit length codes.\n */\n\n/* ===========================================================================\n * Local data. These are initialized only once.\n */\n\n#define DIST_CODE_LEN  512 /* see definition of array dist_code below */\n\n#if defined(GEN_TREES_H) || !defined(STDC)\n/* non ANSI compilers may not accept trees.h */\n\nlocal ct_data static_ltree[L_CODES+2];\n/* The static literal tree. Since the bit lengths are imposed, there is no\n * need for the L_CODES extra codes used during heap construction. However\n * The codes 286 and 287 are needed to build a canonical tree (see _tr_init\n * below).\n */\n\nlocal ct_data static_dtree[D_CODES];\n/* The static distance tree. (Actually a trivial tree since all codes use\n * 5 bits.)\n */\n\nuch _dist_code[DIST_CODE_LEN];\n/* Distance codes. The first 256 values correspond to the distances\n * 3 .. 258, the last 256 values correspond to the top 8 bits of\n * the 15 bit distances.\n */\n\nuch _length_code[MAX_MATCH-MIN_MATCH+1];\n/* length code for each normalized match length (0 == MIN_MATCH) */\n\nlocal int base_length[LENGTH_CODES];\n/* First normalized length for each code (0 = MIN_MATCH) */\n\nlocal int base_dist[D_CODES];\n/* First normalized distance for each code (0 = distance of 1) */\n\n#else\n#  include \"third_party/libz/trees.h\"\n#endif /* GEN_TREES_H */\n\nstruct static_tree_desc_s {\n    const ct_data *static_tree;  /* static tree or NULL */\n    const intf *extra_bits;      /* extra bits for each code or NULL */\n    int     extra_base;          /* base index for extra_bits */\n    int     elems;               /* max number of elements in the tree */\n    int     max_length;          /* max bit length for the codes */\n};\n\nlocal const static_tree_desc  static_l_desc =\n{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};\n\nlocal const static_tree_desc  static_d_desc =\n{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};\n\nlocal const static_tree_desc  static_bl_desc =\n{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};\n\n/* ===========================================================================\n * Local (static) routines in this file.\n */\n\nlocal void tr_static_init OF((void));\nlocal void init_block     OF((deflate_state *s));\nlocal void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));\nlocal void gen_bitlen     OF((deflate_state *s, tree_desc *desc));\nlocal void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));\nlocal void build_tree     OF((deflate_state *s, tree_desc *desc));\nlocal void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));\nlocal void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));\nlocal int  build_bl_tree  OF((deflate_state *s));\nlocal void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,\n                              int blcodes));\nlocal void compress_block OF((deflate_state *s, const ct_data *ltree,\n                              const ct_data *dtree));\nlocal int  detect_data_type OF((deflate_state *s));\nlocal unsigned bi_reverse OF((unsigned code, int len));\nlocal void bi_windup      OF((deflate_state *s));\nlocal void bi_flush       OF((deflate_state *s));\n\n#ifdef GEN_TREES_H\nlocal void gen_trees_header OF((void));\n#endif\n\n#ifndef ZLIB_DEBUG\n#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)\n   /* Send a code of the given tree. c and tree must not have side effects */\n\n#else /* !ZLIB_DEBUG */\n#  define send_code(s, c, tree) \\\n     { if (z_verbose>2) fprintf(stderr,\"\\ncd %3d \",(c)); \\\n       send_bits(s, tree[c].Code, tree[c].Len); }\n#endif\n\n/* ===========================================================================\n * Output a short LSB first on the stream.\n * IN assertion: there is enough room in pendingBuf.\n */\n#define put_short(s, w) { \\\n    put_byte(s, (uch)((w) & 0xff)); \\\n    put_byte(s, (uch)((ush)(w) >> 8)); \\\n}\n\n/* ===========================================================================\n * Send a value on a given number of bits.\n * IN assertion: length <= 16 and value fits in length bits.\n */\n#ifdef ZLIB_DEBUG\nlocal void send_bits      OF((deflate_state *s, int value, int length));\n\nlocal void send_bits(s, value, length)\n    deflate_state *s;\n    int value;  /* value to send */\n    int length; /* number of bits */\n{\n    Tracevv((stderr,\" l %2d v %4x \", length, value));\n    Assert(length > 0 && length <= 15, \"invalid length\");\n    s->bits_sent += (ulg)length;\n\n    /* If not enough room in bi_buf, use (valid) bits from bi_buf and\n     * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid))\n     * unused bits in value.\n     */\n    if (s->bi_valid > (int)Buf_size - length) {\n        s->bi_buf |= (ush)value << s->bi_valid;\n        put_short(s, s->bi_buf);\n        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);\n        s->bi_valid += length - Buf_size;\n    } else {\n        s->bi_buf |= (ush)value << s->bi_valid;\n        s->bi_valid += length;\n    }\n}\n#else /* !ZLIB_DEBUG */\n\n#define send_bits(s, value, length) \\\n{ int len = length;\\\n  if (s->bi_valid > (int)Buf_size - len) {\\\n    int val = (int)value;\\\n    s->bi_buf |= (ush)val << s->bi_valid;\\\n    put_short(s, s->bi_buf);\\\n    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\\\n    s->bi_valid += len - Buf_size;\\\n  } else {\\\n    s->bi_buf |= (ush)(value) << s->bi_valid;\\\n    s->bi_valid += len;\\\n  }\\\n}\n#endif /* ZLIB_DEBUG */\n\n\n/* the arguments must not have side effects */\n\n/* ===========================================================================\n * Initialize the various 'constant' tables.\n */\nlocal void tr_static_init()\n{\n#if defined(GEN_TREES_H) || !defined(STDC)\n    static int static_init_done = 0;\n    int n;        /* iterates over tree elements */\n    int bits;     /* bit counter */\n    int length;   /* length value */\n    int code;     /* code value */\n    int dist;     /* distance index */\n    ush bl_count[MAX_BITS+1];\n    /* number of codes at each bit length for an optimal tree */\n\n    if (static_init_done) return;\n\n    /* For some embedded targets, global variables are not initialized: */\n#ifdef NO_INIT_GLOBAL_POINTERS\n    static_l_desc.static_tree = static_ltree;\n    static_l_desc.extra_bits = extra_lbits;\n    static_d_desc.static_tree = static_dtree;\n    static_d_desc.extra_bits = extra_dbits;\n    static_bl_desc.extra_bits = extra_blbits;\n#endif\n\n    /* Initialize the mapping length (0..255) -> length code (0..28) */\n    length = 0;\n    for (code = 0; code < LENGTH_CODES-1; code++) {\n        base_length[code] = length;\n        for (n = 0; n < (1 << extra_lbits[code]); n++) {\n            _length_code[length++] = (uch)code;\n        }\n    }\n    Assert (length == 256, \"tr_static_init: length != 256\");\n    /* Note that the length 255 (match length 258) can be represented\n     * in two different ways: code 284 + 5 bits or code 285, so we\n     * overwrite length_code[255] to use the best encoding:\n     */\n    _length_code[length - 1] = (uch)code;\n\n    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */\n    dist = 0;\n    for (code = 0 ; code < 16; code++) {\n        base_dist[code] = dist;\n        for (n = 0; n < (1 << extra_dbits[code]); n++) {\n            _dist_code[dist++] = (uch)code;\n        }\n    }\n    Assert (dist == 256, \"tr_static_init: dist != 256\");\n    dist >>= 7; /* from now on, all distances are divided by 128 */\n    for ( ; code < D_CODES; code++) {\n        base_dist[code] = dist << 7;\n        for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {\n            _dist_code[256 + dist++] = (uch)code;\n        }\n    }\n    Assert (dist == 256, \"tr_static_init: 256 + dist != 512\");\n\n    /* Construct the codes of the static literal tree */\n    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;\n    n = 0;\n    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;\n    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;\n    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;\n    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;\n    /* Codes 286 and 287 do not exist, but we must include them in the\n     * tree construction to get a canonical Huffman tree (longest code\n     * all ones)\n     */\n    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);\n\n    /* The static distance tree is trivial: */\n    for (n = 0; n < D_CODES; n++) {\n        static_dtree[n].Len = 5;\n        static_dtree[n].Code = bi_reverse((unsigned)n, 5);\n    }\n    static_init_done = 1;\n\n#  ifdef GEN_TREES_H\n    gen_trees_header();\n#  endif\n#endif /* defined(GEN_TREES_H) || !defined(STDC) */\n}\n\n/* ===========================================================================\n * Generate the file trees.h describing the static trees.\n */\n#ifdef GEN_TREES_H\n#  ifndef ZLIB_DEBUG\n#    include <stdio.h>\n#  endif\n\n#  define SEPARATOR(i, last, width) \\\n      ((i) == (last)? \"\\n};\\n\\n\" :    \\\n       ((i) % (width) == (width) - 1 ? \",\\n\" : \", \"))\n\nvoid gen_trees_header()\n{\n    FILE *header = fopen(\"trees.h\", \"w\");\n    int i;\n\n    Assert (header != NULL, \"Can't open trees.h\");\n    fprintf(header,\n            \"/* header created automatically with -DGEN_TREES_H */\\n\\n\");\n\n    fprintf(header, \"local const ct_data static_ltree[L_CODES+2] = {\\n\");\n    for (i = 0; i < L_CODES+2; i++) {\n        fprintf(header, \"{{%3u},{%3u}}%s\", static_ltree[i].Code,\n                static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));\n    }\n\n    fprintf(header, \"local const ct_data static_dtree[D_CODES] = {\\n\");\n    for (i = 0; i < D_CODES; i++) {\n        fprintf(header, \"{{%2u},{%2u}}%s\", static_dtree[i].Code,\n                static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));\n    }\n\n    fprintf(header, \"const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\\n\");\n    for (i = 0; i < DIST_CODE_LEN; i++) {\n        fprintf(header, \"%2u%s\", _dist_code[i],\n                SEPARATOR(i, DIST_CODE_LEN-1, 20));\n    }\n\n    fprintf(header,\n        \"const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\\n\");\n    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {\n        fprintf(header, \"%2u%s\", _length_code[i],\n                SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));\n    }\n\n    fprintf(header, \"local const int base_length[LENGTH_CODES] = {\\n\");\n    for (i = 0; i < LENGTH_CODES; i++) {\n        fprintf(header, \"%1u%s\", base_length[i],\n                SEPARATOR(i, LENGTH_CODES-1, 20));\n    }\n\n    fprintf(header, \"local const int base_dist[D_CODES] = {\\n\");\n    for (i = 0; i < D_CODES; i++) {\n        fprintf(header, \"%5u%s\", base_dist[i],\n                SEPARATOR(i, D_CODES-1, 10));\n    }\n\n    fclose(header);\n}\n#endif /* GEN_TREES_H */\n\n/* ===========================================================================\n * Initialize the tree data structures for a new zlib stream.\n */\nvoid ZLIB_INTERNAL _tr_init(s)\n    deflate_state *s;\n{\n    tr_static_init();\n\n    s->l_desc.dyn_tree = s->dyn_ltree;\n    s->l_desc.stat_desc = &static_l_desc;\n\n    s->d_desc.dyn_tree = s->dyn_dtree;\n    s->d_desc.stat_desc = &static_d_desc;\n\n    s->bl_desc.dyn_tree = s->bl_tree;\n    s->bl_desc.stat_desc = &static_bl_desc;\n\n    s->bi_buf = 0;\n    s->bi_valid = 0;\n#ifdef ZLIB_DEBUG\n    s->compressed_len = 0L;\n    s->bits_sent = 0L;\n#endif\n\n    /* Initialize the first block of the first file: */\n    init_block(s);\n}\n\n/* ===========================================================================\n * Initialize a new block.\n */\nlocal void init_block(s)\n    deflate_state *s;\n{\n    int n; /* iterates over tree elements */\n\n    /* Initialize the trees. */\n    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;\n    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;\n    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;\n\n    s->dyn_ltree[END_BLOCK].Freq = 1;\n    s->opt_len = s->static_len = 0L;\n    s->sym_next = s->matches = 0;\n}\n\n#define SMALLEST 1\n/* Index within the heap array of least frequent node in the Huffman tree */\n\n\n/* ===========================================================================\n * Remove the smallest element from the heap and recreate the heap with\n * one less element. Updates heap and heap_len.\n */\n#define pqremove(s, tree, top) \\\n{\\\n    top = s->heap[SMALLEST]; \\\n    s->heap[SMALLEST] = s->heap[s->heap_len--]; \\\n    pqdownheap(s, tree, SMALLEST); \\\n}\n\n/* ===========================================================================\n * Compares to subtrees, using the tree depth as tie breaker when\n * the subtrees have equal frequency. This minimizes the worst case length.\n */\n#define smaller(tree, n, m, depth) \\\n   (tree[n].Freq < tree[m].Freq || \\\n   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))\n\n/* ===========================================================================\n * Restore the heap property by moving down the tree starting at node k,\n * exchanging a node with the smallest of its two sons if necessary, stopping\n * when the heap property is re-established (each father smaller than its\n * two sons).\n */\nlocal void pqdownheap(s, tree, k)\n    deflate_state *s;\n    ct_data *tree;  /* the tree to restore */\n    int k;               /* node to move down */\n{\n    int v = s->heap[k];\n    int j = k << 1;  /* left son of k */\n    while (j <= s->heap_len) {\n        /* Set j to the smallest of the two sons: */\n        if (j < s->heap_len &&\n            smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) {\n            j++;\n        }\n        /* Exit if v is smaller than both sons */\n        if (smaller(tree, v, s->heap[j], s->depth)) break;\n\n        /* Exchange v with the smallest son */\n        s->heap[k] = s->heap[j];  k = j;\n\n        /* And continue down the tree, setting j to the left son of k */\n        j <<= 1;\n    }\n    s->heap[k] = v;\n}\n\n/* ===========================================================================\n * Compute the optimal bit lengths for a tree and update the total bit length\n * for the current block.\n * IN assertion: the fields freq and dad are set, heap[heap_max] and\n *    above are the tree nodes sorted by increasing frequency.\n * OUT assertions: the field len is set to the optimal bit length, the\n *     array bl_count contains the frequencies for each bit length.\n *     The length opt_len is updated; static_len is also updated if stree is\n *     not null.\n */\nlocal void gen_bitlen(s, desc)\n    deflate_state *s;\n    tree_desc *desc;    /* the tree descriptor */\n{\n    ct_data *tree        = desc->dyn_tree;\n    int max_code         = desc->max_code;\n    const ct_data *stree = desc->stat_desc->static_tree;\n    const intf *extra    = desc->stat_desc->extra_bits;\n    int base             = desc->stat_desc->extra_base;\n    int max_length       = desc->stat_desc->max_length;\n    int h;              /* heap index */\n    int n, m;           /* iterate over the tree elements */\n    int bits;           /* bit length */\n    int xbits;          /* extra bits */\n    ush f;              /* frequency */\n    int overflow = 0;   /* number of elements with bit length too large */\n\n    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;\n\n    /* In a first pass, compute the optimal bit lengths (which may\n     * overflow in the case of the bit length tree).\n     */\n    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */\n\n    for (h = s->heap_max + 1; h < HEAP_SIZE; h++) {\n        n = s->heap[h];\n        bits = tree[tree[n].Dad].Len + 1;\n        if (bits > max_length) bits = max_length, overflow++;\n        tree[n].Len = (ush)bits;\n        /* We overwrite tree[n].Dad which is no longer needed */\n\n        if (n > max_code) continue; /* not a leaf node */\n\n        s->bl_count[bits]++;\n        xbits = 0;\n        if (n >= base) xbits = extra[n - base];\n        f = tree[n].Freq;\n        s->opt_len += (ulg)f * (unsigned)(bits + xbits);\n        if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);\n    }\n    if (overflow == 0) return;\n\n    Tracev((stderr,\"\\nbit length overflow\\n\"));\n    /* This happens for example on obj2 and pic of the Calgary corpus */\n\n    /* Find the first bit length which could increase: */\n    do {\n        bits = max_length - 1;\n        while (s->bl_count[bits] == 0) bits--;\n        s->bl_count[bits]--;        /* move one leaf down the tree */\n        s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */\n        s->bl_count[max_length]--;\n        /* The brother of the overflow item also moves one step up,\n         * but this does not affect bl_count[max_length]\n         */\n        overflow -= 2;\n    } while (overflow > 0);\n\n    /* Now recompute all bit lengths, scanning in increasing frequency.\n     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all\n     * lengths instead of fixing only the wrong ones. This idea is taken\n     * from 'ar' written by Haruhiko Okumura.)\n     */\n    for (bits = max_length; bits != 0; bits--) {\n        n = s->bl_count[bits];\n        while (n != 0) {\n            m = s->heap[--h];\n            if (m > max_code) continue;\n            if ((unsigned) tree[m].Len != (unsigned) bits) {\n                Tracev((stderr,\"code %d bits %d->%d\\n\", m, tree[m].Len, bits));\n                s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq;\n                tree[m].Len = (ush)bits;\n            }\n            n--;\n        }\n    }\n}\n\n/* ===========================================================================\n * Generate the codes for a given tree and bit counts (which need not be\n * optimal).\n * IN assertion: the array bl_count contains the bit length statistics for\n * the given tree and the field len is set for all tree elements.\n * OUT assertion: the field code is set for all tree elements of non\n *     zero code length.\n */\nlocal void gen_codes(tree, max_code, bl_count)\n    ct_data *tree;             /* the tree to decorate */\n    int max_code;              /* largest code with non zero frequency */\n    ushf *bl_count;            /* number of codes at each bit length */\n{\n    ush next_code[MAX_BITS+1]; /* next code value for each bit length */\n    unsigned code = 0;         /* running code value */\n    int bits;                  /* bit index */\n    int n;                     /* code index */\n\n    /* The distribution counts are first used to generate the code values\n     * without bit reversal.\n     */\n    for (bits = 1; bits <= MAX_BITS; bits++) {\n        code = (code + bl_count[bits - 1]) << 1;\n        next_code[bits] = (ush)code;\n    }\n    /* Check that the bit counts in bl_count are consistent. The last code\n     * must be all ones.\n     */\n    Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,\n            \"inconsistent bit counts\");\n    Tracev((stderr,\"\\ngen_codes: max_code %d \", max_code));\n\n    for (n = 0;  n <= max_code; n++) {\n        int len = tree[n].Len;\n        if (len == 0) continue;\n        /* Now reverse the bits */\n        tree[n].Code = (ush)bi_reverse(next_code[len]++, len);\n\n        Tracecv(tree != static_ltree, (stderr,\"\\nn %3d %c l %2d c %4x (%x) \",\n            n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1));\n    }\n}\n\n/* ===========================================================================\n * Construct one Huffman tree and assigns the code bit strings and lengths.\n * Update the total bit length for the current block.\n * IN assertion: the field freq is set for all tree elements.\n * OUT assertions: the fields len and code are set to the optimal bit length\n *     and corresponding code. The length opt_len is updated; static_len is\n *     also updated if stree is not null. The field max_code is set.\n */\nlocal void build_tree(s, desc)\n    deflate_state *s;\n    tree_desc *desc; /* the tree descriptor */\n{\n    ct_data *tree         = desc->dyn_tree;\n    const ct_data *stree  = desc->stat_desc->static_tree;\n    int elems             = desc->stat_desc->elems;\n    int n, m;          /* iterate over heap elements */\n    int max_code = -1; /* largest code with non zero frequency */\n    int node;          /* new node being created */\n\n    /* Construct the initial heap, with least frequent element in\n     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1].\n     * heap[0] is not used.\n     */\n    s->heap_len = 0, s->heap_max = HEAP_SIZE;\n\n    for (n = 0; n < elems; n++) {\n        if (tree[n].Freq != 0) {\n            s->heap[++(s->heap_len)] = max_code = n;\n            s->depth[n] = 0;\n        } else {\n            tree[n].Len = 0;\n        }\n    }\n\n    /* The pkzip format requires that at least one distance code exists,\n     * and that at least one bit should be sent even if there is only one\n     * possible code. So to avoid special checks later on we force at least\n     * two codes of non zero frequency.\n     */\n    while (s->heap_len < 2) {\n        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);\n        tree[node].Freq = 1;\n        s->depth[node] = 0;\n        s->opt_len--; if (stree) s->static_len -= stree[node].Len;\n        /* node is 0 or 1 so it does not have extra bits */\n    }\n    desc->max_code = max_code;\n\n    /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree,\n     * establish sub-heaps of increasing lengths:\n     */\n    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);\n\n    /* Construct the Huffman tree by repeatedly combining the least two\n     * frequent nodes.\n     */\n    node = elems;              /* next internal node of the tree */\n    do {\n        pqremove(s, tree, n);  /* n = node of least frequency */\n        m = s->heap[SMALLEST]; /* m = node of next least frequency */\n\n        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */\n        s->heap[--(s->heap_max)] = m;\n\n        /* Create a new node father of n and m */\n        tree[node].Freq = tree[n].Freq + tree[m].Freq;\n        s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?\n                                s->depth[n] : s->depth[m]) + 1);\n        tree[n].Dad = tree[m].Dad = (ush)node;\n#ifdef DUMP_BL_TREE\n        if (tree == s->bl_tree) {\n            fprintf(stderr,\"\\nnode %d(%d), sons %d(%d) %d(%d)\",\n                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);\n        }\n#endif\n        /* and insert the new node in the heap */\n        s->heap[SMALLEST] = node++;\n        pqdownheap(s, tree, SMALLEST);\n\n    } while (s->heap_len >= 2);\n\n    s->heap[--(s->heap_max)] = s->heap[SMALLEST];\n\n    /* At this point, the fields freq and dad are set. We can now\n     * generate the bit lengths.\n     */\n    gen_bitlen(s, (tree_desc *)desc);\n\n    /* The field len is now set, we can generate the bit codes */\n    gen_codes ((ct_data *)tree, max_code, s->bl_count);\n}\n\n/* ===========================================================================\n * Scan a literal or distance tree to determine the frequencies of the codes\n * in the bit length tree.\n */\nlocal void scan_tree(s, tree, max_code)\n    deflate_state *s;\n    ct_data *tree;   /* the tree to be scanned */\n    int max_code;    /* and its largest code of non zero frequency */\n{\n    int n;                     /* iterates over all tree elements */\n    int prevlen = -1;          /* last emitted length */\n    int curlen;                /* length of current code */\n    int nextlen = tree[0].Len; /* length of next code */\n    int count = 0;             /* repeat count of the current code */\n    int max_count = 7;         /* max repeat count */\n    int min_count = 4;         /* min repeat count */\n\n    if (nextlen == 0) max_count = 138, min_count = 3;\n    tree[max_code + 1].Len = (ush)0xffff; /* guard */\n\n    for (n = 0; n <= max_code; n++) {\n        curlen = nextlen; nextlen = tree[n + 1].Len;\n        if (++count < max_count && curlen == nextlen) {\n            continue;\n        } else if (count < min_count) {\n            s->bl_tree[curlen].Freq += count;\n        } else if (curlen != 0) {\n            if (curlen != prevlen) s->bl_tree[curlen].Freq++;\n            s->bl_tree[REP_3_6].Freq++;\n        } else if (count <= 10) {\n            s->bl_tree[REPZ_3_10].Freq++;\n        } else {\n            s->bl_tree[REPZ_11_138].Freq++;\n        }\n        count = 0; prevlen = curlen;\n        if (nextlen == 0) {\n            max_count = 138, min_count = 3;\n        } else if (curlen == nextlen) {\n            max_count = 6, min_count = 3;\n        } else {\n            max_count = 7, min_count = 4;\n        }\n    }\n}\n\n/* ===========================================================================\n * Send a literal or distance tree in compressed form, using the codes in\n * bl_tree.\n */\nlocal void send_tree(s, tree, max_code)\n    deflate_state *s;\n    ct_data *tree; /* the tree to be scanned */\n    int max_code;       /* and its largest code of non zero frequency */\n{\n    int n;                     /* iterates over all tree elements */\n    int prevlen = -1;          /* last emitted length */\n    int curlen;                /* length of current code */\n    int nextlen = tree[0].Len; /* length of next code */\n    int count = 0;             /* repeat count of the current code */\n    int max_count = 7;         /* max repeat count */\n    int min_count = 4;         /* min repeat count */\n\n    /* tree[max_code + 1].Len = -1; */  /* guard already set */\n    if (nextlen == 0) max_count = 138, min_count = 3;\n\n    for (n = 0; n <= max_code; n++) {\n        curlen = nextlen; nextlen = tree[n + 1].Len;\n        if (++count < max_count && curlen == nextlen) {\n            continue;\n        } else if (count < min_count) {\n            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);\n\n        } else if (curlen != 0) {\n            if (curlen != prevlen) {\n                send_code(s, curlen, s->bl_tree); count--;\n            }\n            Assert(count >= 3 && count <= 6, \" 3_6?\");\n            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2);\n\n        } else if (count <= 10) {\n            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3);\n\n        } else {\n            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7);\n        }\n        count = 0; prevlen = curlen;\n        if (nextlen == 0) {\n            max_count = 138, min_count = 3;\n        } else if (curlen == nextlen) {\n            max_count = 6, min_count = 3;\n        } else {\n            max_count = 7, min_count = 4;\n        }\n    }\n}\n\n/* ===========================================================================\n * Construct the Huffman tree for the bit lengths and return the index in\n * bl_order of the last bit length code to send.\n */\nlocal int build_bl_tree(s)\n    deflate_state *s;\n{\n    int max_blindex;  /* index of last bit length code of non zero freq */\n\n    /* Determine the bit length frequencies for literal and distance trees */\n    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);\n    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);\n\n    /* Build the bit length tree: */\n    build_tree(s, (tree_desc *)(&(s->bl_desc)));\n    /* opt_len now includes the length of the tree representations, except the\n     * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts.\n     */\n\n    /* Determine the number of bit length codes to send. The pkzip format\n     * requires that at least 4 bit length codes be sent. (appnote.txt says\n     * 3 but the actual value used is 4.)\n     */\n    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {\n        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;\n    }\n    /* Update opt_len to include the bit length tree and counts */\n    s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4;\n    Tracev((stderr, \"\\ndyn trees: dyn %ld, stat %ld\",\n            s->opt_len, s->static_len));\n\n    return max_blindex;\n}\n\n/* ===========================================================================\n * Send the header for a block using dynamic Huffman trees: the counts, the\n * lengths of the bit length codes, the literal tree and the distance tree.\n * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.\n */\nlocal void send_all_trees(s, lcodes, dcodes, blcodes)\n    deflate_state *s;\n    int lcodes, dcodes, blcodes; /* number of codes for each tree */\n{\n    int rank;                    /* index in bl_order */\n\n    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, \"not enough codes\");\n    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,\n            \"too many codes\");\n    Tracev((stderr, \"\\nbl counts: \"));\n    send_bits(s, lcodes - 257, 5);  /* not +255 as stated in appnote.txt */\n    send_bits(s, dcodes - 1,   5);\n    send_bits(s, blcodes - 4,  4);  /* not -3 as stated in appnote.txt */\n    for (rank = 0; rank < blcodes; rank++) {\n        Tracev((stderr, \"\\nbl code %2d \", bl_order[rank]));\n        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);\n    }\n    Tracev((stderr, \"\\nbl tree: sent %ld\", s->bits_sent));\n\n    send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1);  /* literal tree */\n    Tracev((stderr, \"\\nlit tree: sent %ld\", s->bits_sent));\n\n    send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1);  /* distance tree */\n    Tracev((stderr, \"\\ndist tree: sent %ld\", s->bits_sent));\n}\n\n/* ===========================================================================\n * Send a stored block\n */\nvoid ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)\n    deflate_state *s;\n    charf *buf;       /* input block */\n    ulg stored_len;   /* length of input block */\n    int last;         /* one if this is the last block for a file */\n{\n    send_bits(s, (STORED_BLOCK<<1) + last, 3);  /* send block type */\n    bi_windup(s);        /* align on byte boundary */\n    put_short(s, (ush)stored_len);\n    put_short(s, (ush)~stored_len);\n    if (stored_len)\n        zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);\n    s->pending += stored_len;\n#ifdef ZLIB_DEBUG\n    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;\n    s->compressed_len += (stored_len + 4) << 3;\n    s->bits_sent += 2*16;\n    s->bits_sent += stored_len << 3;\n#endif\n}\n\n/* ===========================================================================\n * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)\n */\nvoid ZLIB_INTERNAL _tr_flush_bits(s)\n    deflate_state *s;\n{\n    bi_flush(s);\n}\n\n/* ===========================================================================\n * Send one empty static block to give enough lookahead for inflate.\n * This takes 10 bits, of which 7 may remain in the bit buffer.\n */\nvoid ZLIB_INTERNAL _tr_align(s)\n    deflate_state *s;\n{\n    send_bits(s, STATIC_TREES<<1, 3);\n    send_code(s, END_BLOCK, static_ltree);\n#ifdef ZLIB_DEBUG\n    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */\n#endif\n    bi_flush(s);\n}\n\n/* ===========================================================================\n * Determine the best encoding for the current block: dynamic trees, static\n * trees or store, and write out the encoded block.\n */\nvoid ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)\n    deflate_state *s;\n    charf *buf;       /* input block, or NULL if too old */\n    ulg stored_len;   /* length of input block */\n    int last;         /* one if this is the last block for a file */\n{\n    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */\n    int max_blindex = 0;  /* index of last bit length code of non zero freq */\n\n    /* Build the Huffman trees unless a stored block is forced */\n    if (s->level > 0) {\n\n        /* Check if the file is binary or text */\n        if (s->strm->data_type == Z_UNKNOWN)\n            s->strm->data_type = detect_data_type(s);\n\n        /* Construct the literal and distance trees */\n        build_tree(s, (tree_desc *)(&(s->l_desc)));\n        Tracev((stderr, \"\\nlit data: dyn %ld, stat %ld\", s->opt_len,\n                s->static_len));\n\n        build_tree(s, (tree_desc *)(&(s->d_desc)));\n        Tracev((stderr, \"\\ndist data: dyn %ld, stat %ld\", s->opt_len,\n                s->static_len));\n        /* At this point, opt_len and static_len are the total bit lengths of\n         * the compressed block data, excluding the tree representations.\n         */\n\n        /* Build the bit length tree for the above two trees, and get the index\n         * in bl_order of the last bit length code to send.\n         */\n        max_blindex = build_bl_tree(s);\n\n        /* Determine the best encoding. Compute the block lengths in bytes. */\n        opt_lenb = (s->opt_len + 3 + 7) >> 3;\n        static_lenb = (s->static_len + 3 + 7) >> 3;\n\n        Tracev((stderr, \"\\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u \",\n                opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,\n                s->sym_next / 3));\n\n#ifndef FORCE_STATIC\n        if (static_lenb <= opt_lenb || s->strategy == Z_FIXED)\n#endif\n            opt_lenb = static_lenb;\n\n    } else {\n        Assert(buf != (char*)0, \"lost buf\");\n        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */\n    }\n\n#ifdef FORCE_STORED\n    if (buf != (char*)0) { /* force stored block */\n#else\n    if (stored_len + 4 <= opt_lenb && buf != (char*)0) {\n                       /* 4: two words for the lengths */\n#endif\n        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.\n         * Otherwise we can't have processed more than WSIZE input bytes since\n         * the last block flush, because compression would have been\n         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to\n         * transform a block into a stored block.\n         */\n        _tr_stored_block(s, buf, stored_len, last);\n\n    } else if (static_lenb == opt_lenb) {\n        send_bits(s, (STATIC_TREES<<1) + last, 3);\n        compress_block(s, (const ct_data *)static_ltree,\n                       (const ct_data *)static_dtree);\n#ifdef ZLIB_DEBUG\n        s->compressed_len += 3 + s->static_len;\n#endif\n    } else {\n        send_bits(s, (DYN_TREES<<1) + last, 3);\n        send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1,\n                       max_blindex + 1);\n        compress_block(s, (const ct_data *)s->dyn_ltree,\n                       (const ct_data *)s->dyn_dtree);\n#ifdef ZLIB_DEBUG\n        s->compressed_len += 3 + s->opt_len;\n#endif\n    }\n    Assert (s->compressed_len == s->bits_sent, \"bad compressed size\");\n    /* The above check is made mod 2^32, for files larger than 512 MB\n     * and uLong implemented on 32 bits.\n     */\n    init_block(s);\n\n    if (last) {\n        bi_windup(s);\n#ifdef ZLIB_DEBUG\n        s->compressed_len += 7;  /* align on byte boundary */\n#endif\n    }\n    Tracev((stderr,\"\\ncomprlen %lu(%lu) \", s->compressed_len >> 3,\n           s->compressed_len - 7*last));\n}\n\n/* ===========================================================================\n * Save the match info and tally the frequency counts. Return true if\n * the current block must be flushed.\n */\nint ZLIB_INTERNAL _tr_tally(s, dist, lc)\n    deflate_state *s;\n    unsigned dist;  /* distance of matched string */\n    unsigned lc;    /* match length - MIN_MATCH or unmatched char (dist==0) */\n{\n    s->sym_buf[s->sym_next++] = (uch)dist;\n    s->sym_buf[s->sym_next++] = (uch)(dist >> 8);\n    s->sym_buf[s->sym_next++] = (uch)lc;\n    if (dist == 0) {\n        /* lc is the unmatched char */\n        s->dyn_ltree[lc].Freq++;\n    } else {\n        s->matches++;\n        /* Here, lc is the match length - MIN_MATCH */\n        dist--;             /* dist = match distance - 1 */\n        Assert((ush)dist < (ush)MAX_DIST(s) &&\n               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&\n               (ush)d_code(dist) < (ush)D_CODES,  \"_tr_tally: bad match\");\n\n        s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++;\n        s->dyn_dtree[d_code(dist)].Freq++;\n    }\n    return (s->sym_next == s->sym_end);\n}\n\n/* ===========================================================================\n * Send the block data compressed using the given Huffman trees\n */\nlocal void compress_block(s, ltree, dtree)\n    deflate_state *s;\n    const ct_data *ltree; /* literal tree */\n    const ct_data *dtree; /* distance tree */\n{\n    unsigned dist;      /* distance of matched string */\n    int lc;             /* match length or unmatched char (if dist == 0) */\n    unsigned sx = 0;    /* running index in sym_buf */\n    unsigned code;      /* the code to send */\n    int extra;          /* number of extra bits to send */\n\n    if (s->sym_next != 0) do {\n        dist = s->sym_buf[sx++] & 0xff;\n        dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;\n        lc = s->sym_buf[sx++];\n        if (dist == 0) {\n            send_code(s, lc, ltree); /* send a literal byte */\n            Tracecv(isgraph(lc), (stderr,\" '%c' \", lc));\n        } else {\n            /* Here, lc is the match length - MIN_MATCH */\n            code = _length_code[lc];\n            send_code(s, code + LITERALS + 1, ltree);   /* send length code */\n            extra = extra_lbits[code];\n            if (extra != 0) {\n                lc -= base_length[code];\n                send_bits(s, lc, extra);       /* send the extra length bits */\n            }\n            dist--; /* dist is now the match distance - 1 */\n            code = d_code(dist);\n            Assert (code < D_CODES, \"bad d_code\");\n\n            send_code(s, code, dtree);       /* send the distance code */\n            extra = extra_dbits[code];\n            if (extra != 0) {\n                dist -= (unsigned)base_dist[code];\n                send_bits(s, dist, extra);   /* send the extra distance bits */\n            }\n        } /* literal or match pair ? */\n\n        /* Check that the overlay between pending_buf and sym_buf is ok: */\n        Assert(s->pending < s->lit_bufsize + sx, \"pendingBuf overflow\");\n\n    } while (sx < s->sym_next);\n\n    send_code(s, END_BLOCK, ltree);\n}\n\n/* ===========================================================================\n * Check if the data type is TEXT or BINARY, using the following algorithm:\n * - TEXT if the two conditions below are satisfied:\n *    a) There are no non-portable control characters belonging to the\n *       \"block list\" (0..6, 14..25, 28..31).\n *    b) There is at least one printable character belonging to the\n *       \"allow list\" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).\n * - BINARY otherwise.\n * - The following partially-portable control characters form a\n *   \"gray list\" that is ignored in this detection algorithm:\n *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).\n * IN assertion: the fields Freq of dyn_ltree are set.\n */\nlocal int detect_data_type(s)\n    deflate_state *s;\n{\n    /* block_mask is the bit mask of block-listed bytes\n     * set bits 0..6, 14..25, and 28..31\n     * 0xf3ffc07f = binary 11110011111111111100000001111111\n     */\n    unsigned long block_mask = 0xf3ffc07fUL;\n    int n;\n\n    /* Check for non-textual (\"block-listed\") bytes. */\n    for (n = 0; n <= 31; n++, block_mask >>= 1)\n        if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0))\n            return Z_BINARY;\n\n    /* Check for textual (\"allow-listed\") bytes. */\n    if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0\n            || s->dyn_ltree[13].Freq != 0)\n        return Z_TEXT;\n    for (n = 32; n < LITERALS; n++)\n        if (s->dyn_ltree[n].Freq != 0)\n            return Z_TEXT;\n\n    /* There are no \"block-listed\" or \"allow-listed\" bytes:\n     * this stream either is empty or has tolerated (\"gray-listed\") bytes only.\n     */\n    return Z_BINARY;\n}\n\n/* ===========================================================================\n * Reverse the first len bits of a code, using straightforward code (a faster\n * method would use a table)\n * IN assertion: 1 <= len <= 15\n */\nlocal unsigned bi_reverse(code, len)\n    unsigned code; /* the value to invert */\n    int len;       /* its bit length */\n{\n    register unsigned res = 0;\n    do {\n        res |= code & 1;\n        code >>= 1, res <<= 1;\n    } while (--len > 0);\n    return res >> 1;\n}\n\n/* ===========================================================================\n * Flush the bit buffer, keeping at most 7 bits in it.\n */\nlocal void bi_flush(s)\n    deflate_state *s;\n{\n    if (s->bi_valid == 16) {\n        put_short(s, s->bi_buf);\n        s->bi_buf = 0;\n        s->bi_valid = 0;\n    } else if (s->bi_valid >= 8) {\n        put_byte(s, (Byte)s->bi_buf);\n        s->bi_buf >>= 8;\n        s->bi_valid -= 8;\n    }\n}\n\n/* ===========================================================================\n * Flush the bit buffer and align the output on a byte boundary\n */\nlocal void bi_windup(s)\n    deflate_state *s;\n{\n    if (s->bi_valid > 8) {\n        put_short(s, s->bi_buf);\n    } else if (s->bi_valid > 0) {\n        put_byte(s, (Byte)s->bi_buf);\n    }\n    s->bi_buf = 0;\n    s->bi_valid = 0;\n#ifdef ZLIB_DEBUG\n    s->bits_sent = (s->bits_sent + 7) & ~7;\n#endif\n}\n"
  },
  {
    "path": "third_party/libz/trees.h",
    "content": "// clang-format off\n/* header created automatically with -DGEN_TREES_H */\n\nlocal const ct_data static_ltree[L_CODES+2] = {\n{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},\n{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},\n{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},\n{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},\n{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},\n{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},\n{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},\n{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},\n{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},\n{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},\n{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},\n{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},\n{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},\n{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},\n{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},\n{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},\n{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},\n{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},\n{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},\n{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},\n{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},\n{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},\n{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},\n{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},\n{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},\n{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},\n{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},\n{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},\n{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},\n{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},\n{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},\n{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},\n{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},\n{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},\n{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},\n{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},\n{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},\n{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},\n{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},\n{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},\n{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},\n{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},\n{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},\n{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},\n{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},\n{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},\n{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},\n{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},\n{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},\n{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},\n{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},\n{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},\n{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},\n{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},\n{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},\n{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},\n{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},\n{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}\n};\n\nlocal const ct_data static_dtree[D_CODES] = {\n{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},\n{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},\n{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},\n{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},\n{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},\n{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}\n};\n\nconst uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,\n 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,\n10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\n12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,\n13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,\n13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,\n15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,\n18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,\n23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\n26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,\n27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\n27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\n29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\n29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\n29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29\n};\n\nconst uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,\n13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,\n17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,\n19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,\n22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,\n23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\n25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,\n26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\n27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28\n};\n\nlocal const int base_length[LENGTH_CODES] = {\n0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,\n64, 80, 96, 112, 128, 160, 192, 224, 0\n};\n\nlocal const int base_dist[D_CODES] = {\n    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,\n   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,\n 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576\n};\n\n"
  },
  {
    "path": "third_party/libz/uncompr.c",
    "content": "// clang-format off\n/* uncompr.c -- decompress a memory buffer\n * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* @(#) $Id$ */\n\n#define ZLIB_INTERNAL\n#include \"third_party/libz/zlib.h\"\n\n/* ===========================================================================\n     Decompresses the source buffer into the destination buffer.  *sourceLen is\n   the byte length of the source buffer. Upon entry, *destLen is the total size\n   of the destination buffer, which must be large enough to hold the entire\n   uncompressed data. (The size of the uncompressed data must have been saved\n   previously by the compressor and transmitted to the decompressor by some\n   mechanism outside the scope of this compression library.) Upon exit,\n   *destLen is the size of the decompressed data and *sourceLen is the number\n   of source bytes consumed. Upon return, source + *sourceLen points to the\n   first unused input byte.\n\n     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_BUF_ERROR if there was not enough room in the output buffer, or\n   Z_DATA_ERROR if the input data was corrupted, including if the input data is\n   an incomplete zlib stream.\n*/\nint ZEXPORT uncompress2(dest, destLen, source, sourceLen)\n    Bytef *dest;\n    uLongf *destLen;\n    const Bytef *source;\n    uLong *sourceLen;\n{\n    z_stream stream;\n    int err;\n    const uInt max = (uInt)-1;\n    uLong len, left;\n    Byte buf[1];    /* for detection of incomplete stream when *destLen == 0 */\n\n    len = *sourceLen;\n    if (*destLen) {\n        left = *destLen;\n        *destLen = 0;\n    }\n    else {\n        left = 1;\n        dest = buf;\n    }\n\n    stream.next_in = (z_const Bytef *)source;\n    stream.avail_in = 0;\n    stream.zalloc = (alloc_func)0;\n    stream.zfree = (free_func)0;\n    stream.opaque = (voidpf)0;\n\n    err = inflateInit(&stream);\n    if (err != Z_OK) return err;\n\n    stream.next_out = dest;\n    stream.avail_out = 0;\n\n    do {\n        if (stream.avail_out == 0) {\n            stream.avail_out = left > (uLong)max ? max : (uInt)left;\n            left -= stream.avail_out;\n        }\n        if (stream.avail_in == 0) {\n            stream.avail_in = len > (uLong)max ? max : (uInt)len;\n            len -= stream.avail_in;\n        }\n        err = inflate(&stream, Z_NO_FLUSH);\n    } while (err == Z_OK);\n\n    *sourceLen -= len + stream.avail_in;\n    if (dest != buf)\n        *destLen = stream.total_out;\n    else if (stream.total_out && err == Z_BUF_ERROR)\n        left = 1;\n\n    inflateEnd(&stream);\n    return err == Z_STREAM_END ? Z_OK :\n           err == Z_NEED_DICT ? Z_DATA_ERROR  :\n           err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :\n           err;\n}\n\nint ZEXPORT uncompress(dest, destLen, source, sourceLen)\n    Bytef *dest;\n    uLongf *destLen;\n    const Bytef *source;\n    uLong sourceLen;\n{\n    return uncompress2(dest, destLen, source, &sourceLen);\n}\n"
  },
  {
    "path": "third_party/libz/zconf.h",
    "content": "// clang-format off\n/* zconf.h -- configuration of the zlib compression library\n * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* @(#) $Id$ */\n\n#ifndef ZCONF_H\n#define ZCONF_H\n\n/*\n * If you *really* need a unique prefix for all types and library functions,\n * compile with -DZ_PREFIX. The \"standard\" zlib should be compiled without it.\n * Even better than compiling with -DZ_PREFIX would be to use configure to set\n * this permanently in zconf.h using \"./configure --zprefix\".\n */\n#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */\n#  define Z_PREFIX_SET\n\n/* all linked symbols and init macros */\n#  define _dist_code            z__dist_code\n#  define _length_code          z__length_code\n#  define _tr_align             z__tr_align\n#  define _tr_flush_bits        z__tr_flush_bits\n#  define _tr_flush_block       z__tr_flush_block\n#  define _tr_init              z__tr_init\n#  define _tr_stored_block      z__tr_stored_block\n#  define _tr_tally             z__tr_tally\n#  define adler32               z_adler32\n#  define adler32_combine       z_adler32_combine\n#  define adler32_combine64     z_adler32_combine64\n#  define adler32_z             z_adler32_z\n#  ifndef Z_SOLO\n#    define compress              z_compress\n#    define compress2             z_compress2\n#    define compressBound         z_compressBound\n#  endif\n#  define crc32                 z_crc32\n#  define crc32_combine         z_crc32_combine\n#  define crc32_combine64       z_crc32_combine64\n#  define crc32_combine_gen     z_crc32_combine_gen\n#  define crc32_combine_gen64   z_crc32_combine_gen64\n#  define crc32_combine_op      z_crc32_combine_op\n#  define crc32_z               z_crc32_z\n#  define deflate               z_deflate\n#  define deflateBound          z_deflateBound\n#  define deflateCopy           z_deflateCopy\n#  define deflateEnd            z_deflateEnd\n#  define deflateGetDictionary  z_deflateGetDictionary\n#  define deflateInit           z_deflateInit\n#  define deflateInit2          z_deflateInit2\n#  define deflateInit2_         z_deflateInit2_\n#  define deflateInit_          z_deflateInit_\n#  define deflateParams         z_deflateParams\n#  define deflatePending        z_deflatePending\n#  define deflatePrime          z_deflatePrime\n#  define deflateReset          z_deflateReset\n#  define deflateResetKeep      z_deflateResetKeep\n#  define deflateSetDictionary  z_deflateSetDictionary\n#  define deflateSetHeader      z_deflateSetHeader\n#  define deflateTune           z_deflateTune\n#  define deflate_copyright     z_deflate_copyright\n#  define get_crc_table         z_get_crc_table\n#  ifndef Z_SOLO\n#    define gz_error              z_gz_error\n#    define gz_intmax             z_gz_intmax\n#    define gz_strwinerror        z_gz_strwinerror\n#    define gzbuffer              z_gzbuffer\n#    define gzclearerr            z_gzclearerr\n#    define gzclose               z_gzclose\n#    define gzclose_r             z_gzclose_r\n#    define gzclose_w             z_gzclose_w\n#    define gzdirect              z_gzdirect\n#    define gzdopen               z_gzdopen\n#    define gzeof                 z_gzeof\n#    define gzerror               z_gzerror\n#    define gzflush               z_gzflush\n#    define gzfread               z_gzfread\n#    define gzfwrite              z_gzfwrite\n#    define gzgetc                z_gzgetc\n#    define gzgetc_               z_gzgetc_\n#    define gzgets                z_gzgets\n#    define gzoffset              z_gzoffset\n#    define gzoffset64            z_gzoffset64\n#    define gzopen                z_gzopen\n#    define gzopen64              z_gzopen64\n#    ifdef _WIN32\n#      define gzopen_w              z_gzopen_w\n#    endif\n#    define gzprintf              z_gzprintf\n#    define gzputc                z_gzputc\n#    define gzputs                z_gzputs\n#    define gzread                z_gzread\n#    define gzrewind              z_gzrewind\n#    define gzseek                z_gzseek\n#    define gzseek64              z_gzseek64\n#    define gzsetparams           z_gzsetparams\n#    define gztell                z_gztell\n#    define gztell64              z_gztell64\n#    define gzungetc              z_gzungetc\n#    define gzvprintf             z_gzvprintf\n#    define gzwrite               z_gzwrite\n#  endif\n#  define inflate               z_inflate\n#  define inflateBack           z_inflateBack\n#  define inflateBackEnd        z_inflateBackEnd\n#  define inflateBackInit       z_inflateBackInit\n#  define inflateBackInit_      z_inflateBackInit_\n#  define inflateCodesUsed      z_inflateCodesUsed\n#  define inflateCopy           z_inflateCopy\n#  define inflateEnd            z_inflateEnd\n#  define inflateGetDictionary  z_inflateGetDictionary\n#  define inflateGetHeader      z_inflateGetHeader\n#  define inflateInit           z_inflateInit\n#  define inflateInit2          z_inflateInit2\n#  define inflateInit2_         z_inflateInit2_\n#  define inflateInit_          z_inflateInit_\n#  define inflateMark           z_inflateMark\n#  define inflatePrime          z_inflatePrime\n#  define inflateReset          z_inflateReset\n#  define inflateReset2         z_inflateReset2\n#  define inflateResetKeep      z_inflateResetKeep\n#  define inflateSetDictionary  z_inflateSetDictionary\n#  define inflateSync           z_inflateSync\n#  define inflateSyncPoint      z_inflateSyncPoint\n#  define inflateUndermine      z_inflateUndermine\n#  define inflateValidate       z_inflateValidate\n#  define inflate_copyright     z_inflate_copyright\n#  define inflate_fast          z_inflate_fast\n#  define inflate_table         z_inflate_table\n#  ifndef Z_SOLO\n#    define uncompress            z_uncompress\n#    define uncompress2           z_uncompress2\n#  endif\n#  define zError                z_zError\n#  ifndef Z_SOLO\n#    define zcalloc               z_zcalloc\n#    define zcfree                z_zcfree\n#  endif\n#  define zlibCompileFlags      z_zlibCompileFlags\n#  define zlibVersion           z_zlibVersion\n\n/* all zlib typedefs in zlib.h and zconf.h */\n#  define Byte                  z_Byte\n#  define Bytef                 z_Bytef\n#  define alloc_func            z_alloc_func\n#  define charf                 z_charf\n#  define free_func             z_free_func\n#  ifndef Z_SOLO\n#    define gzFile                z_gzFile\n#  endif\n#  define gz_header             z_gz_header\n#  define gz_headerp            z_gz_headerp\n#  define in_func               z_in_func\n#  define intf                  z_intf\n#  define out_func              z_out_func\n#  define uInt                  z_uInt\n#  define uIntf                 z_uIntf\n#  define uLong                 z_uLong\n#  define uLongf                z_uLongf\n#  define voidp                 z_voidp\n#  define voidpc                z_voidpc\n#  define voidpf                z_voidpf\n\n/* all zlib structs in zlib.h and zconf.h */\n#  define gz_header_s           z_gz_header_s\n#  define internal_state        z_internal_state\n\n#endif\n\n#if defined(__MSDOS__) && !defined(MSDOS)\n#  define MSDOS\n#endif\n#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)\n#  define OS2\n#endif\n#if defined(_WINDOWS) && !defined(WINDOWS)\n#  define WINDOWS\n#endif\n#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)\n#  ifndef WIN32\n#    define WIN32\n#  endif\n#endif\n#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)\n#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)\n#    ifndef SYS16BIT\n#      define SYS16BIT\n#    endif\n#  endif\n#endif\n\n/*\n * Compile with -DMAXSEG_64K if the alloc function cannot allocate more\n * than 64k bytes at a time (needed on systems with 16-bit int).\n */\n#ifdef SYS16BIT\n#  define MAXSEG_64K\n#endif\n#ifdef MSDOS\n#  define UNALIGNED_OK\n#endif\n\n#ifdef __STDC_VERSION__\n#  ifndef STDC\n#    define STDC\n#  endif\n#  if __STDC_VERSION__ >= 199901L\n#    ifndef STDC99\n#      define STDC99\n#    endif\n#  endif\n#endif\n#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))\n#  define STDC\n#endif\n#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))\n#  define STDC\n#endif\n#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))\n#  define STDC\n#endif\n#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))\n#  define STDC\n#endif\n\n#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */\n#  define STDC\n#endif\n\n#ifndef STDC\n#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */\n#    define const       /* note: need a more gentle solution here */\n#  endif\n#endif\n\n#if defined(ZLIB_CONST) && !defined(z_const)\n#  define z_const const\n#else\n#  define z_const\n#endif\n\n#ifdef Z_SOLO\n   typedef unsigned long z_size_t;\n#else\n#  define z_longlong long long\n#  if defined(NO_SIZE_T)\n     typedef unsigned NO_SIZE_T z_size_t;\n#  elif defined(STDC)\n#    include <stddef.h>\n     typedef size_t z_size_t;\n#  else\n     typedef unsigned long z_size_t;\n#  endif\n#  undef z_longlong\n#endif\n\n/* Maximum value for memLevel in deflateInit2 */\n#ifndef MAX_MEM_LEVEL\n#  ifdef MAXSEG_64K\n#    define MAX_MEM_LEVEL 8\n#  else\n#    define MAX_MEM_LEVEL 9\n#  endif\n#endif\n\n/* Maximum value for windowBits in deflateInit2 and inflateInit2.\n * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files\n * created by gzip. (Files created by minigzip can still be extracted by\n * gzip.)\n */\n#ifndef MAX_WBITS\n#  define MAX_WBITS   15 /* 32K LZ77 window */\n#endif\n\n/* The memory requirements for deflate are (in bytes):\n            (1 << (windowBits+2)) +  (1 << (memLevel+9))\n that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)\n plus a few kilobytes for small objects. For example, if you want to reduce\n the default memory requirements from 256K to 128K, compile with\n     make CFLAGS=\"-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7\"\n Of course this will generally degrade compression (there's no free lunch).\n\n   The memory requirements for inflate are (in bytes) 1 << windowBits\n that is, 32K for windowBits=15 (default value) plus about 7 kilobytes\n for small objects.\n*/\n\n                        /* Type declarations */\n\n#ifndef OF /* function prototypes */\n#  ifdef STDC\n#    define OF(args)  args\n#  else\n#    define OF(args)  ()\n#  endif\n#endif\n\n#ifndef Z_ARG /* function prototypes for stdarg */\n#  if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#    define Z_ARG(args)  args\n#  else\n#    define Z_ARG(args)  ()\n#  endif\n#endif\n\n/* The following definitions for FAR are needed only for MSDOS mixed\n * model programming (small or medium model with some far allocations).\n * This was tested only with MSC; for other MSDOS compilers you may have\n * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,\n * just define FAR to be empty.\n */\n#ifdef SYS16BIT\n#  if defined(M_I86SM) || defined(M_I86MM)\n     /* MSC small or medium model */\n#    define SMALL_MEDIUM\n#    ifdef _MSC_VER\n#      define FAR _far\n#    else\n#      define FAR far\n#    endif\n#  endif\n#  if (defined(__SMALL__) || defined(__MEDIUM__))\n     /* Turbo C small or medium model */\n#    define SMALL_MEDIUM\n#    ifdef __BORLANDC__\n#      define FAR _far\n#    else\n#      define FAR far\n#    endif\n#  endif\n#endif\n\n#if defined(WINDOWS) || defined(WIN32)\n   /* If building or using zlib as a DLL, define ZLIB_DLL.\n    * This is not mandatory, but it offers a little performance increase.\n    */\n#  ifdef ZLIB_DLL\n#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))\n#      ifdef ZLIB_INTERNAL\n#        define ZEXTERN extern __declspec(dllexport)\n#      else\n#        define ZEXTERN extern __declspec(dllimport)\n#      endif\n#    endif\n#  endif  /* ZLIB_DLL */\n   /* If building or using zlib with the WINAPI/WINAPIV calling convention,\n    * define ZLIB_WINAPI.\n    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.\n    */\n#  ifdef ZLIB_WINAPI\n#    ifdef FAR\n#      undef FAR\n#    endif\n#    ifndef WIN32_LEAN_AND_MEAN\n#      define WIN32_LEAN_AND_MEAN\n#    endif\n#    include <windows.h>\n     /* No need for _export, use ZLIB.DEF instead. */\n     /* For complete Windows compatibility, use WINAPI, not __stdcall. */\n#    define ZEXPORT WINAPI\n#    ifdef WIN32\n#      define ZEXPORTVA WINAPIV\n#    else\n#      define ZEXPORTVA FAR CDECL\n#    endif\n#  endif\n#endif\n\n#if defined (__BEOS__)\n#  ifdef ZLIB_DLL\n#    ifdef ZLIB_INTERNAL\n#      define ZEXPORT   __declspec(dllexport)\n#      define ZEXPORTVA __declspec(dllexport)\n#    else\n#      define ZEXPORT   __declspec(dllimport)\n#      define ZEXPORTVA __declspec(dllimport)\n#    endif\n#  endif\n#endif\n\n#ifndef ZEXTERN\n#  define ZEXTERN extern\n#endif\n#ifndef ZEXPORT\n#  define ZEXPORT\n#endif\n#ifndef ZEXPORTVA\n#  define ZEXPORTVA\n#endif\n\n#ifndef FAR\n#  define FAR\n#endif\n\n#if !defined(__MACTYPES__)\ntypedef unsigned char  Byte;  /* 8 bits */\n#endif\ntypedef unsigned int   uInt;  /* 16 bits or more */\ntypedef unsigned long  uLong; /* 32 bits or more */\n\n#ifdef SMALL_MEDIUM\n   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */\n#  define Bytef Byte FAR\n#else\n   typedef Byte  FAR Bytef;\n#endif\ntypedef char  FAR charf;\ntypedef int   FAR intf;\ntypedef uInt  FAR uIntf;\ntypedef uLong FAR uLongf;\n\n#ifdef STDC\n   typedef void const *voidpc;\n   typedef void FAR   *voidpf;\n   typedef void       *voidp;\n#else\n   typedef Byte const *voidpc;\n   typedef Byte FAR   *voidpf;\n   typedef Byte       *voidp;\n#endif\n\n#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)\n#  include <limits.h>\n#  if (UINT_MAX == 0xffffffffUL)\n#    define Z_U4 unsigned\n#  elif (ULONG_MAX == 0xffffffffUL)\n#    define Z_U4 unsigned long\n#  elif (USHRT_MAX == 0xffffffffUL)\n#    define Z_U4 unsigned short\n#  endif\n#endif\n\n#ifdef Z_U4\n   typedef Z_U4 z_crc_t;\n#else\n   typedef unsigned long z_crc_t;\n#endif\n\n#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */\n#  define Z_HAVE_UNISTD_H\n#endif\n\n#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */\n#  define Z_HAVE_STDARG_H\n#endif\n\n#ifdef STDC\n#  ifndef Z_SOLO\n#    include <sys/types.h>      /* for off_t */\n#  endif\n#endif\n\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#  ifndef Z_SOLO\n#    include <stdarg.h>         /* for va_list */\n#  endif\n#endif\n\n#ifdef _WIN32\n#  ifndef Z_SOLO\n#    include <stddef.h>         /* for wchar_t */\n#  endif\n#endif\n\n/* a little trick to accommodate both \"#define _LARGEFILE64_SOURCE\" and\n * \"#define _LARGEFILE64_SOURCE 1\" as requesting 64-bit operations, (even\n * though the former does not conform to the LFS document), but considering\n * both \"#undef _LARGEFILE64_SOURCE\" and \"#define _LARGEFILE64_SOURCE 0\" as\n * equivalently requesting no 64-bit operations\n */\n#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1\n#  undef _LARGEFILE64_SOURCE\n#endif\n\n#ifndef Z_HAVE_UNISTD_H\n#  ifdef __WATCOMC__\n#    define Z_HAVE_UNISTD_H\n#  endif\n#endif\n#ifndef Z_HAVE_UNISTD_H\n#  if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)\n#    define Z_HAVE_UNISTD_H\n#  endif\n#endif\n#ifndef Z_SOLO\n#  if defined(Z_HAVE_UNISTD_H)\n#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */\n#    ifdef VMS\n#      include <unixio.h>       /* for off_t */\n#    endif\n#    ifndef z_off_t\n#      define z_off_t off_t\n#    endif\n#  endif\n#endif\n\n#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0\n#  define Z_LFS64\n#endif\n\n#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)\n#  define Z_LARGE64\n#endif\n\n#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)\n#  define Z_WANT64\n#endif\n\n#if !defined(SEEK_SET) && !defined(Z_SOLO)\n#  define SEEK_SET        0       /* Seek from beginning of file.  */\n#  define SEEK_CUR        1       /* Seek from current position.  */\n#  define SEEK_END        2       /* Set file pointer to EOF plus \"offset\" */\n#endif\n\n#ifndef z_off_t\n#  define z_off_t long\n#endif\n\n#if !defined(_WIN32) && defined(Z_LARGE64)\n#  define z_off64_t off64_t\n#else\n#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)\n#    define z_off64_t __int64\n#  else\n#    define z_off64_t z_off_t\n#  endif\n#endif\n\n/* MVS linker does not support external names larger than 8 bytes */\n#if defined(__MVS__)\n  #pragma map(deflateInit_,\"DEIN\")\n  #pragma map(deflateInit2_,\"DEIN2\")\n  #pragma map(deflateEnd,\"DEEND\")\n  #pragma map(deflateBound,\"DEBND\")\n  #pragma map(inflateInit_,\"ININ\")\n  #pragma map(inflateInit2_,\"ININ2\")\n  #pragma map(inflateEnd,\"INEND\")\n  #pragma map(inflateSync,\"INSY\")\n  #pragma map(inflateSetDictionary,\"INSEDI\")\n  #pragma map(compressBound,\"CMBND\")\n  #pragma map(inflate_table,\"INTABL\")\n  #pragma map(inflate_fast,\"INFA\")\n  #pragma map(inflate_copyright,\"INCOPY\")\n#endif\n\n#endif /* ZCONF_H */\n"
  },
  {
    "path": "third_party/libz/zlib.h",
    "content": "// clang-format off\n/* zlib.h -- interface of the 'zlib' general purpose compression library\n  version 1.2.13, October 13th, 2022\n\n  Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n\n  Jean-loup Gailly        Mark Adler\n  jloup@gzip.org          madler@alumni.caltech.edu\n\n\n  The data format used by the zlib library is described by RFCs (Request for\n  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950\n  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).\n*/\n\n#ifndef ZLIB_H\n#define ZLIB_H\n\n#include \"third_party/libz/zconf.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ZLIB_VERSION \"1.2.13\"\n#define ZLIB_VERNUM 0x12d0\n#define ZLIB_VER_MAJOR 1\n#define ZLIB_VER_MINOR 2\n#define ZLIB_VER_REVISION 13\n#define ZLIB_VER_SUBREVISION 0\n\n/*\n    The 'zlib' compression library provides in-memory compression and\n  decompression functions, including integrity checks of the uncompressed data.\n  This version of the library supports only one compression method (deflation)\n  but other algorithms will be added later and will have the same stream\n  interface.\n\n    Compression can be done in a single step if the buffers are large enough,\n  or can be done by repeated calls of the compression function.  In the latter\n  case, the application must provide more input and/or consume the output\n  (providing more output space) before each call.\n\n    The compressed data format used by default by the in-memory functions is\n  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped\n  around a deflate stream, which is itself documented in RFC 1951.\n\n    The library also supports reading and writing files in gzip (.gz) format\n  with an interface similar to that of stdio using the functions that start\n  with \"gz\".  The gzip format is different from the zlib format.  gzip is a\n  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.\n\n    This library can optionally read and write gzip and raw deflate streams in\n  memory as well.\n\n    The zlib format was designed to be compact and fast for use in memory\n  and on communications channels.  The gzip format was designed for single-\n  file compression on file systems, has a larger header than zlib to maintain\n  directory information, and uses a different, slower check method than zlib.\n\n    The library does not install any signal handler.  The decoder checks\n  the consistency of the compressed data, so the library should never crash\n  even in the case of corrupted input.\n*/\n\ntypedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));\ntypedef void   (*free_func)  OF((voidpf opaque, voidpf address));\n\nstruct internal_state;\n\ntypedef struct z_stream_s {\n    z_const Bytef *next_in;     /* next input byte */\n    uInt     avail_in;  /* number of bytes available at next_in */\n    uLong    total_in;  /* total number of input bytes read so far */\n\n    Bytef    *next_out; /* next output byte will go here */\n    uInt     avail_out; /* remaining free space at next_out */\n    uLong    total_out; /* total number of bytes output so far */\n\n    z_const char *msg;  /* last error message, NULL if no error */\n    struct internal_state FAR *state; /* not visible by applications */\n\n    alloc_func zalloc;  /* used to allocate the internal state */\n    free_func  zfree;   /* used to free the internal state */\n    voidpf     opaque;  /* private data object passed to zalloc and zfree */\n\n    int     data_type;  /* best guess about the data type: binary or text\n                           for deflate, or the decoding state for inflate */\n    uLong   adler;      /* Adler-32 or CRC-32 value of the uncompressed data */\n    uLong   reserved;   /* reserved for future use */\n} z_stream;\n\ntypedef z_stream FAR *z_streamp;\n\n/*\n     gzip header information passed to and from zlib routines.  See RFC 1952\n  for more details on the meanings of these fields.\n*/\ntypedef struct gz_header_s {\n    int     text;       /* true if compressed data believed to be text */\n    uLong   time;       /* modification time */\n    int     xflags;     /* extra flags (not used when writing a gzip file) */\n    int     os;         /* operating system */\n    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */\n    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */\n    uInt    extra_max;  /* space at extra (only when reading header) */\n    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */\n    uInt    name_max;   /* space at name (only when reading header) */\n    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */\n    uInt    comm_max;   /* space at comment (only when reading header) */\n    int     hcrc;       /* true if there was or will be a header crc */\n    int     done;       /* true when done reading gzip header (not used\n                           when writing a gzip file) */\n} gz_header;\n\ntypedef gz_header FAR *gz_headerp;\n\n/*\n     The application must update next_in and avail_in when avail_in has dropped\n   to zero.  It must update next_out and avail_out when avail_out has dropped\n   to zero.  The application must initialize zalloc, zfree and opaque before\n   calling the init function.  All other fields are set by the compression\n   library and must not be updated by the application.\n\n     The opaque value provided by the application will be passed as the first\n   parameter for calls of zalloc and zfree.  This can be useful for custom\n   memory management.  The compression library attaches no meaning to the\n   opaque value.\n\n     zalloc must return Z_NULL if there is not enough memory for the object.\n   If zlib is used in a multi-threaded application, zalloc and zfree must be\n   thread safe.  In that case, zlib is thread-safe.  When zalloc and zfree are\n   Z_NULL on entry to the initialization function, they are set to internal\n   routines that use the standard library functions malloc() and free().\n\n     On 16-bit systems, the functions zalloc and zfree must be able to allocate\n   exactly 65536 bytes, but will not be required to allocate more than this if\n   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers\n   returned by zalloc for objects of exactly 65536 bytes *must* have their\n   offset normalized to zero.  The default allocation function provided by this\n   library ensures this (see zutil.c).  To reduce memory requirements and avoid\n   any allocation of 64K objects, at the expense of compression ratio, compile\n   the library with -DMAX_WBITS=14 (see zconf.h).\n\n     The fields total_in and total_out can be used for statistics or progress\n   reports.  After compression, total_in holds the total size of the\n   uncompressed data and may be saved for use by the decompressor (particularly\n   if the decompressor wants to decompress everything in a single step).\n*/\n\n                        /* constants */\n\n#define Z_NO_FLUSH      0\n#define Z_PARTIAL_FLUSH 1\n#define Z_SYNC_FLUSH    2\n#define Z_FULL_FLUSH    3\n#define Z_FINISH        4\n#define Z_BLOCK         5\n#define Z_TREES         6\n/* Allowed flush values; see deflate() and inflate() below for details */\n\n#define Z_OK            0\n#define Z_STREAM_END    1\n#define Z_NEED_DICT     2\n#define Z_ERRNO        (-1)\n#define Z_STREAM_ERROR (-2)\n#define Z_DATA_ERROR   (-3)\n#define Z_MEM_ERROR    (-4)\n#define Z_BUF_ERROR    (-5)\n#define Z_VERSION_ERROR (-6)\n/* Return codes for the compression/decompression functions. Negative values\n * are errors, positive values are used for special but normal events.\n */\n\n#define Z_NO_COMPRESSION         0\n#define Z_BEST_SPEED             1\n#define Z_BEST_COMPRESSION       9\n#define Z_DEFAULT_COMPRESSION  (-1)\n/* compression levels */\n\n#define Z_FILTERED            1\n#define Z_HUFFMAN_ONLY        2\n#define Z_RLE                 3\n#define Z_FIXED               4\n#define Z_DEFAULT_STRATEGY    0\n/* compression strategy; see deflateInit2() below for details */\n\n#define Z_BINARY   0\n#define Z_TEXT     1\n#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */\n#define Z_UNKNOWN  2\n/* Possible values of the data_type field for deflate() */\n\n#define Z_DEFLATED   8\n/* The deflate compression method (the only one supported in this version) */\n\n#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */\n\n#define zlib_version zlibVersion()\n/* for compatibility with versions < 1.0.2 */\n\n\n                        /* basic functions */\n\nZEXTERN const char * ZEXPORT zlibVersion OF((void));\n/* The application can compare zlibVersion and ZLIB_VERSION for consistency.\n   If the first character differs, the library code actually used is not\n   compatible with the zlib.h header file used by the application.  This check\n   is automatically made by deflateInit and inflateInit.\n */\n\n/*\nZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));\n\n     Initializes the internal stream state for compression.  The fields\n   zalloc, zfree and opaque must be initialized before by the caller.  If\n   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default\n   allocation functions.\n\n     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:\n   1 gives best speed, 9 gives best compression, 0 gives no compression at all\n   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION\n   requests a default compromise between speed and compression (currently\n   equivalent to level 6).\n\n     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_STREAM_ERROR if level is not a valid compression level, or\n   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible\n   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null\n   if there is no error message.  deflateInit does not perform any compression:\n   this will be done by deflate().\n*/\n\n\nZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));\n/*\n    deflate compresses as much data as possible, and stops when the input\n  buffer becomes empty or the output buffer becomes full.  It may introduce\n  some output latency (reading input without producing any output) except when\n  forced to flush.\n\n    The detailed semantics are as follows.  deflate performs one or both of the\n  following actions:\n\n  - Compress more input starting at next_in and update next_in and avail_in\n    accordingly.  If not all input can be processed (because there is not\n    enough room in the output buffer), next_in and avail_in are updated and\n    processing will resume at this point for the next call of deflate().\n\n  - Generate more output starting at next_out and update next_out and avail_out\n    accordingly.  This action is forced if the parameter flush is non zero.\n    Forcing flush frequently degrades the compression ratio, so this parameter\n    should be set only when necessary.  Some output may be provided even if\n    flush is zero.\n\n    Before the call of deflate(), the application should ensure that at least\n  one of the actions is possible, by providing more input and/or consuming more\n  output, and updating avail_in or avail_out accordingly; avail_out should\n  never be zero before the call.  The application can consume the compressed\n  output when it wants, for example when the output buffer is full (avail_out\n  == 0), or after each call of deflate().  If deflate returns Z_OK and with\n  zero avail_out, it must be called again after making room in the output\n  buffer because there might be more output pending. See deflatePending(),\n  which can be used if desired to determine whether or not there is more output\n  in that case.\n\n    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to\n  decide how much data to accumulate before producing output, in order to\n  maximize compression.\n\n    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is\n  flushed to the output buffer and the output is aligned on a byte boundary, so\n  that the decompressor can get all input data available so far.  (In\n  particular avail_in is zero after the call if enough output space has been\n  provided before the call.) Flushing may degrade compression for some\n  compression algorithms and so it should be used only when necessary.  This\n  completes the current deflate block and follows it with an empty stored block\n  that is three bits plus filler bits to the next byte, followed by four bytes\n  (00 00 ff ff).\n\n    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the\n  output buffer, but the output is not aligned to a byte boundary.  All of the\n  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.\n  This completes the current deflate block and follows it with an empty fixed\n  codes block that is 10 bits long.  This assures that enough bytes are output\n  in order for the decompressor to finish the block before the empty fixed\n  codes block.\n\n    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as\n  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to\n  seven bits of the current block are held to be written as the next byte after\n  the next deflate block is completed.  In this case, the decompressor may not\n  be provided enough bits at this point in order to complete decompression of\n  the data provided so far to the compressor.  It may need to wait for the next\n  block to be emitted.  This is for advanced applications that need to control\n  the emission of deflate blocks.\n\n    If flush is set to Z_FULL_FLUSH, all output is flushed as with\n  Z_SYNC_FLUSH, and the compression state is reset so that decompression can\n  restart from this point if previous compressed data has been damaged or if\n  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade\n  compression.\n\n    If deflate returns with avail_out == 0, this function must be called again\n  with the same value of the flush parameter and more output space (updated\n  avail_out), until the flush is complete (deflate returns with non-zero\n  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that\n  avail_out is greater than six to avoid repeated flush markers due to\n  avail_out == 0 on return.\n\n    If the parameter flush is set to Z_FINISH, pending input is processed,\n  pending output is flushed and deflate returns with Z_STREAM_END if there was\n  enough output space.  If deflate returns with Z_OK or Z_BUF_ERROR, this\n  function must be called again with Z_FINISH and more output space (updated\n  avail_out) but no more input data, until it returns with Z_STREAM_END or an\n  error.  After deflate has returned Z_STREAM_END, the only possible operations\n  on the stream are deflateReset or deflateEnd.\n\n    Z_FINISH can be used in the first deflate call after deflateInit if all the\n  compression is to be done in a single step.  In order to complete in one\n  call, avail_out must be at least the value returned by deflateBound (see\n  below).  Then deflate is guaranteed to return Z_STREAM_END.  If not enough\n  output space is provided, deflate will not return Z_STREAM_END, and it must\n  be called again as described above.\n\n    deflate() sets strm->adler to the Adler-32 checksum of all input read\n  so far (that is, total_in bytes).  If a gzip stream is being generated, then\n  strm->adler will be the CRC-32 checksum of the input read so far.  (See\n  deflateInit2 below.)\n\n    deflate() may update strm->data_type if it can make a good guess about\n  the input data type (Z_BINARY or Z_TEXT).  If in doubt, the data is\n  considered binary.  This field is only for information purposes and does not\n  affect the compression algorithm in any manner.\n\n    deflate() returns Z_OK if some progress has been made (more input\n  processed or more output produced), Z_STREAM_END if all input has been\n  consumed and all output has been produced (only when flush is set to\n  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example\n  if next_in or next_out was Z_NULL or the state was inadvertently written over\n  by the application), or Z_BUF_ERROR if no progress is possible (for example\n  avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not fatal, and\n  deflate() can be called again with more input and more output space to\n  continue compressing.\n*/\n\n\nZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));\n/*\n     All dynamically allocated data structures for this stream are freed.\n   This function discards any unprocessed input and does not flush any pending\n   output.\n\n     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the\n   stream state was inconsistent, Z_DATA_ERROR if the stream was freed\n   prematurely (some input or output was discarded).  In the error case, msg\n   may be set but then points to a static string (which must not be\n   deallocated).\n*/\n\n\n/*\nZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));\n\n     Initializes the internal stream state for decompression.  The fields\n   next_in, avail_in, zalloc, zfree and opaque must be initialized before by\n   the caller.  In the current version of inflate, the provided input is not\n   read or consumed.  The allocation of a sliding window will be deferred to\n   the first call of inflate (if the decompression does not complete on the\n   first call).  If zalloc and zfree are set to Z_NULL, inflateInit updates\n   them to use default allocation functions.\n\n     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the\n   version assumed by the caller, or Z_STREAM_ERROR if the parameters are\n   invalid, such as a null pointer to the structure.  msg is set to null if\n   there is no error message.  inflateInit does not perform any decompression.\n   Actual decompression will be done by inflate().  So next_in, and avail_in,\n   next_out, and avail_out are unused and unchanged.  The current\n   implementation of inflateInit() does not process any header information --\n   that is deferred until inflate() is called.\n*/\n\n\nZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));\n/*\n    inflate decompresses as much data as possible, and stops when the input\n  buffer becomes empty or the output buffer becomes full.  It may introduce\n  some output latency (reading input without producing any output) except when\n  forced to flush.\n\n  The detailed semantics are as follows.  inflate performs one or both of the\n  following actions:\n\n  - Decompress more input starting at next_in and update next_in and avail_in\n    accordingly.  If not all input can be processed (because there is not\n    enough room in the output buffer), then next_in and avail_in are updated\n    accordingly, and processing will resume at this point for the next call of\n    inflate().\n\n  - Generate more output starting at next_out and update next_out and avail_out\n    accordingly.  inflate() provides as much output as possible, until there is\n    no more input data or no more space in the output buffer (see below about\n    the flush parameter).\n\n    Before the call of inflate(), the application should ensure that at least\n  one of the actions is possible, by providing more input and/or consuming more\n  output, and updating the next_* and avail_* values accordingly.  If the\n  caller of inflate() does not provide both available input and available\n  output space, it is possible that there will be no progress made.  The\n  application can consume the uncompressed output when it wants, for example\n  when the output buffer is full (avail_out == 0), or after each call of\n  inflate().  If inflate returns Z_OK and with zero avail_out, it must be\n  called again after making room in the output buffer because there might be\n  more output pending.\n\n    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,\n  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much\n  output as possible to the output buffer.  Z_BLOCK requests that inflate()\n  stop if and when it gets to the next deflate block boundary.  When decoding\n  the zlib or gzip format, this will cause inflate() to return immediately\n  after the header and before the first block.  When doing a raw inflate,\n  inflate() will go ahead and process the first block, and will return when it\n  gets to the end of that block, or when it runs out of data.\n\n    The Z_BLOCK option assists in appending to or combining deflate streams.\n  To assist in this, on return inflate() always sets strm->data_type to the\n  number of unused bits in the last byte taken from strm->next_in, plus 64 if\n  inflate() is currently decoding the last block in the deflate stream, plus\n  128 if inflate() returned immediately after decoding an end-of-block code or\n  decoding the complete header up to just before the first byte of the deflate\n  stream.  The end-of-block will not be indicated until all of the uncompressed\n  data from that block has been written to strm->next_out.  The number of\n  unused bits may in general be greater than seven, except when bit 7 of\n  data_type is set, in which case the number of unused bits will be less than\n  eight.  data_type is set as noted here every time inflate() returns for all\n  flush options, and so can be used to determine the amount of currently\n  consumed input in bits.\n\n    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the\n  end of each deflate block header is reached, before any actual data in that\n  block is decoded.  This allows the caller to determine the length of the\n  deflate block header for later use in random access within a deflate block.\n  256 is added to the value of strm->data_type when inflate() returns\n  immediately after reaching the end of the deflate block header.\n\n    inflate() should normally be called until it returns Z_STREAM_END or an\n  error.  However if all decompression is to be performed in a single step (a\n  single call of inflate), the parameter flush should be set to Z_FINISH.  In\n  this case all pending input is processed and all pending output is flushed;\n  avail_out must be large enough to hold all of the uncompressed data for the\n  operation to complete.  (The size of the uncompressed data may have been\n  saved by the compressor for this purpose.)  The use of Z_FINISH is not\n  required to perform an inflation in one step.  However it may be used to\n  inform inflate that a faster approach can be used for the single inflate()\n  call.  Z_FINISH also informs inflate to not maintain a sliding window if the\n  stream completes, which reduces inflate's memory footprint.  If the stream\n  does not complete, either because not all of the stream is provided or not\n  enough output space is provided, then a sliding window will be allocated and\n  inflate() can be called again to continue the operation as if Z_NO_FLUSH had\n  been used.\n\n     In this implementation, inflate() always flushes as much output as\n  possible to the output buffer, and always uses the faster approach on the\n  first call.  So the effects of the flush parameter in this implementation are\n  on the return value of inflate() as noted below, when inflate() returns early\n  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of\n  memory for a sliding window when Z_FINISH is used.\n\n     If a preset dictionary is needed after this call (see inflateSetDictionary\n  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary\n  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets\n  strm->adler to the Adler-32 checksum of all output produced so far (that is,\n  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described\n  below.  At the end of the stream, inflate() checks that its computed Adler-32\n  checksum is equal to that saved by the compressor and returns Z_STREAM_END\n  only if the checksum is correct.\n\n    inflate() can decompress and check either zlib-wrapped or gzip-wrapped\n  deflate data.  The header type is detected automatically, if requested when\n  initializing with inflateInit2().  Any information contained in the gzip\n  header is not retained unless inflateGetHeader() is used.  When processing\n  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output\n  produced so far.  The CRC-32 is checked against the gzip trailer, as is the\n  uncompressed length, modulo 2^32.\n\n    inflate() returns Z_OK if some progress has been made (more input processed\n  or more output produced), Z_STREAM_END if the end of the compressed data has\n  been reached and all uncompressed output has been produced, Z_NEED_DICT if a\n  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was\n  corrupted (input stream not conforming to the zlib format or incorrect check\n  value, in which case strm->msg points to a string with a more specific\n  error), Z_STREAM_ERROR if the stream structure was inconsistent (for example\n  next_in or next_out was Z_NULL, or the state was inadvertently written over\n  by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR\n  if no progress was possible or if there was not enough room in the output\n  buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and\n  inflate() can be called again with more input and more output space to\n  continue decompressing.  If Z_DATA_ERROR is returned, the application may\n  then call inflateSync() to look for a good compression block if a partial\n  recovery of the data is to be attempted.\n*/\n\n\nZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));\n/*\n     All dynamically allocated data structures for this stream are freed.\n   This function discards any unprocessed input and does not flush any pending\n   output.\n\n     inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state\n   was inconsistent.\n*/\n\n\n                        /* Advanced functions */\n\n/*\n    The following functions are needed only in some special applications.\n*/\n\n/*\nZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,\n                                     int  level,\n                                     int  method,\n                                     int  windowBits,\n                                     int  memLevel,\n                                     int  strategy));\n\n     This is another version of deflateInit with more compression options.  The\n   fields zalloc, zfree and opaque must be initialized before by the caller.\n\n     The method parameter is the compression method.  It must be Z_DEFLATED in\n   this version of the library.\n\n     The windowBits parameter is the base two logarithm of the window size\n   (the size of the history buffer).  It should be in the range 8..15 for this\n   version of the library.  Larger values of this parameter result in better\n   compression at the expense of memory usage.  The default value is 15 if\n   deflateInit is used instead.\n\n     For the current implementation of deflate(), a windowBits value of 8 (a\n   window size of 256 bytes) is not supported.  As a result, a request for 8\n   will result in 9 (a 512-byte window).  In that case, providing 8 to\n   inflateInit2() will result in an error when the zlib header with 9 is\n   checked against the initialization of inflate().  The remedy is to not use 8\n   with deflateInit2() with this initialization, or at least in that case use 9\n   with inflateInit2().\n\n     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits\n   determines the window size.  deflate() will then generate raw deflate data\n   with no zlib header or trailer, and will not compute a check value.\n\n     windowBits can also be greater than 15 for optional gzip encoding.  Add\n   16 to windowBits to write a simple gzip header and trailer around the\n   compressed data instead of a zlib wrapper.  The gzip header will have no\n   file name, no extra data, no comment, no modification time (set to zero), no\n   header crc, and the operating system will be set to the appropriate value,\n   if the operating system was determined at compile time.  If a gzip stream is\n   being written, strm->adler is a CRC-32 instead of an Adler-32.\n\n     For raw deflate or gzip encoding, a request for a 256-byte window is\n   rejected as invalid, since only the zlib header provides a means of\n   transmitting the window size to the decompressor.\n\n     The memLevel parameter specifies how much memory should be allocated\n   for the internal compression state.  memLevel=1 uses minimum memory but is\n   slow and reduces compression ratio; memLevel=9 uses maximum memory for\n   optimal speed.  The default value is 8.  See zconf.h for total memory usage\n   as a function of windowBits and memLevel.\n\n     The strategy parameter is used to tune the compression algorithm.  Use the\n   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a\n   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no\n   string match), or Z_RLE to limit match distances to one (run-length\n   encoding).  Filtered data consists mostly of small values with a somewhat\n   random distribution.  In this case, the compression algorithm is tuned to\n   compress them better.  The effect of Z_FILTERED is to force more Huffman\n   coding and less string matching; it is somewhat intermediate between\n   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as\n   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The\n   strategy parameter only affects the compression ratio but not the\n   correctness of the compressed output even if it is not set appropriately.\n   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler\n   decoder for special applications.\n\n     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid\n   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is\n   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is\n   set to null if there is no error message.  deflateInit2 does not perform any\n   compression: this will be done by deflate().\n*/\n\nZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,\n                                             const Bytef *dictionary,\n                                             uInt  dictLength));\n/*\n     Initializes the compression dictionary from the given byte sequence\n   without producing any compressed output.  When using the zlib format, this\n   function must be called immediately after deflateInit, deflateInit2 or\n   deflateReset, and before any call of deflate.  When doing raw deflate, this\n   function must be called either before any call of deflate, or immediately\n   after the completion of a deflate block, i.e. after all input has been\n   consumed and all output has been delivered when using any of the flush\n   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The\n   compressor and decompressor must use exactly the same dictionary (see\n   inflateSetDictionary).\n\n     The dictionary should consist of strings (byte sequences) that are likely\n   to be encountered later in the data to be compressed, with the most commonly\n   used strings preferably put towards the end of the dictionary.  Using a\n   dictionary is most useful when the data to be compressed is short and can be\n   predicted with good accuracy; the data can then be compressed better than\n   with the default empty dictionary.\n\n     Depending on the size of the compression data structures selected by\n   deflateInit or deflateInit2, a part of the dictionary may in effect be\n   discarded, for example if the dictionary is larger than the window size\n   provided in deflateInit or deflateInit2.  Thus the strings most likely to be\n   useful should be put at the end of the dictionary, not at the front.  In\n   addition, the current implementation of deflate will use at most the window\n   size minus 262 bytes of the provided dictionary.\n\n     Upon return of this function, strm->adler is set to the Adler-32 value\n   of the dictionary; the decompressor may later use this value to determine\n   which dictionary has been used by the compressor.  (The Adler-32 value\n   applies to the whole dictionary even if only a subset of the dictionary is\n   actually used by the compressor.) If a raw deflate was requested, then the\n   Adler-32 value is not computed and strm->adler is not set.\n\n     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a\n   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is\n   inconsistent (for example if deflate has already been called for this stream\n   or if not at a block boundary for raw deflate).  deflateSetDictionary does\n   not perform any compression: this will be done by deflate().\n*/\n\nZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,\n                                             Bytef *dictionary,\n                                             uInt  *dictLength));\n/*\n     Returns the sliding dictionary being maintained by deflate.  dictLength is\n   set to the number of bytes in the dictionary, and that many bytes are copied\n   to dictionary.  dictionary must have enough space, where 32768 bytes is\n   always enough.  If deflateGetDictionary() is called with dictionary equal to\n   Z_NULL, then only the dictionary length is returned, and nothing is copied.\n   Similarly, if dictLength is Z_NULL, then it is not set.\n\n     deflateGetDictionary() may return a length less than the window size, even\n   when more than the window size in input has been provided. It may return up\n   to 258 bytes less in that case, due to how zlib's implementation of deflate\n   manages the sliding window and lookahead for matches, where matches can be\n   up to 258 bytes long. If the application needs the last window-size bytes of\n   input, then that would need to be saved by the application outside of zlib.\n\n     deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the\n   stream state is inconsistent.\n*/\n\nZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,\n                                    z_streamp source));\n/*\n     Sets the destination stream as a complete copy of the source stream.\n\n     This function can be useful when several compression strategies will be\n   tried, for example when there are several ways of pre-processing the input\n   data with a filter.  The streams that will be discarded should then be freed\n   by calling deflateEnd.  Note that deflateCopy duplicates the internal\n   compression state which can be quite large, so this strategy is slow and can\n   consume lots of memory.\n\n     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent\n   (such as zalloc being Z_NULL).  msg is left unchanged in both source and\n   destination.\n*/\n\nZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));\n/*\n     This function is equivalent to deflateEnd followed by deflateInit, but\n   does not free and reallocate the internal compression state.  The stream\n   will leave the compression level and any other attributes that may have been\n   set unchanged.\n\n     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent (such as zalloc or state being Z_NULL).\n*/\n\nZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,\n                                      int level,\n                                      int strategy));\n/*\n     Dynamically update the compression level and compression strategy.  The\n   interpretation of level and strategy is as in deflateInit2().  This can be\n   used to switch between compression and straight copy of the input data, or\n   to switch to a different kind of input data requiring a different strategy.\n   If the compression approach (which is a function of the level) or the\n   strategy is changed, and if there have been any deflate() calls since the\n   state was initialized or reset, then the input available so far is\n   compressed with the old level and strategy using deflate(strm, Z_BLOCK).\n   There are three approaches for the compression levels 0, 1..3, and 4..9\n   respectively.  The new level and strategy will take effect at the next call\n   of deflate().\n\n     If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does\n   not have enough output space to complete, then the parameter change will not\n   take effect.  In this case, deflateParams() can be called again with the\n   same parameters and more output space to try again.\n\n     In order to assure a change in the parameters on the first try, the\n   deflate stream should be flushed using deflate() with Z_BLOCK or other flush\n   request until strm.avail_out is not zero, before calling deflateParams().\n   Then no more input data should be provided before the deflateParams() call.\n   If this is done, the old level and strategy will be applied to the data\n   compressed before deflateParams(), and the new level and strategy will be\n   applied to the the data compressed after deflateParams().\n\n     deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream\n   state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if\n   there was not enough output space to complete the compression of the\n   available input data before a change in the strategy or approach.  Note that\n   in the case of a Z_BUF_ERROR, the parameters are not changed.  A return\n   value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be\n   retried with more output space.\n*/\n\nZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,\n                                    int good_length,\n                                    int max_lazy,\n                                    int nice_length,\n                                    int max_chain));\n/*\n     Fine tune deflate's internal compression parameters.  This should only be\n   used by someone who understands the algorithm used by zlib's deflate for\n   searching for the best matching string, and even then only by the most\n   fanatic optimizer trying to squeeze out the last compressed bit for their\n   specific input data.  Read the deflate.c source code for the meaning of the\n   max_lazy, good_length, nice_length, and max_chain parameters.\n\n     deflateTune() can be called after deflateInit() or deflateInit2(), and\n   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.\n */\n\nZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,\n                                       uLong sourceLen));\n/*\n     deflateBound() returns an upper bound on the compressed size after\n   deflation of sourceLen bytes.  It must be called after deflateInit() or\n   deflateInit2(), and after deflateSetHeader(), if used.  This would be used\n   to allocate an output buffer for deflation in a single pass, and so would be\n   called before deflate().  If that first deflate() call is provided the\n   sourceLen input bytes, an output buffer allocated to the size returned by\n   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed\n   to return Z_STREAM_END.  Note that it is possible for the compressed size to\n   be larger than the value returned by deflateBound() if flush options other\n   than Z_FINISH or Z_NO_FLUSH are used.\n*/\n\nZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,\n                                       unsigned *pending,\n                                       int *bits));\n/*\n     deflatePending() returns the number of bytes and bits of output that have\n   been generated, but not yet provided in the available output.  The bytes not\n   provided would be due to the available output space having being consumed.\n   The number of bits of output not provided are between 0 and 7, where they\n   await more bits to join them in order to fill out a full byte.  If pending\n   or bits are Z_NULL, then those values are not set.\n\n     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n */\n\nZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,\n                                     int bits,\n                                     int value));\n/*\n     deflatePrime() inserts bits in the deflate output stream.  The intent\n   is that this function is used to start off the deflate output with the bits\n   leftover from a previous deflate stream when appending to it.  As such, this\n   function can only be used for raw deflate, and must be used before the first\n   deflate() call after a deflateInit2() or deflateReset().  bits must be less\n   than or equal to 16, and that many of the least significant bits of value\n   will be inserted in the output.\n\n     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough\n   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the\n   source stream state was inconsistent.\n*/\n\nZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,\n                                         gz_headerp head));\n/*\n     deflateSetHeader() provides gzip header information for when a gzip\n   stream is requested by deflateInit2().  deflateSetHeader() may be called\n   after deflateInit2() or deflateReset() and before the first call of\n   deflate().  The text, time, os, extra field, name, and comment information\n   in the provided gz_header structure are written to the gzip header (xflag is\n   ignored -- the extra flags are set according to the compression level).  The\n   caller must assure that, if not Z_NULL, name and comment are terminated with\n   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are\n   available there.  If hcrc is true, a gzip header crc is included.  Note that\n   the current versions of the command-line version of gzip (up through version\n   1.3.x) do not support header crc's, and will report that it is a \"multi-part\n   gzip file\" and give up.\n\n     If deflateSetHeader is not used, the default gzip header has text false,\n   the time set to zero, and os set to 255, with no extra, name, or comment\n   fields.  The gzip header is returned to the default state by deflateReset().\n\n     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n*/\n\n/*\nZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,\n                                     int  windowBits));\n\n     This is another version of inflateInit with an extra parameter.  The\n   fields next_in, avail_in, zalloc, zfree and opaque must be initialized\n   before by the caller.\n\n     The windowBits parameter is the base two logarithm of the maximum window\n   size (the size of the history buffer).  It should be in the range 8..15 for\n   this version of the library.  The default value is 15 if inflateInit is used\n   instead.  windowBits must be greater than or equal to the windowBits value\n   provided to deflateInit2() while compressing, or it must be equal to 15 if\n   deflateInit2() was not used.  If a compressed stream with a larger window\n   size is given as input, inflate() will return with the error code\n   Z_DATA_ERROR instead of trying to allocate a larger window.\n\n     windowBits can also be zero to request that inflate use the window size in\n   the zlib header of the compressed stream.\n\n     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits\n   determines the window size.  inflate() will then process raw deflate data,\n   not looking for a zlib or gzip header, not generating a check value, and not\n   looking for any check values for comparison at the end of the stream.  This\n   is for use with other formats that use the deflate compressed data format\n   such as zip.  Those formats provide their own check values.  If a custom\n   format is developed using the raw deflate format for compressed data, it is\n   recommended that a check value such as an Adler-32 or a CRC-32 be applied to\n   the uncompressed data as is done in the zlib, gzip, and zip formats.  For\n   most applications, the zlib format should be used as is.  Note that comments\n   above on the use in deflateInit2() applies to the magnitude of windowBits.\n\n     windowBits can also be greater than 15 for optional gzip decoding.  Add\n   32 to windowBits to enable zlib and gzip decoding with automatic header\n   detection, or add 16 to decode only the gzip format (the zlib format will\n   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a\n   CRC-32 instead of an Adler-32.  Unlike the gunzip utility and gzread() (see\n   below), inflate() will *not* automatically decode concatenated gzip members.\n   inflate() will return Z_STREAM_END at the end of the gzip member.  The state\n   would need to be reset to continue decoding a subsequent gzip member.  This\n   *must* be done if there is more data after a gzip member, in order for the\n   decompression to be compliant with the gzip standard (RFC 1952).\n\n     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the\n   version assumed by the caller, or Z_STREAM_ERROR if the parameters are\n   invalid, such as a null pointer to the structure.  msg is set to null if\n   there is no error message.  inflateInit2 does not perform any decompression\n   apart from possibly reading the zlib header if present: actual decompression\n   will be done by inflate().  (So next_in and avail_in may be modified, but\n   next_out and avail_out are unused and unchanged.) The current implementation\n   of inflateInit2() does not process any header information -- that is\n   deferred until inflate() is called.\n*/\n\nZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,\n                                             const Bytef *dictionary,\n                                             uInt  dictLength));\n/*\n     Initializes the decompression dictionary from the given uncompressed byte\n   sequence.  This function must be called immediately after a call of inflate,\n   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor\n   can be determined from the Adler-32 value returned by that call of inflate.\n   The compressor and decompressor must use exactly the same dictionary (see\n   deflateSetDictionary).  For raw inflate, this function can be called at any\n   time to set the dictionary.  If the provided dictionary is smaller than the\n   window and there is already data in the window, then the provided dictionary\n   will amend what's there.  The application must insure that the dictionary\n   that was used for compression is provided.\n\n     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a\n   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is\n   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the\n   expected one (incorrect Adler-32 value).  inflateSetDictionary does not\n   perform any decompression: this will be done by subsequent calls of\n   inflate().\n*/\n\nZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,\n                                             Bytef *dictionary,\n                                             uInt  *dictLength));\n/*\n     Returns the sliding dictionary being maintained by inflate.  dictLength is\n   set to the number of bytes in the dictionary, and that many bytes are copied\n   to dictionary.  dictionary must have enough space, where 32768 bytes is\n   always enough.  If inflateGetDictionary() is called with dictionary equal to\n   Z_NULL, then only the dictionary length is returned, and nothing is copied.\n   Similarly, if dictLength is Z_NULL, then it is not set.\n\n     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the\n   stream state is inconsistent.\n*/\n\nZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));\n/*\n     Skips invalid compressed data until a possible full flush point (see above\n   for the description of deflate with Z_FULL_FLUSH) can be found, or until all\n   available input is skipped.  No output is provided.\n\n     inflateSync searches for a 00 00 FF FF pattern in the compressed data.\n   All full flush points have this pattern, but not all occurrences of this\n   pattern are full flush points.\n\n     inflateSync returns Z_OK if a possible full flush point has been found,\n   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point\n   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.\n   In the success case, the application may save the current current value of\n   total_in which indicates where valid compressed data was found.  In the\n   error case, the application may repeatedly call inflateSync, providing more\n   input each time, until success or end of the input data.\n*/\n\nZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,\n                                    z_streamp source));\n/*\n     Sets the destination stream as a complete copy of the source stream.\n\n     This function can be useful when randomly accessing a large stream.  The\n   first pass through the stream can periodically record the inflate state,\n   allowing restarting inflate at those points when randomly accessing the\n   stream.\n\n     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent\n   (such as zalloc being Z_NULL).  msg is left unchanged in both source and\n   destination.\n*/\n\nZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));\n/*\n     This function is equivalent to inflateEnd followed by inflateInit,\n   but does not free and reallocate the internal decompression state.  The\n   stream will keep attributes that may have been set by inflateInit2.\n\n     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent (such as zalloc or state being Z_NULL).\n*/\n\nZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,\n                                      int windowBits));\n/*\n     This function is the same as inflateReset, but it also permits changing\n   the wrap and window size requests.  The windowBits parameter is interpreted\n   the same as it is for inflateInit2.  If the window size is changed, then the\n   memory allocated for the window is freed, and the window will be reallocated\n   by inflate() if needed.\n\n     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent (such as zalloc or state being Z_NULL), or if\n   the windowBits parameter is invalid.\n*/\n\nZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,\n                                     int bits,\n                                     int value));\n/*\n     This function inserts bits in the inflate input stream.  The intent is\n   that this function is used to start inflating at a bit position in the\n   middle of a byte.  The provided bits will be used before any bytes are used\n   from next_in.  This function should only be used with raw inflate, and\n   should be used before the first inflate() call after inflateInit2() or\n   inflateReset().  bits must be less than or equal to 16, and that many of the\n   least significant bits of value will be inserted in the input.\n\n     If bits is negative, then the input stream bit buffer is emptied.  Then\n   inflatePrime() can be called again to put bits in the buffer.  This is used\n   to clear out bits leftover after feeding inflate a block description prior\n   to feeding inflate codes.\n\n     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n*/\n\nZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));\n/*\n     This function returns two values, one in the lower 16 bits of the return\n   value, and the other in the remaining upper bits, obtained by shifting the\n   return value down 16 bits.  If the upper value is -1 and the lower value is\n   zero, then inflate() is currently decoding information outside of a block.\n   If the upper value is -1 and the lower value is non-zero, then inflate is in\n   the middle of a stored block, with the lower value equaling the number of\n   bytes from the input remaining to copy.  If the upper value is not -1, then\n   it is the number of bits back from the current bit position in the input of\n   the code (literal or length/distance pair) currently being processed.  In\n   that case the lower value is the number of bytes already emitted for that\n   code.\n\n     A code is being processed if inflate is waiting for more input to complete\n   decoding of the code, or if it has completed decoding but is waiting for\n   more output space to write the literal or match data.\n\n     inflateMark() is used to mark locations in the input data for random\n   access, which may be at bit positions, and to note those cases where the\n   output of a code may span boundaries of random access blocks.  The current\n   location in the input stream can be determined from avail_in and data_type\n   as noted in the description for the Z_BLOCK flush parameter for inflate.\n\n     inflateMark returns the value noted above, or -65536 if the provided\n   source stream state was inconsistent.\n*/\n\nZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,\n                                         gz_headerp head));\n/*\n     inflateGetHeader() requests that gzip header information be stored in the\n   provided gz_header structure.  inflateGetHeader() may be called after\n   inflateInit2() or inflateReset(), and before the first call of inflate().\n   As inflate() processes the gzip stream, head->done is zero until the header\n   is completed, at which time head->done is set to one.  If a zlib stream is\n   being decoded, then head->done is set to -1 to indicate that there will be\n   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be\n   used to force inflate() to return immediately after header processing is\n   complete and before any actual data is decompressed.\n\n     The text, time, xflags, and os fields are filled in with the gzip header\n   contents.  hcrc is set to true if there is a header CRC.  (The header CRC\n   was valid if done is set to one.) If extra is not Z_NULL, then extra_max\n   contains the maximum number of bytes to write to extra.  Once done is true,\n   extra_len contains the actual extra field length, and extra contains the\n   extra field, or that field truncated if extra_max is less than extra_len.\n   If name is not Z_NULL, then up to name_max characters are written there,\n   terminated with a zero unless the length is greater than name_max.  If\n   comment is not Z_NULL, then up to comm_max characters are written there,\n   terminated with a zero unless the length is greater than comm_max.  When any\n   of extra, name, or comment are not Z_NULL and the respective field is not\n   present in the header, then that field is set to Z_NULL to signal its\n   absence.  This allows the use of deflateSetHeader() with the returned\n   structure to duplicate the header.  However if those fields are set to\n   allocated memory, then the application will need to save those pointers\n   elsewhere so that they can be eventually freed.\n\n     If inflateGetHeader is not used, then the header information is simply\n   discarded.  The header is always checked for validity, including the header\n   CRC if present.  inflateReset() will reset the process to discard the header\n   information.  The application would need to call inflateGetHeader() again to\n   retrieve the header from the next gzip stream.\n\n     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n*/\n\n/*\nZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,\n                                        unsigned char FAR *window));\n\n     Initialize the internal stream state for decompression using inflateBack()\n   calls.  The fields zalloc, zfree and opaque in strm must be initialized\n   before the call.  If zalloc and zfree are Z_NULL, then the default library-\n   derived memory allocation routines are used.  windowBits is the base two\n   logarithm of the window size, in the range 8..15.  window is a caller\n   supplied buffer of that size.  Except for special applications where it is\n   assured that deflate was used with small window sizes, windowBits must be 15\n   and a 32K byte window must be supplied to be able to decompress general\n   deflate streams.\n\n     See inflateBack() for the usage of these routines.\n\n     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of\n   the parameters are invalid, Z_MEM_ERROR if the internal state could not be\n   allocated, or Z_VERSION_ERROR if the version of the library does not match\n   the version of the header file.\n*/\n\ntypedef unsigned (*in_func) OF((void FAR *,\n                                z_const unsigned char FAR * FAR *));\ntypedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));\n\nZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,\n                                    in_func in, void FAR *in_desc,\n                                    out_func out, void FAR *out_desc));\n/*\n     inflateBack() does a raw inflate with a single call using a call-back\n   interface for input and output.  This is potentially more efficient than\n   inflate() for file i/o applications, in that it avoids copying between the\n   output and the sliding window by simply making the window itself the output\n   buffer.  inflate() can be faster on modern CPUs when used with large\n   buffers.  inflateBack() trusts the application to not change the output\n   buffer passed by the output function, at least until inflateBack() returns.\n\n     inflateBackInit() must be called first to allocate the internal state\n   and to initialize the state with the user-provided window buffer.\n   inflateBack() may then be used multiple times to inflate a complete, raw\n   deflate stream with each call.  inflateBackEnd() is then called to free the\n   allocated state.\n\n     A raw deflate stream is one with no zlib or gzip header or trailer.\n   This routine would normally be used in a utility that reads zip or gzip\n   files and writes out uncompressed files.  The utility would decode the\n   header and process the trailer on its own, hence this routine expects only\n   the raw deflate stream to decompress.  This is different from the default\n   behavior of inflate(), which expects a zlib header and trailer around the\n   deflate stream.\n\n     inflateBack() uses two subroutines supplied by the caller that are then\n   called by inflateBack() for input and output.  inflateBack() calls those\n   routines until it reads a complete deflate stream and writes out all of the\n   uncompressed data, or until it encounters an error.  The function's\n   parameters and return types are defined above in the in_func and out_func\n   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the\n   number of bytes of provided input, and a pointer to that input in buf.  If\n   there is no input available, in() must return zero -- buf is ignored in that\n   case -- and inflateBack() will return a buffer error.  inflateBack() will\n   call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].\n   out() should return zero on success, or non-zero on failure.  If out()\n   returns non-zero, inflateBack() will return with an error.  Neither in() nor\n   out() are permitted to change the contents of the window provided to\n   inflateBackInit(), which is also the buffer that out() uses to write from.\n   The length written by out() will be at most the window size.  Any non-zero\n   amount of input may be provided by in().\n\n     For convenience, inflateBack() can be provided input on the first call by\n   setting strm->next_in and strm->avail_in.  If that input is exhausted, then\n   in() will be called.  Therefore strm->next_in must be initialized before\n   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called\n   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in\n   must also be initialized, and then if strm->avail_in is not zero, input will\n   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].\n\n     The in_desc and out_desc parameters of inflateBack() is passed as the\n   first parameter of in() and out() respectively when they are called.  These\n   descriptors can be optionally used to pass any information that the caller-\n   supplied in() and out() functions need to do their job.\n\n     On return, inflateBack() will set strm->next_in and strm->avail_in to\n   pass back any unused input that was provided by the last in() call.  The\n   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR\n   if in() or out() returned an error, Z_DATA_ERROR if there was a format error\n   in the deflate stream (in which case strm->msg is set to indicate the nature\n   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.\n   In the case of Z_BUF_ERROR, an input or output error can be distinguished\n   using strm->next_in which will be Z_NULL only if in() returned an error.  If\n   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning\n   non-zero.  (in() will always be called before out(), so strm->next_in is\n   assured to be defined if out() returns non-zero.)  Note that inflateBack()\n   cannot return Z_OK.\n*/\n\nZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));\n/*\n     All memory allocated by inflateBackInit() is freed.\n\n     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream\n   state was inconsistent.\n*/\n\nZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));\n/* Return flags indicating compile-time options.\n\n    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:\n     1.0: size of uInt\n     3.2: size of uLong\n     5.4: size of voidpf (pointer)\n     7.6: size of z_off_t\n\n    Compiler, assembler, and debug options:\n     8: ZLIB_DEBUG\n     9: ASMV or ASMINF -- use ASM code\n     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention\n     11: 0 (reserved)\n\n    One-time table building (smaller code, but not thread-safe if true):\n     12: BUILDFIXED -- build static block decoding tables when needed\n     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed\n     14,15: 0 (reserved)\n\n    Library content (indicates missing functionality):\n     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking\n                          deflate code when not needed)\n     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect\n                    and decode gzip streams (to avoid linking crc code)\n     18-19: 0 (reserved)\n\n    Operation variations (changes in library functionality):\n     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate\n     21: FASTEST -- deflate algorithm with only one, lowest compression level\n     22,23: 0 (reserved)\n\n    The sprintf variant used by gzprintf (zero is best):\n     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format\n     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!\n     26: 0 = returns value, 1 = void -- 1 means inferred string length returned\n\n    Remainder:\n     27-31: 0 (reserved)\n */\n\n#ifndef Z_SOLO\n\n                        /* utility functions */\n\n/*\n     The following utility functions are implemented on top of the basic\n   stream-oriented functions.  To simplify the interface, some default options\n   are assumed (compression level and memory usage, standard memory allocation\n   functions).  The source code of these utility functions can be modified if\n   you need special options.\n*/\n\nZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,\n                                 const Bytef *source, uLong sourceLen));\n/*\n     Compresses the source buffer into the destination buffer.  sourceLen is\n   the byte length of the source buffer.  Upon entry, destLen is the total size\n   of the destination buffer, which must be at least the value returned by\n   compressBound(sourceLen).  Upon exit, destLen is the actual size of the\n   compressed data.  compress() is equivalent to compress2() with a level\n   parameter of Z_DEFAULT_COMPRESSION.\n\n     compress returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_BUF_ERROR if there was not enough room in the output\n   buffer.\n*/\n\nZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,\n                                  const Bytef *source, uLong sourceLen,\n                                  int level));\n/*\n     Compresses the source buffer into the destination buffer.  The level\n   parameter has the same meaning as in deflateInit.  sourceLen is the byte\n   length of the source buffer.  Upon entry, destLen is the total size of the\n   destination buffer, which must be at least the value returned by\n   compressBound(sourceLen).  Upon exit, destLen is the actual size of the\n   compressed data.\n\n     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_BUF_ERROR if there was not enough room in the output buffer,\n   Z_STREAM_ERROR if the level parameter is invalid.\n*/\n\nZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));\n/*\n     compressBound() returns an upper bound on the compressed size after\n   compress() or compress2() on sourceLen bytes.  It would be used before a\n   compress() or compress2() call to allocate the destination buffer.\n*/\n\nZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,\n                                   const Bytef *source, uLong sourceLen));\n/*\n     Decompresses the source buffer into the destination buffer.  sourceLen is\n   the byte length of the source buffer.  Upon entry, destLen is the total size\n   of the destination buffer, which must be large enough to hold the entire\n   uncompressed data.  (The size of the uncompressed data must have been saved\n   previously by the compressor and transmitted to the decompressor by some\n   mechanism outside the scope of this compression library.) Upon exit, destLen\n   is the actual size of the uncompressed data.\n\n     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_BUF_ERROR if there was not enough room in the output\n   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In\n   the case where there is not enough room, uncompress() will fill the output\n   buffer with the uncompressed data up to that point.\n*/\n\nZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest,   uLongf *destLen,\n                                    const Bytef *source, uLong *sourceLen));\n/*\n     Same as uncompress, except that sourceLen is a pointer, where the\n   length of the source is *sourceLen.  On return, *sourceLen is the number of\n   source bytes consumed.\n*/\n\n                        /* gzip file access functions */\n\n/*\n     This library supports reading and writing files in gzip (.gz) format with\n   an interface similar to that of stdio, using the functions that start with\n   \"gz\".  The gzip format is different from the zlib format.  gzip is a gzip\n   wrapper, documented in RFC 1952, wrapped around a deflate stream.\n*/\n\ntypedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */\n\n/*\nZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));\n\n     Open the gzip (.gz) file at path for reading and decompressing, or\n   compressing and writing.  The mode parameter is as in fopen (\"rb\" or \"wb\")\n   but can also include a compression level (\"wb9\") or a strategy: 'f' for\n   filtered data as in \"wb6f\", 'h' for Huffman-only compression as in \"wb1h\",\n   'R' for run-length encoding as in \"wb1R\", or 'F' for fixed code compression\n   as in \"wb9F\".  (See the description of deflateInit2 for more information\n   about the strategy parameter.)  'T' will request transparent writing or\n   appending with no compression and not using the gzip format.\n\n     \"a\" can be used instead of \"w\" to request that the gzip stream that will\n   be written be appended to the file.  \"+\" will result in an error, since\n   reading and writing to the same gzip file is not supported.  The addition of\n   \"x\" when writing will create the file exclusively, which fails if the file\n   already exists.  On systems that support it, the addition of \"e\" when\n   reading or writing will set the flag to close the file on an execve() call.\n\n     These functions, as well as gzip, will read and decode a sequence of gzip\n   streams in a file.  The append function of gzopen() can be used to create\n   such a file.  (Also see gzflush() for another way to do this.)  When\n   appending, gzopen does not test whether the file begins with a gzip stream,\n   nor does it look for the end of the gzip streams to begin appending.  gzopen\n   will simply append a gzip stream to the existing file.\n\n     gzopen can be used to read a file which is not in gzip format; in this\n   case gzread will directly read from the file without decompression.  When\n   reading, this will be detected automatically by looking for the magic two-\n   byte gzip header.\n\n     gzopen returns NULL if the file could not be opened, if there was\n   insufficient memory to allocate the gzFile state, or if an invalid mode was\n   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).\n   errno can be checked to determine if the reason gzopen failed was that the\n   file could not be opened.\n*/\n\nZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));\n/*\n     Associate a gzFile with the file descriptor fd.  File descriptors are\n   obtained from calls like open, dup, creat, pipe or fileno (if the file has\n   been previously opened with fopen).  The mode parameter is as in gzopen.\n\n     The next call of gzclose on the returned gzFile will also close the file\n   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor\n   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,\n   mode);.  The duplicated descriptor should be saved to avoid a leak, since\n   gzdopen does not close fd if it fails.  If you are using fileno() to get the\n   file descriptor from a FILE *, then you will have to use dup() to avoid\n   double-close()ing the file descriptor.  Both gzclose() and fclose() will\n   close the associated file descriptor, so they need to have different file\n   descriptors.\n\n     gzdopen returns NULL if there was insufficient memory to allocate the\n   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not\n   provided, or '+' was provided), or if fd is -1.  The file descriptor is not\n   used until the next gz* read, write, seek, or close operation, so gzdopen\n   will not detect if fd is invalid (unless fd is -1).\n*/\n\nZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));\n/*\n     Set the internal buffer size used by this library's functions for file to\n   size.  The default buffer size is 8192 bytes.  This function must be called\n   after gzopen() or gzdopen(), and before any other calls that read or write\n   the file.  The buffer memory allocation is always deferred to the first read\n   or write.  Three times that size in buffer space is allocated.  A larger\n   buffer size of, for example, 64K or 128K bytes will noticeably increase the\n   speed of decompression (reading).\n\n     The new buffer size also affects the maximum length for gzprintf().\n\n     gzbuffer() returns 0 on success, or -1 on failure, such as being called\n   too late.\n*/\n\nZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));\n/*\n     Dynamically update the compression level and strategy for file.  See the\n   description of deflateInit2 for the meaning of these parameters. Previously\n   provided data is flushed before applying the parameter changes.\n\n     gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not\n   opened for writing, Z_ERRNO if there is an error writing the flushed data,\n   or Z_MEM_ERROR if there is a memory allocation error.\n*/\n\nZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));\n/*\n     Read and decompress up to len uncompressed bytes from file into buf.  If\n   the input file is not in gzip format, gzread copies the given number of\n   bytes into the buffer directly from the file.\n\n     After reaching the end of a gzip stream in the input, gzread will continue\n   to read, looking for another gzip stream.  Any number of gzip streams may be\n   concatenated in the input file, and will all be decompressed by gzread().\n   If something other than a gzip stream is encountered after a gzip stream,\n   that remaining trailing garbage is ignored (and no error is returned).\n\n     gzread can be used to read a gzip file that is being concurrently written.\n   Upon reaching the end of the input, gzread will return with the available\n   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then\n   gzclearerr can be used to clear the end of file indicator in order to permit\n   gzread to be tried again.  Z_OK indicates that a gzip stream was completed\n   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the\n   middle of a gzip stream.  Note that gzread does not return -1 in the event\n   of an incomplete gzip stream.  This error is deferred until gzclose(), which\n   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip\n   stream.  Alternatively, gzerror can be used before gzclose to detect this\n   case.\n\n     gzread returns the number of uncompressed bytes actually read, less than\n   len for end of file, or -1 for error.  If len is too large to fit in an int,\n   then nothing is read, -1 is returned, and the error state is set to\n   Z_STREAM_ERROR.\n*/\n\nZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,\n                                     gzFile file));\n/*\n     Read and decompress up to nitems items of size size from file into buf,\n   otherwise operating as gzread() does.  This duplicates the interface of\n   stdio's fread(), with size_t request and return types.  If the library\n   defines size_t, then z_size_t is identical to size_t.  If not, then z_size_t\n   is an unsigned integer type that can contain a pointer.\n\n     gzfread() returns the number of full items read of size size, or zero if\n   the end of the file was reached and a full item could not be read, or if\n   there was an error.  gzerror() must be consulted if zero is returned in\n   order to determine if there was an error.  If the multiplication of size and\n   nitems overflows, i.e. the product does not fit in a z_size_t, then nothing\n   is read, zero is returned, and the error state is set to Z_STREAM_ERROR.\n\n     In the event that the end of file is reached and only a partial item is\n   available at the end, i.e. the remaining uncompressed data length is not a\n   multiple of size, then the final partial item is nevertheless read into buf\n   and the end-of-file flag is set.  The length of the partial item read is not\n   provided, but could be inferred from the result of gztell().  This behavior\n   is the same as the behavior of fread() implementations in common libraries,\n   but it prevents the direct use of gzfread() to read a concurrently written\n   file, resetting and retrying on end-of-file, when size is not 1.\n*/\n\nZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));\n/*\n     Compress and write the len uncompressed bytes at buf to file. gzwrite\n   returns the number of uncompressed bytes written or 0 in case of error.\n*/\n\nZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,\n                                      z_size_t nitems, gzFile file));\n/*\n     Compress and write nitems items of size size from buf to file, duplicating\n   the interface of stdio's fwrite(), with size_t request and return types.  If\n   the library defines size_t, then z_size_t is identical to size_t.  If not,\n   then z_size_t is an unsigned integer type that can contain a pointer.\n\n     gzfwrite() returns the number of full items written of size size, or zero\n   if there was an error.  If the multiplication of size and nitems overflows,\n   i.e. the product does not fit in a z_size_t, then nothing is written, zero\n   is returned, and the error state is set to Z_STREAM_ERROR.\n*/\n\nZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));\n/*\n     Convert, format, compress, and write the arguments (...) to file under\n   control of the string format, as in fprintf.  gzprintf returns the number of\n   uncompressed bytes actually written, or a negative zlib error code in case\n   of error.  The number of uncompressed bytes written is limited to 8191, or\n   one less than the buffer size given to gzbuffer().  The caller should assure\n   that this limit is not exceeded.  If it is exceeded, then gzprintf() will\n   return an error (0) with nothing written.  In this case, there may also be a\n   buffer overflow with unpredictable consequences, which is possible only if\n   zlib was compiled with the insecure functions sprintf() or vsprintf(),\n   because the secure snprintf() or vsnprintf() functions were not available.\n   This can be determined using zlibCompileFlags().\n*/\n\nZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));\n/*\n     Compress and write the given null-terminated string s to file, excluding\n   the terminating null character.\n\n     gzputs returns the number of characters written, or -1 in case of error.\n*/\n\nZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));\n/*\n     Read and decompress bytes from file into buf, until len-1 characters are\n   read, or until a newline character is read and transferred to buf, or an\n   end-of-file condition is encountered.  If any characters are read or if len\n   is one, the string is terminated with a null character.  If no characters\n   are read due to an end-of-file or len is less than one, then the buffer is\n   left untouched.\n\n     gzgets returns buf which is a null-terminated string, or it returns NULL\n   for end-of-file or in case of error.  If there was an error, the contents at\n   buf are indeterminate.\n*/\n\nZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));\n/*\n     Compress and write c, converted to an unsigned char, into file.  gzputc\n   returns the value that was written, or -1 in case of error.\n*/\n\nZEXTERN int ZEXPORT gzgetc OF((gzFile file));\n/*\n     Read and decompress one byte from file.  gzgetc returns this byte or -1\n   in case of end of file or error.  This is implemented as a macro for speed.\n   As such, it does not do all of the checking the other functions do.  I.e.\n   it does not check to see if file is NULL, nor whether the structure file\n   points to has been clobbered or not.\n*/\n\nZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));\n/*\n     Push c back onto the stream for file to be read as the first character on\n   the next read.  At least one character of push-back is always allowed.\n   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will\n   fail if c is -1, and may fail if a character has been pushed but not read\n   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the\n   output buffer size of pushed characters is allowed.  (See gzbuffer above.)\n   The pushed character will be discarded if the stream is repositioned with\n   gzseek() or gzrewind().\n*/\n\nZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));\n/*\n     Flush all pending output to file.  The parameter flush is as in the\n   deflate() function.  The return value is the zlib error number (see function\n   gzerror below).  gzflush is only permitted when writing.\n\n     If the flush parameter is Z_FINISH, the remaining data is written and the\n   gzip stream is completed in the output.  If gzwrite() is called again, a new\n   gzip stream will be started in the output.  gzread() is able to read such\n   concatenated gzip streams.\n\n     gzflush should be called only when strictly necessary because it will\n   degrade compression if called too often.\n*/\n\n/*\nZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,\n                                   z_off_t offset, int whence));\n\n     Set the starting position to offset relative to whence for the next gzread\n   or gzwrite on file.  The offset represents a number of bytes in the\n   uncompressed data stream.  The whence parameter is defined as in lseek(2);\n   the value SEEK_END is not supported.\n\n     If the file is opened for reading, this function is emulated but can be\n   extremely slow.  If the file is opened for writing, only forward seeks are\n   supported; gzseek then compresses a sequence of zeroes up to the new\n   starting position.\n\n     gzseek returns the resulting offset location as measured in bytes from\n   the beginning of the uncompressed stream, or -1 in case of error, in\n   particular if the file is opened for writing and the new starting position\n   would be before the current position.\n*/\n\nZEXTERN int ZEXPORT    gzrewind OF((gzFile file));\n/*\n     Rewind file. This function is supported only for reading.\n\n     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).\n*/\n\n/*\nZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));\n\n     Return the starting position for the next gzread or gzwrite on file.\n   This position represents a number of bytes in the uncompressed data stream,\n   and is zero when starting, even if appending or reading a gzip stream from\n   the middle of a file using gzdopen().\n\n     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)\n*/\n\n/*\nZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));\n\n     Return the current compressed (actual) read or write offset of file.  This\n   offset includes the count of bytes that precede the gzip stream, for example\n   when appending or when using gzdopen() for reading.  When reading, the\n   offset does not include as yet unused buffered input.  This information can\n   be used for a progress indicator.  On error, gzoffset() returns -1.\n*/\n\nZEXTERN int ZEXPORT gzeof OF((gzFile file));\n/*\n     Return true (1) if the end-of-file indicator for file has been set while\n   reading, false (0) otherwise.  Note that the end-of-file indicator is set\n   only if the read tried to go past the end of the input, but came up short.\n   Therefore, just like feof(), gzeof() may return false even if there is no\n   more data to read, in the event that the last read request was for the exact\n   number of bytes remaining in the input file.  This will happen if the input\n   file size is an exact multiple of the buffer size.\n\n     If gzeof() returns true, then the read functions will return no more data,\n   unless the end-of-file indicator is reset by gzclearerr() and the input file\n   has grown since the previous end of file was detected.\n*/\n\nZEXTERN int ZEXPORT gzdirect OF((gzFile file));\n/*\n     Return true (1) if file is being copied directly while reading, or false\n   (0) if file is a gzip stream being decompressed.\n\n     If the input file is empty, gzdirect() will return true, since the input\n   does not contain a gzip stream.\n\n     If gzdirect() is used immediately after gzopen() or gzdopen() it will\n   cause buffers to be allocated to allow reading the file to determine if it\n   is a gzip file.  Therefore if gzbuffer() is used, it should be called before\n   gzdirect().\n\n     When writing, gzdirect() returns true (1) if transparent writing was\n   requested (\"wT\" for the gzopen() mode), or false (0) otherwise.  (Note:\n   gzdirect() is not needed when writing.  Transparent writing must be\n   explicitly requested, so the application already knows the answer.  When\n   linking statically, using gzdirect() will include all of the zlib code for\n   gzip file reading and decompression, which may not be desired.)\n*/\n\nZEXTERN int ZEXPORT    gzclose OF((gzFile file));\n/*\n     Flush all pending output for file, if necessary, close file and\n   deallocate the (de)compression state.  Note that once file is closed, you\n   cannot call gzerror with file, since its structures have been deallocated.\n   gzclose must not be called more than once on the same file, just as free\n   must not be called more than once on the same allocation.\n\n     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a\n   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the\n   last read ended in the middle of a gzip stream, or Z_OK on success.\n*/\n\nZEXTERN int ZEXPORT gzclose_r OF((gzFile file));\nZEXTERN int ZEXPORT gzclose_w OF((gzFile file));\n/*\n     Same as gzclose(), but gzclose_r() is only for use when reading, and\n   gzclose_w() is only for use when writing or appending.  The advantage to\n   using these instead of gzclose() is that they avoid linking in zlib\n   compression or decompression code that is not used when only reading or only\n   writing respectively.  If gzclose() is used, then both compression and\n   decompression code will be included the application when linking to a static\n   zlib library.\n*/\n\nZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));\n/*\n     Return the error message for the last error which occurred on file.\n   errnum is set to zlib error number.  If an error occurred in the file system\n   and not in the compression library, errnum is set to Z_ERRNO and the\n   application may consult errno to get the exact error code.\n\n     The application must not modify the returned string.  Future calls to\n   this function may invalidate the previously returned string.  If file is\n   closed, then the string previously returned by gzerror will no longer be\n   available.\n\n     gzerror() should be used to distinguish errors from end-of-file for those\n   functions above that do not distinguish those cases in their return values.\n*/\n\nZEXTERN void ZEXPORT gzclearerr OF((gzFile file));\n/*\n     Clear the error and end-of-file flags for file.  This is analogous to the\n   clearerr() function in stdio.  This is useful for continuing to read a gzip\n   file that is being written concurrently.\n*/\n\n#endif /* !Z_SOLO */\n\n                        /* checksum functions */\n\n/*\n     These functions are not related to compression but are exported\n   anyway because they might be useful in applications using the compression\n   library.\n*/\n\nZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));\n/*\n     Update a running Adler-32 checksum with the bytes buf[0..len-1] and\n   return the updated checksum. An Adler-32 value is in the range of a 32-bit\n   unsigned integer. If buf is Z_NULL, this function returns the required\n   initial value for the checksum.\n\n     An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed\n   much faster.\n\n   Usage example:\n\n     uLong adler = adler32(0L, Z_NULL, 0);\n\n     while (read_buffer(buffer, length) != EOF) {\n       adler = adler32(adler, buffer, length);\n     }\n     if (adler != original_adler) error();\n*/\n\nZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf,\n                                    z_size_t len));\n/*\n     Same as adler32(), but with a size_t length.\n*/\n\n/*\nZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,\n                                          z_off_t len2));\n\n     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1\n   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for\n   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of\n   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note\n   that the z_off_t type (like off_t) is a signed integer.  If len2 is\n   negative, the result has no meaning or utility.\n*/\n\nZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));\n/*\n     Update a running CRC-32 with the bytes buf[0..len-1] and return the\n   updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.\n   If buf is Z_NULL, this function returns the required initial value for the\n   crc. Pre- and post-conditioning (one's complement) is performed within this\n   function so it shouldn't be done by the application.\n\n   Usage example:\n\n     uLong crc = crc32(0L, Z_NULL, 0);\n\n     while (read_buffer(buffer, length) != EOF) {\n       crc = crc32(crc, buffer, length);\n     }\n     if (crc != original_crc) error();\n*/\n\nZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf,\n                                  z_size_t len));\n/*\n     Same as crc32(), but with a size_t length.\n*/\n\n/*\nZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));\n\n     Combine two CRC-32 check values into one.  For two sequences of bytes,\n   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were\n   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32\n   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and\n   len2.\n*/\n\n/*\nZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2));\n\n     Return the operator corresponding to length len2, to be used with\n   crc32_combine_op().\n*/\n\nZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op));\n/*\n     Give the same result as crc32_combine(), using op in place of len2. op is\n   is generated from len2 by crc32_combine_gen(). This will be faster than\n   crc32_combine() if the generated op is used more than once.\n*/\n\n\n                        /* various hacks, don't look :) */\n\n/* deflateInit and inflateInit are macros to allow checking the zlib version\n * and the compiler's view of z_stream:\n */\nZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,\n                                     const char *version, int stream_size));\nZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,\n                                     const char *version, int stream_size));\nZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,\n                                      int windowBits, int memLevel,\n                                      int strategy, const char *version,\n                                      int stream_size));\nZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,\n                                      const char *version, int stream_size));\nZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,\n                                         unsigned char FAR *window,\n                                         const char *version,\n                                         int stream_size));\n#ifdef Z_PREFIX_SET\n#  define z_deflateInit(strm, level) \\\n          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define z_inflateInit(strm) \\\n          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \\\n          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\\\n                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define z_inflateInit2(strm, windowBits) \\\n          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \\\n                        (int)sizeof(z_stream))\n#  define z_inflateBackInit(strm, windowBits, window) \\\n          inflateBackInit_((strm), (windowBits), (window), \\\n                           ZLIB_VERSION, (int)sizeof(z_stream))\n#else\n#  define deflateInit(strm, level) \\\n          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define inflateInit(strm) \\\n          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \\\n          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\\\n                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define inflateInit2(strm, windowBits) \\\n          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \\\n                        (int)sizeof(z_stream))\n#  define inflateBackInit(strm, windowBits, window) \\\n          inflateBackInit_((strm), (windowBits), (window), \\\n                           ZLIB_VERSION, (int)sizeof(z_stream))\n#endif\n\n#ifndef Z_SOLO\n\n/* gzgetc() macro and its supporting function and exposed data structure.  Note\n * that the real internal state is much larger than the exposed structure.\n * This abbreviated structure exposes just enough for the gzgetc() macro.  The\n * user should not mess with these exposed elements, since their names or\n * behavior could change in the future, perhaps even capriciously.  They can\n * only be used by the gzgetc() macro.  You have been warned.\n */\nstruct gzFile_s {\n    unsigned have;\n    unsigned char *next;\n    z_off64_t pos;\n};\nZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */\n#ifdef Z_PREFIX_SET\n#  undef z_gzgetc\n#  define z_gzgetc(g) \\\n          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))\n#else\n#  define gzgetc(g) \\\n          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))\n#endif\n\n/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or\n * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if\n * both are true, the application gets the *64 functions, and the regular\n * functions are changed to 64 bits) -- in case these are set on systems\n * without large file support, _LFS64_LARGEFILE must also be true\n */\n#ifdef Z_LARGE64\n   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));\n   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));\n   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));\n   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));\n   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));\n   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));\n   ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t));\n#endif\n\n#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)\n#  ifdef Z_PREFIX_SET\n#    define z_gzopen z_gzopen64\n#    define z_gzseek z_gzseek64\n#    define z_gztell z_gztell64\n#    define z_gzoffset z_gzoffset64\n#    define z_adler32_combine z_adler32_combine64\n#    define z_crc32_combine z_crc32_combine64\n#    define z_crc32_combine_gen z_crc32_combine_gen64\n#  else\n#    define gzopen gzopen64\n#    define gzseek gzseek64\n#    define gztell gztell64\n#    define gzoffset gzoffset64\n#    define adler32_combine adler32_combine64\n#    define crc32_combine crc32_combine64\n#    define crc32_combine_gen crc32_combine_gen64\n#  endif\n#  ifndef Z_LARGE64\n     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));\n     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));\n     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));\n     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));\n     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));\n     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));\n     ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));\n#  endif\n#else\n   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));\n   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));\n   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));\n   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));\n   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));\n   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));\n   ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));\n#endif\n\n#else /* Z_SOLO */\n\n   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));\n   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));\n   ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));\n\n#endif /* !Z_SOLO */\n\n/* undocumented functions */\nZEXTERN const char   * ZEXPORT zError           OF((int));\nZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));\nZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));\nZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));\nZEXTERN int            ZEXPORT inflateValidate OF((z_streamp, int));\nZEXTERN unsigned long  ZEXPORT inflateCodesUsed OF((z_streamp));\nZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));\nZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));\n#if defined(_WIN32) && !defined(Z_SOLO)\nZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,\n                                            const char *mode));\n#endif\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#  ifndef Z_SOLO\nZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,\n                                                  const char *format,\n                                                  va_list va));\n#  endif\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ZLIB_H */\n"
  },
  {
    "path": "third_party/libz/zlib.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nPKGS += ZLIB\n\nZLIB ?= o/$(MODE)/third_party/libz/zlib.a\nZLIB_FILES := $(wildcard third_party/libz/*)\nZLIB_SRCS = $(filter %.c,$(ZLIB_FILES))\nZLIB_HDRS = $(filter %.h,$(ZLIB_FILES))\nZLIB_OBJS = $(ZLIB_SRCS:%.c=o/$(MODE)/%.o)\nZLIB_CPPFLAGS = -isystem third_party/libz\n\nCPPFLAGS_STATIC += $(ZLIB_CPPFLAGS)\nifneq ($(ZLIB), )\nCPPFLAGS += $(ZLIB_CPPFLAGS)\nendif\n\n$(ZLIB_OBJS): private CFLAGS += -xc -w\n\no/$(MODE)/third_party/libz/zlib.a: $(ZLIB_OBJS)\no/$(MODE)/i486/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/i486/%.o)\no/$(MODE)/m68k/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/m68k/%.o)\no/$(MODE)/x86_64/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/x86_64/%.o)\no/$(MODE)/x86_64-gcc49/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/x86_64-gcc49/%.o)\no/$(MODE)/arm/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/arm/%.o)\no/$(MODE)/aarch64/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/aarch64/%.o)\no/$(MODE)/riscv64/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/riscv64/%.o)\no/$(MODE)/mips/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/mips/%.o)\no/$(MODE)/mipsel/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/mipsel/%.o)\no/$(MODE)/mips64/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/mips64/%.o)\no/$(MODE)/mips64el/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/mips64el/%.o)\no/$(MODE)/s390x/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/s390x/%.o)\no/$(MODE)/microblaze/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/microblaze/%.o)\no/$(MODE)/powerpc/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/powerpc/%.o)\no/$(MODE)/powerpc64le/third_party/libz/zlib.a: $(ZLIB_SRCS:%.c=o/$(MODE)/powerpc64le/%.o)\n\no/$(MODE)/third_party/libz:\t\\\n\to/$(MODE)/third_party/libz/zlib.a\n"
  },
  {
    "path": "third_party/libz/zutil.c",
    "content": "// clang-format off\n/* zutil.c -- target dependent utility functions for the compression library\n * Copyright (C) 1995-2017 Jean-loup Gailly\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* @(#) $Id$ */\n\n#include \"third_party/libz/zutil.h\"\n#ifndef Z_SOLO\n#  include \"third_party/libz/gzguts.h\"\n#endif\n\nz_const char * const z_errmsg[10] = {\n    (z_const char *)\"need dictionary\",     /* Z_NEED_DICT       2  */\n    (z_const char *)\"stream end\",          /* Z_STREAM_END      1  */\n    (z_const char *)\"\",                    /* Z_OK              0  */\n    (z_const char *)\"file error\",          /* Z_ERRNO         (-1) */\n    (z_const char *)\"stream error\",        /* Z_STREAM_ERROR  (-2) */\n    (z_const char *)\"data error\",          /* Z_DATA_ERROR    (-3) */\n    (z_const char *)\"insufficient memory\", /* Z_MEM_ERROR     (-4) */\n    (z_const char *)\"buffer error\",        /* Z_BUF_ERROR     (-5) */\n    (z_const char *)\"incompatible version\",/* Z_VERSION_ERROR (-6) */\n    (z_const char *)\"\"\n};\n\n\nconst char * ZEXPORT zlibVersion()\n{\n    return ZLIB_VERSION;\n}\n\nuLong ZEXPORT zlibCompileFlags()\n{\n    uLong flags;\n\n    flags = 0;\n    switch ((int)(sizeof(uInt))) {\n    case 2:     break;\n    case 4:     flags += 1;     break;\n    case 8:     flags += 2;     break;\n    default:    flags += 3;\n    }\n    switch ((int)(sizeof(uLong))) {\n    case 2:     break;\n    case 4:     flags += 1 << 2;        break;\n    case 8:     flags += 2 << 2;        break;\n    default:    flags += 3 << 2;\n    }\n    switch ((int)(sizeof(voidpf))) {\n    case 2:     break;\n    case 4:     flags += 1 << 4;        break;\n    case 8:     flags += 2 << 4;        break;\n    default:    flags += 3 << 4;\n    }\n    switch ((int)(sizeof(z_off_t))) {\n    case 2:     break;\n    case 4:     flags += 1 << 6;        break;\n    case 8:     flags += 2 << 6;        break;\n    default:    flags += 3 << 6;\n    }\n#ifdef ZLIB_DEBUG\n    flags += 1 << 8;\n#endif\n    /*\n#if defined(ASMV) || defined(ASMINF)\n    flags += 1 << 9;\n#endif\n     */\n#ifdef ZLIB_WINAPI\n    flags += 1 << 10;\n#endif\n#ifdef BUILDFIXED\n    flags += 1 << 12;\n#endif\n#ifdef DYNAMIC_CRC_TABLE\n    flags += 1 << 13;\n#endif\n#ifdef NO_GZCOMPRESS\n    flags += 1L << 16;\n#endif\n#ifdef NO_GZIP\n    flags += 1L << 17;\n#endif\n#ifdef PKZIP_BUG_WORKAROUND\n    flags += 1L << 20;\n#endif\n#ifdef FASTEST\n    flags += 1L << 21;\n#endif\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#  ifdef NO_vsnprintf\n    flags += 1L << 25;\n#    ifdef HAS_vsprintf_void\n    flags += 1L << 26;\n#    endif\n#  else\n#    ifdef HAS_vsnprintf_void\n    flags += 1L << 26;\n#    endif\n#  endif\n#else\n    flags += 1L << 24;\n#  ifdef NO_snprintf\n    flags += 1L << 25;\n#    ifdef HAS_sprintf_void\n    flags += 1L << 26;\n#    endif\n#  else\n#    ifdef HAS_snprintf_void\n    flags += 1L << 26;\n#    endif\n#  endif\n#endif\n    return flags;\n}\n\n#ifdef ZLIB_DEBUG\n#include <stdlib.h>\n#  ifndef verbose\n#    define verbose 0\n#  endif\nint ZLIB_INTERNAL z_verbose = verbose;\n\nvoid ZLIB_INTERNAL z_error(m)\n    char *m;\n{\n    fprintf(stderr, \"%s\\n\", m);\n    exit(1);\n}\n#endif\n\n/* exported to allow conversion of error code to string for compress() and\n * uncompress()\n */\nconst char * ZEXPORT zError(err)\n    int err;\n{\n    return ERR_MSG(err);\n}\n\n#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800\n    /* The older Microsoft C Run-Time Library for Windows CE doesn't have\n     * errno.  We define it as a global variable to simplify porting.\n     * Its value is always 0 and should not be used.\n     */\n    int errno = 0;\n#endif\n\n#ifndef HAVE_MEMCPY\n\nvoid ZLIB_INTERNAL zmemcpy(dest, source, len)\n    Bytef* dest;\n    const Bytef* source;\n    uInt  len;\n{\n    if (len == 0) return;\n    do {\n        *dest++ = *source++; /* ??? to be unrolled */\n    } while (--len != 0);\n}\n\nint ZLIB_INTERNAL zmemcmp(s1, s2, len)\n    const Bytef* s1;\n    const Bytef* s2;\n    uInt  len;\n{\n    uInt j;\n\n    for (j = 0; j < len; j++) {\n        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;\n    }\n    return 0;\n}\n\nvoid ZLIB_INTERNAL zmemzero(dest, len)\n    Bytef* dest;\n    uInt  len;\n{\n    if (len == 0) return;\n    do {\n        *dest++ = 0;  /* ??? to be unrolled */\n    } while (--len != 0);\n}\n#endif\n\n#ifndef Z_SOLO\n\n#ifdef SYS16BIT\n\n#ifdef __TURBOC__\n/* Turbo C in 16-bit mode */\n\n#  define MY_ZCALLOC\n\n/* Turbo C malloc() does not allow dynamic allocation of 64K bytes\n * and farmalloc(64K) returns a pointer with an offset of 8, so we\n * must fix the pointer. Warning: the pointer must be put back to its\n * original form in order to free it, use zcfree().\n */\n\n#define MAX_PTR 10\n/* 10*64K = 640K */\n\nlocal int next_ptr = 0;\n\ntypedef struct ptr_table_s {\n    voidpf org_ptr;\n    voidpf new_ptr;\n} ptr_table;\n\nlocal ptr_table table[MAX_PTR];\n/* This table is used to remember the original form of pointers\n * to large buffers (64K). Such pointers are normalized with a zero offset.\n * Since MSDOS is not a preemptive multitasking OS, this table is not\n * protected from concurrent access. This hack doesn't work anyway on\n * a protected system like OS/2. Use Microsoft C instead.\n */\n\nvoidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size)\n{\n    voidpf buf;\n    ulg bsize = (ulg)items*size;\n\n    (void)opaque;\n\n    /* If we allocate less than 65520 bytes, we assume that farmalloc\n     * will return a usable pointer which doesn't have to be normalized.\n     */\n    if (bsize < 65520L) {\n        buf = farmalloc(bsize);\n        if (*(ush*)&buf != 0) return buf;\n    } else {\n        buf = farmalloc(bsize + 16L);\n    }\n    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;\n    table[next_ptr].org_ptr = buf;\n\n    /* Normalize the pointer to seg:0 */\n    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;\n    *(ush*)&buf = 0;\n    table[next_ptr++].new_ptr = buf;\n    return buf;\n}\n\nvoid ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr)\n{\n    int n;\n\n    (void)opaque;\n\n    if (*(ush*)&ptr != 0) { /* object < 64K */\n        farfree(ptr);\n        return;\n    }\n    /* Find the original pointer */\n    for (n = 0; n < next_ptr; n++) {\n        if (ptr != table[n].new_ptr) continue;\n\n        farfree(table[n].org_ptr);\n        while (++n < next_ptr) {\n            table[n-1] = table[n];\n        }\n        next_ptr--;\n        return;\n    }\n    Assert(0, \"zcfree: ptr not found\");\n}\n\n#endif /* __TURBOC__ */\n\n\n#ifdef M_I86\n/* Microsoft C in 16-bit mode */\n\n#  define MY_ZCALLOC\n\n#if (!defined(_MSC_VER) || (_MSC_VER <= 600))\n#  define _halloc  halloc\n#  define _hfree   hfree\n#endif\n\nvoidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size)\n{\n    (void)opaque;\n    return _halloc((long)items, size);\n}\n\nvoid ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr)\n{\n    (void)opaque;\n    _hfree(ptr);\n}\n\n#endif /* M_I86 */\n\n#endif /* SYS16BIT */\n\n\n#ifndef MY_ZCALLOC /* Any system without a special alloc function */\n\n#ifndef STDC\nextern voidp  malloc OF((uInt size));\nextern voidp  calloc OF((uInt items, uInt size));\nextern void   free   OF((voidpf ptr));\n#endif\n\nvoidpf ZLIB_INTERNAL zcalloc(opaque, items, size)\n    voidpf opaque;\n    unsigned items;\n    unsigned size;\n{\n    (void)opaque;\n    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :\n                              (voidpf)calloc(items, size);\n}\n\nvoid ZLIB_INTERNAL zcfree(opaque, ptr)\n    voidpf opaque;\n    voidpf ptr;\n{\n    (void)opaque;\n    free(ptr);\n}\n\n#endif /* MY_ZCALLOC */\n\n#endif /* !Z_SOLO */\n"
  },
  {
    "path": "third_party/libz/zutil.h",
    "content": "// clang-format off\n/* zutil.h -- internal interface and configuration of the compression library\n * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the compression library and is\n   subject to change. Applications should only use zlib.h.\n */\n\n/* @(#) $Id$ */\n\n#ifndef ZUTIL_H\n#define ZUTIL_H\n\n#ifdef HAVE_HIDDEN\n#  define ZLIB_INTERNAL __attribute__((visibility (\"hidden\")))\n#else\n#  define ZLIB_INTERNAL\n#endif\n\n#include \"third_party/libz/zlib.h\"\n\n#if defined(STDC) && !defined(Z_SOLO)\n#  if !(defined(_WIN32_WCE) && defined(_MSC_VER))\n#    include <stddef.h>\n#  endif\n#  include <string.h>\n#  include <stdlib.h>\n#endif\n\n#ifndef local\n#  define local static\n#endif\n/* since \"static\" is used to mean two completely different things in C, we\n   define \"local\" for the non-static meaning of \"static\", for readability\n   (compile with -Dlocal if your debugger can't find static symbols) */\n\ntypedef unsigned char  uch;\ntypedef uch FAR uchf;\ntypedef unsigned short ush;\ntypedef ush FAR ushf;\ntypedef unsigned long  ulg;\n\n#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)\n#  include <limits.h>\n#  if (ULONG_MAX == 0xffffffffffffffff)\n#    define Z_U8 unsigned long\n#  elif (ULLONG_MAX == 0xffffffffffffffff)\n#    define Z_U8 unsigned long long\n#  elif (UINT_MAX == 0xffffffffffffffff)\n#    define Z_U8 unsigned\n#  endif\n#endif\n\nextern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */\n/* (size given to avoid silly warnings with Visual C++) */\n\n#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]\n\n#define ERR_RETURN(strm,err) \\\n  return (strm->msg = ERR_MSG(err), (err))\n/* To be used only when the state is known to be valid */\n\n        /* common constants */\n\n#ifndef DEF_WBITS\n#  define DEF_WBITS MAX_WBITS\n#endif\n/* default windowBits for decompression. MAX_WBITS is for compression only */\n\n#if MAX_MEM_LEVEL >= 8\n#  define DEF_MEM_LEVEL 8\n#else\n#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL\n#endif\n/* default memLevel */\n\n#define STORED_BLOCK 0\n#define STATIC_TREES 1\n#define DYN_TREES    2\n/* The three kinds of block type */\n\n#define MIN_MATCH  3\n#define MAX_MATCH  258\n/* The minimum and maximum match lengths */\n\n#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */\n\n        /* target dependencies */\n\n#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))\n#  define OS_CODE  0x00\n#  ifndef Z_SOLO\n#    if defined(__TURBOC__) || defined(__BORLANDC__)\n#      if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))\n         /* Allow compilation with ANSI keywords only enabled */\n         void _Cdecl farfree( void *block );\n         void *_Cdecl farmalloc( unsigned long nbytes );\n#      else\n#        include <alloc.h>\n#      endif\n#    else /* MSC or DJGPP */\n#      include <malloc.h>\n#    endif\n#  endif\n#endif\n\n#ifdef AMIGA\n#  define OS_CODE  1\n#endif\n\n#if defined(VAXC) || defined(VMS)\n#  define OS_CODE  2\n#  define F_OPEN(name, mode) \\\n     fopen((name), (mode), \"mbc=60\", \"ctx=stm\", \"rfm=fix\", \"mrs=512\")\n#endif\n\n#ifdef __370__\n#  if __TARGET_LIB__ < 0x20000000\n#    define OS_CODE 4\n#  elif __TARGET_LIB__ < 0x40000000\n#    define OS_CODE 11\n#  else\n#    define OS_CODE 8\n#  endif\n#endif\n\n#if defined(ATARI) || defined(atarist)\n#  define OS_CODE  5\n#endif\n\n#ifdef OS2\n#  define OS_CODE  6\n#  if defined(M_I86) && !defined(Z_SOLO)\n#    include <malloc.h>\n#  endif\n#endif\n\n#if defined(MACOS) || defined(TARGET_OS_MAC)\n#  define OS_CODE  7\n#  ifndef Z_SOLO\n#    if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os\n#      include <unix.h> /* for fdopen */\n#    else\n#      ifndef fdopen\n#        define fdopen(fd,mode) NULL /* No fdopen() */\n#      endif\n#    endif\n#  endif\n#endif\n\n#ifdef __acorn\n#  define OS_CODE 13\n#endif\n\n#if defined(WIN32) && !defined(__CYGWIN__)\n#  define OS_CODE  10\n#endif\n\n#ifdef _BEOS_\n#  define OS_CODE  16\n#endif\n\n#ifdef __TOS_OS400__\n#  define OS_CODE 18\n#endif\n\n#ifdef __APPLE__\n#  define OS_CODE 19\n#endif\n\n#if defined(_BEOS_) || defined(RISCOS)\n#  define fdopen(fd,mode) NULL /* No fdopen() */\n#endif\n\n#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX\n#  if defined(_WIN32_WCE)\n#    define fdopen(fd,mode) NULL /* No fdopen() */\n#  else\n#    define fdopen(fd,type)  _fdopen(fd,type)\n#  endif\n#endif\n\n#if defined(__BORLANDC__) && !defined(MSDOS)\n  #pragma warn -8004\n  #pragma warn -8008\n  #pragma warn -8066\n#endif\n\n/* provide prototypes for these when building zlib without LFS */\n#if !defined(_WIN32) && \\\n    (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)\n    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));\n    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));\n    ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));\n#endif\n\n        /* common defaults */\n\n#ifndef OS_CODE\n#  define OS_CODE  3     /* assume Unix */\n#endif\n\n#ifndef F_OPEN\n#  define F_OPEN(name, mode) fopen((name), (mode))\n#endif\n\n         /* functions */\n\n#if defined(pyr) || defined(Z_SOLO)\n#  define NO_MEMCPY\n#endif\n#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)\n /* Use our own functions for small and medium model with MSC <= 5.0.\n  * You may have to use the same strategy for Borland C (untested).\n  * The __SC__ check is for Symantec.\n  */\n#  define NO_MEMCPY\n#endif\n#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)\n#  define HAVE_MEMCPY\n#endif\n#ifdef HAVE_MEMCPY\n#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */\n#    define zmemcpy _fmemcpy\n#    define zmemcmp _fmemcmp\n#    define zmemzero(dest, len) _fmemset(dest, 0, len)\n#  else\n#    define zmemcpy memcpy\n#    define zmemcmp memcmp\n#    define zmemzero(dest, len) memset(dest, 0, len)\n#  endif\n#else\n   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));\n   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));\n   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));\n#endif\n\n/* Diagnostic functions */\n#ifdef ZLIB_DEBUG\n#  include <stdio.h>\n   extern int ZLIB_INTERNAL z_verbose;\n   extern void ZLIB_INTERNAL z_error OF((char *m));\n#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}\n#  define Trace(x) {if (z_verbose>=0) fprintf x ;}\n#  define Tracev(x) {if (z_verbose>0) fprintf x ;}\n#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}\n#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}\n#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}\n#else\n#  define Assert(cond,msg)\n#  define Trace(x)\n#  define Tracev(x)\n#  define Tracevv(x)\n#  define Tracec(c,x)\n#  define Tracecv(c,x)\n#endif\n\n#ifndef Z_SOLO\n   voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,\n                                    unsigned size));\n   void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));\n#endif\n\n#define ZALLOC(strm, items, size) \\\n           (*((strm)->zalloc))((strm)->opaque, (items), (size))\n#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))\n#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}\n\n/* Reverse the bytes in a 32-bit value */\n#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \\\n                    (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))\n\n#endif /* ZUTIL_H */\n"
  },
  {
    "path": "third_party/ltp/README.md",
    "content": "# Linux Test Project\n\nThis folder downloads prebuilt binaries from the [Linux Test\nProject](https://github.com/linux-test-project/ltp).\n\n## Changes\n\n1. Comment out the capability code in lib/tst_capability.c\n2. Comment out the code that opens /proc/meminfo\n3. Remove `clone()` + `O_PATH` test from `close_range02`\n4. Remove `ifconfig lo up 127.0.0.1` code from sendmsg01\n5. Remove last test case (msg_control efault) from sendmsg01\n6. Fix readlink03 to work with Musl and not require root\n\n## Build\n\nThe binaries were compiled on Alpine Linux using:\n\n```\n./configure CFLAGS=\"-Os -fno-omit-frame-pointer\" \\\n            LDFLAGS=\"-Wl,-z,common-page-size=65536,-z,max-page-size=65536\"\nmake -j16\nmake install\n```\n\n## Deploy\n\nThe above commands install to `/opt/ltp` by default. Our operations team\nthem uses [deploy-ltp](deploy-ltp) to deploy individual test programs to\nGoogle Cloud Storage once they've been confirmed to work.\n"
  },
  {
    "path": "third_party/ltp/bin/1/accept01.elf.gz.sha256",
    "content": "8be297aac04898e802eff3a59dabf089f21b8e244240187667588ec43a0abbe1 *third_party/ltp/bin/1/accept01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/accept4_01.elf.gz.sha256",
    "content": "4298c541d8fe9236140640fbd01e36f49439b99b29a9ffc35300262ebd4d1cca *third_party/ltp/bin/1/accept4_01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/access01.elf.gz.sha256",
    "content": "1b2dd6ced61e14ca16a3b093990dab15dd7ca2b2d3eae45c1131c3630da570f2 *third_party/ltp/bin/1/access01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/access03.elf.gz.sha256",
    "content": "efdf8705968d75ee29be6bb51849356851fd3cb884dde4830a91602f422052b7 *third_party/ltp/bin/1/access03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/alarm02.elf.gz.sha256",
    "content": "084c112cee6317841f8f4ccde65b171d7f374f0dd22a5718767e4f2af33db86a *third_party/ltp/bin/1/alarm02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/alarm03.elf.gz.sha256",
    "content": "1705faec22f30906c5c0acec673a5fb59b4f1bc35249dbbe1eb26812966041a9 *third_party/ltp/bin/1/alarm03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/alarm05.elf.gz.sha256",
    "content": "6aa3e65361ac20913accb491075a35629781cfb8feef1d4f865bb33d79df9d26 *third_party/ltp/bin/1/alarm05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/alarm06.elf.gz.sha256",
    "content": "477dd8cb87977b612b848f2a1a5745f3dca786fdc590214ff25d460e8cc053dd *third_party/ltp/bin/1/alarm06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/alarm07.elf.gz.sha256",
    "content": "9a26f2b216ed97c3e7f809a7baec9678f08b5f8a693d7ab40db3ecbcdc9e180f *third_party/ltp/bin/1/alarm07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/atof01.elf.gz.sha256",
    "content": "bbdd6e440e7ed00422a571ff0526bc3b9a3b388854672c2111f30b42471b6832 *third_party/ltp/bin/1/atof01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/autogroup01.elf.gz.sha256",
    "content": "0f2e7b22e8205a6b138d9acd41780189053df87e8e908e32232423cd286b526f *third_party/ltp/bin/1/autogroup01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/bind01.elf.gz.sha256",
    "content": "dd5d91d70ec7fc6817229eb2075a2a98a9b88aa809722a650693e25578c11772 *third_party/ltp/bin/1/bind01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/bind03.elf.gz.sha256",
    "content": "13cc3baf18a1cc26cf3d16acf0355a152045606a9f33883869200ed214b4890f *third_party/ltp/bin/1/bind03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/brk02.elf.gz.sha256",
    "content": "a18a7545537a72b944debb1154def6090e69796fb71da0a97aaba9cf0130884a *third_party/ltp/bin/1/brk02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/chmod01.elf.gz.sha256",
    "content": "7d08068f43e0f4a543d76a86fb81d2b6f2cc9598aa26e7cef8a59819d0b4547c *third_party/ltp/bin/1/chmod01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/chmod07.elf.gz.sha256",
    "content": "efe3d9b51a682d45af0196918cda079233d978341bae6c26aaaad9074b149710 *third_party/ltp/bin/1/chmod07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/chown01.elf.gz.sha256",
    "content": "7ebb1a680b65137bacb5b3eabc20e45fc631d1d791e93bcb9f72a9b4383be8b6 *third_party/ltp/bin/1/chown01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/chown02.elf.gz.sha256",
    "content": "c05ceec3d671c95655c88f16f4f34ed8bd35f63c3b47ab02a0b85d52c6ee8de6 *third_party/ltp/bin/1/chown02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/chown05.elf.gz.sha256",
    "content": "9e1087977140d520c2050f9299fd4ed4bd5e8dc2cc6036884b2c0e372ef16c57 *third_party/ltp/bin/1/chown05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/clock_getres01.elf.gz.sha256",
    "content": "70b0d8ab83e8c0b95e1f04f0e710d734fa4857f402375b7aef7c2a69c7c08593 *third_party/ltp/bin/1/clock_getres01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/clock_gettime01.elf.gz.sha256",
    "content": "950a082264b3991fa86b90caa34f86e6980f79cce01c035c523ea15e0dd080e3 *third_party/ltp/bin/1/clock_gettime01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/clock_gettime04.elf.gz.sha256",
    "content": "78d3dc1a6026ebab9d8f0642845a243c64b9e61f218ab698efa4479db71f4479 *third_party/ltp/bin/1/clock_gettime04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/clock_nanosleep02.elf.gz.sha256",
    "content": "22688da9bf35eed2e16978ab97a55d3cca5e29d0e64e443dea987945db7901c5 *third_party/ltp/bin/1/clock_nanosleep02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/clock_nanosleep04.elf.gz.sha256",
    "content": "355b83af7d72cc06329ae52c3c9866e276f3e2f5df139815d53dfca35090d748 *third_party/ltp/bin/1/clock_nanosleep04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/close01.elf.gz.sha256",
    "content": "740b3669067d009ce873a57328f66556db81a5b4ba303c1a968e5aaa289d18b5 *third_party/ltp/bin/1/close01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/close02.elf.gz.sha256",
    "content": "af019102260b3e0877e8a9e326bb144caa839311987f1617aba29390537848b7 *third_party/ltp/bin/1/close02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/close_range02.elf.gz.sha256",
    "content": "a4f384affd1c3ead5c6e6d60ac535e509afe7f3338a7b43d10cc6c4487625628 *third_party/ltp/bin/1/close_range02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/confstr01.elf.gz.sha256",
    "content": "638aa1c54b881fcc4a83d25bcc4c59e100f3a8fcaef8222f45da1ddfbeec09df *third_party/ltp/bin/1/confstr01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/creat01.elf.gz.sha256",
    "content": "06aa90ba72b162c0067c20a90146f042ac675e5f1aadabc5f2015aa4319a4bb4 *third_party/ltp/bin/1/creat01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/creat03.elf.gz.sha256",
    "content": "796ddd79c19afb126cbcc9290a74a5fc22f45b6fcbff037ffa2bf05b366dcf60 *third_party/ltp/bin/1/creat03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/creat05.elf.gz.sha256",
    "content": "394d43d022f284e02e014890f89fa79c6a05831f31923b147fb65b6cb3129c0a *third_party/ltp/bin/1/creat05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup01.elf.gz.sha256",
    "content": "ab34c37bd989596be9cdc9fc5805a919695ed605432fd7e982ed14986344d700 *third_party/ltp/bin/1/dup01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup02.elf.gz.sha256",
    "content": "e78930aea6769b941ad10c9085296da1ece6969ece3fa46f7c292fefc6c4c6bc *third_party/ltp/bin/1/dup02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup04.elf.gz.sha256",
    "content": "d2e1329cf2a2ad36fcf0c4d332691df9f56a5b2c8a6b657534755de8dbe77e53 *third_party/ltp/bin/1/dup04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup05.elf.gz.sha256",
    "content": "3e4b4c5ca82c5fca7fce88516565f3010a26a5124e2ddd2c87ab7618863bab92 *third_party/ltp/bin/1/dup05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup07.elf.gz.sha256",
    "content": "ea2eb8e010d90948bd82cbd69d48e4410e549da541467549ae49f6b46d7603b8 *third_party/ltp/bin/1/dup07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup201.elf.gz.sha256",
    "content": "0bd811ba6e42d298e7ece94fa1d0334de4f706efef744965b4118e8433f67b22 *third_party/ltp/bin/1/dup201.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup202.elf.gz.sha256",
    "content": "848fbd203c32427755363f2fc534b51aba352f671593962b5389991b6bc32825 *third_party/ltp/bin/1/dup202.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup203.elf.gz.sha256",
    "content": "072b255d5d937555065a383ccc0ab7449fcb6100146f3c9ae74a7344337e701a *third_party/ltp/bin/1/dup203.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup204.elf.gz.sha256",
    "content": "7451ebc1f71fde791b8dc545e9a9aad09a974ec0caa109061215957517c326b2 *third_party/ltp/bin/1/dup204.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup206.elf.gz.sha256",
    "content": "b040a0781d857f7a2284ff35640c3675063b3c2e17b537d627059099285010a1 *third_party/ltp/bin/1/dup206.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup207.elf.gz.sha256",
    "content": "ae9760d8028c77861a02b864aef91ed624f2b2fb5afef04937ac8a76d0b70e28 *third_party/ltp/bin/1/dup207.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup3_01.elf.gz.sha256",
    "content": "70a3f8bea3406e1042aa2ce8ab0c6239db5ee55bfac9ff35572020669dfedfd7 *third_party/ltp/bin/1/dup3_01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/dup3_02.elf.gz.sha256",
    "content": "3b2d058d83cd655583a54b6864ff8aeeb09e8dfaf21a8d9cd18d66fe69744838 *third_party/ltp/bin/1/dup3_02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/exit01.elf.gz.sha256",
    "content": "5402cb31e0f7b44e20be3e90db7876aaa49bb45f872003366142b657a93d73a0 *third_party/ltp/bin/1/exit01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/exit02.elf.gz.sha256",
    "content": "87fe3a84d0e01fa8bbeaf9c04b49fa7a716034553977188d152ec13fff8ce9ee *third_party/ltp/bin/1/exit02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/exit_group01.elf.gz.sha256",
    "content": "78b017a90373f1ca99e68cedd790c2c91a30864f6fb07e1b9a2ac678fea1be0b *third_party/ltp/bin/1/exit_group01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fchdir01.elf.gz.sha256",
    "content": "bbf63ea543617807cf25c9829f7c872f20b2a8506642f7ceda3b3dc45de0c6c2 *third_party/ltp/bin/1/fchdir01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fchdir02.elf.gz.sha256",
    "content": "4e3a89620777a97a9f8c1b2f1a6d962d719edf398bd852b6029d4711207eff53 *third_party/ltp/bin/1/fchdir02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fchmod01.elf.gz.sha256",
    "content": "368881273c24340c7d918e535fa2a7aa588e5c065faf1976fab5f0f5d23a10d0 *third_party/ltp/bin/1/fchmod01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fchmod02.elf.gz.sha256",
    "content": "95f7d6a3b8d98b3e9c7d9e088e3e2f2e0e1ea771be0971c528c6d0e1a892173b *third_party/ltp/bin/1/fchmod02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fchmod04.elf.gz.sha256",
    "content": "d0670a210185cf62b28c5a450caadc5957ce1c54dac19462d3a616250b22e136 *third_party/ltp/bin/1/fchmod04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fchown01.elf.gz.sha256",
    "content": "b82b9a4adb364e528140952ddeff991a84188375fb1ef59fbc51ba87ab7358eb *third_party/ltp/bin/1/fchown01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fchown02.elf.gz.sha256",
    "content": "53d4621f4c7f7ae4cf7a0df627a1935d827f6c3c3cd9a64af2bb7bbf2a8399a4 *third_party/ltp/bin/1/fchown02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fchown05.elf.gz.sha256",
    "content": "db4cdccae551cf5bb4c4712561cea71317170992cd0f4114844040de8f0568ab *third_party/ltp/bin/1/fchown05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fchownat01.elf.gz.sha256",
    "content": "c05577ea1253f0f19ea628ebf84b9c5b9113a9f9fd3711ceeff5765cd915c2d2 *third_party/ltp/bin/1/fchownat01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl01.elf.gz.sha256",
    "content": "09f22692842ee24f473ff4cc61b831fb8799a19110e0cc9158137bec1daa7d8f *third_party/ltp/bin/1/fcntl01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl01_64.elf.gz.sha256",
    "content": "8dc9e54c488302bf2a8c32b368708bee978a52549d1a27c94a92c628bb562151 *third_party/ltp/bin/1/fcntl01_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl02.elf.gz.sha256",
    "content": "2b4d15750fe260d8ff5261b13167d8bfb6769b1266b4b3ffa1f60bbacb93b3b2 *third_party/ltp/bin/1/fcntl02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl02_64.elf.gz.sha256",
    "content": "5f0eab69a639f11bba2407a1d9412e5a6ecdb361ce3bc55893f90564b44ed621 *third_party/ltp/bin/1/fcntl02_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl03.elf.gz.sha256",
    "content": "51afd73dd7413c5769c995d2858dd14781db969508c54aa45b7e24753dc74bc7 *third_party/ltp/bin/1/fcntl03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl03_64.elf.gz.sha256",
    "content": "09807c43c483f7396045beab3437e4138a242bc58166de1b2340f0e43fe01834 *third_party/ltp/bin/1/fcntl03_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl04.elf.gz.sha256",
    "content": "097816716e5af5ab53c3a4d128f561cd5e7895a135f88ef3593ba5a12f8e679e *third_party/ltp/bin/1/fcntl04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl04_64.elf.gz.sha256",
    "content": "af6ed53c0d6ad6e2c687458edd54e5240cdb5ade06fef38e754e8eb1ba9ee776 *third_party/ltp/bin/1/fcntl04_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl08.elf.gz.sha256",
    "content": "de2ddc59ebe8d21b543412ae688b3e04dd344c8bf2402f5d2e9ad544e1332ab5 *third_party/ltp/bin/1/fcntl08.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl08_64.elf.gz.sha256",
    "content": "19d1beb1950a931b82467deab065a7a0d6502f771208bca575c32aa1d8d1be71 *third_party/ltp/bin/1/fcntl08_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl09.elf.gz.sha256",
    "content": "f6cca69c98a0b07f67808f4626fc4dd2ed82d416e830d46a585d2b6fbee7c7f4 *third_party/ltp/bin/1/fcntl09.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl09_64.elf.gz.sha256",
    "content": "e5e918b6113c28c4f305c98ddbdfaa3dc90a93b76046058a049fe0a67f5a4a15 *third_party/ltp/bin/1/fcntl09_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl10.elf.gz.sha256",
    "content": "fb11b9b1e92133f4ad9968deb82501a1af81790650f19b31a35d4f5ddbe02a81 *third_party/ltp/bin/1/fcntl10.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl10_64.elf.gz.sha256",
    "content": "393cdabc749afa5fc06c6d88879e349f7feb972bbf29e315b0bea13855ef1c60 *third_party/ltp/bin/1/fcntl10_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl11.elf.gz.sha256",
    "content": "d0b1b8ba0d11d2374cbdeba62af83ad56898f2af4cb44ec5596ad4142983f7c6 *third_party/ltp/bin/1/fcntl11.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl11_64.elf.gz.sha256",
    "content": "9a3f730adf0f77a5801acad6f52ee673a58fa125a0f1cdf799f58e367b9c2848 *third_party/ltp/bin/1/fcntl11_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl14.elf.gz.sha256",
    "content": "1657bdde6f677d8abf6f37870743cdf2e058847a42820d92d630ad1f5d64fc75 *third_party/ltp/bin/1/fcntl14.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl14_64.elf.gz.sha256",
    "content": "175df03f43977a98f497f2a486dc3dd024bd37560b7a90fb21c459bf6c8d56f9 *third_party/ltp/bin/1/fcntl14_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl15.elf.gz.sha256",
    "content": "7f68ad245b0e5116d83946c494677a3de1808faf5a177a92044aa76f1fddfc98 *third_party/ltp/bin/1/fcntl15.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl15_64.elf.gz.sha256",
    "content": "ad5bd350b9374461b3ff9666b20c0751cb90e1156892ec6c7bcdb18d15e5451e *third_party/ltp/bin/1/fcntl15_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl16.elf.gz.sha256",
    "content": "945443b33f8aee9dd418d19aade3900ba709f459241f85eca2a0e84d93c35a71 *third_party/ltp/bin/1/fcntl16.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl16_64.elf.gz.sha256",
    "content": "c96ab7546fb9dc1309d5778499cfc58a9a47ac9ede03448d9c6df0d60d102b93 *third_party/ltp/bin/1/fcntl16_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl17.elf.gz.sha256",
    "content": "32d7623cfd68553be65d44cc11875741f0bd692b6b0f0313c259f083796aa2e5 *third_party/ltp/bin/1/fcntl17.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl17_64.elf.gz.sha256",
    "content": "cea4fdd758c5ba7b87fa7785dfa16460bc8d6b4c0337d1eb8dc87cfaf4be48b5 *third_party/ltp/bin/1/fcntl17_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl19.elf.gz.sha256",
    "content": "9671f64ef747a47beebb34ae8e0811c07595452ec11459f4ded933ad5d9a22e4 *third_party/ltp/bin/1/fcntl19.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl19_64.elf.gz.sha256",
    "content": "8f0000ace04e6041c03878277beee8501849ac0f042b7ac6391bc11faaf53a32 *third_party/ltp/bin/1/fcntl19_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl20.elf.gz.sha256",
    "content": "ee7e1cc1012778fcde900f8ca30aa38ae1a4045f3074c5f8b405e615e1d0642f *third_party/ltp/bin/1/fcntl20.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl20_64.elf.gz.sha256",
    "content": "f1fa5b0d3f272929d0cc00bb06d161fd5133e653641a0f0d40f4255b495402d5 *third_party/ltp/bin/1/fcntl20_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl21.elf.gz.sha256",
    "content": "ce829b80eda9ae119b82d966cc5ae908eafeb6ae51164bf9c64065f7947af29c *third_party/ltp/bin/1/fcntl21.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl21_64.elf.gz.sha256",
    "content": "1f909aec2c9c723479d22782ec6f0654e8fbc34450e6769cf2dbfb63c85877b8 *third_party/ltp/bin/1/fcntl21_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl22.elf.gz.sha256",
    "content": "29cd5f6d757480443f6cc41d10284cb319281ccad6be56b536c53507068ec8c9 *third_party/ltp/bin/1/fcntl22.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl22_64.elf.gz.sha256",
    "content": "90ebdc991791bd387639108fc98ce597665b8ce4511bf5376becf9a775265f34 *third_party/ltp/bin/1/fcntl22_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl27.elf.gz.sha256",
    "content": "cbb879fbcedb8227e113a567d40da005d3db1433dd69bf8a0d79b246c1192aca *third_party/ltp/bin/1/fcntl27.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl27_64.elf.gz.sha256",
    "content": "eaf116f11886cf8de8c62d1a298842a7103523e34c6d040f98deefa319b20cf4 *third_party/ltp/bin/1/fcntl27_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl28.elf.gz.sha256",
    "content": "c41838a5633d4c6407da308ba37c927d3d2730a756c3f36928b14f323cc68e3e *third_party/ltp/bin/1/fcntl28.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl28_64.elf.gz.sha256",
    "content": "c403dba04bb89c7c0e651a93d7839201d4f3c27b641a52230c3d00ce7b554d57 *third_party/ltp/bin/1/fcntl28_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl29.elf.gz.sha256",
    "content": "554d471ed7a7da9af63becd6a5d6366ccda8a32ec1f366c1a90f8070636a964e *third_party/ltp/bin/1/fcntl29.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fcntl29_64.elf.gz.sha256",
    "content": "3fef8b5e3700c33a9b478e5b9e1d49d094c7ae557d625e1ab608fc32ca0c7a3f *third_party/ltp/bin/1/fcntl29_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fdatasync01.elf.gz.sha256",
    "content": "19035b4de2775803abf5d63feac2e23f72880d2c6521aef85b5f0dd1d2cdbb72 *third_party/ltp/bin/1/fdatasync01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fdatasync02.elf.gz.sha256",
    "content": "f0d28ea4c7f12285ff068f1058dfb24f97eded8c09b0503cc1799642865137d6 *third_party/ltp/bin/1/fdatasync02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/flock01.elf.gz.sha256",
    "content": "997cd0e43b95396a3743410f8cc79ffa779660a319be340e845b7451fe645510 *third_party/ltp/bin/1/flock01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/flock02.elf.gz.sha256",
    "content": "3da2c168fdf3d406aea42dc5db5cfd11b90a3ba69e069bc4073163e6264999be *third_party/ltp/bin/1/flock02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/flock03.elf.gz.sha256",
    "content": "4dbfb6d65d191f16271a33795d2beafcd4b87f687f5f8bde594760f39b52d48a *third_party/ltp/bin/1/flock03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/flock04.elf.gz.sha256",
    "content": "37c0cf648faa4e7bfee8c2c2ec814d69f6099083fbca163e6215b87ada5f807e *third_party/ltp/bin/1/flock04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/flock06.elf.gz.sha256",
    "content": "d0f43b4e4c4b4331a2df751579e7292873f379136594086c5bd3e1fac27eb1f5 *third_party/ltp/bin/1/flock06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fork01.elf.gz.sha256",
    "content": "5477be68eee3e82e1c61eaee8b0bad80e7ad1e5bd1b2fb82b263b28ffbbfe98a *third_party/ltp/bin/1/fork01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fork03.elf.gz.sha256",
    "content": "564b2cd7a593011e784a3b3dae28c916f91768654d89102538bdb66baee06890 *third_party/ltp/bin/1/fork03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fork04.elf.gz.sha256",
    "content": "65b22f25cf86b1e5cf5e06ee2f6e84aac391821adfe5e605c661f7254d332859 *third_party/ltp/bin/1/fork04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fork05.elf.gz.sha256",
    "content": "2a35455fb1d9a3611d312f0744acca05a9f20c120eeab33f1308f74d89ca2a2e *third_party/ltp/bin/1/fork05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fork06.elf.gz.sha256",
    "content": "e509b64486b0805a1a4261af80a7c2cd651f7fac9e24462789fa459acbcae17f *third_party/ltp/bin/1/fork06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fork07.elf.gz.sha256",
    "content": "2f283551ce16491e8765621eb69e456c51dadf1c735d5d5c5e3cbfa10539a8b2 *third_party/ltp/bin/1/fork07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fork08.elf.gz.sha256",
    "content": "ae8923f64dcd55c98f0258576e5ae9d5a2b89b44d6ff1262ec23b13db5c421ba *third_party/ltp/bin/1/fork08.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fork09.elf.gz.sha256",
    "content": "2c4fbf7dbf4b0522b7865490a505119c3243318feb3a84b6a6f986d57d5e3ee3 *third_party/ltp/bin/1/fork09.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fork10.elf.gz.sha256",
    "content": "2d1b4854e75c001bafaf8f23e5cff8aa3ddd7fcfebee5e599d3c55ccf4269460 *third_party/ltp/bin/1/fork10.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fork11.elf.gz.sha256",
    "content": "04fb3f2f1aedd2656adab52cb48ad818e003c9c1a37db6973b6b3474187842a7 *third_party/ltp/bin/1/fork11.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fstat02.elf.gz.sha256",
    "content": "6dd97e653f3c247bccf93d288ac211b6b5f578db0fc497ea5b3cf2767ebdd432 *third_party/ltp/bin/1/fstat02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fsync02.elf.gz.sha256",
    "content": "08a13ddc919b7f16222df0ec437710cdd6a38a3039452ed8a26bcc0d664ecbd1 *third_party/ltp/bin/1/fsync02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/fsync03.elf.gz.sha256",
    "content": "2bcf35c4167845690cf91406fe0dc920513b3e9a5b52636b3b0b626851b39914 *third_party/ltp/bin/1/fsync03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/ftruncate01.elf.gz.sha256",
    "content": "682580f6365afb2cdcad497d03525280686c4fa5848a79e5259fdcc14a22e344 *third_party/ltp/bin/1/ftruncate01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/ftruncate01_64.elf.gz.sha256",
    "content": "2c402e75d8b909054da02b02535943e7f78cac73e267166febdb9d79d9aac9bb *third_party/ltp/bin/1/ftruncate01_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/ftruncate03.elf.gz.sha256",
    "content": "ba812430672cf0173d503b3905793fd1741fe2b5c84488c9c8c3257316a5b977 *third_party/ltp/bin/1/ftruncate03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/ftruncate03_64.elf.gz.sha256",
    "content": "4b1084c19c2fc914e5a86947c307530f26074a9ff49feb09ad366a14c3d1788e *third_party/ltp/bin/1/ftruncate03_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/futex_wait01.elf.gz.sha256",
    "content": "c9235da2c4c5de63a72c74a36fbda638c1bef2a4df0fd08a183d504ea9f81311 *third_party/ltp/bin/1/futex_wait01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/futex_wait02.elf.gz.sha256",
    "content": "18565f8dd16395a085b6c894a9213b31f418b60370b214777b56c8a2f795024f *third_party/ltp/bin/1/futex_wait02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/futex_wait04.elf.gz.sha256",
    "content": "2e1e8f1ed6b92a6f3fbb98d6f5c07b299ba4d82ece38a1a42b969d6cd10fd56c *third_party/ltp/bin/1/futex_wait04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/futex_wait05.elf.gz.sha256",
    "content": "3dd5f2518f22602646e4ced98c45d2eba8dd8e37a5b4146600a069f290f46ded *third_party/ltp/bin/1/futex_wait05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/futex_wake01.elf.gz.sha256",
    "content": "bace142aab8bae74c4388e57d0e12e5152bdd8e995f0ba0dc019f6294eef71ba *third_party/ltp/bin/1/futex_wake01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/futex_wake04.elf.gz.sha256",
    "content": "88dd31b660ff1fe1fc1f6f7af4549afb03395096cf0a780186b485646698d4fc *third_party/ltp/bin/1/futex_wake04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getcwd02.elf.gz.sha256",
    "content": "8bc18661f65b9a8dc1578cde9a07240870a99ab925a7f0a55091d4c97ba1bb3f *third_party/ltp/bin/1/getcwd02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getcwd03.elf.gz.sha256",
    "content": "58fdd9525c7aa7a8a89c0aa70b6108aa70a3f57e2b64881355703977199255a8 *third_party/ltp/bin/1/getcwd03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getcwd04.elf.gz.sha256",
    "content": "1df242ad97b20d6fee49394e51bc5fea699aa0cc51d10159723b291f4bb60760 *third_party/ltp/bin/1/getcwd04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getdents01.elf.gz.sha256",
    "content": "300786f1f462fb0eb5fbf2d6baaf7050f02a165d5fc20c5cab0f0f3e2114b29f *third_party/ltp/bin/1/getdents01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getdomainname01.elf.gz.sha256",
    "content": "5426855ec456873e72622436e30000e4a8c28005dcc7e38e96ed846c6c0d1f6b *third_party/ltp/bin/1/getdomainname01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getegid01.elf.gz.sha256",
    "content": "f22444b80db6c7ba5914de096eb8ab4b53d0830dfac0e59b999c6b4f1e274d9a *third_party/ltp/bin/1/getegid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getegid02.elf.gz.sha256",
    "content": "b74ddea5184a2c36b51dd805184b00b1025d4855f3f4bd0d56f0f688f7f46c9d *third_party/ltp/bin/1/getegid02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/geteuid01.elf.gz.sha256",
    "content": "ef215995e4096d9b840a2848c98db22bcfcada481b05e3e87fa4c5099314d3a2 *third_party/ltp/bin/1/geteuid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/geteuid02.elf.gz.sha256",
    "content": "c39cc88e1cc37b4b9f34d3fa1b60e5f5f2e17fe91dc644a3cd8c127116c8222d *third_party/ltp/bin/1/geteuid02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getgid01.elf.gz.sha256",
    "content": "595a4c8adb76a83e2fac3ae335577017d92bc3938b2eeaf9cfbb0065a94cca21 *third_party/ltp/bin/1/getgid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getgid03.elf.gz.sha256",
    "content": "456c5252cab241d94fd9ba7cd3dd4a972de0c2f036e551080968c0ef9a9931c1 *third_party/ltp/bin/1/getgid03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getgroups03.elf.gz.sha256",
    "content": "9cf7085236f7808c3253a63ecd018c94df7ae1c03fe1a0a42ab45e25b77e1ae3 *third_party/ltp/bin/1/getgroups03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/gethostname01.elf.gz.sha256",
    "content": "c5b299bd1fcdd8ed1eccd9059156cea86a4f5a79f9780f5b1180350841ee0d18 *third_party/ltp/bin/1/gethostname01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getitimer01.elf.gz.sha256",
    "content": "dcf974e6927fd6cf594a974517e85490b6161b4f118b5358d19cbb2e61748641 *third_party/ltp/bin/1/getitimer01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getpagesize01.elf.gz.sha256",
    "content": "1b10f68c094dd732a530624ae8987747c0b9661f90288589371758c6261b36e8 *third_party/ltp/bin/1/getpagesize01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getpgid01.elf.gz.sha256",
    "content": "5e4501d06f36acf2cdd8c154c792ef4fc68a5d39ec39f6a685cf1871c548afff *third_party/ltp/bin/1/getpgid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getpgid02.elf.gz.sha256",
    "content": "34442a9fe3dbfe251ac5c5dc27d2fa9fd3818e1125d88a05f6dbc9e5ba06a97d *third_party/ltp/bin/1/getpgid02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getpgrp01.elf.gz.sha256",
    "content": "53d857be1d935758dc4506c15e038b06159326a5f385218410459099f58a7791 *third_party/ltp/bin/1/getpgrp01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getpid01.elf.gz.sha256",
    "content": "02609d2e939c67054847e73c8139c05d3881460c21d8f39f481ab87fceaf90ec *third_party/ltp/bin/1/getpid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getpid02.elf.gz.sha256",
    "content": "9a013299b2aa6594c78679565ba13a0d0328eb4b653309d12c79d1106fd36653 *third_party/ltp/bin/1/getpid02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getppid01.elf.gz.sha256",
    "content": "6fe5b617de4314af42841172725bb1d6c1e7d0da93fc34f0050734975e70a368 *third_party/ltp/bin/1/getppid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getppid02.elf.gz.sha256",
    "content": "102f3fa6b84aa8169897c3dad81a7e0dc42699fbcdc1b686abed77763f69a0b8 *third_party/ltp/bin/1/getppid02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getpriority02.elf.gz.sha256",
    "content": "868d0e61ed6e71c968e0e9cb6cd96d741d105bbc15b9d6d6c4059056c5d61330 *third_party/ltp/bin/1/getpriority02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getrandom02.elf.gz.sha256",
    "content": "787875bcfd619c58e3a2e2388cc67b9192a88a252d7b09ebc40a9bb546e284f4 *third_party/ltp/bin/1/getrandom02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getrandom03.elf.gz.sha256",
    "content": "b1ba2d5ec5e4b1000093fc027ad1a6a2710aed038384b822174194a131ba3cb1 *third_party/ltp/bin/1/getrandom03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getrandom04.elf.gz.sha256",
    "content": "d150112c5d509a1ed27d49c8677ef315ea136a6d19a0dccf5e4d2cdc40c61fc9 *third_party/ltp/bin/1/getrandom04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getrlimit01.elf.gz.sha256",
    "content": "df74c75e2668563ed4eadbd12766f396b33c115177f8dff0a6e1c26b5f9555f9 *third_party/ltp/bin/1/getrlimit01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getrlimit02.elf.gz.sha256",
    "content": "7b8538a1df3996ce686632b8ddbf905f1aa9149b541c3fd2fc2aeb51a10699f6 *third_party/ltp/bin/1/getrlimit02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getrlimit03.elf.gz.sha256",
    "content": "73baf6abf9d4b7ae864c90da0e7c23dc2cef907c7f365e2ac4d6e8f9dac75d35 *third_party/ltp/bin/1/getrlimit03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getrusage01.elf.gz.sha256",
    "content": "74100647c6d47569fb7fa1155bdb57b580d9542cbdc7f082db25dca4a81802f0 *third_party/ltp/bin/1/getrusage01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getsid01.elf.gz.sha256",
    "content": "32aeb85fd9fca70354e97f1ddb2b86a8e2657aa7713ebbefd2553b1fe0205a1d *third_party/ltp/bin/1/getsid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getsid02.elf.gz.sha256",
    "content": "67748e64e03b8356fdb6c79f0ee72e9208a8b806665f72612a87ab592064209e *third_party/ltp/bin/1/getsid02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/gettid01.elf.gz.sha256",
    "content": "e7f964678c8b55e90d1a2653867a28b8316d05f73ff9106c6786deca7a99d38e *third_party/ltp/bin/1/gettid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/gettimeofday01.elf.gz.sha256",
    "content": "9c749c6feacfb986118c2be8edaeee672cf0ec16b6605459bbd6b501eec6fe86 *third_party/ltp/bin/1/gettimeofday01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/gettimeofday02.elf.gz.sha256",
    "content": "c4f3d667506d325ecd638848ca7e92102cbb824c53d5fe28da69a1b2af8d7c6f *third_party/ltp/bin/1/gettimeofday02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getuid01.elf.gz.sha256",
    "content": "caf95d8ebabe3013f69e090e4a88e893268b0a01ed01cb403ea127bec0da30e0 *third_party/ltp/bin/1/getuid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/getuid03.elf.gz.sha256",
    "content": "8094c8254ec6bcfcb2d632d28357cc8e41b4298b239fae1b3e0c65793c09e52b *third_party/ltp/bin/1/getuid03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/growfiles.elf.gz.sha256",
    "content": "8c03c7f0ea872e28fe3ae4a530a49b8ba8c565cd5005234187f939c1560b65ea *third_party/ltp/bin/1/growfiles.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/hackbench.elf.gz.sha256",
    "content": "8d24a5411ea08f171cb92e6d92da85d220bf49c07ef5d7608410f8018538bf39 *third_party/ltp/bin/1/hackbench.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/hugemmap06.elf.gz.sha256",
    "content": "7d4c5b7371a630fe7467a58b962aff14d6c8d7e23ff8712a45f6ff124f33d0f4 *third_party/ltp/bin/1/hugemmap06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/in6_01.elf.gz.sha256",
    "content": "870f8045255618e6e80169c54a9fc12a2b610919f3452d6686f9a477b6d28fec *third_party/ltp/bin/1/in6_01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/inode01.elf.gz.sha256",
    "content": "592c1e57029cf801980f1e7926cf679d5e10f74fb69610da1bcdc87136362108 *third_party/ltp/bin/1/inode01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/inode02.elf.gz.sha256",
    "content": "a0f7cd8e90a7c6ab6ef995870147493f60f2e31105f92067e06f011a2fe13896 *third_party/ltp/bin/1/inode02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/kill02.elf.gz.sha256",
    "content": "5dd7518e70ec897317073595fca2e21bd0da16fca626e86d1e7e432b70129619 *third_party/ltp/bin/1/kill02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/kill03.elf.gz.sha256",
    "content": "eb1621ad8cd414750f9c5fb2db874ada6aadc1ac9aeda53133773dbfebf8ec4b *third_party/ltp/bin/1/kill03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/kill06.elf.gz.sha256",
    "content": "e4161cee47be47043984f6d77ec0439dc0c01af85f65f27ae8367d8c0a6fef90 *third_party/ltp/bin/1/kill06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/kill08.elf.gz.sha256",
    "content": "4dad7568238887ede7a96c8ad76df6a24d0a22113ce592d85eed6eb91479b1b1 *third_party/ltp/bin/1/kill08.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/kill09.elf.gz.sha256",
    "content": "7ad95b410c5415ff9966f63fa8a49c6437a1ca2b2703f08a3a59a35eca0aad63 *third_party/ltp/bin/1/kill09.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/link02.elf.gz.sha256",
    "content": "b98765d904531196e421b1e6719a3721ad2d6c21c3ad1dd0b915e473699ee4b1 *third_party/ltp/bin/1/link02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/link03.elf.gz.sha256",
    "content": "195cda95093c0b6ba4e7ace1b72416b7e0359cbd5271b80c2bc1bceb2b24e285 *third_party/ltp/bin/1/link03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/link05.elf.gz.sha256",
    "content": "416fd1baf3f4018c8c0a52745f1dd6aa4653c762fd455b8368f36c8bb8528659 *third_party/ltp/bin/1/link05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/linkat01.elf.gz.sha256",
    "content": "28c6d5041f7cf3c7211af02a98dc62ab4b3ab3420e3ab4d1f8ea1bac0bc59556 *third_party/ltp/bin/1/linkat01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/listen01.elf.gz.sha256",
    "content": "0394528e7cb651ac719c17b2d7608ac060f0ec3770f40bf924d2154f43c3c64c *third_party/ltp/bin/1/listen01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/llseek01.elf.gz.sha256",
    "content": "418b433c47e5f9546e9bad51cc562127e05ea035852b956c40a8dec90878aa48 *third_party/ltp/bin/1/llseek01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/llseek02.elf.gz.sha256",
    "content": "040efb8fc8b1655f2c8b26766294f29e2ed9339501f89fb9ad7cfafcbe6da398 *third_party/ltp/bin/1/llseek02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/llseek03.elf.gz.sha256",
    "content": "a0ebac43922529a0fbc6d01a25788e8334c059b5da239c425b52639f4bb0db40 *third_party/ltp/bin/1/llseek03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/locktests.elf.gz.sha256",
    "content": "4f9d5a58a86c019b036ba93c5a8143cf7d46bd2811cf0ca8412ae3c3c28100ce *third_party/ltp/bin/1/locktests.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/lseek01.elf.gz.sha256",
    "content": "3c71ccd178c7df973d9a0e15e04dda547e60c6b9ae59b2e51548d3f53d6ed72f *third_party/ltp/bin/1/lseek01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/lseek02.elf.gz.sha256",
    "content": "417156dc71fb0452d208f1812beab018340870e97f156e78bf4f1daddd8ae83e *third_party/ltp/bin/1/lseek02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/lseek07.elf.gz.sha256",
    "content": "ee1747bdf558435cc12664f663509c07329f25676cac4951b56df4a870e16190 *third_party/ltp/bin/1/lseek07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mkdir05.elf.gz.sha256",
    "content": "cc5eaaa8d08ddd857f43c692f2775a33c53a81075f4a94d165c569a370fbdae8 *third_party/ltp/bin/1/mkdir05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap-corruption01.elf.gz.sha256",
    "content": "014915878570853de3c6271a3089d1f8b59dc1f6bc8edc6cf3dc9168bf678a54 *third_party/ltp/bin/1/mmap-corruption01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap001.elf.gz.sha256",
    "content": "f2e9521f0b91fd320abfe427d5f8a376c3360e9549f54e1b3324ca097f38cf87 *third_party/ltp/bin/1/mmap001.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap01.elf.gz.sha256",
    "content": "2ac88ff6d2fe9427eda950091002a01c7b3316a01f628475a3ffaf3337e050ca *third_party/ltp/bin/1/mmap01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap02.elf.gz.sha256",
    "content": "88f95306e64572baa6bdda9aa68bb36556a051460f25b1e50812c8c19d5eaec6 *third_party/ltp/bin/1/mmap02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap03.elf.gz.sha256",
    "content": "f3a004bf6077f718d1f92ce748efbb4097be05165c22ef66ede987fd10d2a8ce *third_party/ltp/bin/1/mmap03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap04.elf.gz.sha256",
    "content": "f0d956f7483b10d18fc16cb450b19cd3f54c11d98a7da887c1aa3fa4fa6d8993 *third_party/ltp/bin/1/mmap04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap05.elf.gz.sha256",
    "content": "e62bef67c05ebe2c520c93d401f0ea38371b2ef11536afd8ce75143f199b46fa *third_party/ltp/bin/1/mmap05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap06.elf.gz.sha256",
    "content": "8f01e2e8bbb5afbebf8cccba189634f68142571a071c59a1ac113132b7f94659 *third_party/ltp/bin/1/mmap06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap07.elf.gz.sha256",
    "content": "b2601237a7122478500d378edb57658613ca96723ed2000953ca4d46488d5db4 *third_party/ltp/bin/1/mmap07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap08.elf.gz.sha256",
    "content": "1a69d969e57b00410fcc0adeefbdaae4e83b25cbc08be3b972ea6931a9e84ae6 *third_party/ltp/bin/1/mmap08.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap09.elf.gz.sha256",
    "content": "22b1fe8bf5120d123786a25d7ebc4b6b47a346a06e7d70a5589388a3da5af599 *third_party/ltp/bin/1/mmap09.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap10.elf.gz.sha256",
    "content": "740e73ea5956984197773da0c7879de7fcc6e1920f38ccab83acc32cb1808f15 *third_party/ltp/bin/1/mmap10.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap11.elf.gz.sha256",
    "content": "fdc9232bda153aa9591170adfe1b015997892fc28c1e073404282ef445603f6e *third_party/ltp/bin/1/mmap11.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap12.elf.gz.sha256",
    "content": "0d20d755f7dc2ffae3545da6ea6075db0ea07b32b0b1e8caccd8d7b5afa8caa8 *third_party/ltp/bin/1/mmap12.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmap19.elf.gz.sha256",
    "content": "39500e89a3248f7b300b0d41d7562efdce61a0e7813d884df8e5717e3d673c2d *third_party/ltp/bin/1/mmap19.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmapstress01.elf.gz.sha256",
    "content": "a55e338b4ad0ad1530215a79538c1d2d9e0615d5b4e8f20dc0e24f72515a0594 *third_party/ltp/bin/1/mmapstress01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mmapstress04.elf.gz.sha256",
    "content": "2a4645c0d3431a776ea163deef9dfcb2f506d8c26bb2d7affd4130fa3f9d79ed *third_party/ltp/bin/1/mmapstress04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mprotect02.elf.gz.sha256",
    "content": "ca741a3c4347a3d6ca6b04f8d34ce8e857f22ccecbfd1484ce13a6db460012ef *third_party/ltp/bin/1/mprotect02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/mprotect03.elf.gz.sha256",
    "content": "adbe22b176dca1ad5933eb50f839a8150b05d05eeab5d10224676142c502d998 *third_party/ltp/bin/1/mprotect03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/msync01.elf.gz.sha256",
    "content": "1b897961089537a1a97597594ca001ffa642378959bfc1fbd31096dcc9efda98 *third_party/ltp/bin/1/msync01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/msync02.elf.gz.sha256",
    "content": "0a4e6a25bb2fb549a868b5427ad07a4e278ec73ab1c5f577bc51c90190d17442 *third_party/ltp/bin/1/msync02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/munmap01.elf.gz.sha256",
    "content": "e322c26d1f9b3bf0f90fd77ebdeb734f4acaacdca6b7cc2c6cc93c9194f28487 *third_party/ltp/bin/1/munmap01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/munmap02.elf.gz.sha256",
    "content": "bf01f1e504f08a7632fc84960133f42afed0f3a5565a8ba81354ae74343c5686 *third_party/ltp/bin/1/munmap02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/munmap03.elf.gz.sha256",
    "content": "5a276dceec248d0cccb084d00df4f1767c983d8ddc7a274328f3eebc9a9b8c30 *third_party/ltp/bin/1/munmap03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/nanosleep01.elf.gz.sha256",
    "content": "06f00ff8c739a0ce4acbb3e4509158dd25d783b3010d5bdb5b9d258b9f1306c9 *third_party/ltp/bin/1/nanosleep01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/nanosleep02.elf.gz.sha256",
    "content": "d07f4546e0e46ab70e950b18140d7ea150ca4fa82f714b3843f8467c2cae9d54 *third_party/ltp/bin/1/nanosleep02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/nanosleep04.elf.gz.sha256",
    "content": "dbbd60eb4d8b1c23c8645b49e54de15cac0b115e33055a30113b4dd458635de4 *third_party/ltp/bin/1/nanosleep04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/nice04.elf.gz.sha256",
    "content": "769b42883f1b13b22ca4e5f34342c51d88fa93cac4c8b20e126b13831433b8ef *third_party/ltp/bin/1/nice04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/open01.elf.gz.sha256",
    "content": "b31fca912159b0a99525e19384406f795b59c80badf221d7e01f8eac4a4c54ac *third_party/ltp/bin/1/open01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/open03.elf.gz.sha256",
    "content": "09b8341b422624d7b1d3950d539fbef0ab111d1530f8efc283b38445e710d094 *third_party/ltp/bin/1/open03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/open04.elf.gz.sha256",
    "content": "d81143cbbcf3801d3b5e73cf861473fc86f3fd3cdb5290489b87b52bd5b1bea9 *third_party/ltp/bin/1/open04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/open06.elf.gz.sha256",
    "content": "e26997671b0e8b7f05f1ad4305e202788fecfd7e9bf4a87a6a6345f6e5492aba *third_party/ltp/bin/1/open06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/open09.elf.gz.sha256",
    "content": "a250953d56b1f0dfc82142bc61c6a6ce6d07e9234446fcccb1e8e99ca722e511 *third_party/ltp/bin/1/open09.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/open11.elf.gz.sha256",
    "content": "3648a047b316250630689b4c00f0c48c56e40cef33c1c75bf4f73af4264c29e1 *third_party/ltp/bin/1/open11.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/open14.elf.gz.sha256",
    "content": "0fb8de5191ca259a19ed84ffa5a4df6b19ae5ed433a17637c30a2f168428ca08 *third_party/ltp/bin/1/open14.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/openat03.elf.gz.sha256",
    "content": "4947a512eb005803409bd2e3d01f35d424d93fdf074f64420ee1a0d1621671b8 *third_party/ltp/bin/1/openat03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pause01.elf.gz.sha256",
    "content": "e268cb5284fca775edbf8aa95f6b896bcd1dc3f5335b12414446e2971d877c3e *third_party/ltp/bin/1/pause01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pause02.elf.gz.sha256",
    "content": "bea9da1959066fe0e4a6bdd3e83ba00477f3270359926f8bb9be4d4074d3a75a *third_party/ltp/bin/1/pause02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pause03.elf.gz.sha256",
    "content": "e78b20292b20cc58fe74a67e6ca7dacb42841820648e090dd60a5f35c35a40ff *third_party/ltp/bin/1/pause03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pipe01.elf.gz.sha256",
    "content": "21681ba03b3811ac626f32cd1c8531d347f754f90bfe59071734abec7954fb80 *third_party/ltp/bin/1/pipe01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pipe02.elf.gz.sha256",
    "content": "f4f1e32188a174d5c346102355bf65a0f3367bd10caeaeaca5e56cacb141426d *third_party/ltp/bin/1/pipe02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pipe03.elf.gz.sha256",
    "content": "8299ba2566f7e07364f39243b85ecf4c7cd14331558b251bd3248daca95407e4 *third_party/ltp/bin/1/pipe03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pipe04.elf.gz.sha256",
    "content": "121381ad75936770b6a4ee0b8202d7cf0f0ad490c6c7d26c5f7b7ba5acbbe31f *third_party/ltp/bin/1/pipe04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pipe06.elf.gz.sha256",
    "content": "c1bff6d82fb71383dfcf87f3890c0308f2ac697f731956a856b326193bd09ffd *third_party/ltp/bin/1/pipe06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pipe07.elf.gz.sha256",
    "content": "7fcc23914bc884afea92ace5b2206ba9e6f501ad45e37e75632ff9cd7e6ca7f3 *third_party/ltp/bin/1/pipe07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pipe08.elf.gz.sha256",
    "content": "9f35c887772144d180fb37bacbcedd60905b45ca372025d099e090c869fc7de5 *third_party/ltp/bin/1/pipe08.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pipe09.elf.gz.sha256",
    "content": "2f33e0fa69da950f3d1dba574252dcf5bc44ab12e500a607f768953d76a7a391 *third_party/ltp/bin/1/pipe09.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pipe10.elf.gz.sha256",
    "content": "51fb550c891654f5a12bf66673acf5522e7c28633f4ee6a4ef36927c22d29fca *third_party/ltp/bin/1/pipe10.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pipe11.elf.gz.sha256",
    "content": "da084f81a3ee615c824786fdcca7214598a856c368d0a8c9ff28bd6e68c6a012 *third_party/ltp/bin/1/pipe11.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pipe13.elf.gz.sha256",
    "content": "b1ed3088eade525609e2593b13b6b2e1dd67fd27395d735706426e981f8968c0 *third_party/ltp/bin/1/pipe13.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/poll01.elf.gz.sha256",
    "content": "dbf72c32fed35dd081d164752e5a082c8cdbbfff25d7a2fe5331b471b432000e *third_party/ltp/bin/1/poll01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/poll02.elf.gz.sha256",
    "content": "93a873fd84076c55c4d8b7fcf04603395bc9f0582fc20c8ef79567b902bc1823 *third_party/ltp/bin/1/poll02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pread01.elf.gz.sha256",
    "content": "7042380746ac89df2813979de12a05dba2aaff845ff29bbf3b5b2989dbbd8087 *third_party/ltp/bin/1/pread01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pread01_64.elf.gz.sha256",
    "content": "58a552a0ec34dc38645be19c99ed729e9f1340829d64197b44eba42576f7bb5a *third_party/ltp/bin/1/pread01_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pread02.elf.gz.sha256",
    "content": "fa11ee195ffe4a00829b01ab9accb4ec986b54a9a2c6af75bb20b5e7f74c2e66 *third_party/ltp/bin/1/pread02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pread02_64.elf.gz.sha256",
    "content": "45aea3fb8a5a627f60fff94da4f5ba508c47972c5fe932ef1d9c80d5e7526fee *third_party/ltp/bin/1/pread02_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/preadv01.elf.gz.sha256",
    "content": "02aeca903f6cd92946dbc39352f7f4ab48682c392178601a588425e0da47f4f0 *third_party/ltp/bin/1/preadv01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/preadv01_64.elf.gz.sha256",
    "content": "d0d7e905516756a692dc3ab4e37fefc2849a5f70171dfdae407d1cd27c4a5f44 *third_party/ltp/bin/1/preadv01_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pselect02.elf.gz.sha256",
    "content": "3638423affdb93f0849da45a3e621c5180f2350ea42c17b9297b995a9db7dd1c *third_party/ltp/bin/1/pselect02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pselect02_64.elf.gz.sha256",
    "content": "82cb9b8b6d96690ad8c677688425b9968521b85f89a0dc1a9a4490f79a88463a *third_party/ltp/bin/1/pselect02_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pselect03.elf.gz.sha256",
    "content": "3a72874442ae9cd33039bfd2a27cf529eb6d39b01fd39a7e838087dbaeec9c28 *third_party/ltp/bin/1/pselect03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pselect03_64.elf.gz.sha256",
    "content": "fb0fa986770b7a9f83834858a8119ccc7abb385ad4290b41a3fc971509fcadfc *third_party/ltp/bin/1/pselect03_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pty06.elf.gz.sha256",
    "content": "4c9c2882f36bfab3ac4097136030837f72222b30bc460dcd0a9b8b9f1056c2c2 *third_party/ltp/bin/1/pty06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pwrite01_64.elf.gz.sha256",
    "content": "b913600fe7b9324ee6e380b0c6f50b97a78007902394f664f216a95ffe549b66 *third_party/ltp/bin/1/pwrite01_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pwrite02.elf.gz.sha256",
    "content": "b64f0ffea3a0856a5690ab3b4ece8204159d828b5a96e466141b9c6e44cb1c9e *third_party/ltp/bin/1/pwrite02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pwrite02_64.elf.gz.sha256",
    "content": "8ff1db19280f2bf7f1d8954ecc16d499ace3b175ed7e9a7d83237ba8d2c689d9 *third_party/ltp/bin/1/pwrite02_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pwrite03.elf.gz.sha256",
    "content": "ebced3744c2071d2847eb58712314cce880cdabff42a38be5130a88be7f3ac64 *third_party/ltp/bin/1/pwrite03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pwrite03_64.elf.gz.sha256",
    "content": "8c9e8bb322933a397eaa02ffb5d9a3cab76847b92b56964230c5a65d6fd5fe02 *third_party/ltp/bin/1/pwrite03_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pwrite04.elf.gz.sha256",
    "content": "abc5becf429df58a85064a6b1172784215d7880f6b2367f0916eeaa1de198ef6 *third_party/ltp/bin/1/pwrite04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pwrite04_64.elf.gz.sha256",
    "content": "942550b0a88e9446f89ea5bc1d38627d6882e311b64ed4ab7914df269661956b *third_party/ltp/bin/1/pwrite04_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pwritev01.elf.gz.sha256",
    "content": "86f58c0c80e38e875d1713bd393179b0e4e9e1950694205324dbf31b8c5d89e7 *third_party/ltp/bin/1/pwritev01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/pwritev01_64.elf.gz.sha256",
    "content": "5afae7e0378b2030d9a18da16c8e2701f0fbb1f59673294106f2439dcc1c2501 *third_party/ltp/bin/1/pwritev01_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/read01.elf.gz.sha256",
    "content": "65542951cf0909e5d468ceff0e2de96947faeaf1c44f8088beb3fbb378131026 *third_party/ltp/bin/1/read01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/read03.elf.gz.sha256",
    "content": "5ec2e33296157424f9c2e19be3258aeaeb012709bfda083bcb0ff4823f8ed303 *third_party/ltp/bin/1/read03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/read04.elf.gz.sha256",
    "content": "d05c8cde47f3404844317e130d17b378549d77e49bbae757360c31b7aff99848 *third_party/ltp/bin/1/read04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/readdir01.elf.gz.sha256",
    "content": "2a6d3c39ba60c1155fb253804b895dff3a5eadc25a433c89ef8cfaea22848706 *third_party/ltp/bin/1/readdir01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/readlink01.elf.gz.sha256",
    "content": "f358605ca4385f53bf96a92fe697f3bd5367608c33e045365a70afa4b89c3dfa *third_party/ltp/bin/1/readlink01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/readv01.elf.gz.sha256",
    "content": "0c6d1e63495fd8ac78db765922a80ed6319c8ae96338be62f8a9192b2ae35e46 *third_party/ltp/bin/1/readv01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/recvmsg02.elf.gz.sha256",
    "content": "831eed3db116df2d4f9e7851156d8c64b8433e89d4fefe7df8e8127c417b677d *third_party/ltp/bin/1/recvmsg02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/rename09.elf.gz.sha256",
    "content": "c53212eca0e8a21fc4f4de8cf4117961d343e5fc3d8f39aaf2ae074629783b05 *third_party/ltp/bin/1/rename09.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/rename14.elf.gz.sha256",
    "content": "02fa3a4b6c2cc65a1046489bdf2ae4a90ff6eac5d136f7a0bfc0162851de7884 *third_party/ltp/bin/1/rename14.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/rmdir01.elf.gz.sha256",
    "content": "0bc718218998bfc10791a227603593985e6923e92cde446ddaa45321429d68eb *third_party/ltp/bin/1/rmdir01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/sbrk02.elf.gz.sha256",
    "content": "e9acf385a169d98858ba49c5546ed1f154c9c467f0c547ecba27ab5b77c4301e *third_party/ltp/bin/1/sbrk02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/sendto01.elf.gz.sha256",
    "content": "2954400919c7eeb9b06833cdf9007ed800074835c830c0810d48b9d63e8e0fb0 *third_party/ltp/bin/1/sendto01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/set_robust_list01.elf.gz.sha256",
    "content": "5b28043519629b8cfd33f1870b5c7a9bde3d23a4954b2d2a5d4ee47632822bf2 *third_party/ltp/bin/1/set_robust_list01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/set_tid_address01.elf.gz.sha256",
    "content": "f1df4c36b54930fa95fb6568b3c657adcd454e07e2757359356635449b9892b1 *third_party/ltp/bin/1/set_tid_address01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setegid02.elf.gz.sha256",
    "content": "6ca2790f5eb1012cb3d95731e2c953147da9b3e4b162d173643524d8e7ec4919 *third_party/ltp/bin/1/setegid02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setgroups01.elf.gz.sha256",
    "content": "ac3968766d412aeab81b059c8ff5c39ad762c1070a9c6f11b2182ccb36d4eda9 *third_party/ltp/bin/1/setgroups01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setgroups02.elf.gz.sha256",
    "content": "6a22b183a2b4efa4bcd53bab3269e0082e4b1bd46facb5a8c3e64420c57b6e3f *third_party/ltp/bin/1/setgroups02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setgroups04.elf.gz.sha256",
    "content": "6038f53502a887529397ddfaec1c01e1833b18450f97686d32b83225d71e45b5 *third_party/ltp/bin/1/setgroups04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setitimer02.elf.gz.sha256",
    "content": "8e76702d9f6a77a861a40b8e8c78dad1cc3d56a6a9b9118567c7712e311f354d *third_party/ltp/bin/1/setitimer02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setpgid01.elf.gz.sha256",
    "content": "0d076705f91735d912bcc86d3ae43b5baae5f84d2afc30415fabd01ae7a11f4e *third_party/ltp/bin/1/setpgid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setpgid02.elf.gz.sha256",
    "content": "7149e13e06a56e913b9705bba46f914fdfd1fefebc9a267a41439f317ee828e7 *third_party/ltp/bin/1/setpgid02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setpgrp01.elf.gz.sha256",
    "content": "164591fb99436aec3b5effed6665787acb463a804ceae2556abdec64bd594783 *third_party/ltp/bin/1/setpgrp01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setpgrp02.elf.gz.sha256",
    "content": "c42c931e20e6365b55ccba56b1f637faf5278c3fcbd65b98cf4066afde4f2e7b *third_party/ltp/bin/1/setpgrp02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setpriority02.elf.gz.sha256",
    "content": "af131a00f22eed43cd895814ed834d99564002374b1c9c52683b07445bbb7bd8 *third_party/ltp/bin/1/setpriority02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setrlimit03.elf.gz.sha256",
    "content": "ae4c9ebfc97a42a71f444029f1b9f4687702538ba46d1f5def3671bcc65936e7 *third_party/ltp/bin/1/setrlimit03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setsid01.elf.gz.sha256",
    "content": "c90414499a5eb6d29771eb56c5f471c30133eaff19a795780ba998a8c40389d0 *third_party/ltp/bin/1/setsid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/setsockopt03.elf.gz.sha256",
    "content": "a27b861248014aff915e32c000b81fa168473ef40ba29f35e79a9731649f0885 *third_party/ltp/bin/1/setsockopt03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/sigaction02.elf.gz.sha256",
    "content": "64b78a817c0058052b4160d47c6aef147318d977175daa5ef037a5cf63f87a50 *third_party/ltp/bin/1/sigaction02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/sigaltstack01.elf.gz.sha256",
    "content": "1a36e1e84133725f402025b5af620b7b5ab346bdd969e2989762f4b0c23d4641 *third_party/ltp/bin/1/sigaltstack01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/sigaltstack02.elf.gz.sha256",
    "content": "d38033619add02d9f8d7779bb757eacc894e352e3b6bc977a06003a19377fe5d *third_party/ltp/bin/1/sigaltstack02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/signal01.elf.gz.sha256",
    "content": "c0a181b5eb7005f0f71621345a9fa14cc1a491b1617329ea32c10bd1018d7144 *third_party/ltp/bin/1/signal01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/signal02.elf.gz.sha256",
    "content": "56e417b2db416f6a8c167a8861b77c2293c05cd29e35ee948b2bfaa8d631bded *third_party/ltp/bin/1/signal02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/signal04.elf.gz.sha256",
    "content": "5e7a8fb01c3145bb83dc60d86c5dd577a08341e8bd6d94401950aff95e385871 *third_party/ltp/bin/1/signal04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/signal06.elf.gz.sha256",
    "content": "12fa72017075bf4d6dc312adef7f8406a176a96572feb343c1af245a154d3c65 *third_party/ltp/bin/1/signal06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/sigprocmask01.elf.gz.sha256",
    "content": "1de80efa5a2f21ade69acdd3004150b82bf935d9360dc6adfe3a293ba3f700ca *third_party/ltp/bin/1/sigprocmask01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/socket02.elf.gz.sha256",
    "content": "70f0fc9a44b9cc7156c296069e83d468d5a61622e185a4a4c0c0bb75417e84e0 *third_party/ltp/bin/1/socket02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/socketpair02.elf.gz.sha256",
    "content": "5765497c9558fa8961c5858ccce0624c47f3fe8dfeac6e879985921e3a7bdff7 *third_party/ltp/bin/1/socketpair02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/stat01.elf.gz.sha256",
    "content": "13c6b9ff1896587ac4c29d926c7121b376ec0680bb6ca1053f38d8327ec2156a *third_party/ltp/bin/1/stat01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/stat01_64.elf.gz.sha256",
    "content": "ccc8f4bf9c35477a11530d3047480293e5ec16c59a28d2b9dfcfb9e74b6106f5 *third_party/ltp/bin/1/stat01_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/stat02.elf.gz.sha256",
    "content": "acc4241f08a5babe083492ba382a1796e8e6530a0c34c134ad9f48d765cdc617 *third_party/ltp/bin/1/stat02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/stat02_64.elf.gz.sha256",
    "content": "11cec60f48f61a56b6ba8888053281ccb89dccb8f7bf0684b52f4ef4cedd7783 *third_party/ltp/bin/1/stat02_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/symlink01.elf.gz.sha256",
    "content": "dce1982979e6e83a3df53a193be057094182bf8e650b911f5bc83187b306145e *third_party/ltp/bin/1/symlink01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/symlink02.elf.gz.sha256",
    "content": "5fb24c797609f400c143bc69b60a8f437f40ab701c9b92eb6ae336dd1c6bf021 *third_party/ltp/bin/1/symlink02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/symlink04.elf.gz.sha256",
    "content": "ea03a48b5c600459424036e3a46292aeeef8453eeed49aa8d4f622d044638b7d *third_party/ltp/bin/1/symlink04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/symlinkat01.elf.gz.sha256",
    "content": "e52b143e4a64b35864c552d3f764835a2e2880ec38514a7587d5a79500dae631 *third_party/ltp/bin/1/symlinkat01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/tkill01.elf.gz.sha256",
    "content": "eb4e15a8f29ea32f2a97250cbf15cb213fdb7ecad15d6bf2ffed560c4e97f428 *third_party/ltp/bin/1/tkill01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/tkill02.elf.gz.sha256",
    "content": "82bbe34d40233f60172f9496f3293b178dc7b47d5f855e511b74d10de0324193 *third_party/ltp/bin/1/tkill02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/truncate02.elf.gz.sha256",
    "content": "46d32c84cc020f326328124c49b4b5a2a8e4b81c7eb6273567420cbdaea5a14f *third_party/ltp/bin/1/truncate02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/truncate02_64.elf.gz.sha256",
    "content": "63eac26bd0a45df2597004189cf694a7a564507e9746e4adf63089075ce0cf38 *third_party/ltp/bin/1/truncate02_64.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/unlink05.elf.gz.sha256",
    "content": "834910d2f9085c7d1ce7a4a4667cb7b0af2a21253064df37d8ebf710d9a1e9f6 *third_party/ltp/bin/1/unlink05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/unlink08.elf.gz.sha256",
    "content": "08eedbb4bf61861219cf96ee11699c93809ba832c87146fa01681c5c65472b40 *third_party/ltp/bin/1/unlink08.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/wait01.elf.gz.sha256",
    "content": "cf49c0184638388f915d000b8aa859f73a933b85a6fe5497e90dca6701161aec *third_party/ltp/bin/1/wait01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/wait02.elf.gz.sha256",
    "content": "6f159e2243a448201a047297f89846bc4abe6023767455dce440573f1b632ff7 *third_party/ltp/bin/1/wait02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/wait401.elf.gz.sha256",
    "content": "ae331a2c396b826680340ea58c527224bebf1c678b11e4ba39b30d127d98c713 *third_party/ltp/bin/1/wait401.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/wait402.elf.gz.sha256",
    "content": "e351aa3622f3b04443378b365acbcbaa3dffdaa0c7a84097da225115788ef6ec *third_party/ltp/bin/1/wait402.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/wait403.elf.gz.sha256",
    "content": "a9b9882e4b0de38bd6f5415d8c781a5bc278e9b56a50b3b82f6a6e1a85f9b0ce *third_party/ltp/bin/1/wait403.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/waitpid01.elf.gz.sha256",
    "content": "63c02350568536aceb56fce92f4785183db1b698616bac201ea30463def428c2 *third_party/ltp/bin/1/waitpid01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/waitpid02.elf.gz.sha256",
    "content": "0af42f79a8ddcdc100b7d3a1653026fd2a6ba5af7d7a93db83c7f9f5d2788345 *third_party/ltp/bin/1/waitpid02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/waitpid03.elf.gz.sha256",
    "content": "dc62dd2dd6e618e6db288c378c9e48a6d1e8ec1c75c4b6971842706020311c21 *third_party/ltp/bin/1/waitpid03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/waitpid06.elf.gz.sha256",
    "content": "ce522b4946aa50508fb826f2c43c19e2253a60403ddd48ee5481cc551b0db979 *third_party/ltp/bin/1/waitpid06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/waitpid07.elf.gz.sha256",
    "content": "0726074d264b78b63d59d943a6e2f8140a7f5fc332eda7335163e22e8f4584a3 *third_party/ltp/bin/1/waitpid07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/waitpid08.elf.gz.sha256",
    "content": "a027b9dd6e072d9cace6ad2a2b2f70d1f036a21a3baa7a0da34e40648cb0b65c *third_party/ltp/bin/1/waitpid08.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/waitpid09.elf.gz.sha256",
    "content": "cd11d922727a8bdb73eb13ca19d71ab4e251a05ba5df73297fb8712ea599642b *third_party/ltp/bin/1/waitpid09.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/waitpid10.elf.gz.sha256",
    "content": "39f654111445c5d08a8a205acd25e8e0553e2790829ff3e34ba9a1bac94a44e1 *third_party/ltp/bin/1/waitpid10.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/waitpid11.elf.gz.sha256",
    "content": "962b495403cb0eca3a7ceac0d2c0e5b98622fd8c25344095736dd78a88b96df4 *third_party/ltp/bin/1/waitpid11.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/waitpid12.elf.gz.sha256",
    "content": "8632012d4eccae4ee8b8f32fe180de7c4e042f1bd488956fc139b0508386cff7 *third_party/ltp/bin/1/waitpid12.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/waitpid13.elf.gz.sha256",
    "content": "73c1f5c1fa00177ca1c36aa9a98917e3295aee8099e6ef705f5a78d3a654565c *third_party/ltp/bin/1/waitpid13.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/write01.elf.gz.sha256",
    "content": "2b59ab58f387f49ba98c510b5b94f303b8eb85282789f967e27bd5f82a16e78b *third_party/ltp/bin/1/write01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/write02.elf.gz.sha256",
    "content": "30452c744031eb9f5af8d7f0b4d1ef6c7103bc2e3e97632a2944fac389364d89 *third_party/ltp/bin/1/write02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/write04.elf.gz.sha256",
    "content": "3fdf2c8db8d4f93101c269043971f85791499cde0b4045d904c75a6a61b9986b *third_party/ltp/bin/1/write04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/write06.elf.gz.sha256",
    "content": "1ce321b4356d0c97da68c527d33fe3fe5a016e19f6041d68aebb14c645ca98a3 *third_party/ltp/bin/1/write06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/writev02.elf.gz.sha256",
    "content": "ee155830ea50363e414d7bd0fde857637a415ab453a6693bd6d43ff7485cca1b *third_party/ltp/bin/1/writev02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/writev05.elf.gz.sha256",
    "content": "ebb0fb7e020d038f8a288b51392f41b4f4f6b75d1f2fb6878bfda4f26b468f78 *third_party/ltp/bin/1/writev05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/1/writev06.elf.gz.sha256",
    "content": "3a2b1c281c5a211a334e1893ed84b721d6ff0c22994af2707283ab06d5a9d797 *third_party/ltp/bin/1/writev06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/access02.elf.gz.sha256",
    "content": "9368875704e12392ac53261299b3181f9c76474ef875f0b590f2e21d30901091 *third_party/ltp/bin/2/access02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/bind02.elf.gz.sha256",
    "content": "3620839d1d64a2c5f8dee342d22d438517cde0971ccfe7616ebd9c8cfaec078d *third_party/ltp/bin/2/bind02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/brk01.elf.gz.sha256",
    "content": "c5afb56b324941ce049354500b293467f1c0cd6dc1d886864b9462371ce11432 *third_party/ltp/bin/2/brk01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/brk02.elf.gz.sha256",
    "content": "fe429b657f1e8a65c40d566fca8da086cd0de2fdf59a4ac6b2f34d8d4d2141a6 *third_party/ltp/bin/2/brk02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/chdir04.elf.gz.sha256",
    "content": "7cdba32b464fe8c16494e08b18487481a5bb15e4c6448379e649bf42a96cc4c5 *third_party/ltp/bin/2/chdir04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/connect01.elf.gz.sha256",
    "content": "50d584df7e614760d7ebc22f6eed06eb7c7e932aa478da24ffeb2bcda782f213 *third_party/ltp/bin/2/connect01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/dup03.elf.gz.sha256",
    "content": "691a3caf3fd9ab1d7dfa4d032101aa40302c63df6a324db8b8f6f93b1e000a0c *third_party/ltp/bin/2/dup03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/dup06.elf.gz.sha256",
    "content": "f489b9f96d25a3d2d10734d19935d98ee16ae735ef57825a3dc2135087483755 *third_party/ltp/bin/2/dup06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/dup205.elf.gz.sha256",
    "content": "8efa5bfc032f063cffdb5cd1d010c13f434bd29dd641db124b475857ca0dc650 *third_party/ltp/bin/2/dup205.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/futex_wait03.elf.gz.sha256",
    "content": "c1daf4bad52772eee5d0e83bd882573ce70989116e8a8da894f5a223712de654 *third_party/ltp/bin/2/futex_wait03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/futimesat01.elf.gz.sha256",
    "content": "17515a80781ce556b2e91f6b040d71adbcec9708d83cc8136e1c84c4476d6b79 *third_party/ltp/bin/2/futimesat01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/getdents02.elf.gz.sha256",
    "content": "fe3a9277a16b094082957b75258d839c0da8b4cae56a4b7bd07f9205b252bd0d *third_party/ltp/bin/2/getdents02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/getrandom01.elf.gz.sha256",
    "content": "002976a6e49c9e73a57541353b25e5e0efe57ab99bd9e806263021e24a75a568 *third_party/ltp/bin/2/getrandom01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/getrandom04.elf.gz.sha256",
    "content": "66dd65f3346d021d27bda351de70b91bff80d59ac443f7060748d531df3bbbcf *third_party/ltp/bin/2/getrandom04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/hackbench.elf.gz.sha256",
    "content": "5f3061485393f0dac27de43f169f9b4be2ddee3cc278d1eff1dce152c0103baf *third_party/ltp/bin/2/hackbench.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/mmap2.elf.gz.sha256",
    "content": "f3b2d9ad3f7e8b6e90db1aa716e64ec97a6aa611242df33e5913fe354d0455a9 *third_party/ltp/bin/2/mmap2.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/open02.elf.gz.sha256",
    "content": "8ade9edd57d039fe51bc4400ffbc7a545d247e909d2eb6d209c40a381f312899 *third_party/ltp/bin/2/open02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/open07.elf.gz.sha256",
    "content": "bc8eb692b8ae633d1f768fa01c66be26c4bc16d931a3ed386a993ef7c4ab1db6 *third_party/ltp/bin/2/open07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/open08.elf.gz.sha256",
    "content": "132514ae5966874cf4c3855000ed1f3cbc1ca10861401a154c7d2303d641a41e *third_party/ltp/bin/2/open08.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/open10.elf.gz.sha256",
    "content": "0b6b4a340ba9d9eed842712a8afe0ffea1e282be92163c7936bbee1f30e2bc57 *third_party/ltp/bin/2/open10.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/openat01.elf.gz.sha256",
    "content": "2c0dd12a7a46a991509023eeb0332fd223cabfc7051dea9158b536925acf47dd *third_party/ltp/bin/2/openat01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/openfile.elf.gz.sha256",
    "content": "3ef52015346a4945909f8859ee182416dea977061b6592f55cf6fbcd2cc366c1 *third_party/ltp/bin/2/openfile.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/pwrite01.elf.gz.sha256",
    "content": "8ad3c8196adf1f467185fb430a9409caecd7fb6f08ce0a178fca0deff1d20b61 *third_party/ltp/bin/2/pwrite01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/read02.elf.gz.sha256",
    "content": "d1db0f7229f63bedc50dd43820031f407aed5c0cb694a780a3492aad7db3929f *third_party/ltp/bin/2/read02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/readlink03.elf.gz.sha256",
    "content": "02a8f7686cb1e184aa813be5b64bba08faa5e38dff334972ceb9ed63a5481b16 *third_party/ltp/bin/2/readlink03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/readlinkat01.elf.gz.sha256",
    "content": "02156788bd1c7a088bfc422a08d061c1ce67328b1ce0d853d13f740e09f3572b *third_party/ltp/bin/2/readlinkat01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/readlinkat02.elf.gz.sha256",
    "content": "18a5054b08bc84f925b8c47549b70881b0c5c24b361ac1b79168d5633f69f59f *third_party/ltp/bin/2/readlinkat02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/readv02.elf.gz.sha256",
    "content": "ba52249f2f407d692f89859e4e5eb8715dde683094b775bbe973089b2d6b4d8d *third_party/ltp/bin/2/readv02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/realpath01.elf.gz.sha256",
    "content": "b7656c9575ad27a75af02c9dd52894d8aa60a6f1fb4339751ebfb501ad8e62d2 *third_party/ltp/bin/2/realpath01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/recvfrom01.elf.gz.sha256",
    "content": "11ed12c8a25c2256dc1257e7d7ac62698e46576c021dd586b8b6c444e6836e43 *third_party/ltp/bin/2/recvfrom01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/recvmmsg01.elf.gz.sha256",
    "content": "86e8cf3758da39ba9dace496ecc052318bf91e7dbd69ababfe9dbceea1b8c4f7 *third_party/ltp/bin/2/recvmmsg01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/rt_sigaction02.elf.gz.sha256",
    "content": "f0ab09ac7c784043389f72f290760f3fa241f73dd4c0efbbae53ec59be9baff3 *third_party/ltp/bin/2/rt_sigaction02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/rt_sigaction03.elf.gz.sha256",
    "content": "74f3e359bab69e5d0da50f949dc6a6a46a7cb6fcb3cee6bd9648c961dcdd3198 *third_party/ltp/bin/2/rt_sigaction03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/rt_sigprocmask02.elf.gz.sha256",
    "content": "579f1357990ddc7d78c151715104d026a8bcbe55c28e4d214e24e3d333f3d367 *third_party/ltp/bin/2/rt_sigprocmask02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sched_yield01.elf.gz.sha256",
    "content": "aca8190fb3366054fd6322b1eb186aea9ac325f86bcb7a34392813d29b46edac *third_party/ltp/bin/2/sched_yield01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/select01.elf.gz.sha256",
    "content": "8fa811cc572cc9bedcdb97da5395dee06fca33f52b52e8aae83744d47ea0343c *third_party/ltp/bin/2/select01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/select02.elf.gz.sha256",
    "content": "3975aa51447b1fe8e69015564ab6cfc7afd781e16322e0e60af10c16d0a1ca1a *third_party/ltp/bin/2/select02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/select04.elf.gz.sha256",
    "content": "9dfdeb0fd1a0a22dd0bc8f259ca54bc169f5809311547a90c45584f764b532dd *third_party/ltp/bin/2/select04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/send01.elf.gz.sha256",
    "content": "9d475bd6f436a877585f14fb58e62ce1afd22d808dfbd7f3d9db90679f0bcaeb *third_party/ltp/bin/2/send01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sendfile02.elf.gz.sha256",
    "content": "40478041a2d0c43ce106fbbe7385d04f911c52e384c80bf4c2f4cbcf2dbed4b0 *third_party/ltp/bin/2/sendfile02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sendfile03.elf.gz.sha256",
    "content": "1fa8abcd91ce4c3eb83b0bcf52ab463c405f3aa15cf9e7ea1350984047e5cd4a *third_party/ltp/bin/2/sendfile03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sendfile04.elf.gz.sha256",
    "content": "d1a6ee7b75606789424ada66e18502fb0e92f0ebe72379334e3d5d9c90e7bd18 *third_party/ltp/bin/2/sendfile04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sendfile05.elf.gz.sha256",
    "content": "99c8bbc1bbdbf4f1d84860be2bd6f494d8e05ed6cf7902e471796ac958e1082b *third_party/ltp/bin/2/sendfile05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sendfile06.elf.gz.sha256",
    "content": "bc09d9799121255f7bc3b557f159812b823ea42f34a6656c3bb33078d110897d *third_party/ltp/bin/2/sendfile06.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sendfile07.elf.gz.sha256",
    "content": "f2d8a64bd6694ce9925915c6adac1351971158652f2e22b615e02d3d61354d8f *third_party/ltp/bin/2/sendfile07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sendfile08.elf.gz.sha256",
    "content": "807d230350273ecaa427e4cdf7ca480a8f66c5af0947592d88aa29a94e49b427 *third_party/ltp/bin/2/sendfile08.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sendfile09.elf.gz.sha256",
    "content": "88a3924ed1b9a5e7280d1e1c00bc669ee4df0dbe61628714c245d0a8126811c4 *third_party/ltp/bin/2/sendfile09.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sendmmsg01.elf.gz.sha256",
    "content": "2cbba35b579b7fc29ba99e34cbfa919412360b9d485c510210fe9699dccdc729 *third_party/ltp/bin/2/sendmmsg01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sendmmsg02.elf.gz.sha256",
    "content": "80f0012930e97cc8be9adeb53adf56e0246b98c401fdcc4d822bd54ccda076fb *third_party/ltp/bin/2/sendmmsg02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sigaction01.elf.gz.sha256",
    "content": "3bc6239ece267972ea0e5509cae5650987c5bc886cb3afd6cb0225de5440eb94 *third_party/ltp/bin/2/sigaction01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/sigsuspend01.elf.gz.sha256",
    "content": "f8a745528bef9159e15d7a625343ff2f86a97ab3d140be9d450ce597c16c5332 *third_party/ltp/bin/2/sigsuspend01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/socket01.elf.gz.sha256",
    "content": "401c551efc12b285571672dd3546a338f29dd3e35dc45059174518b7cc71a1d2 *third_party/ltp/bin/2/socket01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/socketpair01.elf.gz.sha256",
    "content": "7ba8a0d26d27a48e60b47e1f5af1620dc9ee9d32d8908d464e566fdb9ddadcc2 *third_party/ltp/bin/2/socketpair01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/stat03.elf.gz.sha256",
    "content": "8cb9128d2db2bcbb657a52878b24aeb6461f2c9120756761db0606a1bb873c73 *third_party/ltp/bin/2/stat03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/symlink05.elf.gz.sha256",
    "content": "357bc07ee6171331803990fbb63de629e184327f3155d63217f7a57e10c69f91 *third_party/ltp/bin/2/symlink05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/unlink07.elf.gz.sha256",
    "content": "dc753d4a97f412901e87959ba35b1b49dbda73f4b47b694a8c645d73b6338774 *third_party/ltp/bin/2/unlink07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/unlinkat01.elf.gz.sha256",
    "content": "c20bf0468e220a227186d3af685e1a049ea954ff078c558201af1418dd1dec5c *third_party/ltp/bin/2/unlinkat01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/waitpid04.elf.gz.sha256",
    "content": "a3acaf72bb54f2f62dc107b933d7a7890cbdf122d882e7f050ff2a6526c1a1a6 *third_party/ltp/bin/2/waitpid04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/write03.elf.gz.sha256",
    "content": "31563d37978d8bdca450a5871b0919725e44b36385ec09d2a0a2d41417d6e410 *third_party/ltp/bin/2/write03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/write05.elf.gz.sha256",
    "content": "60c1271e3bcc8edd41db7be66784353963b7f39378d7ee8eb9c61c1debe6d268 *third_party/ltp/bin/2/write05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/writetest.elf.gz.sha256",
    "content": "66c8fe0246cff55b991dfa99cfe4dbf79496c150668f6a4b2824471ab9d017f7 *third_party/ltp/bin/2/writetest.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/writev01.elf.gz.sha256",
    "content": "8a4c9747e04aca4c344a7a6355999e6f588407df0c76cd2a84ca96febd60a189 *third_party/ltp/bin/2/writev01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/2/writev07.elf.gz.sha256",
    "content": "685d5ca289154099710d50f6b3a5a41bb1dd6315e871549ec2fa2fda5b91d879 *third_party/ltp/bin/2/writev07.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll-ltp.elf.gz.sha256",
    "content": "b585b40b3b0d2516c6cf7d20d11bf4a3ac89a60a1f660e0920d0a657bc7510a8 *third_party/ltp/bin/3/epoll-ltp.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_create01.elf.gz.sha256",
    "content": "3dc54ebcac58ea6376cec89ffaafba02edfdcbe6380764f481418379a6cebe31 *third_party/ltp/bin/3/epoll_create01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_create02.elf.gz.sha256",
    "content": "be269790557a320c38fbb3f5db1f9c50c09824e9d09729a3fa669574efc26418 *third_party/ltp/bin/3/epoll_create02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_create1_01.elf.gz.sha256",
    "content": "29dc5e388dd33896370086a10f520b4dfb4f88f73fb6c5181dd9866e8458a2e1 *third_party/ltp/bin/3/epoll_create1_01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_create1_02.elf.gz.sha256",
    "content": "81d077f43a02e073db04718997766a014729361e55dcbad61f37af777222f3fa *third_party/ltp/bin/3/epoll_create1_02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_ctl01.elf.gz.sha256",
    "content": "559d2a2f969402510130212f9c9dc88d48ce55efc653eb155c15399dd5aa8915 *third_party/ltp/bin/3/epoll_ctl01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_ctl02.elf.gz.sha256",
    "content": "288f7d07c7218c3c03893eeb1e32b9e514aeea8ca52dd78d2ff3450f5d6d61bb *third_party/ltp/bin/3/epoll_ctl02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_ctl03.elf.gz.sha256",
    "content": "479bfe2e44cfc44c6476d0c895d0c12f723fd5e1c442e4c6e32769305a5a25b4 *third_party/ltp/bin/3/epoll_ctl03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_ctl04.elf.gz.sha256",
    "content": "93fe3b4cf72cccf453c272645fd989e9fb75f5ae8ac5cdf82323b1f54a42b509 *third_party/ltp/bin/3/epoll_ctl04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_ctl05.elf.gz.sha256",
    "content": "26d4923505f83f373f5191cd69f6117ebfeb82ec74648a2ea78ef1d91995f836 *third_party/ltp/bin/3/epoll_ctl05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_pwait01.elf.gz.sha256",
    "content": "0774cf71a8f19ca4395be5e0f2fa605982f724c4d4ea1e077bdeacdaf242ec7a *third_party/ltp/bin/3/epoll_pwait01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_pwait02.elf.gz.sha256",
    "content": "2b5ca980fbb6976f3565d832dad4ee6f522586889f1aeb67cf428d2e3e690762 *third_party/ltp/bin/3/epoll_pwait02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_pwait03.elf.gz.sha256",
    "content": "7d11233252271fa946876419342ca1f49645325b69bfb245cd425886cf8b5f8f *third_party/ltp/bin/3/epoll_pwait03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_pwait04.elf.gz.sha256",
    "content": "c5e5d91950a6662c0f58399c3a5a7ef0713dcdf704368fda88f753e726e63368 *third_party/ltp/bin/3/epoll_pwait04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_pwait05.elf.gz.sha256",
    "content": "631bb578c78cfd4428d4c26af02b245913ab0de5504d9a312e9b9a5312009eb6 *third_party/ltp/bin/3/epoll_pwait05.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_wait01.elf.gz.sha256",
    "content": "b6dc4ee9817420327f4b9ccd9e252f57d91f337b4eec00531de1b8c0191ede7b *third_party/ltp/bin/3/epoll_wait01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_wait02.elf.gz.sha256",
    "content": "7bc827e67a98e6371e632f5466cf04d5d5648f8d9e132fe2d4df27bb7eea1e97 *third_party/ltp/bin/3/epoll_wait02.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_wait03.elf.gz.sha256",
    "content": "9efa76c18b6fd754ad37ca27372fc65edafd7bf9cecd29edadab73d500763400 *third_party/ltp/bin/3/epoll_wait03.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/epoll_wait04.elf.gz.sha256",
    "content": "5498ea4a38b6e02e842b0b30f95e50f80245d07690155fd78513a8d2c7d76255 *third_party/ltp/bin/3/epoll_wait04.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/recvmmsg01.elf.gz.sha256",
    "content": "572131b6aa05185c680c0a5cf6d27ac147f8986f0fc265535e3a8e11da508e44 *third_party/ltp/bin/3/recvmmsg01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/bin/3/sendmsg01.elf.gz.sha256",
    "content": "5e2565d2591a38baf96cf616f69cc1237740c25b200c9cdaa9c8dedfc6a104e7 *third_party/ltp/bin/3/sendmsg01.elf.gz\n"
  },
  {
    "path": "third_party/ltp/cpuinfo",
    "content": "processor\t: 0\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 0\ncpu cores\t: 8\napicid\t\t: 0\ninitial apicid\t: 0\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 1\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 1\ncpu cores\t: 8\napicid\t\t: 2\ninitial apicid\t: 2\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 2\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 2\ncpu cores\t: 8\napicid\t\t: 4\ninitial apicid\t: 4\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 3\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 3\ncpu cores\t: 8\napicid\t\t: 6\ninitial apicid\t: 6\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 4\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 4\ncpu cores\t: 8\napicid\t\t: 8\ninitial apicid\t: 8\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 5\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 4798.388\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 5\ncpu cores\t: 8\napicid\t\t: 10\ninitial apicid\t: 10\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 6\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 4731.353\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 6\ncpu cores\t: 8\napicid\t\t: 12\ninitial apicid\t: 12\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 7\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 7\ncpu cores\t: 8\napicid\t\t: 14\ninitial apicid\t: 14\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 8\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 0\ncpu cores\t: 8\napicid\t\t: 1\ninitial apicid\t: 1\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 9\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 1\ncpu cores\t: 8\napicid\t\t: 3\ninitial apicid\t: 3\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 10\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 2\ncpu cores\t: 8\napicid\t\t: 5\ninitial apicid\t: 5\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 11\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 3\ncpu cores\t: 8\napicid\t\t: 7\ninitial apicid\t: 7\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 12\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 4904.594\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 4\ncpu cores\t: 8\napicid\t\t: 9\ninitial apicid\t: 9\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 13\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 5\ncpu cores\t: 8\napicid\t\t: 11\ninitial apicid\t: 11\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 14\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 3100.000\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 6\ncpu cores\t: 8\napicid\t\t: 13\ninitial apicid\t: 13\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 15\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 158\nmodel name\t: Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz\nstepping\t: 13\nmicrocode\t: 0xca\ncpu MHz\t\t: 4904.135\ncache size\t: 16384 KB\nphysical id\t: 0\nsiblings\t: 16\ncore id\t\t: 7\ncpu cores\t: 8\napicid\t\t: 15\ninitial apicid\t: 15\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 22\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities\nvmx flags\t: vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec\nbugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb\nbogomips\t: 6202.33\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 39 bits physical, 48 bits virtual\npower management:\n\n"
  },
  {
    "path": "third_party/ltp/deploy-ltp",
    "content": "#!/bin/sh\nset -ex\n# e.g. deploy-ltp chmod01\n\nT=/mnt/videos/website/justine.lol/ltp/bin\nL=/opt/ltp/testcases/bin/\nV=1\nmkdir -p $T/$V\n\nfor f; do\n  if [ ! -f $L/$f ]; then\n    echo \"not found: $L/$f\" >&2\n    exit 1\n  fi\n\n  cp $L/$f $T/$V/${f##*/}.elf\n  rm -f $T/$V/${f##*/}.elf.gz\n  gzip $T/$V/${f##*/}.elf\n  sha256sum -b $T/$V/${f##*/}.elf.gz >$T/$V/${f##*/}.elf.gz.sha256\n  mkdir -p ~/blink/third_party/ltp/bin/$V\n  cp $T/$V/${f##*/}.elf.gz.sha256 ~/blink/third_party/ltp/bin/$V/${f##*/}.elf.gz.sha256\n\n  sed -i -e 's!/mnt/videos/website/justine.lol/ltp/bin!third_party/ltp/bin!' \\\n      ~/blink/third_party/ltp/bin/$V/${f##*/}.elf.gz.sha256\ndone\n\nsyncweb\n\nssh debian gsutil -m -h Cache-Control:public,max-age=31536000 cp -r -a public-read \\\n    /mnt/videos/website/justine.lol/ltp/bin/$V/${f##*/}.elf.gz \\\n    gs://justine/ltp/bin/$V/\n"
  },
  {
    "path": "third_party/ltp/ltp.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\n.PRECIOUS: third_party/ltp/%.gz\nthird_party/ltp/%.gz: third_party/ltp/%.gz.sha256 o/tool/sha256sum\n\tcurl -so $@ https://justine.storage.googleapis.com/ltp/$(subst third_party/ltp/,,$@)\n\to/tool/sha256sum -c $<\n\n.PRECIOUS: third_party/ltp/bin/%.elf\nthird_party/ltp/bin/%.elf: third_party/ltp/bin/%.elf.gz\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/$(MODE)/third_party/ltp/bin/%.elf.ok:\t\t\t\t\t\\\n\t\tthird_party/ltp/bin/%.elf\t\t\t\t\\\n\t\to/lib/ld-musl-x86_64.so.1\t\t\t\t\\\n\t\to/$(MODE)/blink/blink\t\t\t\t\t\\\n\t\to/proc/cpuinfo\t\t\t\t\t\t\\\n\t\to/proc/meminfo\n\t@mkdir -p $(@D)\n\to/$(MODE)/blink/blink $< $(LTP_ARGS)\n\t@touch $@\n\no/$(MODE)/third_party/ltp/bin/1/growfiles.elf.ok: private LTP_ARGS = -f \"$(TMPDIR)/gf\"\n\n.PRECIOUS: o/proc/%\no/proc/%: third_party/ltp/%\n\t@mkdir -p $(@D)\n\tcp -f $< $@\n\tchmod +x $@\n\nLTP_TESTS =\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/hackbench.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/accept01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/accept4_01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/alarm03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/alarm05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/alarm06.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/alarm07.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/atof01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/bind01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/bind03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/brk02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/chown01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/clock_getres01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/clock_nanosleep04.elf.ok\t\\\n\to/$(MODE)/third_party/ltp/bin/1/close01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/close02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/close_range02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/confstr01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/creat01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/creat03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/dup03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup07.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup201.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup202.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup203.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup204.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/dup205.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup206.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup207.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup3_01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/dup3_02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/exit01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/exit02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/exit_group01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fchdir01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fchdir02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fchmod01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fchown01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fchownat01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl01_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl02_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl03_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl04_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl08.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl08_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl09.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl09_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl10.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl10_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl11.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl11_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl14.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl14_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl15.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl15_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl16.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl16_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl17.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl17_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl19.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl19_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl20.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl20_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl21.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl21_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl22.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl22_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl27.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl27_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl28.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl28_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl29.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fcntl29_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fdatasync01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fdatasync02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/flock01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/flock02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/flock03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/flock04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/flock06.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fork01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fork03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fork04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fork05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fork06.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fork07.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fork08.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fork10.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fork11.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fsync03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/ftruncate01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/ftruncate01_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/ftruncate03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/ftruncate03_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/futex_wait01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/futex_wait04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/futex_wake01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getcwd02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getcwd03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getdents01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/getdents02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getdomainname01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getegid01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getegid02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/geteuid01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/geteuid02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getgid03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/gethostname01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getitimer01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getpagesize01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getpgid01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getpgrp01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getpid02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getppid02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getpriority02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/getrandom01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getrandom02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getrandom03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getrlimit02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getrusage01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getsid01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/gettid01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/gettimeofday01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getuid01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/growfiles.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/hackbench.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/in6_01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/inode01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/kill06.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/kill08.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/kill09.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/link02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/link03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/link05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/listen01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/llseek01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/llseek02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/llseek03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/locktests.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/lseek01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/lseek02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/lseek07.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap06.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap07.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap08.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap09.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap19.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmapstress04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mprotect02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mprotect03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/msync01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/msync02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/munmap01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/munmap02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/munmap03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/nanosleep02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fstat02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/open03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/open06.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/open07.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/open09.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pipe01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pipe02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pipe03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pipe04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pipe06.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pipe07.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pipe08.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pipe09.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pipe10.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pipe11.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pipe13.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/poll01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pread01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pread01_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pread02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pread02_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/preadv01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/preadv01_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pselect02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pselect02_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pselect03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pselect03_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/pwrite01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pwrite01_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pwrite02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pwrite02_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pwrite03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pwrite03_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pwrite04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pwrite04_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pwritev01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pwritev01_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/read01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/read02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/read03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/read04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/readdir01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/readv01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/recvmsg02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/rmdir01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/sbrk02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/select01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/select04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/set_robust_list01.elf.ok\t\\\n\to/$(MODE)/third_party/ltp/bin/1/set_tid_address01.elf.ok\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setpgid01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setpgid02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setpgrp01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setpgrp02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setsid01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sigaction01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/sigaction02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/rt_sigaction02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/rt_sigaction03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/sigaltstack01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/sigaltstack02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/signal01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/signal02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/signal04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/signal06.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/sigprocmask01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/rt_sigprocmask02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sigsuspend01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/socket01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/socket02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/socketpair01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/socketpair02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/stat02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/stat02_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/symlink01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/symlink02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/symlink04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/symlink05.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/symlinkat01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/tkill01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/tkill02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/truncate02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/truncate02_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/unlink05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/wait01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/wait02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/wait401.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/wait402.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/wait403.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/waitpid01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/waitpid02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/waitpid03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/waitpid04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/waitpid06.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/waitpid07.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/waitpid08.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/waitpid09.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/waitpid10.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/waitpid11.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/waitpid12.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/waitpid13.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/write01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/write02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/write03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/write04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/write05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/write06.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/writetest.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/writev01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/writev02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/writev05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/writev06.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/writev07.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/sendto01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setitimer02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/unlinkat01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/futimesat01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/unlink07.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/send01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/sendmsg01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sched_yield01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/readlinkat01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/readlinkat02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/readv02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/realpath01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/openat01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/recvmmsg01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sendmmsg01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sendmmsg02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/recvfrom01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sendfile02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sendfile03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sendfile04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sendfile05.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sendfile06.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sendfile07.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sendfile08.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/sendfile09.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/openfile.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/connect01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/chdir04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll-ltp.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_create01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_create02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_create1_01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_create1_02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_ctl01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_ctl02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_ctl03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_ctl04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_ctl05.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_pwait01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_pwait02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_pwait04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_pwait05.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_wait01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_wait03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_wait04.elf.ok\n\nifneq ($(HOST_SYSTEM), FreeBSD)\n# These tests make the system get wrekt.\nLTP_TESTS +=\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pause02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/creat05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fork09.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/inode02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/open04.elf.ok\nendif\n\nifneq ($(HOST_SYSTEM), FreeBSD)\n# Something weird about the sticky bit.\nLTP_TESTS += o/$(MODE)/third_party/ltp/bin/1/open01.elf.ok\nendif\n\nifneq ($(HOST_SYSTEM), FreeBSD)\n# The FreeBSD manual states \"The maximum number of seconds allowed for\n# it_interval and it_value in setitimer() is 100000000\", but this test\n# needs the platform to support values like INT_MAX.\nLTP_TESTS += o/$(MODE)/third_party/ltp/bin/1/alarm02.elf.ok\nendif\n\nifneq ($(HOST_SYSTEM), FreeBSD)\n# This passes but complains about an EXDEV errno mismatch (possibly with\n# procfs) and therefore would be expensive and/or tricky to polyfill.\nLTP_TESTS += o/$(MODE)/third_party/ltp/bin/1/linkat01.elf.ok\nendif\n\n# These tests won't pass unless Linux-specific rlimits are present,\n# RLIMIT_LOCKS, RLIMIT_MSGQUEUE, RLIMIT_RTTIME, etc.\nifneq ($(HOST_SYSTEM), FreeBSD)\nLTP_TESTS +=\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getrlimit01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getrlimit03.elf.ok\nendif\n\n# These tests require procfs which currently isn't simulated.\nifneq ($(HOST_SYSTEM), FreeBSD)\nLTP_TESTS +=\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/clock_gettime04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/futex_wait02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/futex_wait03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/nanosleep04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getpgid02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getppid01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getuid03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getsid02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getpid01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pause03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pause01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fsync02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap12.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/kill03.elf.ok\nendif\n\nifeq ($(shell id -u), 0)\nLTP_TESTS +=\t\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setegid02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/open08.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/open10.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/stat03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/rename09.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/access01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/access02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/access03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/autogroup01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/chmod07.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/chown02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/chown05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/clock_gettime01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fchmod02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fchmod04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fchown02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/fchown05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/futex_wake04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getgid01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getgroups03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getrandom04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/hugemmap06.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mkdir05.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap10.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap11.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/nice04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/open02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/open11.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/open14.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/openat03.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/readlink01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setgroups01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setgroups02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setgroups04.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setpriority02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setrlimit03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/setsockopt03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/stat01.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/stat01_64.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/futex_wait05.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/poll02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/unlink08.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/bind02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_pwait03.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/3/epoll_wait02.elf.ok\nendif\n\n# TODO: Cygwin doesn't properly raise an EACCES errno.\nifneq ($(HOST_OS), Cygwin)\nLTP_TESTS += o/$(MODE)/third_party/ltp/bin/2/readlink03.elf.ok\nendif\n\nifneq ($(HOST_OS), Cygwin)\n# partial failure only on cygwin\n# chmod01.c:50: TFAIL: stat(testfile) mode=0000\n# chmod01.c:50: TFAIL: stat(testdir_1) mode=0000\n# chmod01.c:50: TFAIL: stat(testdir_1) mode=0777\n# chmod01.c:50: TFAIL: stat(testdir_1) mode=4777\nLTP_TESTS += o/$(MODE)/third_party/ltp/bin/1/chmod01.elf.ok\nendif\n\n################################################################################\n# MEDIUM TESTS\n\nLTP_TESTS_MEDIUM =\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/clock_nanosleep02.elf.ok\t\\\n\to/$(MODE)/third_party/ltp/bin/1/getcwd04.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/gettimeofday02.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/kill02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap-corruption01.elf.ok\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmap001.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/mmapstress01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/nanosleep01.elf.ok\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/rename14.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/mmap2.elf.ok\n\nifeq ($(shell id -u), 0)\nLTP_TESTS_MEDIUM +=\t\t\t\t\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/2/select02.elf.ok\t\t\t\\\n\to/$(MODE)/third_party/ltp/bin/1/pty06.elf.ok\nendif\n\n################################################################################\n\no/$(MODE)/third_party/ltp: $(LTP_TESTS)\n\t@mkdir -p $(@D)\n\t@touch $@\n\no/$(MODE)/third_party/ltp/medium: $(LTP_TESTS_MEDIUM)\n\t@mkdir -p $(@D)\n\t@touch $@\n"
  },
  {
    "path": "third_party/ltp/meminfo",
    "content": "MemTotal:        1147256 kB\nMemFree:          819664 kB\nMemAvailable:     814180 kB\nBuffers:            2108 kB\nCached:           128936 kB\nSwapCached:            0 kB\nActive:           105240 kB\nInactive:          76048 kB\nActive(anon):      56492 kB\nInactive(anon):    16656 kB\nActive(file):      48748 kB\nInactive(file):    59392 kB\nUnevictable:           0 kB\nMlocked:               0 kB\nSwapTotal:       1888252 kB\nSwapFree:        1888252 kB\nDirty:                24 kB\nWriteback:             0 kB\nAnonPages:         50252 kB\nMapped:            25052 kB\nShmem:             22904 kB\nSlab:              61316 kB\nSReclaimable:      24848 kB\nSUnreclaim:        36468 kB\nKernelStack:        3984 kB\nPageTables:         3712 kB\nNFS_Unstable:          0 kB\nBounce:                0 kB\nWritebackTmp:          0 kB\nCommitLimit:     2461880 kB\nCommitted_AS:     279548 kB\nVmallocTotal:   34359738367 kB\nVmallocUsed:      179168 kB\nVmallocChunk:   34359310332 kB\nPercpu:            22528 kB\nHardwareCorrupted:     0 kB\nAnonHugePages:     12288 kB\nCmaTotal:              0 kB\nCmaFree:               0 kB\nHugePages_Total:       0\nHugePages_Free:        0\nHugePages_Rsvd:        0\nHugePages_Surp:        0\nHugepagesize:       2048 kB\nDirectMap4k:       65408 kB\nDirectMap2M:     1138688 kB\nDirectMap1G:           0 kB\n"
  },
  {
    "path": "third_party/musl/README.md",
    "content": "# Musl Libc\n\nThis folder downloads prebuilt binaries from the [Musl\nLibc](https://www.musl-libc.org/) project.\n\n## Changes\n\nNone.\n\n## Build\n\nThe binaries were compiled on Alpine Linux using:\n\n```\nexport CC=\"cc -fno-omit-frame-pointer -Wl,-z,common-page-size=65536,-z,max-page-size=65536\"\n./configure --enable-debug\nmake -j16\n```\n"
  },
  {
    "path": "third_party/musl/lib/1/ld-musl-x86_64.so.1.gz.sha256",
    "content": "07fa95292e7c861e1d99ab28572a8aadc76b745c1db6c64c60990c114f6af82c *third_party/musl/lib/1/ld-musl-x86_64.so.1.gz\n"
  },
  {
    "path": "third_party/musl/musl.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\n.PRECIOUS: third_party/musl/%.gz\nthird_party/musl/%.gz: third_party/musl/%.gz.sha256 o/tool/sha256sum\n\tcurl -so $@ https://justine.storage.googleapis.com/musl/$(subst third_party/musl/,,$@)\n\to/tool/sha256sum -c $<\n\n.PRECIOUS: third_party/musl/%\nthird_party/musl/%: third_party/musl/%.gz\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/lib/ld-musl-x86_64.so.1: third_party/musl/lib/1/ld-musl-x86_64.so.1\n\t@mkdir -p $(@D)\n\tcp -f $< $@\n\tchmod +x $@\n"
  },
  {
    "path": "third_party/qemu/4/qemu-aarch64.gz.sha256",
    "content": "92cee22c128bc356818fac36ef9a43c7548d2aeea1e25cc3b9f5b269abd2f5f6 *third_party/qemu/4/qemu-aarch64.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-aarch64_be.gz.sha256",
    "content": "f0e89d14992bdfb6b1913459e673198dc087875ac0622208b12073662fa9f0c2 *third_party/qemu/4/qemu-aarch64_be.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-alpha.gz.sha256",
    "content": "1f9e6eccd09e12b3aa8b5c1a1947603e3ba8d1c4599dde34dceb1215895925fb *third_party/qemu/4/qemu-alpha.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-arm.gz.sha256",
    "content": "c08bc8e7a2569392b0eabffe521615d0e755fdd3bb48b8b6716afb8fd8b0588d *third_party/qemu/4/qemu-arm.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-armeb.gz.sha256",
    "content": "6c1214789f287855d67957999ca3a61a7f25b4d0a27b948a98751803942d3ae4 *third_party/qemu/4/qemu-armeb.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-cris.gz.sha256",
    "content": "14e789b9ee15415ab034d5bda25db3085d9327b703811a86a96cb7f779469ebb *third_party/qemu/4/qemu-cris.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-hexagon.gz.sha256",
    "content": "e7031aaf2889cc52d96a00d817bc87aea8db5b2df9b25b7d1ca8bc3e504d0fe5 *third_party/qemu/4/qemu-hexagon.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-hppa.gz.sha256",
    "content": "a1396a75e75c795d4fb72a003be466a8d126e7e2cca6aabaf3c26a4a347e4d31 *third_party/qemu/4/qemu-hppa.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-i386.gz.sha256",
    "content": "1ad12c52b2bbb2ae336283b2292f5cda2551b778ce2f63b949fde85e17771b9c *third_party/qemu/4/qemu-i386.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-loongarch64.gz.sha256",
    "content": "b78f0e6f5df9b10d2d13984bb20162e4ee9841e1c7543f7316a803abdb201768 *third_party/qemu/4/qemu-loongarch64.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-m68k.gz.sha256",
    "content": "bdffa53e495e77171d84b439fa38cd240c0f1295e1ac8e526a2b7a464494570a *third_party/qemu/4/qemu-m68k.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-microblaze.gz.sha256",
    "content": "aacce2d5e6f8a515522135f533ad57b3383d9aff25235fc263beedfb6e45f7ff *third_party/qemu/4/qemu-microblaze.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-microblazeel.gz.sha256",
    "content": "d26748f4a8e7e23e93e47156f70c4e26e6187f741a0aeba438263411bb52b4c1 *third_party/qemu/4/qemu-microblazeel.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-mips.gz.sha256",
    "content": "145e87b5b2ca717cfa91dbb320e2306d3f3b8c10407eb07c2e402d835d0d176a *third_party/qemu/4/qemu-mips.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-mips64.gz.sha256",
    "content": "dc148b117b080182439caa827afed9d89bdc706ec59cc55536efe86aeafe9669 *third_party/qemu/4/qemu-mips64.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-mips64el.gz.sha256",
    "content": "041d9399696f4d9c1a8a5799c21d686f178a85437054d6c0f5e0c1e345983a67 *third_party/qemu/4/qemu-mips64el.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-mipsel.gz.sha256",
    "content": "0f25801c9dc3262aee3b1d95bdf213bd45cf6af1ec469998a0dc4a524d0d73ae *third_party/qemu/4/qemu-mipsel.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-mipsn32.gz.sha256",
    "content": "5624c6a18eaab48c261173a711f999570ad6cddea42e5fcf520138f9c66acc12 *third_party/qemu/4/qemu-mipsn32.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-mipsn32el.gz.sha256",
    "content": "39032a5efc0167dc4166e8d335ecac27e413f1b6d4dbfa0d2c998eb3cc81693c *third_party/qemu/4/qemu-mipsn32el.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-nios2.gz.sha256",
    "content": "278d87635b3a39cf01e67d7926451c85f911010c45e40b0685b07704adbe4c5f *third_party/qemu/4/qemu-nios2.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-or1k.gz.sha256",
    "content": "a31f7252474f64f2a803cf228945378909ed707b68bba01a0c8176beaafbe3c5 *third_party/qemu/4/qemu-or1k.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-ppc.gz.sha256",
    "content": "0621e2d7577bf784cff0b44bb6158e957c3ab8143931e9275b8c7ff18fdd67a5 *third_party/qemu/4/qemu-ppc.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-ppc64.gz.sha256",
    "content": "33e734b5054209fcd48a6d18ade6d6c6a59a245e1414dbaef5043a374f9eb8f1 *third_party/qemu/4/qemu-ppc64.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-ppc64le.gz.sha256",
    "content": "49e2dd1c85af1a12ff6a73b5564c7616ee114b589db495433ed4d2799de43718 *third_party/qemu/4/qemu-ppc64le.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-riscv32.gz.sha256",
    "content": "f31f3c5dd3c086a3e432252904af3e874dcb2c61f65ac4b8dc010b041d8c58a1 *third_party/qemu/4/qemu-riscv32.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-riscv64.gz.sha256",
    "content": "f1731902f27677d74a137c0c4a50de6e4c96490b170c9a3a080ee59a38979be6 *third_party/qemu/4/qemu-riscv64.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-s390x.gz.sha256",
    "content": "ce7cde2b19d7a23800468fa94f1ce4290102f77480b1b152e47c26d5f5a08091 *third_party/qemu/4/qemu-s390x.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-sh4.gz.sha256",
    "content": "ea0606d9c4ab96261c47626134b56067658c973c25237c764a541232cafc6383 *third_party/qemu/4/qemu-sh4.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-sh4eb.gz.sha256",
    "content": "eef7d69fbd8bf8e022086d6ffba07186e37bf35e2f5ad414c31b6a83960f5bad *third_party/qemu/4/qemu-sh4eb.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-sparc.gz.sha256",
    "content": "20e3b8f70bc9385ff97fdcb4b8bfb082aab34457869104da6d2068f5fcd69d6f *third_party/qemu/4/qemu-sparc.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-sparc32plus.gz.sha256",
    "content": "fb8902e14cf0ead708fb3d0abc9114a84f597b0fb05f393e4db65b11b4ef4135 *third_party/qemu/4/qemu-sparc32plus.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-sparc64.gz.sha256",
    "content": "7c596da70fd4483b0eb3e08bc10e9ee6774fe9b59399396fca4bce1a686576de *third_party/qemu/4/qemu-sparc64.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-x86_64.gz.sha256",
    "content": "1b1d3b50eeb85a98fcf7a06a15306e5d1d3f90ddfa64251051f4a92bc166ddeb *third_party/qemu/4/qemu-x86_64.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-xtensa.gz.sha256",
    "content": "b8ebc4457e25a52338193294903a7ff759aeebea9eb258eb9b33c926a13d395c *third_party/qemu/4/qemu-xtensa.gz\n"
  },
  {
    "path": "third_party/qemu/4/qemu-xtensaeb.gz.sha256",
    "content": "4ec6a562fc4eea1f0452fce83277fdbfb4c817f4a0aaa1ecc2804f1907e8dc72 *third_party/qemu/4/qemu-xtensaeb.gz\n"
  },
  {
    "path": "third_party/qemu/README.md",
    "content": "# Qemu\n\nThis folder contains prebuilt binaries of Qemu 7.2.0-rc4. Qemu is\nsimilar to Blink except it's bigger and it's been around longer. As\nsuch, we've found Qemu enormously useful as a testing tool for Blink.\nThat's because Qemu is able to emulate multiple hardware architectures\nfrom the comfort of an x86-64 workstation. That helps us quickly verify\nour tinier, nimbler emulator for x86-64 binaries will work once shipped!\n\n## Local Changes\n\nNone.\n\n## License\n\nUnlike Bilnk with observes the ISC license, Qemu is licensed GPL. You\nhave the freedom to obtain the Qemu source code from the internet and\nreproduce our build process using the following instructions.\n\n## Build Process\n\nThese binaries were compiled as follows:\n\n```\ncd ~/vendor/qemu-7.2.0-rc4\n./configure --disable-system --enable-linux-user --disable-bsd-user --static \\\n--prefix=/opt/qemu-static-best --disable-stack-protector --enable-seccomp \\\n--disable-selinux --disable-glusterfs --disable-debug-info --cc=/usr/bin/gcc \\\n--extra-cflags='-fno-stack-protector' \\\n--extra-ldflags='-Wl,-z,norelro -Wl,-z,noseparate-code -Wl,-z,common-page-size=65536 -Wl,-z,max-page-size=65536' &&\nmake -j5 && make install\n```\n\nOn the following system:\n\n```\n$ uname -a\nLinux debian 6.1.0-rc4+ #2 SMP PREEMPT_DYNAMIC Thu Nov 10 20:53:21 PST 2022 x86_64 GNU/Linux\n```\n\n## Deploy Process\n\nOur operations team used the following script to make these binaries\nfreely available on Google Cloud Storage.\n\n```sh\n#!/bin/sh\nset -ex\n\nT=/mnt/videos/website/justine.lol/qemu\nQ=/opt/qemu-static-best\nV=4\nmkdir -p $T/$V\nmkdir -p ~/blink/third_party/qemu/$V\n\nfor f in $(ls -1 $Q/bin | grep -v -- -system- | grep -v daemon); do\n\n  cp $Q/bin/$f $T/$V/${f##*/}\n  strip $T/$V/${f##*/}\n  rm -f $T/$V/${f##*/}.gz\n  gzip $T/$V/${f##*/}\n  sha256sum -b $T/$V/${f##*/}.gz >$T/$V/${f##*/}.gz.sha256\n  cp $T/$V/${f##*/}.gz.sha256 ~/blink/third_party/qemu/$V/${f##*/}.gz.sha256\n\n  sed -i -e 's!/mnt/videos/website/justine.lol!third_party!' \\\n      ~/blink/third_party/qemu/$V/${f##*/}.gz.sha256\n\n  ssh debian gsutil -m -h Cache-Control:public,max-age=31536000 cp -r -a public-read \\\n      /mnt/videos/website/justine.lol/qemu/$V/${f##*/}.gz \\\n      gs://justine/qemu/$V/\ndone\n\nrm -rf /mnt/videos/website/justine.lol/qemu\n```\n"
  },
  {
    "path": "third_party/qemu/qemu.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\nthird_party/qemu/%.gz: third_party/qemu/%.gz.sha256 o/tool/sha256sum\n\tcurl -so $@ https://justine.storage.googleapis.com/qemu/$(subst third_party/qemu/,,$@)\n\to/tool/sha256sum -c $<\n\no/third_party/qemu/4/qemu-x86_64: third_party/qemu/4/qemu-x86_64.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-aarch64: third_party/qemu/4/qemu-aarch64.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-aarch64_be: third_party/qemu/4/qemu-aarch64_be.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-arm: third_party/qemu/4/qemu-arm.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-i386: third_party/qemu/4/qemu-i386.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-m68k: third_party/qemu/4/qemu-m68k.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-microblaze: third_party/qemu/4/qemu-microblaze.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-riscv64: third_party/qemu/4/qemu-riscv64.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-mips: third_party/qemu/4/qemu-mips.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-mipsel: third_party/qemu/4/qemu-mipsel.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-mips64: third_party/qemu/4/qemu-mips64.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-mips64el: third_party/qemu/4/qemu-mips64el.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-ppc: third_party/qemu/4/qemu-ppc.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-ppc64: third_party/qemu/4/qemu-ppc64.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-ppc64le: third_party/qemu/4/qemu-ppc64le.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-s390x: third_party/qemu/4/qemu-s390x.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-alpha: third_party/qemu/4/qemu-alpha.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-armeb: third_party/qemu/4/qemu-armeb.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-cris: third_party/qemu/4/qemu-cris.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-hexagon: third_party/qemu/4/qemu-hexagon.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-hppa: third_party/qemu/4/qemu-hppa.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-loongarch64: third_party/qemu/4/qemu-loongarch64.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-microblazeel: third_party/qemu/4/qemu-microblazeel.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-mipsn32: third_party/qemu/4/qemu-mipsn32.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-mipsn32el: third_party/qemu/4/qemu-mipsn32el.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-nios2: third_party/qemu/4/qemu-nios2.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-or1k: third_party/qemu/4/qemu-or1k.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-riscv32: third_party/qemu/4/qemu-riscv32.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-sh4: third_party/qemu/4/qemu-sh4.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-sh4eb: third_party/qemu/4/qemu-sh4eb.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-sparc: third_party/qemu/4/qemu-sparc.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-sparc32plus: third_party/qemu/4/qemu-sparc32plus.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-sparc64: third_party/qemu/4/qemu-sparc64.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-xtensa: third_party/qemu/4/qemu-xtensa.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n\no/third_party/qemu/4/qemu-xtensaeb: third_party/qemu/4/qemu-xtensaeb.gz\n\t@mkdir -p $(@D)\n\tgzip -dc <$< >$@\n\tchmod +x $@\n"
  },
  {
    "path": "third_party/sectorlisp/LICENSE",
    "content": "Copyright 2020 Justine Alexandra Roberts Tunney\nCopyright 2021 Alain Greppin\n\nPermission to use, copy, modify, and/or distribute this software for\nany purpose with or without fee is hereby granted, provided that the\nabove copyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL\nWARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE\nAUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\nDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\nPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\nTORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n"
  },
  {
    "path": "third_party/sectorlisp/README.md",
    "content": "# Running SectorLISP in Blinkenlights\n\n[SectorLISP](https://justine.lol/sectorlisp2/) is an tiniest garbage\ncollected programming environment in the world. It's written as an i8086\nBIOS program that's compatible with the original IBM PC. You can run\nSectorLISP in Blink, by passing the `-r` (REAL MODE) flag.\n\n## Running SectorLISP\n\nIf you build Blink, then you can use the binaries provided for your\nconvenience in this folder.\n\n```sh\nmake -j8 o//blink\n\n# easy mode\no//blink/blinkenlights -r third_party/sectorlisp/sectorlisp-friendly.bin\n\n# professional mode\no//blink/blinkenlights -r third_party/sectorlisp/sectorlisp.bin\n```\n\nThen press `c` to continue. The teletypewriter should become\nhighlighted, which means it's waiting for keystrokes.\n\n## LISP Hello World\n\nYou can then type in code like the following, which interns an atom:\n\n```lisp\n(QUOTE HI)\n```\n\nThe above code followed by the `ENTER` key will display:\n\n```lisp\nHI\n```\n\nFor the purposes of readability in this tutorial, the above workflow\nwill be described as follows:\n\n```lisp\n>> (QUOTE HI)\nHI\n```\n\n## Keyboard Control\n\nOnce you've pressed `c` (CONTINUE) the program TTY takes over control.\nYou can drop back into the debugger by pressing `CTRL-C`. For example,\nif you want to exit Blink entirely while using SectorLISP, you'd press\n`CTRL-C` (INTERRUPT) followed by `q` (QUIT).\n\nOne thing you may have noticed, is that SectorLISP's interning algorithm\nis slow. You can speed up or slow down execution at any time, by\npressing `CTRL-C` (INTERRUPT) and, once in debugger mode, use `CTRL-T`\n(TURBO) or `ALT-T` (SLOWMO) as many times as desired. Then, execution\nmay be resumed by `c` (CONTINUE) which hands control back over to the\nSectorLISP program.\n\nAn alternative to pressing `c` (CONTINUE) is to press `s` (STEP). This\nwill allow you to go instruction by instruction. Be careful if you run\ninto an `INT` instruction, since `INT $0x16` for example, is your BIOS\nkeyboard service. In stepping mode, Blink will read one keystroke, and\nthen drop back into debugger control mode.\n\n## LISP Data Structures\n\nHere's an example of how you can build data structures:\n\n```lisp\n> (CONS (QUOTE A) (QUOTE B))\n(A∙B)\n```\n\n## Recursive Functions\n\nSectorLISP is purely expressional. It also doesn't have macros, which\nare what make the modern LISP syntax most people are used to possible.\nYou instead need to write LISP the old fashioned way, as it is written\nin John McCarthy's original paper.\n\nHere's an example of a recursive function which finds the first atom in\nthe tree `((A) B C)`, which is `A`.\n\n```lisp\n>> ((LAMBDA (FF X) (FF X))\n    (QUOTE (LAMBDA (X)\n             (COND ((ATOM X) X)\n                   ((QUOTE T) (FF (CAR X))))))\n    (QUOTE ((A) B C)))\nA\n```\n\nThe friendly version of SectorLISP makes it possible to break giant\nexpressions like the above into smaller pieces. For example, the actual\nfunction from the S-expression above could be defined as follows:\n\n```lisp\n(DEFINE FF .\n  (LAMBDA (X)\n    (COND ((ATOM X) X)\n          ((QUOTE T) (FF (CAR X))))))\n```\n\nThe friendly version also has the advantage of not exhibiting undefined\nbehavior upon mistyped keystrokes!\n\n## On Real Mode\n\nWe call real mode \"real\" because it puts your virtual machine in a mode\nthat simulates non-virtualized memory ops. This adds a certain level of\nfun when programming, because it makes things so much simpler than long\nmode, which mandates that all memory operations be indirected through a\n4-level radix trie.\n\nThe i8086 is still able to virtualize memory using segment registers:\n\n- `%cs` (CODE SEGMENT)\n- `%ds` (DATA SEGMENT)\n- `%ss` (STACK SEGMENT)\n- `%es` (EXTRA SEGMENT)\n\nBIOS programs are loaded to the address 0x7c00. What SectorLISP does is\nit sets all the segments to the load address, which effectively\nredefines `NULL` to be equal to the base of the program image.\n"
  },
  {
    "path": "third_party/xterm.js/LICENSE",
    "content": "xterm.js was downloaded from:\n\nhttps://cdn.jsdelivr.net/npm/xterm@5.1.0/lib/xterm.min.js\nhttps://cdn.jsdelivr.net/npm/xterm@5.1.0/css/xterm.css\n\nCopyright (c) 2017-2019, The xterm.js authors (https://github.com/xtermjs/xterm.js)\nCopyright (c) 2014-2016, SourceLair Private Company (https://www.sourcelair.com)\nCopyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "third_party/xterm.js/xterm.css",
    "content": "/**\n * Copyright (c) 2014 The xterm.js authors. All rights reserved.\n * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)\n * https://github.com/chjj/term.js\n * @license MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * Originally forked from (with the author's permission):\n *   Fabrice Bellard's javascript vt100 for jslinux:\n *   http://bellard.org/jslinux/\n *   Copyright (c) 2011 Fabrice Bellard\n *   The original design remains. The terminal itself\n *   has been extended to include xterm CSI codes, among\n *   other features.\n */\n\n/**\n *  Default styles for xterm.js\n */\n\n.xterm {\n    cursor: text;\n    position: relative;\n    user-select: none;\n    -ms-user-select: none;\n    -webkit-user-select: none;\n}\n\n.xterm.focus,\n.xterm:focus {\n    outline: none;\n}\n\n.xterm .xterm-helpers {\n    position: absolute;\n    top: 0;\n    /**\n     * The z-index of the helpers must be higher than the canvases in order for\n     * IMEs to appear on top.\n     */\n    z-index: 5;\n}\n\n.xterm .xterm-helper-textarea {\n    padding: 0;\n    border: 0;\n    margin: 0;\n    /* Move textarea out of the screen to the far left, so that the cursor is not visible */\n    position: absolute;\n    opacity: 0;\n    left: -9999em;\n    top: 0;\n    width: 0;\n    height: 0;\n    z-index: -5;\n    /** Prevent wrapping so the IME appears against the textarea at the correct position */\n    white-space: nowrap;\n    overflow: hidden;\n    resize: none;\n}\n\n.xterm .composition-view {\n    /* TODO: Composition position got messed up somewhere */\n    background: #000;\n    color: #FFF;\n    display: none;\n    position: absolute;\n    white-space: nowrap;\n    z-index: 1;\n}\n\n.xterm .composition-view.active {\n    display: block;\n}\n\n.xterm .xterm-viewport {\n    /* On OS X this is required in order for the scroll bar to appear fully opaque */\n    background-color: #000;\n    overflow-y: scroll;\n    cursor: default;\n    position: absolute;\n    right: 0;\n    left: 0;\n    top: 0;\n    bottom: 0;\n}\n\n.xterm .xterm-screen {\n    position: relative;\n}\n\n.xterm .xterm-screen canvas {\n    position: absolute;\n    left: 0;\n    top: 0;\n}\n\n.xterm .xterm-scroll-area {\n    visibility: hidden;\n}\n\n.xterm-char-measure-element {\n    display: inline-block;\n    visibility: hidden;\n    position: absolute;\n    top: 0;\n    left: -9999em;\n    line-height: normal;\n}\n\n.xterm.enable-mouse-events {\n    /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */\n    cursor: default;\n}\n\n.xterm.xterm-cursor-pointer,\n.xterm .xterm-cursor-pointer {\n    cursor: pointer;\n}\n\n.xterm.column-select.focus {\n    /* Column selection mode */\n    cursor: crosshair;\n}\n\n.xterm .xterm-accessibility,\n.xterm .xterm-message {\n    position: absolute;\n    left: 0;\n    top: 0;\n    bottom: 0;\n    z-index: 10;\n    color: transparent;\n}\n\n.xterm .live-region {\n    position: absolute;\n    left: -9999px;\n    width: 1px;\n    height: 1px;\n    overflow: hidden;\n}\n\n.xterm-dim {\n    opacity: 0.5;\n}\n\n.xterm-underline-1 { text-decoration: underline; }\n.xterm-underline-2 { text-decoration: double underline; }\n.xterm-underline-3 { text-decoration: wavy underline; }\n.xterm-underline-4 { text-decoration: dotted underline; }\n.xterm-underline-5 { text-decoration: dashed underline; }\n\n.xterm-strikethrough {\n    text-decoration: line-through;\n}\n\n.xterm-screen .xterm-decoration-container .xterm-decoration {\n\tz-index: 6;\n\tposition: absolute;\n}\n\n.xterm-decoration-overview-ruler {\n    z-index: 7;\n    position: absolute;\n    top: 0;\n    right: 0;\n    pointer-events: none;\n}\n\n.xterm-decoration-top {\n    z-index: 2;\n    position: relative;\n}\n"
  },
  {
    "path": "tool/config/clock_settime.c",
    "content": "#include <time.h>\n\nint main(int argc, char *argv[]) {\n  clock_settime(-1, 0);\n}\n"
  },
  {
    "path": "tool/config/config.mk",
    "content": "#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐\n#── vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi ──────────────────────┘\n\no/$(MODE)/tool/config/%.com: tool/config/%.c\n\t@mkdir -p $(@D)\n\t$(CC) -o $@ $< $(LDLIBS)\n\no/$(MODE)/tool/config/zlib.com: private LDLIBS += -lz\no/$(MODE)/tool/config/libunwind.com: private LDLIBS += -lunwind -lucontext -llzma\n"
  },
  {
    "path": "tool/config/dev_urandom.c",
    "content": "// tests for non-buggy sysctl(KERN_ARND)\n#include <fcntl.h>\n#include <string.h>\n#include <unistd.h>\n\n#ifdef _WIN32\n#error posix /dev does not exist on windows.\n#endif\n\n/*\n * assuming the system is working correctly there's a 1 in\n * 235716896562095165800448 chance this check should flake\n */\n#define BYTES 9\n#define TRIES 16\n\nstatic ssize_t GetRandom(unsigned char *p, size_t n) {\n  int fd;\n  ssize_t rc;\n  if ((fd = open(\"/dev/urandom\", O_RDONLY)) == -1) return -1;\n  rc = read(fd, p, n);\n  close(fd);\n  return rc;\n}\n\nint main(int argc, char *argv[]) {\n  size_t i, j;\n  int haszero, fails = 0;\n  unsigned char x[BYTES];\n  for (i = 0; i < TRIES; ++i) {\n    memset(x, 0, sizeof(x));\n    if (GetRandom(x, sizeof(x)) != sizeof(x)) return 1;\n    for (haszero = j = 0; j < BYTES; ++j) {\n      if (!x[j]) haszero = 1;\n    }\n    if (haszero) ++fails;\n  }\n  if (fails < TRIES) {\n    return 0;\n  } else {\n    return 2;\n  }\n}\n"
  },
  {
    "path": "tool/config/dup3.c",
    "content": "// checks for dup3() system call\n#include <fcntl.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  char path[128];\n  snprintf(path, 128, \"/tmp/blink.config.%d\", getpid());\n  if (open(path, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0600) != 3) return 1;\n  if (fcntl(3, F_GETFD) != FD_CLOEXEC) return 2;\n  if (dup3(3, 4, 0) != 4) return 3;\n  if (fcntl(4, F_GETFD) != 0) return 4;\n  if (dup3(3, 4, O_CLOEXEC) != 4) return 5;\n  if (fcntl(4, F_GETFD) != FD_CLOEXEC) return 6;\n  if (unlink(path)) return 7;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/epoll_pwait1.c",
    "content": "// Checks for RHEL6+ level epoll() support.\n#include <sys/epoll.h>\n\nint main(int argc, char *argv[]) {\n  epoll_create(-1);\n  epoll_create1(-1);\n  epoll_pwait(-1, 0, 0, 0, 0);\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/epoll_pwait2.c",
    "content": "#include <sys/epoll.h>\n\nint main(int argc, char *argv[]) {\n  epoll_pwait2(-1, 0, 0, 0, 0);\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/f_getown_ex.c",
    "content": "// checks if F_GETOWN_EX will break build\n#include <fcntl.h>\n\nint main(int argc, char *argv[]) {\n  unsigned long magnums[] = {\n      F_GETOWN_EX,   //\n      F_SETOWN_EX,   //\n      F_OWNER_TID,   //\n      F_OWNER_PID,   //\n      F_OWNER_PGRP,  //\n  };\n  (void)magnums;\n}\n"
  },
  {
    "path": "tool/config/fdatasync.c",
    "content": "// checks for fdatasync() system call\n#include <fcntl.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  char path[128];\n  int fd, rc;\n  snprintf(path, 128, \"/tmp/blink.config.%d\", getpid());\n  fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0600);\n  if (fd == -1) return 1;\n  rc = fdatasync(fd);\n  if (rc == -1) return 2;\n  if (rc) return 3;\n  close(fd);\n  if (unlink(path)) return 4;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/fexecve.c",
    "content": "// checks for fexecve\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  char *const args[] = {0};\n  char *const envs[] = {0};\n  fexecve(0, args, envs);\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/fork.c",
    "content": "// checks if fork() works\n#include <sys/wait.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  int ws;\n  pid_t pid, rc;\n  pid = fork();\n  if (pid == -1) return 1;\n  if (!pid) _exit(42);\n  rc = wait(&ws);\n  if (rc == -1) return 2;\n  if (rc != pid) return 3;\n  if (!WIFEXITED(ws)) return 4;\n  if (WEXITSTATUS(ws) != 42) return 5;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/getdomainname.c",
    "content": "// checks if getdomainname() works\n#include <string.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  int rc;\n  char buf[256];\n  memset(buf, 0, 256);\n  rc = getdomainname(buf, 256);\n  if (rc == -1) return 1;           // library failed\n  if (rc) return 2;                 // library broken\n  if (strlen(buf) > 255) return 4;  // library broken\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/getentropy.c",
    "content": "// checks for getentropy() with bsd style include\n#include <unistd.h>\n\n/*\n * assuming the system is working correctly there's a 1 in\n * 235716896562095165800448 chance this check should flake\n */\n#define BYTES 9\n#define TRIES 16\n\nint main(int argc, char *argv[]) {\n  int rc;\n  size_t i, j;\n  int haszero, fails = 0;\n  for (i = 0; i < TRIES; ++i) {\n    unsigned char x[BYTES] = {0};\n    rc = getentropy(x, sizeof(x));\n    if (rc == -1) return 1;\n    if (rc) return 2;\n    for (haszero = j = 0; j < BYTES; ++j) {\n      if (!x[j]) haszero = 1;\n    }\n    if (haszero) ++fails;\n  }\n  if (fails < TRIES) {\n    return 0;\n  } else {\n    return 3;\n  }\n}\n"
  },
  {
    "path": "tool/config/getrandom.c",
    "content": "// tests for getrandom()\n#include <sys/random.h>\n\n/*\n * assuming the system is working correctly there's a 1 in\n * 235716896562095165800448 chance this check should flake\n */\n#define BYTES 9\n#define TRIES 16\n\nint main(int argc, char *argv[]) {\n  ssize_t rc;\n  size_t i, j;\n  int haszero, fails = 0;\n  for (i = 0; i < TRIES; ++i) {\n    unsigned char x[BYTES] = {0};\n    rc = getrandom(x, BYTES, 0);\n    if (rc == -1) return 1;\n    if (rc != BYTES) return 2;\n    for (haszero = j = 0; j < BYTES; ++j) {\n      if (!x[j]) haszero = 1;\n    }\n    if (haszero) ++fails;\n  }\n  if (fails < TRIES) {\n    return 0;\n  } else {\n    return 3;\n  }\n}\n"
  },
  {
    "path": "tool/config/kern_arnd.c",
    "content": "// tests for non-buggy sysctl(KERN_ARND)\n#include <sys/types.h>\n// order sometimes matters\n#include <string.h>\n#include <sys/param.h>\n#include <sys/sysctl.h>\n\n/*\n * \"On FreeBSD old implementations returned longs, newer versions\n * support variable sizes up to 256 byte. The code below would not work\n * properly when the sysctl returns long and we want to request\n * something not a multiple of longs, which should never be the case.\"\n * -Quoth the OpenSSL source code\n *\n * \"On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only\n * filled in an int, leaving the rest uninitialized. Since NetBSD 4.0 it\n * returns a variable number of bytes with the current version\n * supporting up to 256 bytes.\" -Quoth the OpenSSL source code.\n */\n\n/*\n * assuming the system is working correctly there's a 1 in\n * 235716896562095165800448 chance this check should flake\n */\n#define BYTES 9\n#define TRIES 16\n\nint main(int argc, char *argv[]) {\n  int haszero;\n  int fails = 0;\n  size_t i, j, m;\n  unsigned char x[BYTES];\n  int mib[2] = {CTL_KERN, KERN_ARND};\n  for (i = 0; i < TRIES; ++i) {\n    memset(x, 0, sizeof(x));\n    m = sizeof(x);\n    if (sysctl(mib, 2, &x, &m, 0, 0) == -1) return 1;\n    if (m != sizeof(x)) return 2;\n    for (haszero = j = 0; j < BYTES; ++j) {\n      if (!x[j]) haszero = 1;\n    }\n    if (haszero) ++fails;\n  }\n  if (fails < TRIES) {\n    return 0;\n  } else {\n    return 3;\n  }\n}\n"
  },
  {
    "path": "tool/config/libunwind.c",
    "content": "// checks for libunwind backtrace support\n#define UNW_LOCAL_ONLY\n#ifdef __x86_64__\n#include <libunwind-x86_64.h>\n#else\n#include <libunwind.h>\n#endif\n#include <stdio.h>\n#include <string.h>\n\n#define APPEND(...) o += snprintf(b + o, n - o, __VA_ARGS__)\n\nconst char *GetBacktrace(void) {\n  static char b[2048];\n  int o = 0;\n  char sym[256];\n  int n = sizeof(b);\n  unw_cursor_t cursor;\n  unw_context_t context;\n  unw_word_t offset, pc;\n  unw_getcontext(&context);\n  unw_init_local(&cursor, &context);\n  APPEND(\"backtrace\");\n  while (unw_step(&cursor) > 0) {\n    unw_get_reg(&cursor, UNW_REG_IP, &pc);\n    if (!pc) break;\n    APPEND(\"\\n\\t%lx \", pc);\n    if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {\n      APPEND(\"%s+%ld\", sym, offset);\n    } else {\n      APPEND(\"<unknown>\");\n    }\n  }\n  return b;\n}\n\nconst char *MyApp(void) {\n  return GetBacktrace();\n}\n\nconst char *(*MyAppPtr)(void) = MyApp;\n\nint main(int argc, char *argv[]) {\n  const char *bt;\n  bt = MyAppPtr();\n  if (!strstr(bt, \"MyApp\")) return 1;\n  if (!strstr(bt, \"main\")) return 2;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/lm.c",
    "content": "// checks that -lm won't break the build\n#include <math.h>\n\ndouble three(void) {\n  return 3;\n}\n\ndouble (*f)(void) = three;\n\nint main(int argc, char *argv[]) {\n  if (pow(f(), f()) != 27.) return 1;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/lrt.c",
    "content": "// checks that -lrt won't break the build\n#include <time.h>\n\nint main(int argc, char *argv[]) {\n  struct timespec ts;\n  if (clock_getres(CLOCK_REALTIME, &ts)) return 1;\n  if (clock_gettime(CLOCK_REALTIME, &ts)) return 1;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/map_anonymous.c",
    "content": "// checks for MAP_ANONYMOUS feature\n#include <sys/mman.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  void *p;\n  p = mmap(0, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE,\n           MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  if (p == MAP_FAILED) return 1;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/map_shared.c",
    "content": "// checks if mmap(MAP_SHARED) works\n#include <stdio.h>\n#include <sys/mman.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  FILE *f;\n  void *map;\n  int ws, *x;\n  pid_t pid, rc;\n  if (!(f = tmpfile())) return 1;\n  if (ftruncate(fileno(f), sizeof(int))) return 2;\n  map = mmap(0, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fileno(f), 0);\n  if (map == MAP_FAILED) return 3;\n  x = (int *)map;\n  pid = fork();\n  if (pid == -1) return 4;\n  if (!pid) {\n    *x = 42;\n    msync(map, sizeof(int), MS_INVALIDATE);\n    _exit(0);\n  }\n  rc = wait(&ws);\n  if (rc == -1) return 5;\n  if (rc != pid) return 6;\n  if (!WIFEXITED(ws)) return 7;\n  if (WEXITSTATUS(ws)) return 8;\n  if (*x != 42) return 9;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/memccpy.c",
    "content": "// checks for memccpy() xsi extension\n#include <string.h>\n\nint main(int argc, char *argv[]) {\n  char buf[16];\n  if (memccpy(buf, \"hi\", '\\0', sizeof(buf)) != buf + 3) return 1;\n  if (strcmp(buf, \"hi\")) return 2;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/mkfifo.c",
    "content": "// tests for mkfifo() support\n// e.g. not provided by cosmopolitan libc\n#include <fcntl.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  char path[128];\n  snprintf(path, 128, \"/tmp/blink.config.%d\", getpid());\n  if (mkfifo(path, 0644)) return 2;\n  if (unlink(path)) return 3;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/mkfifoat.c",
    "content": "// tests for mkfifoat() support\n// not present on MacOS until 13+ c. 2022\n#include <fcntl.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  char path[128];\n  snprintf(path, 128, \"/tmp/blink.config.%d\", getpid());\n  if (mkfifoat(AT_FDCWD, path, 0644)) return 2;\n  if (unlink(path)) return 3;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/noop.c",
    "content": "// c program that does nothing\n\nint main() {\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/pipe2.c",
    "content": "// checks for pipe2() system call\n#include <fcntl.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  int fds[2];\n  if (pipe2(fds, 0)) return 1;\n  if (fcntl(fds[0], F_GETFD) != 0) return 2;\n  if (fcntl(fds[1], F_GETFD) != 0) return 3;\n  if (pipe2(fds, O_CLOEXEC)) return 4;\n  if (fcntl(fds[0], F_GETFD) != FD_CLOEXEC) return 5;\n  if (fcntl(fds[1], F_GETFD) != FD_CLOEXEC) return 6;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/preadv.c",
    "content": "// tests for preadv() and pwritev() support\n// missing on MacOS (before 2020), Cygwin, Haiku, etc.\n#include <stdio.h>\n#include <sys/uio.h>\n\nint main(int argc, char *argv[]) {\n  FILE *f;\n  char x, y;\n  struct iovec vx, vy;\n\n  if (!(f = tmpfile())) return 1;\n\n  x = 123;\n  vx.iov_base = &x;\n  vx.iov_len = 1;\n  if (pwritev(fileno(f), &vx, 1, 5) != 1) return 2;\n\n  vy.iov_base = &y;\n  vy.iov_len = 1;\n  if (preadv(fileno(f), &vy, 1, 5) != 1) return 3;\n\n  if (y != 123) return 4;\n\n  fclose(f);\n\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/pthread.c",
    "content": "// checks posix threads works\n#include <pthread.h>\n\nvoid *Worker(void *arg) {\n  return arg;\n}\n\nint main(int argc, char *argv[]) {\n  pthread_t th;\n  void *arg, *res;\n  arg = (void *)argv;\n  if (pthread_create(&th, 0, Worker, arg)) return 1;\n  if (pthread_join(th, &res)) return 2;\n  if (res != arg) return 3;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/pthread_process_shared.c",
    "content": "// test for interprocess mutexes and condition variables\n// clang-format off\n#include <stdio.h>\n#include <unistd.h>\n#include <pthread.h>\n#include <sys/mman.h>\n#include <sys/wait.h>\n#include <stdatomic.h>\n\nint main(int argc, char *argv[]) {\n  int ws;\n  FILE *f;\n  pid_t pid;\n  pthread_condattr_t ca;\n  pthread_mutexattr_t ma;\n  struct Shared {\n    atomic_int state;\n    pthread_cond_t cond;\n    pthread_mutex_t lock;\n  } *s;\n  if (!(f = tmpfile())) return 0;\n  if (ftruncate(fileno(f), 4096)) return 1;\n  if ((s = (struct Shared *)mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0)) == MAP_FAILED) return 2;\n  if (pthread_condattr_init(&ca)) return 3;\n  if (pthread_mutexattr_init(&ma)) return 4;\n  if (pthread_condattr_setpshared(&ca, PTHREAD_PROCESS_SHARED)) return 5;\n  if (pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED)) return 6;\n  if (pthread_cond_init(&s->cond, &ca)) return 7;\n  if (pthread_mutex_init(&s->lock, &ma)) return 8;\n  if (pthread_mutexattr_destroy(&ma)) return 9;\n  if (pthread_condattr_destroy(&ca)) return 10;\n  if ((pid = fork()) == -1) return 11;\n  if (!pid) {\n    alarm(2);\n    if (pthread_mutex_lock(&s->lock)) return 12;\n    s->state = 1;\n    if (pthread_cond_wait(&s->cond, &s->lock)) return 13;\n    if (pthread_mutex_unlock(&s->lock)) return 14;\n    while (s->state != 2);\n    if (pthread_mutex_lock(&s->lock)) return 15;\n    if (pthread_cond_signal(&s->cond)) return 16;\n    if (pthread_mutex_unlock(&s->lock)) return 17;\n    _exit(0);\n  }\n  alarm(2);\n  while (s->state != 1);\n  if (pthread_mutex_lock(&s->lock)) return 18;\n  if (pthread_cond_signal(&s->cond)) return 19;\n  if (pthread_mutex_unlock(&s->lock)) return 20;\n  if (pthread_mutex_lock(&s->lock)) return 21;\n  s->state = 2;\n  if (pthread_cond_wait(&s->cond, &s->lock)) return 22;\n  if (pthread_mutex_unlock(&s->lock)) return 23;\n  if (wait(&ws) != pid) return 24;\n  if (!WIFEXITED(ws)) return 25;\n  if (WEXITSTATUS(ws)) return 26;\n  if (pthread_mutex_destroy(&s->lock)) return 27;\n  if (pthread_cond_destroy(&s->cond)) return 28;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/pthread_setcancelstate.c",
    "content": "// checks if pthread_setcancelstate is available and usable\n#include <pthread.h>\n\nvoid *Worker(void *arg) {\n  return arg;\n}\n\nint main(int argc, char *argv[]) {\n  if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0))\n    return 1;\n  if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0))\n    return 1;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/realpath.c",
    "content": "// checks that realpath() won't break build\n#include <limits.h>\n#include <stdlib.h>\n\nint main(int argc, char *argv[]) {\n  char path[PATH_MAX];\n  if (!realpath(\"/tmp\", path)) return 1;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/rtlgenrandom.c",
    "content": "// tests for RtlGenRandom()\n#include <stdbool.h>\n#include <stdlib.h> // Required for __MINGW64_VERSION_MAJOR, not using __MINGW32__ since old MinGW32 also defines it. See https://github.com/cpredef/predef/blob/master/Compilers.md#mingw-and-mingw-w64.\n#ifndef __MINGW64_VERSION_MAJOR\n#include <w32api/_mingw.h>\n#endif\n\nbool __stdcall SystemFunction036(void *, __LONG32);\n\nint main(int argc, char *argv[]) {\n  long x = 0;\n  if (!SystemFunction036(&x, sizeof(x))) return 1;\n  if (!x) return 2;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/sa_len.c",
    "content": "// checks for bsd style sockaddr length field\n#include <sys/socket.h>\n\nint main(int argc, char *argv[]) {\n  struct sockaddr sa;\n  sa.sa_len = 1;\n  (void)sa;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/sched_getaffinity.c",
    "content": "// checks for sched_getaffinity()\n#include <sched.h>\n\nint main(int argc, char *argv[]) {\n  int rc;\n  cpu_set_t cs;\n  CPU_ZERO(&cs);\n  rc = sched_getaffinity(0, sizeof(cs), &cs);\n  if (rc == -1) return 1;         // system call failed\n  if (rc) return 2;               // libc wrapper broken\n  if (!CPU_COUNT(&cs)) return 3;  // system call broken\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/sched_h.c",
    "content": "// checks for sched.h header\n#include <sched.h>\n\nint main(int argc, char *argv[]) {\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/sched_yield.c",
    "content": "// checks for sched_yield() support\n#include <sched.h>\n\nint main(int argc, char *argv[]) {\n  if (sched_yield()) return 1;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/scm_credentials.c",
    "content": "// checks that SCM_CREDENTIALS won't break the build\n#include <sys/socket.h>\n#include <sys/un.h>\n\nint main(int argc, char *argv[]) {\n  struct ucred ucred;\n  ucred.pid = SCM_CREDENTIALS;\n  ucred.uid = SCM_CREDENTIALS;\n  ucred.gid = SCM_CREDENTIALS;\n  (void)ucred;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/seekdir.c",
    "content": "// checks for telldir() and seekdir() support\n#include <dirent.h>\n#include <string.h>\n\nint main(int argc, char *argv[]) {\n  DIR *d;\n  long spot;\n  char name[256];\n  struct dirent *e;\n  if (!(d = opendir(\"/tmp\"))) return 1;\n  // read first entry, saving this position\n  if ((spot = telldir(d)) == -1) return 2;\n  if (!(e = readdir(d))) return 3;\n  strcpy(name, e->d_name);\n  // read second entry, ensuring it's different\n  if (!(e = readdir(d))) return 4;\n  if (!strcmp(name, e->d_name)) return 5;\n  // read the first entry again, ensuring it's what we remember\n  seekdir(d, spot);\n  if (!(e = readdir(d))) return 6;\n  if (strcmp(name, e->d_name)) return 7;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/sendto_zero.c",
    "content": "// checks if sendto(0.0.0.0) will copy address from connect()\n#include <netinet/in.h>\n#include <netinet/udp.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/socket.h>\n#include <sys/syscall.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  pid_t pid;\n  int rc, ws;\n  socklen_t socklen;\n  char buf[8] = {0};\n  struct sockaddr_in addr = {\n      .sin_family = AF_INET,\n      .sin_addr.s_addr = htonl(INADDR_LOOPBACK),\n  };\n  socklen = sizeof(addr);\n  if (socket(AF_INET, SOCK_DGRAM, 0) != 3) return 1;\n  if (bind(3, (struct sockaddr *)&addr, sizeof(addr))) return 2;\n  if (getsockname(3, (struct sockaddr *)&addr, &socklen)) return 3;\n  if ((pid = fork()) == -1) return 4;\n  if (!pid) {\n    alarm(5);\n    if (read(3, buf, 8) != 2) _exit(5);\n    if (strcmp(buf, \"hi\")) _exit(6);\n    _exit(0);\n  }\n  if (close(3)) return 7;\n  if (socket(AF_INET, SOCK_DGRAM, 0) != 3) return 8;\n  if (connect(3, (struct sockaddr *)&addr, sizeof(addr))) return 9;\n  addr.sin_addr.s_addr = 0;\n  if (sendto(3, \"hi\", 2, 0, (struct sockaddr *)&addr, sizeof(addr)) != 2) {\n    // OpenBSD 7.2 fails with EISCONN here.\n    perror(\"sendto\");\n    return 10;\n  }\n  if (wait(&ws) != pid) return 11;\n  return WEXITSTATUS(ws);\n}\n"
  },
  {
    "path": "tool/config/setgroups.c",
    "content": "// checks setgroups() won't break build\n#include <grp.h>\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  (void)setgroups(0, 0);\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/setresuid.c",
    "content": "// checks that setresuid() won't break the build\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  int rc = setresuid(-1, -1, -1);  // noop by definition\n  if (rc == -1) return 1;          // failed\n  if (rc) return 2;                // broken\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/setreuid.c",
    "content": "// checks that setreuid() won't break the build\n#include <unistd.h>\n\nint main(int argc, char *argv[]) {\n  int rc = setreuid(-1, -1);  // noop by definition\n  if (rc == -1) return 1;     // failed\n  if (rc) return 2;           // broken\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/siocgifconf.c",
    "content": "// checks if we can enumerate network interfaces\n#include <net/if.h>\n#include <sys/ioctl.h>\n#include <sys/socket.h>\n\nchar buf[16384];\n\nint main(int argc, char *argv[]) {\n  int rc;\n  struct ifreq *ifreq;\n  struct ifconf ifconf;\n  unsigned long magnums_we_care_about[] = {\n      IFNAMSIZ,        //\n      SIOCGIFADDR,     //\n      SIOCGIFNETMASK,  //\n      SIOCGIFBRDADDR,  //\n      SIOCGIFDSTADDR,  //\n  };\n  ifconf.ifc_buf = buf;\n  ifconf.ifc_len = sizeof(buf);\n  socket(AF_INET, SOCK_DGRAM, 0);\n  rc = ioctl(3, SIOCGIFCONF, &ifconf);\n  if (rc) return 1;\n  if (!ifconf.ifc_len) return 2;\n  ifreq = ifconf.ifc_req;\n  (void)ifreq;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/sockatmark.c",
    "content": "// checks if sockatmark is available\n#include <sys/socket.h>\n\nint main(int argc, char *argv[]) {\n  int rc;\n  socket(AF_INET, SOCK_STREAM, 0);\n  if (sockatmark(3) == -1) return 1;\n  return 0;\n}"
  },
  {
    "path": "tool/config/stdatomic.c",
    "content": "// checks for c11 atomics\n#include <stdatomic.h>\n\natomic_int x;\n\nint main(int argc, char *argv[]) {\n  if (atomic_exchange_explicit(&x, 123, memory_order_relaxed) != 0) return 1;\n  if (atomic_exchange_explicit(&x, 456, memory_order_relaxed) != 123) return 2;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/strchrnul.c",
    "content": "// checks for strchrnul() support\n#include <string.h>\n\nint main(int argc, char *argv[]) {\n  char s[] = \"abc\";\n  if (strchrnul(s, 'a') != s) return 1;\n  if (strchrnul(s, 'b') != s + 1) return 2;\n  if (strchrnul(s, 'c') != s + 2) return 3;\n  if (strchrnul(s, 'd') != s + 3) return 4;\n  if (strchrnul(s, 'e') != s + 3) return 5;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/struct_timezone.c",
    "content": "// checks if struct timezone is specified\n#include <sys/time.h>\n\nint main(int argc, char *argv[]) {\n  struct timezone tz;\n  tz.tz_minuteswest = 1;\n  tz.tz_dsttime = 1;\n  (void)tz;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/sync.c",
    "content": "// check for sync() xsi extension\n#include <unistd.h>\n\nvoid DontCallMeBro(void) {\n  sync();\n}\n\nint main(int argc, char *argv[]) {\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/sys_getentropy.c",
    "content": "// checks for getentropy() with apple style include\n#include <sys/random.h>\n\n/*\n * assuming the system is working correctly there's a 1 in\n * 235716896562095165800448 chance this check should flake\n */\n#define BYTES 9\n#define TRIES 16\n\nint main(int argc, char *argv[]) {\n  int rc;\n  size_t i, j;\n  int haszero, fails = 0;\n  for (i = 0; i < TRIES; ++i) {\n    unsigned char x[BYTES] = {0};\n    rc = getentropy(x, sizeof(x));\n    if (rc == -1) return 1;\n    if (rc) return 2;\n    for (haszero = j = 0; j < BYTES; ++j) {\n      if (!x[j]) haszero = 1;\n    }\n    if (haszero) ++fails;\n  }\n  if (fails < TRIES) {\n    return 0;\n  } else {\n    return 3;\n  }\n}\n"
  },
  {
    "path": "tool/config/sys_getrandom.c",
    "content": "// tests for syscall(SYS_getrandom)\n#include <sys/syscall.h>\n#include <unistd.h>\n\n/*\n * assuming the system is working correctly there's a 1 in\n * 235716896562095165800448 chance this check should flake\n */\n#define BYTES 9\n#define TRIES 16\n\nint main(int argc, char *argv[]) {\n  ssize_t rc;\n  size_t i, j;\n  int haszero, fails = 0;\n  for (i = 0; i < TRIES; ++i) {\n    unsigned char x[BYTES] = {0};\n    rc = syscall(SYS_getrandom, x, BYTES, 0);\n    if (rc == -1) return 1;\n    if (rc != BYTES) return 2;\n    for (haszero = j = 0; j < BYTES; ++j) {\n      if (!x[j]) haszero = 1;\n    }\n    if (haszero) ++fails;\n  }\n  if (fails < TRIES) {\n    return 0;\n  } else {\n    return 3;\n  }\n}\n"
  },
  {
    "path": "tool/config/sys_mount_h.c",
    "content": "#include <sys/types.h>\n// ordering matters on openbsd\n// checks for sys/mount.h header\n#include <sys/mount.h>\n\nint main(int argc, char *argv[]) {\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/sysctl.c",
    "content": "// tests for bsd sysctl() system call\n#include <sys/types.h>\n// ordering sometimes matters\n#include <sys/sysctl.h>\n#include <sys/time.h>\n\nint features_we_care_about[] = {\n    CTL_HW,         //\n    CTL_KERN,       //\n    KERN_BOOTTIME,  //\n    HW_NCPU,        //\n#ifdef HW_MEMSIZE\n    HW_MEMSIZE,\n#else\n    HW_PHYSMEM,\n#endif\n};\n\nint main(int argc, char *argv[]) {\n  struct timeval x;\n  size_t n = sizeof(x);\n  int mib[] = {CTL_KERN, KERN_BOOTTIME};\n  if (sysctl(mib, 2, &x, &n, 0, 0) == -1) return 1;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/sysinfo.c",
    "content": "// tests for linux sysinfo() system call\n#include <sys/sysinfo.h>\n\nint main(int argc, char *argv[]) {\n  struct sysinfo si;\n  if (sysinfo(&si)) return 1;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/vasprintf.c",
    "content": "// checks for vasprintf() function\n// available in gnu/bsd/mac/cygwin\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nchar *xasprintf(const char *fmt, ...) {\n  int rc;\n  char *s;\n  va_list va;\n  va_start(va, fmt);\n  rc = vasprintf(&s, fmt, va);\n  va_end(va);\n  if (rc == -1) exit(1);         // vasprintf failed\n  if (rc != strlen(s)) exit(2);  // vasprintf broken\n  return s;\n}\n\nint main(int argc, char *argv[]) {\n  char *s;\n  s = xasprintf(\"hello %d\", 123);\n  if (strcmp(s, \"hello 123\")) exit(3);\n  free(s);\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/wait4.c",
    "content": "// checks if wait4() will break build\n#include <errno.h>\n#include <sys/resource.h>\n#include <sys/wait.h>\n\nint main(int argc, char *argv[]) {\n  int ws;\n  pid_t rc;\n  struct rusage ru;\n  rc = wait4(-1, &ws, -1, &ru);\n  if (rc != (pid_t)-1) return 1;\n  if (errno != EINVAL) return 2;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/wcwidth.c",
    "content": "// checks for wcwidth() support\n#include <wchar.h>\n\nint main(int argc, char *argv[]) {\n  if (wcwidth(0) != 0) return 1;\n  if (wcwidth(32) != 1) return 2;\n  if (wcwidth(0x672c) != 2) return 3;\n  return 0;\n}\n"
  },
  {
    "path": "tool/config/zlib.c",
    "content": "// checks if system provides a working zlib\n#include <stdlib.h>\n#include <string.h>\n#include <zlib.h>\n\n#define unassert(x)          \\\n  do {                       \\\n    if (!(x)) {              \\\n      exit(__COUNTER__ + 1); \\\n    }                        \\\n  } while (0)\n\nvoid *Deflate(const void *data, unsigned size, unsigned *out_size) {\n  void *res;\n  uLong bound;\n  z_stream zs = {0};\n  bound = compressBound(size);\n  unassert(res = malloc(bound));\n  unassert(deflateInit2(&zs, 4, Z_DEFLATED, -MAX_WBITS, 8,\n                        Z_DEFAULT_STRATEGY) == Z_OK);\n  zs.next_in = (z_const Bytef *)data;\n  zs.avail_in = size;\n  zs.avail_out = bound;\n  zs.next_out = (Bytef *)res;\n  unassert(deflate(&zs, Z_FINISH) == Z_STREAM_END);\n  unassert(deflateEnd(&zs) == Z_OK);\n  unassert(res = realloc(res, zs.total_out));\n  *out_size = zs.total_out;\n  return res;\n}\n\nvoid Inflate(void *out, unsigned outsize, const void *in, unsigned insize) {\n  z_stream zs;\n  zs.next_in = (z_const Bytef *)in;\n  zs.avail_in = insize;\n  zs.total_in = insize;\n  zs.next_out = (Bytef *)out;\n  zs.avail_out = outsize;\n  zs.total_out = outsize;\n  zs.zalloc = Z_NULL;\n  zs.zfree = Z_NULL;\n  unassert(inflateInit2(&zs, -MAX_WBITS) == Z_OK);\n  unassert(inflate(&zs, Z_FINISH) == Z_STREAM_END);\n  unassert(inflateEnd(&zs) == Z_OK);\n}\n\nint main(int argc, char *argv[]) {\n  char plain[64];\n  void *compressed;\n  const char *golden;\n  unsigned compressed_size;\n  memset(plain, 0, sizeof(plain));\n  compressed = Deflate(\"hello world\", 12, &compressed_size);\n  Inflate(plain, sizeof(plain), compressed, compressed_size);\n  unassert(!strcmp(plain, \"hello world\"));\n  free(compressed);\n  return 0;\n}\n"
  },
  {
    "path": "tool/dispatch.py",
    "content": "#!/usr/bin/env python3\n\nimport os\nimport sys\n\nDISPATCH = '''\\\n    /*000*/ OpAlubAdd,\n    /*001*/ OpAluw,\n    /*002*/ OpAlubFlipAdd,\netc...\n'''.split('\\n')\n\nCOUNT = [0 for _ in range(0x500)]\n\nfor arg in sys.argv[1:]:\n  with open(arg) as f:\n    for line in f:\n      line = line.strip()\n      if not line: continue\n      count, op = line.split()\n      count = int(count)\n      op = int(op)\n      COUNT[op] += count\n\ntoto = sum(COUNT)\nS = []\nfor op in range(len(DISPATCH)):\n  S.append((COUNT[op], op))\nS.sort(reverse=True)\nRANK = {}\nfor i, (_, op) in enumerate(S):\n  RANK[op] = i + 1\nREPORT = []\n\nfor op in range(len(DISPATCH)):\n  if COUNT[op]:\n    print(\"%-40s // #%-4d (%.6f%%)\" % (DISPATCH[op], RANK[op], COUNT[op] / float(toto) * 100))\n  else:\n    print(\"%-40s //\" % (DISPATCH[op]))\n"
  },
  {
    "path": "tool/fastsize.sh",
    "content": "#!/bin/sh\nm=${1:-tiny}\n\nF=\"\no/$m/x86_64/blink/blink\n\"\n\nmake -j8 $F m=$m || exit\n\nfor f in $F; do\n  cp $f $f.strip\ndone\n\no/third_party/gcc/x86_64/bin/x86_64-linux-musl-strip o/$m/x86_64/blink/blink.strip\n\nfor f in $F; do\n  ls -hal $f.strip\ndone\n"
  },
  {
    "path": "tool/flock.c",
    "content": "#include <stdlib.h>\n#include <string.h>\n#include <sys/file.h>\n\nint main(int argc, char *argv[]) {\n  if (argc != 3) return 1;\n  if (strcmp(argv[1], \"-x\")) return 2;\n  if (flock(atoi(argv[2]), LOCK_EX)) return 3;\n  return 0;\n}\n"
  },
  {
    "path": "tool/release-cosmo.sh",
    "content": "#!/bin/sh\nm=tiny\n\necho -n 'did you update blink/tunables.h and ape/ape.s? [n] '\nread didit\nif [ \"$didit\" != \"y\" ]; then\n  exit 1\nfi\n\nset -ex\n./configure\nmake -j8 check\n\n# create the linux arm64 build\nmake m=$m -j8 o/$m/aarch64/blink/blink\no/third_party/gcc/aarch64/bin/aarch64-linux-musl-strip \\\n  o/$m/aarch64/blink/blink\ngzip -c9 o/$m/aarch64/blink/blink \\\n     >o/$m/aarch64/blink/blink-aarch64.gz\ncp o/$m/aarch64/blink/blink-aarch64.gz \\\n   ~/cosmo/ape/blink-aarch64.gz\n\n# create the apple arm64 build\nrsync -avz --exclude=o \\\n      --exclude='*.xz' \\\n      --exclude='*.gz' \\\n      --exclude='*.dbg' \\\n      --exclude='*.com' \\\n      --exclude='*.dbg' \\\n      --exclude='*.elf' \\\n      ~/blink silicon:\nssh silicon cd blink \\&\\& \\\n    /usr/local/bin/make m=$m -j8 o/$m/blink/blink \\; \\\n    /usr/local/bin/make m=$m -j8 o/$m/blink/blink \\&\\& \\\n    strip o/$m/blink/blink \\&\\& \\\n    gzip -c9 o/$m/blink/blink \\>o/$m/blink/blink.gz\nscp silicon:blink/o/$m/blink/blink.gz \\\n    /home/jart/cosmo/ape/blink-darwin-arm64.gz\n\n# smoke test the release\n(\n  cd ~/cosmo\n  make -j8 o//test/libc/thread/pthread_create_test.com\n)\nscp ~/cosmo/o//test/libc/thread/pthread_create_test.com silicon:\nssh silicon ./pthread_create_test.com\nscp ~/cosmo/o//test/libc/thread/pthread_create_test.com pi:\nssh pi ./pthread_create_test.com\n\n# we're finished\no//blink/blink -v\nls -hal \\\n   ~/cosmo/ape/blink-aarch64.gz \\\n   ~/cosmo/ape/blink-darwin-arm64.gz\n"
  },
  {
    "path": "tool/release-linux.sh",
    "content": "#!/bin/bash\nset -ex\nv=1.1\n\nd=/mnt/videos/blink-$v\n[ ! -d $d ]\nmkdir -p $d\n\n./configure --static --enable-vfs\n\nmake -j32 \\\no//x86_64/blink/blink \\\no//x86_64/blink/blinkenlights \\\no//aarch64/blink/blink \\\no//aarch64/blink/blinkenlights \\\no//arm/blink/blink \\\no//arm/blink/blinkenlights \\\no//i486/blink/blink \\\no//i486/blink/blinkenlights \\\no//mips/blink/blink \\\no//mips/blink/blinkenlights \\\no//mipsel/blink/blink \\\no//mipsel/blink/blinkenlights \\\no//mips64/blink/blink \\\no//mips64/blink/blinkenlights \\\no//mips64el/blink/blink \\\no//mips64el/blink/blinkenlights \\\no//powerpc/blink/blink \\\no//powerpc/blink/blinkenlights \\\no//powerpc64le/blink/blink \\\no//powerpc64le/blink/blinkenlights \\\no//s390x/blink/blink \\\no//s390x/blink/blinkenlights\n\npdf() {\n  groff -Tps -man $1 >$2.ps\n  ps2pdf $2.ps $2.pdf\n}\n\ngit archive --format=tar.gz -o $d/blink-$v.tar.gz --prefix=blink-$v/ master\npdf blink/blink.1 $d/blink-$v\npdf blink/blinkenlights.1 $d/blinkenlights-$v\ngzip -9 <o//x86_64/blink/blink >$d/blink-$v-linux-x86_64.elf.gz\ngzip -9 <o//x86_64/blink/blinkenlights >$d/blinkenlights-$v-linux-x86_64.elf.gz\ngzip -9 <o//aarch64/blink/blink >$d/blink-$v-linux-aarch64.elf.gz\ngzip -9 <o//aarch64/blink/blinkenlights >$d/blinkenlights-$v-linux-aarch64.elf.gz\ngzip -9 <o//arm/blink/blink >$d/blink-$v-linux-arm.elf.gz\ngzip -9 <o//arm/blink/blinkenlights >$d/blinkenlights-$v-linux-arm.elf.gz\ngzip -9 <o//i486/blink/blink >$d/blink-$v-linux-i486.elf.gz\ngzip -9 <o//i486/blink/blinkenlights >$d/blinkenlights-$v-linux-i486.elf.gz\ngzip -9 <o//mips/blink/blink >$d/blink-$v-linux-mips.elf.gz\ngzip -9 <o//mips/blink/blinkenlights >$d/blinkenlights-$v-linux-mips.elf.gz\ngzip -9 <o//mipsel/blink/blink >$d/blink-$v-linux-mipsel.elf.gz\ngzip -9 <o//mipsel/blink/blinkenlights >$d/blinkenlights-$v-linux-mipsel.elf.gz\ngzip -9 <o//mips64/blink/blink >$d/blink-$v-linux-mips64.elf.gz\ngzip -9 <o//mips64/blink/blinkenlights >$d/blinkenlights-$v-linux-mips64.elf.gz\ngzip -9 <o//mips64el/blink/blink >$d/blink-$v-linux-mips64el.elf.gz\ngzip -9 <o//mips64el/blink/blinkenlights >$d/blinkenlights-$v-linux-mips64el.elf.gz\ngzip -9 <o//powerpc/blink/blink >$d/blink-$v-linux-powerpc.elf.gz\ngzip -9 <o//powerpc/blink/blinkenlights >$d/blinkenlights-$v-linux-powerpc.elf.gz\ngzip -9 <o//powerpc64le/blink/blink >$d/blink-$v-linux-powerpc64le.elf.gz\ngzip -9 <o//powerpc64le/blink/blinkenlights >$d/blinkenlights-$v-linux-powerpc64le.elf.gz\ngzip -9 <o//s390x/blink/blink >$d/blink-$v-linux-s390x.elf.gz\ngzip -9 <o//s390x/blink/blinkenlights >$d/blinkenlights-$v-linux-s390x.elf.gz\n"
  },
  {
    "path": "tool/sha256sum.c",
    "content": "/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│\n│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│ Copyright 2022 Justine Alexandra Roberts Tunney                              │\n│                                                                              │\n│ Permission to use, copy, modify, and/or distribute this software for         │\n│ any purpose with or without fee is hereby granted, provided that the         │\n│ above copyright notice and this permission notice appear in all copies.      │\n│                                                                              │\n│ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n│ PERFORMANCE OF THIS SOFTWARE.                                                │\n╚─────────────────────────────────────────────────────────────────────────────*/\n#include <errno.h>\n#include <limits.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n// this file should not have dependencies, because everything will be\n// re-downloaded if the o/tool/sha256sum artifact becomes invalidated\n\n#define PROG \"sha256sum\"\n#define USAGE \\\n  \"\\\nUsage: \" PROG \" [-?hbctw] [PATH...]\\n\\\n  -h          help\\n\\\n  -c          check mode\\n\\\n  -b          binary mode\\n\\\n  -t          textual mode\\n\\\n  -w          warning mode\\n\"\n\n#define ROTR(a, b)   (((a) >> (b)) | ((a) << (32 - (b))))\n#define CH(x, y, z)  (((x) & (y)) ^ (~(x) & (z)))\n#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))\n#define EP0(x)       (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))\n#define EP1(x)       (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))\n#define SIG0(x)      (ROTR(x, 7) ^ ROTR(x, 18) ^ ((x) >> 3))\n#define SIG1(x)      (ROTR(x, 17) ^ ROTR(x, 19) ^ ((x) >> 10))\n\nstruct Sha256Ctx {\n  uint8_t data[64];\n  uint32_t datalen;\n  uint64_t bitlen;\n  uint32_t state[8];\n};\n\nstatic const uint32_t kSha256Tab[64] = {\n    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,  //\n    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,  //\n    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,  //\n    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,  //\n    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,  //\n    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,  //\n    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,  //\n    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,  //\n    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,  //\n    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,  //\n    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,  //\n    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,  //\n    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,  //\n    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,  //\n    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,  //\n    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,  //\n};\n\nstatic bool g_warn;\nstatic char g_mode;\nstatic bool g_check;\nstatic int g_mismatches;\n\nstatic void Sha256Transform(uint32_t state[8], const uint8_t data[64]) {\n  unsigned i;\n  uint32_t a, b, c, d, e, f, g, h, t1, t2, m[64];\n  for (i = 0; i < 16; ++i, data += 4) {\n    m[i] = (uint32_t)data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];\n  }\n  for (; i < 64; ++i) {\n    m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];\n  }\n  a = state[0];\n  b = state[1];\n  c = state[2];\n  d = state[3];\n  e = state[4];\n  f = state[5];\n  g = state[6];\n  h = state[7];\n  for (i = 0; i < 64; ++i) {\n    t1 = h + EP1(e) + CH(e, f, g) + kSha256Tab[i] + m[i];\n    t2 = EP0(a) + MAJ(a, b, c);\n    h = g;\n    g = f;\n    f = e;\n    e = d + t1;\n    d = c;\n    c = b;\n    b = a;\n    a = t1 + t2;\n  }\n  state[0] += a;\n  state[1] += b;\n  state[2] += c;\n  state[3] += d;\n  state[4] += e;\n  state[5] += f;\n  state[6] += g;\n  state[7] += h;\n}\n\nstatic void Sha256Init(struct Sha256Ctx *ctx) {\n  ctx->datalen = 0;\n  ctx->bitlen = 0;\n  ctx->state[0] = 0x6a09e667;\n  ctx->state[1] = 0xbb67ae85;\n  ctx->state[2] = 0x3c6ef372;\n  ctx->state[3] = 0xa54ff53a;\n  ctx->state[4] = 0x510e527f;\n  ctx->state[5] = 0x9b05688c;\n  ctx->state[6] = 0x1f83d9ab;\n  ctx->state[7] = 0x5be0cd19;\n}\n\nstatic void Sha256Update(struct Sha256Ctx *ctx, const uint8_t *data,\n                         long size) {\n  long i;\n  for (i = 0; i < size; ++i) {\n    ctx->data[ctx->datalen] = data[i];\n    ctx->datalen++;\n    if (ctx->datalen == 64) {\n      Sha256Transform(ctx->state, ctx->data);\n      ctx->bitlen += 512;\n      ctx->datalen = 0;\n    }\n  }\n}\n\nstatic void Sha256Final(struct Sha256Ctx *ctx, uint8_t *hash) {\n  long i;\n  i = ctx->datalen;\n  ctx->data[i++] = 0x80;\n  if (ctx->datalen < 56) {\n    memset(ctx->data + i, 0, 56 - i);\n  } else {\n    memset(ctx->data + i, 0, 64 - i);\n    Sha256Transform(ctx->state, ctx->data);\n    memset(ctx->data, 0, 56);\n  }\n  ctx->bitlen += ctx->datalen * 8;\n  ctx->data[63] = ctx->bitlen;\n  ctx->data[62] = ctx->bitlen >> 8;\n  ctx->data[61] = ctx->bitlen >> 16;\n  ctx->data[60] = ctx->bitlen >> 24;\n  ctx->data[59] = ctx->bitlen >> 32;\n  ctx->data[58] = ctx->bitlen >> 40;\n  ctx->data[57] = ctx->bitlen >> 48;\n  ctx->data[56] = ctx->bitlen >> 56;\n  Sha256Transform(ctx->state, ctx->data);\n  for (i = 0; i < 4; ++i) {\n    hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0xff;\n    hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0xff;\n    hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0xff;\n    hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0xff;\n    hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0xff;\n    hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0xff;\n    hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0xff;\n    hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0xff;\n  }\n}\n\nstatic char *FormatUint32(char *p, uint32_t x) {\n  char t;\n  size_t i, a, b;\n  i = 0;\n  do {\n    p[i++] = x % 10 + '0';\n    x = x / 10;\n  } while (x > 0);\n  p[i] = '\\0';\n  if (i) {\n    for (a = 0, b = i - 1; a < b; ++a, --b) {\n      t = p[a];\n      p[a] = p[b];\n      p[b] = t;\n    }\n  }\n  return p + i;\n}\n\nstatic char *FormatInt32(char *p, int32_t x) {\n  if (x < 0) *p++ = '-', x = -(uint32_t)x;\n  return FormatUint32(p, x);\n}\n\nstatic size_t StrCat(char *dst, const char *src, size_t dsize) {\n  size_t m, n = dsize;\n  const char *p = dst;\n  const char *q = src;\n  while (n-- != 0 && *dst != '\\0') dst++;\n  m = dst - p;\n  n = dsize - m;\n  if (n-- == 0) {\n    return m + strlen(src);\n  }\n  while (*src != '\\0') {\n    if (n != 0) {\n      *dst++ = *src;\n      n--;\n    }\n    src++;\n  }\n  *dst = '\\0';\n  return m + (src - q);\n}\n\nstatic void GetOpts(int argc, char *argv[]) {\n  int opt;\n  g_mode = ' ';\n  while ((opt = getopt(argc, argv, \"?hbctw\")) != -1) {\n    switch (opt) {\n      case 'w':\n        g_warn = true;\n        break;\n      case 'c':\n        g_check = true;\n        break;\n      case 't':\n        g_mode = ' ';\n        break;\n      case 'b':\n        g_mode = '*';\n        break;\n      case 'h':\n      case '?':\n        (void)write(1, USAGE, sizeof(USAGE) - 1);\n        exit(0);\n      default:\n        (void)write(2, USAGE, sizeof(USAGE) - 1);\n        exit(64);\n    }\n  }\n}\n\nstatic void Write(int fd, const char *s, ...) {\n  va_list va;\n  char buf[512];\n  buf[0] = 0;\n  va_start(va, s);\n  do {\n    StrCat(buf, s, sizeof(buf));\n  } while ((s = va_arg(va, const char *)));\n  va_end(va);\n  (void)write(fd, buf, strlen(buf));\n}\n\nstatic bool IsModeCharacter(char c) {\n  switch (c) {\n    case ' ':\n    case '*':\n      return true;\n    default:\n      return false;\n  }\n}\n\nstatic bool IsSupportedPath(const char *path) {\n  size_t i;\n  for (i = 0;; ++i) {\n    switch (path[i]) {\n      case 0:\n        if (i) return true;\n        // fallthrough\n      case '\\r':\n      case '\\n':\n      case '\\\\':\n        Write(2, PROG, \": \", path, \": unsupported path\\n\", NULL);\n        return false;\n      default:\n        break;\n    }\n  }\n}\n\nstatic bool GetDigest(const char *path, FILE *f, uint8_t digest[32]) {\n  size_t got;\n  uint8_t buf[512];\n  struct Sha256Ctx ctx;\n  Sha256Init(&ctx);\n  while ((got = fread(buf, 1, sizeof(buf), f))) {\n    Sha256Update(&ctx, buf, got);\n  }\n  if (ferror(f)) {\n    Write(2, PROG, \": \", path, \": \", strerror(errno), \"\\n\", NULL);\n    return false;\n  }\n  Sha256Final(&ctx, digest);\n  return true;\n}\n\nstatic char *CopyHex(char *s, const void *p, size_t n) {\n  const char *d, *e;\n  for (d = (const char *)p, e = d + n; d < e; ++d) {\n    *s++ = \"0123456789abcdef\"[(*d >> 4) & 15];\n    *s++ = \"0123456789abcdef\"[(*d >> 0) & 15];\n  }\n  *s = 0;\n  return s;\n}\n\nstatic bool ProduceDigest(const char *path, FILE *f) {\n  char hexdigest[65];\n  char mode[2] = {g_mode};\n  unsigned char digest[32];\n  if (!IsSupportedPath(path)) return false;\n  if (!GetDigest(path, f, digest)) return false;\n  CopyHex(hexdigest, digest, 32);\n  Write(1, hexdigest, \" \", mode, path, \"\\n\", NULL);\n  return true;\n}\n\nstatic char *Chomp(char *line) {\n  size_t i;\n  if (line) {\n    for (i = strlen(line); i--;) {\n      if (line[i] == '\\r' || line[i] == '\\n') {\n        line[i] = '\\0';\n      } else {\n        break;\n      }\n    }\n  }\n  return line;\n}\n\nstatic int HexToInt(int c) {\n  if ('0' <= c && c <= '9') {\n    return c - '0';\n  } else if ('a' <= c && c <= 'f') {\n    return c - 'a' + 10;\n  } else if ('A' <= c && c <= 'F') {\n    return c - 'A' + 10;\n  } else {\n    return -1;\n  }\n}\n\nstatic bool CheckDigests(const char *path, FILE *f) {\n  FILE *f2;\n  bool k = true;\n  int a, b, i, line;\n  const char *path2, *status;\n  uint8_t wantdigest[32], gotdigest[32];\n  char buf[64 + 2 + PATH_MAX + 1 + 1], *p;\n  for (line = 0; fgets(buf, sizeof(buf), f); ++line) {\n    if (!*Chomp(buf)) continue;\n    for (p = buf, i = 0; i < 32; ++i) {\n      if ((a = HexToInt(*p++ & 255)) == -1) goto InvalidLine;\n      if ((b = HexToInt(*p++ & 255)) == -1) goto InvalidLine;\n      wantdigest[i] = a << 4 | b;\n    }\n    if (*p++ != ' ') goto InvalidLine;\n    if (!IsModeCharacter(*p++)) goto InvalidLine;\n    path2 = p;\n    if (!*path2) goto InvalidLine;\n    if (!IsSupportedPath(path2)) continue;\n    if ((f2 = fopen(path2, \"rb\"))) {\n      if (GetDigest(path2, f2, gotdigest)) {\n        if (!memcmp(wantdigest, gotdigest, 32)) {\n          status = \"OK\";\n        } else {\n          status = \"FAILED\";\n          ++g_mismatches;\n          k = false;\n        }\n        Write(1, path2, \": \", status, \"\\n\", NULL);\n      } else {\n        k = false;\n      }\n      fclose(f2);\n    } else {\n      Write(2, PROG, \": \", path2, \": \", strerror(errno), \"\\n\", NULL);\n      k = false;\n    }\n    continue;\n  InvalidLine:\n    if (g_warn) {\n      char linestr[12];\n      FormatInt32(linestr, line + 1);\n      Write(2, PROG, \": \", path, \":\", linestr, \": \",\n            \"improperly formatted checksum line\", \"\\n\", NULL);\n    }\n  }\n  if (ferror(f)) {\n    Write(2, PROG, \": \", path, \": \", strerror(errno), \"\\n\", NULL);\n    k = false;\n  }\n  return k;\n}\n\nstatic bool Process(const char *path, FILE *f) {\n  if (g_check) {\n    return CheckDigests(path, f);\n  } else {\n    return ProduceDigest(path, f);\n  }\n}\n\nint main(int argc, char *argv[]) {\n  int i;\n  FILE *f;\n  bool k = true;\n  GetOpts(argc, argv);\n  if (optind == argc) {\n    f = stdin;\n    k &= Process(\"-\", f);\n  } else {\n    for (i = optind; i < argc; ++i) {\n      if ((f = fopen(argv[i], \"rb\"))) {\n        k &= Process(argv[i], f);\n        fclose(f);\n      } else {\n        Write(2, PROG, \": \", argv[i], \": \", strerror(errno), \"\\n\", NULL);\n        k = false;\n      }\n    }\n  }\n  if (g_mismatches) {\n    char ibuf[12];\n    FormatInt32(ibuf, g_mismatches);\n    Write(2, PROG, \": WARNING: \", ibuf, \" computed checksum did NOT match\\n\",\n          NULL);\n  }\n  return !k;\n}\n"
  },
  {
    "path": "tool/size.sh",
    "content": "#!/bin/sh\nm=${1:-tiny}\n\nF=\"\no/$m/blink/blink\no/$m/x86_64/blink/blink\no/$m/aarch64/blink/blink\no/$m/i486/blink/blink\n\"\n\nmake -j8 $F m=$m || exit\n\nfor f in $F; do\n  cp $f $f.strip\ndone\n\nstrip o/$m/blink/blink.strip\no/third_party/gcc/x86_64/bin/x86_64-linux-musl-strip o/$m/x86_64/blink/blink.strip\no/third_party/gcc/aarch64/bin/aarch64-linux-musl-strip o/$m/aarch64/blink/blink.strip\no/third_party/gcc/i486/bin/i486-linux-musl-strip o/$m/i486/blink/blink.strip\n\nfor f in $F; do\n  ls -hal $f.strip\ndone\n"
  },
  {
    "path": "tool/stdatomic/stdatomic.h",
    "content": "#ifndef COSMOPOLITAN_LIBC_BITS_ATOMIC_H_\n#define COSMOPOLITAN_LIBC_BITS_ATOMIC_H_\n#if !(__ASSEMBLER__ + __LINKER__ + 0)\n\n/**\n * @fileoverview Cosmopolitan C11 Atomics Library\n *\n * - Forty-two different ways to say MOV.\n * - Fourteen different ways to say XCHG.\n * - Twenty different ways to say LOCK CMPXCHG.\n *\n * @see libc/atomic.h\n */\n\n#if __STDC_VERSION__ + 0 < 201112\n#define _Atomic(TYPE) TYPE volatile\n#endif\n\n#define atomic_bool           _Atomic(_Bool)\n#define atomic_bool32         _Atomic(__INT32_TYPE__)\n#define atomic_char           _Atomic(char)\n#define atomic_schar          _Atomic(signed char)\n#define atomic_uchar          _Atomic(unsigned char)\n#define atomic_short          _Atomic(short)\n#define atomic_ushort         _Atomic(unsigned short)\n#define atomic_int            _Atomic(int)\n#define atomic_uint           _Atomic(unsigned int)\n#define atomic_long           _Atomic(long)\n#define atomic_ulong          _Atomic(unsigned long)\n#define atomic_llong          _Atomic(long long)\n#define atomic_ullong         _Atomic(unsigned long long)\n#define atomic_char16_t       _Atomic(__CHAR16_TYPE__)\n#define atomic_char32_t       _Atomic(__CHAR32_TYPE__)\n#define atomic_wchar_t        _Atomic(__WCHAR_TYPE__)\n#define atomic_intptr_t       _Atomic(__INTPTR_TYPE__)\n#define atomic_uintptr_t      _Atomic(__UINTPTR_TYPE__)\n#define atomic_size_t         _Atomic(__SIZE_TYPE__)\n#define atomic_ptrdiff_t      _Atomic(__PTRDIFF_TYPE__)\n#define atomic_int_fast8_t    _Atomic(__INT_FAST8_TYPE__)\n#define atomic_uint_fast8_t   _Atomic(__UINT_FAST8_TYPE__)\n#define atomic_int_fast16_t   _Atomic(__INT_FAST16_TYPE__)\n#define atomic_uint_fast16_t  _Atomic(__UINT_FAST16_TYPE__)\n#define atomic_int_fast32_t   _Atomic(__INT_FAST32_TYPE__)\n#define atomic_uint_fast32_t  _Atomic(__UINT_FAST32_TYPE__)\n#define atomic_int_fast64_t   _Atomic(__INT_FAST64_TYPE__)\n#define atomic_uint_fast64_t  _Atomic(__UINT_FAST64_TYPE__)\n#define atomic_int_least8_t   _Atomic(__INT_LEAST8_TYPE__)\n#define atomic_uint_least8_t  _Atomic(__UINT_LEAST8_TYPE__)\n#define atomic_int_least16_t  _Atomic(__INT_LEAST16_TYPE__)\n#define atomic_uint_least16_t _Atomic(__UINT_LEAST16_TYPE__)\n#define atomic_int_least32_t  _Atomic(__INT_LEAST32_TYPE__)\n#define atomic_uint_least32_t _Atomic(__UINT_LEAST32_TYPE__)\n#define atomic_int_least64_t  _Atomic(__INT_LEAST64_TYPE__)\n#define atomic_uint_least64_t _Atomic(__UINT_LEAST64_TYPE__)\n\n#ifdef __CLANG_ATOMIC_BOOL_LOCK_FREE\n#define ATOMIC_BOOL_LOCK_FREE     __CLANG_ATOMIC_BOOL_LOCK_FREE\n#define ATOMIC_CHAR_LOCK_FREE     __CLANG_ATOMIC_CHAR_LOCK_FREE\n#define ATOMIC_CHAR16_T_LOCK_FREE __CLANG_ATOMIC_CHAR16_T_LOCK_FREE\n#define ATOMIC_CHAR32_T_LOCK_FREE __CLANG_ATOMIC_CHAR32_T_LOCK_FREE\n#define ATOMIC_WCHAR_T_LOCK_FREE  __CLANG_ATOMIC_WCHAR_T_LOCK_FREE\n#define ATOMIC_SHORT_LOCK_FREE    __CLANG_ATOMIC_SHORT_LOCK_FREE\n#define ATOMIC_INT_LOCK_FREE      __CLANG_ATOMIC_INT_LOCK_FREE\n#define ATOMIC_LONG_LOCK_FREE     __CLANG_ATOMIC_LONG_LOCK_FREE\n#define ATOMIC_LLONG_LOCK_FREE    __CLANG_ATOMIC_LLONG_LOCK_FREE\n#define ATOMIC_POINTER_LOCK_FREE  __CLANG_ATOMIC_POINTER_LOCK_FREE\n#else\n#define ATOMIC_BOOL_LOCK_FREE     __GCC_ATOMIC_BOOL_LOCK_FREE\n#define ATOMIC_CHAR_LOCK_FREE     __GCC_ATOMIC_CHAR_LOCK_FREE\n#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE\n#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE\n#define ATOMIC_WCHAR_T_LOCK_FREE  __GCC_ATOMIC_WCHAR_T_LOCK_FREE\n#define ATOMIC_SHORT_LOCK_FREE    __GCC_ATOMIC_SHORT_LOCK_FREE\n#define ATOMIC_INT_LOCK_FREE      __GCC_ATOMIC_INT_LOCK_FREE\n#define ATOMIC_LONG_LOCK_FREE     __GCC_ATOMIC_LONG_LOCK_FREE\n#define ATOMIC_LLONG_LOCK_FREE    __GCC_ATOMIC_LLONG_LOCK_FREE\n#define ATOMIC_POINTER_LOCK_FREE  __GCC_ATOMIC_POINTER_LOCK_FREE\n#endif\n\n#define memory_order         int\n#define memory_order_relaxed 0\n#define memory_order_consume 1\n#define memory_order_acquire 2\n#define memory_order_release 3\n#define memory_order_acq_rel 4\n#define memory_order_seq_cst 5\n\n#define ATOMIC_VAR_INIT(...)     __VA_ARGS__\n#define atomic_is_lock_free(obj) ((void)(obj), sizeof(obj) <= sizeof(void *))\n\n#define atomic_flag      atomic_bool\n#define ATOMIC_FLAG_INIT ATOMIC_VAR_INIT(0)\n#define atomic_flag_test_and_set_explicit(x, order) \\\n  atomic_exchange_explicit(x, 1, order)\n#define atomic_flag_clear_explicit(x, order) atomic_store_explicit(x, 0, order)\n\n#define atomic_compare_exchange_strong(pObject, pExpected, desired) \\\n  atomic_compare_exchange_strong_explicit(                          \\\n      pObject, pExpected, desired, memory_order_seq_cst, memory_order_seq_cst)\n#define atomic_compare_exchange_weak(pObject, pExpected, desired) \\\n  atomic_compare_exchange_weak_explicit(                          \\\n      pObject, pExpected, desired, memory_order_seq_cst, memory_order_seq_cst)\n#define atomic_exchange(pObject, desired) \\\n  atomic_exchange_explicit(pObject, desired, memory_order_seq_cst)\n#define atomic_fetch_add(pObject, operand) \\\n  atomic_fetch_add_explicit(pObject, operand, memory_order_seq_cst)\n#define atomic_fetch_and(pObject, operand) \\\n  atomic_fetch_and_explicit(pObject, operand, memory_order_seq_cst)\n#define atomic_fetch_or(pObject, operand) \\\n  atomic_fetch_or_explicit(pObject, operand, memory_order_seq_cst)\n#define atomic_fetch_sub(pObject, operand) \\\n  atomic_fetch_sub_explicit(pObject, operand, memory_order_seq_cst)\n#define atomic_fetch_xor(pObject, operand) \\\n  atomic_fetch_xor_explicit(pObject, operand, memory_order_seq_cst)\n#define atomic_load(pObject) atomic_load_explicit(pObject, memory_order_seq_cst)\n#define atomic_store(pObject, desired) \\\n  atomic_store_explicit(pObject, desired, memory_order_seq_cst)\n#define atomic_flag_test_and_set(x) \\\n  atomic_flag_test_and_set_explicit(x, memory_order_seq_cst)\n#define atomic_flag_clear(x) atomic_flag_clear_explicit(x, memory_order_seq_cst)\n\n#if defined(__CLANG_ATOMIC_BOOL_LOCK_FREE)\n\n#define atomic_init(obj, value)    __c11_atomic_init(obj, value)\n#define atomic_thread_fence(order) __c11_atomic_thread_fence(order)\n#define atomic_signal_fence(order) __c11_atomic_signal_fence(order)\n#define atomic_compare_exchange_strong_explicit(object, expected, desired, \\\n                                                success, failure)          \\\n  __c11_atomic_compare_exchange_strong(object, expected, desired, success, \\\n                                       failure)\n#define atomic_compare_exchange_weak_explicit(object, expected, desired, \\\n                                              success, failure)          \\\n  __c11_atomic_compare_exchange_weak(object, expected, desired, success, \\\n                                     failure)\n#define atomic_exchange_explicit(object, desired, order) \\\n  __c11_atomic_exchange(object, desired, order)\n#define atomic_fetch_add_explicit(object, operand, order) \\\n  __c11_atomic_fetch_add(object, operand, order)\n#define atomic_fetch_and_explicit(object, operand, order) \\\n  __c11_atomic_fetch_and(object, operand, order)\n#define atomic_fetch_or_explicit(object, operand, order) \\\n  __c11_atomic_fetch_or(object, operand, order)\n#define atomic_fetch_sub_explicit(object, operand, order) \\\n  __c11_atomic_fetch_sub(object, operand, order)\n#define atomic_fetch_xor_explicit(object, operand, order) \\\n  __c11_atomic_fetch_xor(object, operand, order)\n#define atomic_load_explicit(object, order) __c11_atomic_load(object, order)\n#define atomic_store_explicit(object, desired, order) \\\n  __c11_atomic_store(object, desired, order)\n\n#elif (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407\n\n#define atomic_init(obj, value)    ((void)(*(obj) = (value)))\n#define atomic_thread_fence(order) __atomic_thread_fence(order)\n#define atomic_signal_fence(order) __atomic_signal_fence(order)\n#define atomic_compare_exchange_strong_explicit(pObject, pExpected, desired, \\\n                                                success, failure)            \\\n  __atomic_compare_exchange_n(pObject, pExpected, desired, 0, success, failure)\n#define atomic_compare_exchange_weak_explicit(pObject, pExpected, desired, \\\n                                              success, failure)            \\\n  __atomic_compare_exchange_n(pObject, pExpected, desired, 1, success, failure)\n#define atomic_exchange_explicit(pObject, desired, order) \\\n  __atomic_exchange_n(pObject, desired, order)\n#define atomic_fetch_add_explicit(pObject, operand, order) \\\n  __atomic_fetch_add(pObject, operand, order)\n#define atomic_fetch_and_explicit(pObject, operand, order) \\\n  __atomic_fetch_and(pObject, operand, order)\n#define atomic_fetch_or_explicit(pObject, operand, order) \\\n  __atomic_fetch_or(pObject, operand, order)\n#define atomic_fetch_sub_explicit(pObject, operand, order) \\\n  __atomic_fetch_sub(pObject, operand, order)\n#define atomic_fetch_xor_explicit(pObject, operand, order) \\\n  __atomic_fetch_xor(pObject, operand, order)\n#define atomic_load_explicit(pObject, order) __atomic_load_n(pObject, order)\n#define atomic_store_explicit(pObject, desired, order) \\\n  __atomic_store_n(pObject, desired, order)\n\n#elif (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 401\n\n#define atomic_init(obj, value)    ((void)(*(obj) = (value)))\n#define atomic_thread_fence(order) __sync_synchronize()\n#define atomic_signal_fence(order) __asm__ volatile(\"\" ::: \"memory\")\n#define __atomic_apply_stride(object, operand) \\\n  (((__typeof__(*(object)))0) + (operand))\n#define atomic_compare_exchange_strong_explicit(object, expected, desired,    \\\n                                                success_order, failure_order) \\\n  __extension__({                                                             \\\n    __typeof__(expected) __ep = (expected);                                   \\\n    __typeof__(*__ep) __e = *__ep;                                            \\\n    (void)(success_order);                                                    \\\n    (void)(failure_order);                                                    \\\n    (*__ep = __sync_val_compare_and_swap(object, __e, desired)) == __e;       \\\n  })\n#define atomic_compare_exchange_weak_explicit(object, expected, desired,    \\\n                                              success_order, failure_order) \\\n  atomic_compare_exchange_strong_explicit(object, expected, desired,        \\\n                                          success_order, failure_order)\n#if __has_builtin(__sync_swap)\n#define atomic_exchange_explicit(object, desired, order) \\\n  ((void)(order), __sync_swap(object, desired))\n#else\n#define atomic_exchange_explicit(object, desired, order) \\\n  __extension__({                                        \\\n    __typeof__(object) __o = (object);                   \\\n    __typeof__(desired) __d = (desired);                 \\\n    (void)(order);                                       \\\n    __sync_synchronize();                                \\\n    __sync_lock_test_and_set(__o, __d);                  \\\n  })\n#endif\n#define atomic_fetch_add_explicit(object, operand, order) \\\n  ((void)(order),                                         \\\n   __sync_fetch_and_add(object, __atomic_apply_stride(object, operand)))\n#define atomic_fetch_and_explicit(object, operand, order) \\\n  ((void)(order), __sync_fetch_and_and(object, operand))\n#define atomic_fetch_or_explicit(object, operand, order) \\\n  ((void)(order), __sync_fetch_and_or(object, operand))\n#define atomic_fetch_sub_explicit(object, operand, order) \\\n  ((void)(order),                                         \\\n   __sync_fetch_and_sub(object, __atomic_apply_stride(object, operand)))\n#define atomic_fetch_xor_explicit(object, operand, order) \\\n  ((void)(order), __sync_fetch_and_xor(object, operand))\n#define atomic_load_explicit(object, order) \\\n  ((void)(order), __sync_fetch_and_add(object, 0))\n#define atomic_store_explicit(object, desired, order) \\\n  ((void)atomic_exchange_explicit(object, desired, order))\n\n#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))\n\n#define atomic_init(obj, value)    ((void)(*(obj) = (value)))\n#define atomic_thread_fence(order) __asm__ volatile(\"mfence\" ::: \"memory\")\n#define atomic_signal_fence(order) __asm__ volatile(\"\" ::: \"memory\")\n#define atomic_compare_exchange_strong_explicit(object, expected, desired,    \\\n                                                success_order, failure_order) \\\n  __extension__({                                                             \\\n    char DidIt;                                                               \\\n    __typeof__(object) IfThing = (object);                                    \\\n    __typeof__(IfThing) IsEqualToMe = (expected);                             \\\n    __typeof__(*IfThing) ReplaceItWithMe = (desired), ax;                     \\\n    (void)(success_order);                                                    \\\n    (void)(failure_order);                                                    \\\n    __asm__ volatile(\"lock cmpxchg\\t%3,(%1)\\n\\t\"                              \\\n                     \"setz\\t%b0\"                                              \\\n                     : \"=q\"(DidIt), \"=r\"(IfThing), \"+a\"(ax)                   \\\n                     : \"r\"(ReplaceItWithMe), \"2\"(*IsEqualToMe)                \\\n                     : \"memory\", \"cc\");                                       \\\n    *IsEqualToMe = ax;                                                        \\\n    DidIt;                                                                    \\\n  })\n#define atomic_compare_exchange_weak_explicit(object, expected, desired,    \\\n                                              success_order, failure_order) \\\n  atomic_compare_exchange_strong_explicit(object, expected, desired,        \\\n                                          success_order, failure_order)\n#define atomic_exchange_explicit(object, desired, order)                \\\n  __extension__({                                                       \\\n    __typeof__(object) __o = (object);                                  \\\n    __typeof__(*__o) __d = (desired);                                   \\\n    (void)(order);                                                      \\\n    __asm__ volatile(\"xchg\\t%0,%1\" : \"=r\"(__d), \"+m\"(*__o) : \"0\"(__d)); \\\n    __d;                                                                \\\n  })\n#define atomic_fetch_add_explicit(object, operand, order)                    \\\n  __extension__({                                                            \\\n    __typeof__(object) __o = (object);                                       \\\n    __typeof__(*__o) __d = (desired);                                        \\\n    (void)(order);                                                           \\\n    __asm__ volatile(\"lock xadd\\t%0,%1\" : \"=r\"(__d), \"+m\"(*__o) : \"0\"(__d)); \\\n    __d;                                                                     \\\n  })\n#define atomic_fetch_sub_explicit(object, operand, order) \\\n  atomic_fetch_add_explicit(object, -(operand), order)\n#define atomic_load_explicit(object, order) \\\n  atomic_fetch_add_explicit(object, 0, order)\n#define atomic_store_explicit(object, desired, order) \\\n  ((void)atomic_exchange_explicit(object, desired, order))\n\n#else /* non-gcc or old gcc w/o x86 */\n#error \"atomic operations not supported with this compiler and/or architecture\"\n#endif\n\n#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */\n#endif /* COSMOPOLITAN_LIBC_BITS_ATOMIC_H_ */\n"
  }
]