diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index d643fd4..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "wasm3-sys/wasm3"] - path = wasm3-sys/wasm3 - url = https://github.com/wasm3/wasm3 diff --git a/wasm3-sys/wasm3 b/wasm3-sys/wasm3 deleted file mode 160000 index 6b8bcb1..0000000 --- a/wasm3-sys/wasm3 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6b8bcb1e07bf26ebef09a7211b0a37a446eafd52 diff --git a/wasm3-sys/wasm3/.codespellrc b/wasm3-sys/wasm3/.codespellrc new file mode 100644 index 0000000..5a26d39 --- /dev/null +++ b/wasm3-sys/wasm3/.codespellrc @@ -0,0 +1,5 @@ +[codespell] +skip = ./test/wasi/brotli/alice29.txt,./test/.spec-*,./build* +quiet-level = 2 +ignore-words-list = gameboy,iif,strng,woh + diff --git a/wasm3-sys/wasm3/.github/workflows/publish.yml b/wasm3-sys/wasm3/.github/workflows/publish.yml new file mode 100644 index 0000000..5b9ba1e --- /dev/null +++ b/wasm3-sys/wasm3/.github/workflows/publish.yml @@ -0,0 +1,180 @@ +name: publish + +on: + push: + tags: + - "v*.*.*" + +env: + draft: true + +jobs: + wasm3-windows: + runs-on: windows-latest + name: ${{ matrix.config.target }} + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + config: + - {target: wasm3-win-x64, platform: "-A x64", toolset: "-T ClangCL" } + - {target: wasm3-win-x86, platform: "-A Win32", toolset: "-T ClangCL" } + - {target: wasm3-strace-win-x64, platform: "-A x64", toolset: "-T ClangCL", cflags: "-DDEBUG -Dd_m3EnableStrace=2 -Dd_m3RecordBacktraces=1" } + + env: + LDFLAGS: -s + steps: + - uses: actions/checkout@v2 + - name: Configure + env: + CFLAGS: ${{ matrix.config.cflags }} + run: | + mkdir build + cd build + cmake ${{ matrix.config.platform }} ${{ matrix.config.toolset }} .. + - name: Build + run: | + cmake --build build --config Release + cp ./build/Release/wasm3.exe ./${{ matrix.config.target }}.exe + - name: Publish + uses: softprops/action-gh-release@v1 + with: + draft: ${{ env.draft }} + files: "*.exe" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + wasm3-linux-x64: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Setup musl + run: | + sudo apt update + sudo apt install musl-tools + - name: Setup cmake + uses: jwlawson/actions-setup-cmake@v1.9 + with: + cmake-version: '3.16.x' + - name: Configure + env: + CC: musl-gcc + LDFLAGS: "-static -s" + run: | + mkdir build + cd build + cmake --version + cmake .. + - name: Build + run: | + cmake --build build --verbose + cp ./build/wasm3 ./wasm3-linux-x64.elf + - name: Publish + uses: softprops/action-gh-release@v1 + with: + draft: ${{ env.draft }} + files: "*.elf" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + wasm3-cosmopolitan: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Build αcτµαlly pδrταblε εxεcµταblε + run: | + cd platforms/cosmopolitan + ./build.sh + cp ./wasm3.com ../../wasm3-cosmopolitan.com + cp ./wasm3.com.dbg ../../wasm3-cosmopolitan.com.dbg + - name: Publish + uses: softprops/action-gh-release@v1 + with: + draft: ${{ env.draft }} + files: | + *.com + *.com.dbg + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + wasm3-wasi: + runs-on: ubuntu-latest + timeout-minutes: 10 + + env: + LDFLAGS: -s + steps: + - uses: actions/checkout@v2 + - name: Install Python dependencies + run: | + python3 -m pip install pip==20.1.1 + python3 -m pip install --upgrade setuptools wheel + pip3 --version + - name: Install Wasienv + env: + WASMER_RELEASE_TAG: "1.0.2" + run: curl https://raw.githubusercontent.com/wasienv/wasienv/master/install.sh | sh + - name: Configure + run: | + source $HOME/.wasienv/wasienv.sh + mkdir build + cd build + wasimake cmake .. + - name: Build + run: | + source $HOME/.wasienv/wasienv.sh + cmake --build build + cp ./build/wasm3.wasm ./wasm3-wasi.wasm + - name: Configure, Build wasm3-strace + env: + CFLAGS: -DDEBUG -Dd_m3EnableStrace=2 -Dd_m3RecordBacktraces=1 + run: | + source $HOME/.wasienv/wasienv.sh + mkdir build-strace + cd build-strace + wasimake cmake .. + cmake --build . + cp ./wasm3.wasm ../wasm3-strace.wasm + - name: Publish + uses: softprops/action-gh-release@v1 + with: + draft: ${{ env.draft }} + files: "*.wasm" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + wasm3-android-coremark: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - uses: seanmiddleditch/gha-setup-ninja@master + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Install NDK + run: | + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;22.1.7171670" + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --uninstall "cmake;3.18.1" + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "cmake;3.10.2.4988404" + - name: Build + run: | + cd platforms/android + ./gradlew build + - name: Copy + run: | + cp ./platforms/android/app/build/outputs/apk/debug/app-debug.apk ./wasm3-android-coremark.apk + - name: Publish + uses: softprops/action-gh-release@v1 + with: + draft: ${{ env.draft }} + files: "*.apk" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/wasm3-sys/wasm3/.github/workflows/tests.yml b/wasm3-sys/wasm3/.github/workflows/tests.yml new file mode 100644 index 0000000..c0ed423 --- /dev/null +++ b/wasm3-sys/wasm3/.github/workflows/tests.yml @@ -0,0 +1,607 @@ +name: tests + +on: + push: + paths-ignore: ['**.md', '**.svg', '**.png'] + pull_request: + paths-ignore: ['**.md', '**.svg', '**.png'] + +jobs: + linux: + runs-on: ubuntu-latest + name: linux-${{ matrix.config.target }} + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + config: + - {target: clang, cc: clang, } + - {target: clang-x86, cc: clang, flags: -DCMAKE_C_FLAGS="-m32", install: "gcc-multilib" } + - {target: gcc, cc: gcc, } + # Builds without uvwasi + - {target: gcc-no-uvwasi, cc: gcc, flags: -DBUILD_WASI=simple } + - {target: clang-no-uvwasi, cc: clang, flags: -DBUILD_WASI=simple } + # Debug builds + - {target: gcc-debug, cc: gcc, flags: -DCMAKE_BUILD_TYPE=Debug } + - {target: clang-no-uvwasi-debug, cc: clang, flags: -DCMAKE_BUILD_TYPE=Debug -DBUILD_WASI=simple } + + # TODO: fails on numeric operations + #- {target: gcc-x86, cc: gcc, flags: "-m32", install: "gcc-multilib" } + + steps: + - uses: actions/checkout@v2 + - name: Install ${{ matrix.config.install }} + if: ${{ matrix.config.install }} + run: | + sudo apt update + sudo apt install ${{ matrix.config.install }} + - name: Configure + env: + CC: ${{ matrix.config.cc }} + CFLAGS: ${{ matrix.config.cflags }} + run: | + mkdir build + cd build + cmake ${{ matrix.config.flags }} .. + - name: Build + run: | + cmake --build build + - name: Test WebAssembly spec + run: cd test && python3 run-spec-test.py + - name: Test previous WebAssembly specs + run: | + cd test + python3 run-spec-test.py --spec=v1.1 + - name: Test WASI apps + run: cd test && python3 run-wasi-test.py + + linux-alpine: + runs-on: ubuntu-latest + container: alpine:3.10 + + steps: + - uses: actions/checkout@v2 + - name: Prepare + run: apk add build-base cmake python3 git --update-cache + - name: Configure + run: | + mkdir build + cd build + cmake .. + - name: Build + run: cmake --build build + - name: Test WebAssembly spec + run: cd test && python3 run-spec-test.py + - name: Test WASI apps + run: cd test && python3 run-wasi-test.py + + macos: + runs-on: macos-latest + name: macos-${{ matrix.config.target }} + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + config: + - {target: uvwasi, } + - {target: no-uvwasi, flags: -DBUILD_WASI=simple } + + steps: + - uses: actions/checkout@v2 + - name: Configure + run: | + mkdir build + cd build + cmake ${{ matrix.config.flags }} .. + - name: Build + run: | + cmake --build build + - name: Test WebAssembly spec + run: cd test && python3 run-spec-test.py + - name: Test previous WebAssembly specs + run: | + cd test + python3 run-spec-test.py --spec=v1.1 + - name: Test WASI apps + run: cd test && python3 run-wasi-test.py + + windows: + runs-on: windows-latest + name: windows-${{ matrix.config.target }} + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + config: + - {target: clang-x64, platform: "-A x64", toolset: "-T ClangCL" } + - {target: msvc-x64, platform: "-A x64", toolset: "" } + - {target: clang-x86, platform: "-A Win32", toolset: "-T ClangCL" } + - {target: msvc-x86, platform: "-A Win32", toolset: "" } + # Builds without uvwasi + - {target: clang-x64-no-uvwasi, platform: "-A x64", toolset: "-T ClangCL", flags: "-DBUILD_WASI=simple" } + - {target: msvc-x64-no-uvwasi, platform: "-A x64", toolset: "", flags: "-DBUILD_WASI=simple" } + - {target: clang-x86-no-uvwasi, platform: "-A Win32", toolset: "-T ClangCL", flags: "-DBUILD_WASI=simple" } + - {target: msvc-x86-no-uvwasi, platform: "-A Win32", toolset: "", flags: "-DBUILD_WASI=simple" } + + defaults: + run: + shell: cmd + + steps: + - uses: actions/checkout@v2 + - name: Configure + run: | + mkdir build + cd build + cmake ${{ matrix.config.platform }} ${{ matrix.config.toolset }} ${{ matrix.config.flags }} .. + - name: Build + run: | + cmake --build build --config Release + cp ./build/Release/wasm3.exe ./build/ + - name: Test WebAssembly spec + run: | + cd test + python run-spec-test.py + - name: Test previous WebAssembly specs + run: | + cd test + python run-spec-test.py --spec=v1.1 + - name: Test WASI apps + run: | + cd test + python run-wasi-test.py + + wasi: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Install Python dependencies + run: | + python3 -m pip install pip==20.1.1 + python3 -m pip install --upgrade setuptools wheel + pip3 --version + - name: Install Wasienv + env: + WASMER_RELEASE_TAG: "1.0.2" + run: curl https://raw.githubusercontent.com/wasienv/wasienv/master/install.sh | sh + - name: Configure + run: | + source $HOME/.wasienv/wasienv.sh + mkdir build-wasi + cd build-wasi + wasimake cmake .. + - name: Build + run: | + source $HOME/.wasienv/wasienv.sh + cmake --build build-wasi + - name: Test WebAssembly spec (in Wasmer) + run: | + source $HOME/.wasmer/wasmer.sh + cd test + python3 run-spec-test.py --exec "wasmer run --mapdir=/:. ../build-wasi/wasm3.wasm -- --repl" + + - name: Test WASI apps (in Wasmer) + run: | + source $HOME/.wasmer/wasmer.sh + cd test + python3 run-wasi-test.py --exec "wasmer run --mapdir=/:. ../build-wasi/wasm3.wasm --" --fast + + - name: Configure (native) + run: | + mkdir build + cd build + cmake .. + - name: Build (native) + run: | + cmake --build build + - name: Test WebAssembly spec (in Wasm3, self-hosting) + run: | + cd test + cp ../build-wasi/wasm3.wasm ./ + python3 run-spec-test.py --exec "../build/wasm3 --stack-size 2097152 ../build-wasi/wasm3.wasm --repl" + - name: Test WASI apps (in Wasm3, self-hosting) + run: | + cd test + python3 run-wasi-test.py --fast --exec "../build/wasm3 --stack-size 2097152 ../build-wasi/wasm3.wasm" + + ios: + runs-on: macos-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: List Xcode versions + run: ls /Applications | grep Xcode + - name: Select Xcode 11 + run: sudo xcode-select -switch /Applications/Xcode_11.3.app + - name: Build (iPhone 11) + run: | + cd platforms/ios + xcodebuild build -scheme wasm3 -project wasm3.xcodeproj -configuration Release -destination 'platform=iOS Simulator,name=iPhone 11,OS=13.3' + + android: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - uses: seanmiddleditch/gha-setup-ninja@master + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Install NDK + run: | + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;22.1.7171670" + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --uninstall "cmake;3.18.1" + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "cmake;3.10.2.4988404" + - name: Build + run: | + cd platforms/android + ./gradlew build + + python: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + path: wasm3 + - name: Checkout pywasm3 + uses: actions/checkout@v2 + with: + repository: wasm3/pywasm3 + path: pywasm3 + - name: Set up Python + uses: actions/setup-python@v2 + - name: Update and Build Python module + run: | + rm -rf ./pywasm3/wasm3 + cp -r wasm3/source ./pywasm3/wasm3 + pip install ./pywasm3 + - name: Install WABT + run: | + sudo apt update + sudo apt install wabt + - name: Test + run: | + pip install pytest + cd ./pywasm3 + pytest + + cosmopolitan: + runs-on: ubuntu-20.04 + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Build αcτµαlly pδrταblε εxεcµταblε + run: | + cd platforms/cosmopolitan + gcc -v + ./build.sh + - name: Prepare tests + run: | + cd test + cp ../platforms/cosmopolitan/wasm3.com ./wasm3-lin.com + cp ../platforms/cosmopolitan/wasm3.com ./wasm3-win.com + sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register" + - name: Test WebAssembly spec + run: | + cd test + python3 run-spec-test.py --exec "./wasm3-lin.com --repl" + - name: Test WASI apps + run: | + cd test + python3 run-wasi-test.py --fast --exec "./wasm3-lin.com" + - name: Install Wine64 + run: | + sudo apt update + sudo apt install wine64 + wine --version + - name: Test WebAssembly spec (in Wine) + run: | + cd test + python3 run-spec-test.py --exec "wine ./wasm3-win.com --repl" + - name: Test WASI apps (in Wine) + run: | + cd test + python3 run-wasi-test.py --fast --exec "wine ./wasm3-win.com" + + cross-qemu: + runs-on: ubuntu-20.04 + name: cross-qemu-${{ matrix.config.target }} + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + config: + #- {target: i386, toolchain: gcc-multilib, cc: clang -m32, qemu: qemu-i386-static } + - {target: arm, toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static } + - {target: armhf, toolchain: gcc-arm-linux-gnueabihf, cc: arm-linux-gnueabihf-gcc, qemu: qemu-arm-static } + - {target: aarch64, toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static } + - {target: riscv64, toolchain: gcc-riscv64-linux-gnu, cc: riscv64-linux-gnu-gcc, qemu: qemu-riscv64-static } + - {target: ppc, toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static } + - {target: ppc64, toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static } + #- {target: ppc64le, toolchain: gcc-powerpc64le-linux-gnu, cc: powerpc64le-linux-gnu-gcc, qemu: qemu-ppc64le-static } + - {target: s390x, toolchain: gcc-s390x-linux-gnu, cc: s390x-linux-gnu-gcc, qemu: qemu-s390x-static } + - {target: mips, toolchain: gcc-mips-linux-gnu, cc: mips-linux-gnu-gcc, qemu: qemu-mips-static } + - {target: mips64, toolchain: gcc-mips64-linux-gnuabi64, cc: mips64-linux-gnuabi64-gcc, qemu: qemu-mips64-static } + - {target: mipsel, toolchain: gcc-mipsel-linux-gnu, cc: mipsel-linux-gnu-gcc, qemu: qemu-mipsel-static } + - {target: mips64el,toolchain: gcc-mips64el-linux-gnuabi64, cc: mips64el-linux-gnuabi64-gcc,qemu: qemu-mips64el-static } + - {target: alpha, toolchain: gcc-alpha-linux-gnu, cc: alpha-linux-gnu-gcc, qemu: qemu-alpha-static } + - {target: sparc64, toolchain: gcc-sparc64-linux-gnu, cc: sparc64-linux-gnu-gcc, qemu: qemu-sparc64-static, skip_wasi: true } + + #- {target: i386 (u64 slots), toolchain: gcc-multilib, cc: clang -m32, qemu: qemu-i386-static, cflags: -Dd_m3Use32BitSlots=0 } + - {target: arm (u64 slots), toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static, cflags: -Dd_m3Use32BitSlots=0 } + - {target: aarch64 (u64 slots), toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static, cflags: -Dd_m3Use32BitSlots=0 } + - {target: ppc (u64 slots), toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static, cflags: -Dd_m3Use32BitSlots=0 } + - {target: ppc64 (u64 slots), toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static, cflags: -Dd_m3Use32BitSlots=0 } + + steps: + - uses: actions/checkout@v2 + - name: Install QEMU + run: | + sudo apt update + sudo apt install qemu-user-static + - name: Install ${{ matrix.config.toolchain }} + run: | + sudo apt install ${{ matrix.config.toolchain }} + - name: Build + run: | + mkdir build + cd build + ${{ matrix.config.cc }} -DASSERTS -Dd_m3HasWASI ${{ matrix.config.cflags }} \ + -I../source ../source/*.c ../platforms/app/main.c \ + -O3 -g0 -flto -lm -static \ + -o wasm3 + - name: Test WebAssembly spec + run: | + cd test + python3 run-spec-test.py --exec "${{ matrix.config.qemu }} ../build/wasm3 --repl" + - name: Test WASI apps + if: ${{ !matrix.config.skip_wasi }} + run: | + cd test + python3 run-wasi-test.py --fast --exec "${{ matrix.config.qemu }} ../build/wasm3" + + platformio: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install PlatformIO + run: | + python -m pip install --upgrade pip + pip install -U platformio + - name: Build AVR ATmega1284 + run: | + cd platforms/embedded/arduino + pio run -e mega1284 + ! nm .pio/build/mega1284/firmware.elf | grep printf + - name: Build ESP8266 + run: | + cd platforms/embedded/esp8266 + pio run + # TODO: + #- name: Build ESP32 + # run: | + # cd platforms/embedded/esp32-pio + # pio run + + platformio-arm: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install PlatformIO + run: | + python -m pip install --upgrade pip + pip install -U platformio + - name: Build Arduino MKR1000 + run: | + cd platforms/embedded/arduino + pio run -e mkr1000 + - name: Build Blue Pill (JeeH) + run: | + cd platforms/embedded/bluepill + pio run + - name: Build TinyBLE + run: | + cd platforms/embedded/arduino + pio run -e tinyBLE + - name: Build MXChip AZ3166 + run: | + cd platforms/embedded/arduino + pio run -e az3166 + + platformio-riscv: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install PlatformIO + run: | + python -m pip install --upgrade pip + pip install -U platformio + - name: Build HiFive1 + run: | + cd platforms/embedded/hifive1 + pio run + - name: Build Sipeed MAIX + run: | + cd platforms/embedded/arduino + pio run -e maix + + particle: + runs-on: ubuntu-latest + timeout-minutes: 10 + if: "github.event_name == 'push'" + + steps: + - uses: actions/checkout@v2 + - name: Set up Particle CLI + run: sudo npm install -g particle-cli + - name: Log in + env: + PARTICLE_TOKEN: ${{ secrets.PARTICLE_TOKEN }} + run: particle login --token $PARTICLE_TOKEN + - name: Build Photon + run: | + cd platforms/embedded/particle + particle compile --followSymlinks photon + particle compile --followSymlinks argon + particle compile --followSymlinks pi + + esp32-idf: + runs-on: ubuntu-latest + container: igrr/idf-qemu:release-v4.0-esp-develop-20191228 + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Build for ESP32 (IDF v4.0) + run: | + . $IDF_PATH/export.sh + cd platforms/embedded/esp32-idf + export EXTRA_CFLAGS="-Werror" + idf.py build + shell: bash + - name: Test for ESP32 in QEMU + run: | + cd platforms/embedded/esp32-idf + make-flash-img.sh wasm3 flash_img.bin + qemu-system-xtensa -machine esp32 -nographic -drive file=flash_img.bin,if=mtd,format=raw -no-reboot | tee out.txt + grep "Result: 46368" out.txt + grep "Elapsed: " out.txt + grep "Restarting..." out.txt + test $(($(grep "ets Jun 8 2016" out.txt | wc -l))) -eq 1 + - name: Check that IDF and PIO examples are in sync + run: | + diff -q platforms/embedded/esp32-idf/main/main.cpp platforms/embedded/esp32-pio/src/main.cpp + # TODO: also check that the build flags are in sync + + cpp: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Configure + run: | + cd platforms/cpp + mkdir build + cd build + cmake .. + - name: Build + run: | + cd platforms/cpp + cmake --build build + - name: Run + run: | + cd platforms/cpp/build + ./wasm3_cpp_example + + as-cpp: + name: maintenance (build as C++) + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Build + run: | + mkdir build + cd build + clang -xc++ -Dd_m3HasWASI \ + -I../source ../source/*.c ../platforms/app/main.c \ + -O3 -g0 -lm \ + -o wasm3 + - name: Test + run: ./build/wasm3 ./test/wasi/simple/test.wasm + + with-logs: + name: maintenance (debug logs) + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Build + run: | + mkdir build + cd build + clang -xc++ -Dd_m3HasWASI -DDEBUG \ + -Dd_m3EnableOpTracing=1 \ + -Dd_m3EnableStrace=1 \ + -Dd_m3LogParse=1 \ + -Dd_m3LogModule=1 \ + -Dd_m3LogCompile=1 \ + -Dd_m3LogWasmStack=1 \ + -Dd_m3LogEmit=1 \ + -Dd_m3LogCodePages=1 \ + -Dd_m3LogRuntime=1 \ + -Dd_m3LogNativeStack=1 \ + -I../source ../source/*.c ../platforms/app/main.c \ + -O3 -g0 -lm \ + -o wasm3 + - name: Test + run: ./build/wasm3 ./test/wasi/simple/test.wasm > /dev/null + + preprocessed-ops: + name: maintenance (preprocess ops) + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Install sponge + run: | + sudo apt update + sudo apt install moreutils + - name: Build + run: | + make -f extra/utils.mk preprocess + mkdir build + cd build + gcc -Dd_m3HasWASI \ + -I../source ../source/*.c ../platforms/app/main.c \ + -O3 -g0 -lm \ + -o wasm3 + - name: Test + run: ./build/wasm3 ./test/wasi/simple/test.wasm + + spellcheck: + runs-on: ubuntu-latest + steps: + - name: Set up Python + uses: actions/setup-python@v2 + - name: Install codespell + run: | + pip install codespell + - name: Spellcheck + run: | + codespell diff --git a/wasm3-sys/wasm3/.gitignore b/wasm3-sys/wasm3/.gitignore new file mode 100644 index 0000000..c5e6674 --- /dev/null +++ b/wasm3-sys/wasm3/.gitignore @@ -0,0 +1,12 @@ +/build* +/source-* +test/.spec-* +test/*.log +test/tailcall/*.S +node_modules/ +__pycache__/ +.project +.cproject +.settings +.vscode +.DS_Store diff --git a/wasm3-sys/wasm3/CMakeLists.txt b/wasm3-sys/wasm3/CMakeLists.txt new file mode 100755 index 0000000..92ba950 --- /dev/null +++ b/wasm3-sys/wasm3/CMakeLists.txt @@ -0,0 +1,223 @@ +cmake_minimum_required(VERSION 3.11) + +# Detect WasiEnv +if(DEFINED ENV{WASI_CC}) + set(WASIENV 1) +endif() + +# Detect MinGW +if(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "GNU") + set(MINGW 1) +endif() + +# Set options + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "set build type to Release") +endif() + +if(WASIENV) + set(BUILD_WASI "metawasi" CACHE STRING "WASI implementation") +elseif(EMSCRIPTEN OR EMSCRIPTEN_LIB) + set(BUILD_WASI "none" CACHE STRING "WASI implementation") +else() + set(BUILD_WASI "uvwasi" CACHE STRING "WASI implementation") +endif() +set_property(CACHE BUILD_WASI PROPERTY STRINGS none simple uvwasi metawasi) + +option(BUILD_NATIVE "Build with machine-specific optimisations" ON) + +set(OUT_FILE "wasm3") + +if(NOT APP_DIR) + set(APP_DIR "platforms/app") +endif() + +# Configure the toolchain + +if(CLANG OR CLANG_SUFFIX) + set(CMAKE_C_COMPILER "clang${CLANG_SUFFIX}") + set(CMAKE_CXX_COMPILER "clang++${CLANG_SUFFIX}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld") + + if(BUILD_FUZZ) + set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") + set(OUT_FILE "wasm3-fuzzer") + set(APP_DIR "platforms/app_fuzz") + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "set build type to Debug") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer,address") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=fuzzer,address") + endif() +endif() + +if(CLANG_CL) + set(CMAKE_C_COMPILER "clang-cl") + set(CMAKE_CXX_COMPILER "clang-cl") + set(CMAKE_LINKER "lld-link") +endif() + +if(EMSCRIPTEN OR EMSCRIPTEN_LIB) + set(CMAKE_C_COMPILER "emcc") + set(CMAKE_CXX_COMPILER "em++") + + if (EMSCRIPTEN_LIB) + set(APP_DIR "platforms/emscripten_lib") + set(OUT_FILE "wasm3.wasm") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s STANDALONE_WASM") + else() + set(APP_DIR "platforms/emscripten") + set(OUT_FILE "wasm3.html") + endif() +endif() + +if(BUILD_32BIT) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") +endif() + + + +project(wasm3) + +message("----") +message("Generator: ${CMAKE_GENERATOR}") +message("Compiler: ${CMAKE_C_COMPILER_ID}") +message("Build Type: ${CMAKE_BUILD_TYPE}") + + +include(CheckIPOSupported) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED YES) +set(CMAKE_C_EXTENSIONS NO) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED YES) +set(CMAKE_CXX_EXTENSIONS NO) + + +file(GLOB app_srcs "${APP_DIR}/*.c") +add_executable(${OUT_FILE} ${app_srcs}) + +#-fno-optimize-sibling-calls + +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG=1") + +if(EMSCRIPTEN OR EMSCRIPTEN_LIB) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s GLOBAL_BASE=1024 -s TOTAL_STACK=2MB -s INITIAL_MEMORY=4MB -s ALLOW_MEMORY_GROWTH") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s EXPORTED_FUNCTIONS=\"[\\\"_malloc\\\",\\\"_free\\\",\\\"_main\\\"]\"") + + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -flto -Wfatal-errors -s ASSERTIONS=0") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} --strip-all --gc-sections") + + if(WASM_EXT) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mbulk-memory -mnontrapping-fptoint -msign-ext -mtail-call") + endif() + +elseif(WASIENV) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasTracer") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -Wfatal-errors -fomit-frame-pointer -fno-stack-check -fno-stack-protector") + + if(WASM_EXT) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mbulk-memory -mnontrapping-fptoint -msign-ext -mtail-call") + endif() + + # TODO: LTO breaks wasm imports currently: + # https://www.mail-archive.com/llvm-bugs@lists.llvm.org/msg36273.html + + #-flto -Wl,--lto-O3 + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,stack-size=8388608") + +elseif(WIN32 AND NOT MINGW) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasTracer -D_CRT_SECURE_NO_WARNINGS /WX- /diagnostics:column") + + string(REGEX REPLACE "/W[0-4]" "/W0" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + + if (CMAKE_C_COMPILER_ID MATCHES "MSVC") + + if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /d2noftol3") + endif() + + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oxs /Oy /GS- /Zi /Zo /arch:AVX2") + + # Uncomment this if you want to disassemble the release build, + # for example: dumpbin /DISASM wasm3.exe /out:wasm3.S + #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG:FULL") + + else() + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oxs /Oy /GS- /Qvec -Clang -O3") + endif() + + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8388608") # stack size + +else() + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasTracer") #-Dd_m3FixedHeap=1048576 + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wparentheses -Wundef -Wpointer-arith -Wstrict-aliasing=2") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration") # -Werror=cast-align + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers") + if (CMAKE_C_COMPILER_ID MATCHES "Clang") + # TODO: Place clang-specific options here + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wjump-misses-init") + endif() + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -O0") + + set(CMAKE_C_FLAGS_RELEASE "-O3 -Wfatal-errors -fomit-frame-pointer -fno-stack-check -fno-stack-protector") #-fno-inline + + if(BUILD_NATIVE) + if(APPLE AND CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm64") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mcpu=native") + else() + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -march=native") + endif() + endif() + + set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-O0") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-O3") + + target_link_libraries(${OUT_FILE} m) + +endif() + +if(BUILD_WASI MATCHES "simple") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasWASI") +elseif(BUILD_WASI MATCHES "metawasi") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasMetaWASI") +elseif(BUILD_WASI MATCHES "uvwasi") + include(FetchContent) + FetchContent_Declare( + uvwasi + GIT_REPOSITORY https://github.com/vshymanskyy/uvwasi.git + GIT_TAG b063d686848c32a26119513056874f051c74258a + ) + + FetchContent_GetProperties(uvwasi) + if(NOT uvwasi_POPULATED) + FetchContent_Populate(uvwasi) + include_directories("${uvwasi_SOURCE_DIR}/include") + add_subdirectory(${uvwasi_SOURCE_DIR} ${uvwasi_BINARY_DIR} EXCLUDE_FROM_ALL) + endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasUVWASI") + target_link_libraries(${OUT_FILE} uvwasi_a uv_a) +endif() + +check_ipo_supported(RESULT result) +if(result AND NOT WASIENV) # TODO: LTO breaks wasm imports + set_property(TARGET ${OUT_FILE} PROPERTY INTERPROCEDURAL_OPTIMIZATION True) + message("LTO: ON") +else() + message("LTO: OFF") +endif() + +add_subdirectory(source) +target_link_libraries(${OUT_FILE} m3) + +message("Flags: ${CMAKE_C_FLAGS}") +message("Debug flags: ${CMAKE_C_FLAGS_DEBUG}") +message("Release flags: ${CMAKE_C_FLAGS_RELEASE}") + +message("----") diff --git a/wasm3-sys/wasm3/LICENSE b/wasm3-sys/wasm3/LICENSE new file mode 100644 index 0000000..e580601 --- /dev/null +++ b/wasm3-sys/wasm3/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Steven Massey, Volodymyr Shymanskyy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wasm3-sys/wasm3/README.md b/wasm3-sys/wasm3/README.md new file mode 100644 index 0000000..f43e895 --- /dev/null +++ b/wasm3-sys/wasm3/README.md @@ -0,0 +1,113 @@ + + +# Wasm3 + +[![WAPM](https://wapm.io/package/vshymanskyy/wasm3/badge.svg)](https://wapm.io/package/vshymanskyy/wasm3) +[![GitHub issues](https://img.shields.io/github/issues-raw/wasm3/wasm3?style=flat-square&label=issues&color=success)](https://github.com/wasm3/wasm3/issues) +[![Tests status](https://img.shields.io/github/workflow/status/wasm3/wasm3/tests/main?style=flat-square&logo=github&label=tests)](https://github.com/wasm3/wasm3/actions) +[![Fuzzing Status](https://img.shields.io/badge/oss--fuzz-fuzzing-success?style=flat-square)](https://bugs.chromium.org/p/oss-fuzz/issues/list?can=1&q=proj:wasm3) +[![GitHub license](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/wasm3/wasm3) + +The fastest WebAssembly interpreter, and the most universal runtime. +Based on [**CoreMark 1.0**](./docs/Performance.md) and [**independent**](https://00f.net/2021/02/22/webassembly-runtimes-benchmarks) benchmarks. Your mileage may vary. + + +[![Twitter](https://img.shields.io/twitter/follow/wasm3_engine?style=flat-square&color=1da1f2&label=twitter&logo=twitter)](https://twitter.com/wasm3_engine) +[![Discord](https://img.shields.io/discord/671415645073702925?style=flat-square&logo=discord&color=7289da&label=discord)](https://discord.gg/qmZjgnd) +[![Telegram](https://img.shields.io/badge/telegram-chat-0088cc?style=flat-square&logo=telegram)](https://t.me/joinchat/DD8s3xVG8Vj_LxRDm52eTQ) + +## Getting Started + +Here's a small [getting started guide](https://wapm.io/package/vshymanskyy/wasm3). Click here to start: + +[![LIVE DEMO](extra/button.png)](https://webassembly.sh/?run-command=wasm3) + + +## Installation + +**Please follow the [installation instructions](./docs/Installation.md).** + +Wasm3 can also be used as a library for: + +[ Python3](https://github.com/wasm3/pywasm3) │ +[ Rust](https://github.com/Veykril/wasm3-rs) │ +[ C/C++](https://github.com/wasm3/wasm3) │ +[ GoLang](https://github.com/matiasinsaurralde/go-wasm3) │ +[  Zig](https://github.com/alichay/zig-wasm3) +[ Swift](https://github.com/shareup/wasm-interpreter-apple) │ +[ .Net](https://github.com/tana/Wasm3DotNet) │ +[ Arduino, PlatformIO, Particle](https://github.com/wasm3/wasm3-arduino) + + +## Status + +`wasm3` passes the [WebAssembly spec testsuite](https://github.com/WebAssembly/spec/tree/master/test/core) and is able to run many `WASI` apps. + +Minimum useful system requirements: **~64Kb** for code and **~10Kb** RAM + +`wasm3` runs on a wide range of architectures (`x86`, `x86_64`, `ARM`, `RISC-V`, `PowerPC`, `MIPS`, `Xtensa`, `ARC32`, ...) and [platforms](/platforms): +- Linux, + Windows, + OS X, + FreeBSD, + Android, + iOS +- OpenWrt, Yocto, Buildroot (routers, modems, etc.) +- Raspberry Pi, Orange Pi and other SBCs +- MCUs: Arduino, ESP8266, ESP32, Particle, ... [see full list](./docs/Hardware.md) +- Browsers. Yes, using WebAssembly itself! +- `wasm3` can execute `wasm3` (self-hosting) + +## Advanced features and [post-mvp proposals](https://github.com/WebAssembly/proposals) support + +☑ Sign-extension operators +☑ Non-trapping float-to-int conversions +☑ Import/Export of Mutable Globals +☑ Structured execution tracing +☑ Big-Endian systems support +☑ Self-hosting +☑ Gas metering +☑ Multi-value +☐ Reference types +☐ Bulk memory operations +☐ Tail call optimization + +## Motivation + +**Why use a "slow interpreter" versus a "fast JIT"?** + +In many situations, speed is not the main concern. Runtime executable size, memory usage, startup latency can be improved with the interpreter approach. Portability and security are much easier to achieve and maintain. Additionally, development impedance is much lower. A simple library like Wasm3 is easy to compile and integrate into an existing project. (Wasm3 builds in a just few seconds). Finally, on some platforms (i.e. iOS and WebAssembly itself) you can't generate executable code pages in runtime, so JIT is unavailable. + +**Why would you want to run WASM on embedded devices?** + +Wasm3 started as a research project and remains so by many means. Evaluating the engine in different environments is part of the research. Given that we have `Lua`, `JS`, `Python`, `Lisp`, `...` running on MCUs, `WebAssembly` is actually a promising alternative. It provides toolchain decoupling as well as a completely sandboxed, well-defined, predictable environment. Among practical use cases we can list `edge computing`, `scripting`, running `IoT rules`, `smart contracts`, etc. + +## Used by + +[](https://wasmcloud.dev/)  +[](https://wowcube.com/)  +[](https://scailable.net/)  +[](https://blynk.io/)  +[](https://www.iden3.io/)  +[](https://github.com/kateinoigakukun/wasmic-ios)  +[](https://github.com/balena-io-playground/balena-wasm3)  +[](https://github.com/deislabs/krustlet-wasm3)  +[](https://shareup.app/blog/introducing-shareup/)  +[](https://github.com/saghul/txiki.js)  + +## Further Resources + +[Demos](./docs/Demos.md) +[Installation instructions](./docs/Installation.md) +[Cookbook](./docs/Cookbook.md) +[Troubleshooting](./docs/Troubleshooting.md) +[Build and Development instructions](./docs/Development.md) +[Supported Hardware](./docs/Hardware.md) +[Testing & Fuzzing](./docs/Testing.md) +[Performance](./docs/Performance.md) +[Interpreter Architecture](./docs/Interpreter.md) +[Logging](./docs/Diagnostics.md) +[Awesome WebAssembly Tools](https://github.com/vshymanskyy/awesome-wasm-tools/blob/main/README.md) + +### License +This project is released under The MIT License (MIT) diff --git a/wasm3-sys/wasm3/docs/Cookbook.md b/wasm3-sys/wasm3/docs/Cookbook.md new file mode 100644 index 0000000..8dd9241 --- /dev/null +++ b/wasm3-sys/wasm3/docs/Cookbook.md @@ -0,0 +1,409 @@ +# WASM module examples + +### Rust WASI app + +Create a new project: +```sh +$ cargo new --bin hello +$ cd hello +$ rustup target add wasm32-wasi +``` + +Build and run: +```sh +$ cargo build --release --target wasm32-wasi + +$ wasm3 ./target/wasm32-wasi/release/hello.wasm +Hello, world! +``` + +### AssemblyScript WASI app + +Create `hello.ts`: +```ts +import "wasi" +import {Console} from "as-wasi" + +Console.log('Hello World!'); +``` + +Create `package.json`: +```json +{ + "scripts": { + "asbuild:debug": "asc hello.ts -b hello.wasm --debug", + "asbuild:optimized": "asc hello.ts -b hello.wasm -O3s --noAssert", + "asbuild:tiny": "asc hello.ts -b hello.wasm -O3z --noAssert --runtime stub --use abort=", + "build": "npm run asbuild:optimized" + }, + "devDependencies": { + "assemblyscript": "*", + "as-wasi": "*" + } +} +``` + +Build and run: +```sh +$ npm install +$ npm run build + +$ wasm3 hello.wasm +Hello World! +``` + +### TinyGo WASI app + +Create `hello.go`: +```go +package main + +import "fmt" + +func main() { + fmt.Printf("Hello, %s!\n", "world") +} +``` + +Build and run: +```sh +$ tinygo build -o hello.wasm -target wasi -no-debug hello.go + +$ wasm3 hello.wasm +Hello, world! +``` + +### Zig WASI app + +Create `hello.zig`: +```zig +const std = @import("std"); + +pub fn main() !void { + const stdout = std.io.getStdOut().writer(); + try stdout.print("Hello, {s}!\n", .{"world"}); +} +``` + +Build and run: +```sh +$ zig build-exe -O ReleaseSmall -target wasm32-wasi hello.zig + +$ wasm3 hello.wasm +Hello, world! +``` + +## Zig library + +Create `add.zig`: +```zig +export fn add(a: i32, b: i32) i64 { + return a + b; +} +``` + +Build and run: +```sh +$ zig build-lib add.zig -O ReleaseSmall -target wasm32-freestanding + +$ wasm3 --repl add.wasm +wasm3> add 1 2 +Result: 3 +``` + +### C/C++ WASI app + +The easiest way to start is to use [Wasienv](https://github.com/wasienv/wasienv). + +Create `hello.cpp`: +```cpp +#include + +int main() { + std::cout << "Hello, world!" << std::endl; + return 0; +} +``` + +Or `hello.c`: +```c +#include + +int main() { + printf("Hello, %s!\n", "world"); + return 0; +} +``` + +Build and run: +```sh +$ wasic++ -O3 hello.cpp -o hello.wasm +$ wasicc -O3 hello.c -o hello.wasm + +$ wasm3 hello.wasm +Hello World! +``` + +Limitations: +- `setjmp/longjmp` and `C++ exceptions` are not available +- no support for `threads` and `atomics` +- no support for `dynamic libraries` + +### Grain WASI app + +Create `hello.gr`: +``` +print("Hello, world!") +``` + +Build and run: +```sh +$ grain compile hello.gr -o hello.wasm + +$ wasm3 hello.wasm +Hello, world! +``` + +### WAT WASI app + +Create `hello.wat`: +```wat +(module + ;; wasi_snapshot_preview1!fd_write(file_descriptor, *iovs, iovs_len, nwritten) -> status_code + (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32))) + + (memory 1) + (export "memory" (memory 0)) + + ;; Put a message to linear memory at offset 32 + (data (i32.const 32) "Hello, world!\n") + + (func $main (export "_start") + ;; Create a new io vector at address 0x4 + (i32.store (i32.const 4) (i32.const 32)) ;; iov.iov_base - pointer to the start of the message + (i32.store (i32.const 8) (i32.const 14)) ;; iov.iov_len - length of the message + + (call $fd_write + (i32.const 1) ;; file_descriptor - 1 for stdout + (i32.const 4) ;; *iovs - pointer to the io vector + (i32.const 1) ;; iovs_len - count of items in io vector + (i32.const 20) ;; nwritten - where to store the number of bytes written + ) + drop ;; discard the WASI status code + ) +) +``` + + +Build and run: +```sh +$ wat2wasm hello.wat -o hello.wasm + +$ wasm3 hello.wasm +Hello, world! +``` + +### WAT library + +Create `swap.wat`: +```wat +(module + (func (export "swap") (param i32 i32) (result i32 i32) + (get_local 1) + (get_local 0) + ) +) +``` + +Build and run: +```sh +$ wat2wasm swap.wat -o swap.wasm + +$ wasm3 --repl swap.wasm +wasm3> :invoke swap 123 456 +Result: 456:i32, 123:i32 +``` + +# Tracing + +Drag'n'drop any of the WASI apps to [`WebAssembly.sh`](https://webassembly.sh/) and run: +```sh +$ wasm3-strace /tmp/hello.wasm +``` + +The execution trace will be produced: +```js +_start () { + __wasilibc_init_preopen () { + malloc (i32: 16) { + dlmalloc (i32: 16) { + sbrk (i32: 0) { + } = 131072 + sbrk (i32: 65536) { +``` +
+ Click to expand! + +```js + } = 131072 + } = 131088 + } = 131088 + calloc (i32: 24, i32: 0) { + dlmalloc (i32: 96) { + } = 131120 + memset (i32: 131120, i32: 65504, i32: 0) { + } = 131120 + } = 131120 + po_map_assertvalid (i32: 131088) { + } + po_map_assertvalid (i32: 131088) { + } + } + wasi_unstable!fd_prestat_get(3, 65528) { } = 0 + malloc (i32: 2) { + dlmalloc (i32: 2) { + } = 131232 + } = 131232 + wasi_unstable!fd_prestat_dir_name(3, 131232, 1) { } = 0 + __wasilibc_register_preopened_fd (i32: 3, i32: 131120) { + po_map_assertvalid (i32: 131088) { + } + po_map_assertvalid (i32: 131088) { + } + strdup (i32: 131232) { + strlen (i32: 131232) { + } = 1 + malloc (i32: 2) { + dlmalloc (i32: 2) { + } = 131248 + } = 131248 + memcpy (i32: 131248, i32: 131233, i32: 131232) { + } = 131248 + } = 131248 + wasi_unstable!fd_fdstat_get(3, 65496) { } = 0 + po_map_assertvalid (i32: 131088) { + } + po_map_assertvalid (i32: 131088) { + } + } = 0 + free (i32: 131232) { + dlfree (i32: 131232) { + } + } + wasi_unstable!fd_prestat_get(4, 65528) { } = 0 + malloc (i32: 2) { + dlmalloc (i32: 2) { + } = 131232 + } = 131232 + wasi_unstable!fd_prestat_dir_name(4, 131232, 1) { } = 0 + __wasilibc_register_preopened_fd (i32: 4, i32: 131120) { + po_map_assertvalid (i32: 131088) { + } + po_map_assertvalid (i32: 131088) { + } + strdup (i32: 131232) { + strlen (i32: 131232) { + } = 1 + malloc (i32: 2) { + dlmalloc (i32: 2) { + } = 131264 + } = 131264 + memcpy (i32: 131264, i32: 131233, i32: 131232) { + } = 131264 + } = 131264 + wasi_unstable!fd_fdstat_get(4, 65496) { } = 0 + po_map_assertvalid (i32: 131088) { + } + po_map_assertvalid (i32: 131088) { + } + } = 0 + free (i32: 131232) { + dlfree (i32: 131232) { + } + } + wasi_unstable!fd_prestat_get(5, 65528) { } = 8 + __wasm_call_ctors () { + } + __original_main () { + printf (i32: 65536, i32: 0) { + vfprintf (i32: 69512, i32: 0, i32: 65536) { + printf_core (i32: 0, i32: -1, i32: 65536, i32: -16, i32: 65480) { + } = 0 + __towrite (i32: 69512) { + } = 0 + printf_core (i32: 69512, i32: 8, i32: 65536, i32: -1, i32: 65480) { + __fwritex (i32: 65536, i32: 0, i32: 7) { + memcpy (i32: 68472, i32: 0, i32: 65536) { + } = 68472 + } = 7 + __fwritex (i32: 65543, i32: 0, i32: 0) { + memcpy (i32: 68479, i32: 0, i32: 65543) { + } = 68479 + } = 0 + pop_arg (i32: 64456, i32: 0, i32: 9) { + } + strnlen (i32: 65548, i32: 0) { + memchr (i32: 65548, i32: 4, i32: 0) { + } = 65553 + } = 5 + __fwritex (i32: 67222, i32: 65553, i32: 0) { + memcpy (i32: 68479, i32: 0, i32: 67222) { + } = 68479 + } = 0 + __fwritex (i32: 65548, i32: 65553, i32: 5) { + memcpy (i32: 68479, i32: 0, i32: 65548) { + } = 68479 + } = 5 + __fwritex (i32: 65545, i32: 0, i32: 2) { + __stdout_write (i32: 69512, i32: 0, i32: 65545) { + __isatty (i32: 1) { + wasi_unstable!fd_fdstat_get(1, 64376) { } = 0 + } = 1 + __stdio_write (i32: 69512, i32: 64368, i32: 65545) { + writev (i32: 1, i32: -16, i32: 64384) { +Hello, world! + wasi_unstable!fd_write(1, 64384, 2, 64380) { } = 0 + } = 14 + } = 2 + } = 2 + memcpy (i32: 68472, i32: -1, i32: 65547) { + } = 68472 + } = 2 + } = 14 + } = 14 + } = 14 + } = 0 + __prepare_for_exit () { + dummy () { + } + __stdio_exit () { + __ofl_lock () { + } = 69504 + } + } +} +``` +
+ +# Gas Metering + +```sh +$ npm install -g wasm-metering + +$ wasm-meter hello.wasm hello-metered.wasm + +$ wasm3 hello-metered.wasm +Warning: Gas is limited to 500000000.0000 +Hello, world! +Gas used: 20.8950 + +$ wasm3 --gas-limit 10 hello-metered.wasm +Warning: Gas is limited to 10.0000 +Gas used: 10.0309 +Error: [trap] Out of gas +``` + +# Other resources + +- [WebAssembly by examples](https://wasmbyexample.dev/home.en-us.html) by Aaron Turner +- [Writing WebAssembly](https://docs.wasmtime.dev/wasm.html) in Wasmtime docs diff --git a/wasm3-sys/wasm3/docs/Demos.md b/wasm3-sys/wasm3/docs/Demos.md new file mode 100644 index 0000000..1a19548 --- /dev/null +++ b/wasm3-sys/wasm3/docs/Demos.md @@ -0,0 +1,15 @@ +# Wasm3 demos + +- **In-browser Wasm3 (with MetaWASI support) on Webassembly.sh** │ [try it](https://webassembly.sh/?run-command=wasm3) +- **PyGame + pywasm3 examples** | [github](https://github.com/wasm3/pywasm3/tree/main/examples) +- **DOOM compiled to WASI, running on pywasm3** | [video](https://twitter.com/wasm3_engine/status/1393588527863144450), [github](https://github.com/wasm3/pywasm3-doom-demo) +- **Wasm3 self-compilation using `clang.wasm`** | [github](https://github.com/wasm3/wasm3-self-compiling) +- **Dino game** + - on PyBadge/Arduino | [video](https://twitter.com/vshymanskyy/status/1345048053041029121), [github](https://github.com/wasm3/wasm3-arduino/tree/main/examples/Wasm_Dino_PyBadge) + - on Raspberry Pi Pico | [github](https://github.com/vshymanskyy/wasm3_dino_rpi_pico) + - on ESP32 TTGO TDisplay | [github](https://github.com/wasm3/wasm3-arduino/tree/main/examples/Wasm_Dino_ESP32_TDisplay) +- **Basic WiFi/Gpio access, updating `wasm` file over-the-air** │ [video](https://twitter.com/alvaroviebrantz/status/1221618910803513344), [github](https://github.com/alvarowolfx/wasm-arduino-wifi) [ESP32 / Web] +- **RGB lamp animation using WebAssembly** │ [video](https://twitter.com/wasm3_engine/status/1222835097289752576), [github](https://github.com/vshymanskyy/Wasm3_RGB_Lamp) [nRF51 / nRF52 / ESP8266 / ESP32] +- **LCD display rendering with AssemblyScript** │ [video](https://twitter.com/h1romas4/status/1228581467850100736), [github](https://github.com/h1romas4/m5stack-wasm3-testing) [M5Stack / ESP32] +- **Conway's Game Of Life with AssemblyScript** │ [video](https://www.youtube.com/watch?v=Hc2sbhGMrig), [github](https://github.com/h1romas4/maixduino-wasm3-testing) [Maixduino / K210] + diff --git a/wasm3-sys/wasm3/docs/Development.md b/wasm3-sys/wasm3/docs/Development.md new file mode 100644 index 0000000..0008221 --- /dev/null +++ b/wasm3-sys/wasm3/docs/Development.md @@ -0,0 +1,151 @@ +# Wasm3 development notes + +This project uses CMake. +General build steps look like: +```sh +mkdir -p build +cd build +cmake .. +make -j8 +``` + +Wasm3 is continuously tested with Clang, GCC, MSVC compilers, and on multiple platforms. +It can be easily integrated into any build system, as shown in `platforms`. + +## Build on Linux, OS X + +### Clang + +```sh +mkdir build +cd build +cmake -GNinja -DCLANG_SUFFIX="-9" .. +ninja +``` + +### GCC + +```sh +mkdir build +cd build +cmake -GNinja .. +ninja +``` + +## Build on Windows + +Prerequisites: +- [Build Tools for Visual Studio 2019](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019) +- [CMake](https://cmake.org/download/) +- [Ninja](https://github.com/ninja-build/ninja/releases) +- [Clang 9](https://releases.llvm.org/download.html#9.0.0) + +Recommended tools: +- [Cmder](https://cmder.net/) +- [Python3](https://www.python.org/downloads/) +- [ptime](http://www.pc-tools.net/win32/ptime/) + +```sh +# Prepare environment (if needed): +"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" +set PATH=C:\Python36-32\;C:\Python36-32\Scripts\;%PATH% +``` + +### Build with MSBuild + +```sh +# Create a build directory as usual, then build a specific configuration +mkdir build +cd build + +# Configure Clang, x64 +cmake -G"Visual Studio 16 2019" -A x64 -T ClangCL .. + +# Configure Clang, x86 +cmake -G"Visual Studio 16 2019" -A Win32 -T ClangCL .. + +# Configure MSVC, x64 +cmake -G"Visual Studio 16 2019" -A x64 .. + +# Configure MSVC, x86 +cmake -G"Visual Studio 16 2019" -A Win32 .. + +# Build +cmake --build . --config Release +cp ./Release/wasm3.exe ./ +``` + +### Build with Ninja + +```sh +set PATH=C:\Program Files\CMake\bin;%PATH% +set PATH=C:\Program Files\LLVM\bin;%PATH% + +# Clang +cmake -GNinja -DCLANG_CL=1 .. +ninja + +# MSVC +cmake -GNinja .. +ninja +``` + +## Build using compiler directly + +This can be useful for cross-compilation, quick builds or when a build system (CMake, Ninja, etc.) is not available. + +### gcc/clang +```sh +gcc -O3 -g0 -s -Isource -Dd_m3HasWASI source/*.c platforms/app/main.c -lm -o wasm3 +``` + +### msvc/clang-cl +```sh +cl source/*.c platforms/app/main.c /Isource /MD /Ox /Oy /Gw /GS- /W0 /Dd_m3HasWASI /Fewasm3.exe /link advapi32.lib +``` + +### mingw-w64 +```sh +x86_64-w64-mingw32-gcc -O3 -g0 -s -Isource -Dd_m3HasWASI source/*.c platforms/app/main.c -lm -lpthread -static -o wasm3.exe +``` + +## Build for microcontrollers + +In `./platforms/` folder you can find projects for different targets. Some of them are using Platformio, so you can follow the regular pio build process. Others have custom instructions in respective `README.md` files. + +## Build with WasiEnv + +```sh +wasimake cmake -GNinja .. +ninja +``` + +If you want to enable experimental WASM features during the build: + +```sh +export CFLAGS="-Xclang -target-feature -Xclang +tail-call" +wasimake cmake -GNinja .. +ninja +``` + +Here's how some options can be used with different tools: + +```log +Clang target-feature option WABT option Chromium --js-flags option +---------------------------------------------------------------------------------------------------------------- ++multivalue --enable-multi-value --experimental-wasm-mv ++tail-call --enable-tail-call --experimental-wasm-return-call ++bulk-memory --enable-bulk-memory --experimental-wasm-bulk-memory ++nontrapping-fptoint --enable-saturating-float-to-int --experimental-wasm-sat-f2i-conversions ++sign-ext --enable-sign-extension --experimental-wasm-se ++simd128, +unimplemented-simd128 --enable-simd --experimental-wasm-simd +``` + +```sh +# List clang options: +llc -march=wasm32 -mattr=help + +# List Chromium options: +chromium-browser --single-process --js-flags="--help" 2>&1 | grep wasm +``` + diff --git a/wasm3-sys/wasm3/docs/Diagnostics.md b/wasm3-sys/wasm3/docs/Diagnostics.md new file mode 100644 index 0000000..5f9b947 --- /dev/null +++ b/wasm3-sys/wasm3/docs/Diagnostics.md @@ -0,0 +1,57 @@ + +## Logs + +To enable various logs, modify the defines in `m3_config.h`. These are only enabled when compiled in debug mode. + +```C +# define d_m3LogParse 0 // .wasm binary decoding info +# define d_m3LogModule 0 // Wasm module info +# define d_m3LogCompile 0 // wasm -> metacode generation phase +# define d_m3LogWasmStack 0 // dump the wasm stack when pushed or popped +# define d_m3LogEmit 0 // metacode-generation info +# define d_m3LogCodePages 0 // dump metacode pages when released +# define d_m3LogRuntime 0 // higher-level runtime information +# define d_m3LogNativeStack 0 // track the memory usage of the C-stack +``` + + +## Operation Profiling + +To profile the interpreter's operations enable `d_m3EnableOpProfiling` in `m3_config.h`. This profiling option works in either release or debug builds. + +When a runtime is released or `m3_PrintProfilerInfo ()` is called, a table of the executed operations and +their instance counts will be printed to stderr. + +``` + 23199904 op_SetSlot_i32 + 12203917 op_i32_Add_ss + 6682992 op_u32_GreaterThan_sr + 2021555 op_u32_ShiftLeft_sr + 1136577 op_u32_ShiftLeft_ss + 1019725 op_CopySlot_32 + 775431 op_i32_Subtract_ss + 703307 op_i32_Store_i32_rs + 337656 op_i32_Multiply_rs + 146383 op_u32_Or_rs + 99168 op_u64_Or_rs + 50311 op_u32_ShiftRight_rs + 43319 op_u32_ShiftLeft_rs + 21104 op_i64_Load_i64_s + 17450 op_i32_LessThan_sr + 7129 op_If_s + 5574 op_i32_Wrap_i64_r + 1630 op_f64_Load_f64_r + 1116 op_u32_Divide_sr + 903 op_i32_GreaterThan_ss + 390 op_u64_And_rs + 108 op_Select_f64_rss + 77 op_u64_ShiftLeft_sr + 64 op_Select_i32_ssr + 11 op_f64_Store_f64_ss + 10 op_MemGrow + 8 op_f64_GreaterThan_sr + 4 op_u64_LessThan_rs + 1 op_u32_Xor_ss + 1 op_i64_Subtract_ss +``` + diff --git a/wasm3-sys/wasm3/docs/Hardware.md b/wasm3-sys/wasm3/docs/Hardware.md new file mode 100644 index 0000000..498224d --- /dev/null +++ b/wasm3-sys/wasm3/docs/Hardware.md @@ -0,0 +1,60 @@ +# Wasm3 hardware support + +## Recommended devices (ideal for beginners) + +- ESP32-based + - **LilyGO TTGO T7 V1.4** │ [AliExpress](https://www.aliexpress.com/item/32977375539.html) + - **M5Stack Fire** │ [AliExpress](https://www.aliexpress.com/item/32847906756.html) +- nRF52840-based + - **Adafruit CLUE** │ [Adafruit](https://www.adafruit.com/clue) + - **Arduino Nano 33 BLE (or BLE Sense)** │ [Arduino](https://store.arduino.cc/arduino-nano-33-ble) + - **Particle Argon** │ [Particle](https://store.particle.io/collections/bluetooth/products/argon) + - **Adafruit Feather nRF52840** | [Adafruit](https://www.adafruit.com/product/4062) +- Other + - **Raspberry Pi Pico** | [Raspberry Pi](https://www.raspberrypi.org/products/raspberry-pi-pico) + - **Adafruit PyGamer/PyBadge/PyBadge LC** │ [Adafruit](https://www.adafruit.com/product/4242) + - **SparkFun Artemis** | [SparkFun](https://www.sparkfun.com/search/results?term=Artemis) + - **Teensy 4.0** │ [PJRC](https://www.pjrc.com/store/teensy40.html) + - **Wemos W600 PICO** │ [AliExpress](https://www.aliexpress.com/item/4000314757449.html) + +## Compatibility table + +Device | Chipset | Architecture | Clock | Flash | RAM +--- |:---: | --- | -----:| --- | --- +Espressif ESP32 | | Xtensa LX6 ⚠️ | 240MHz | 4 MB | 520KB +Particle Argon, Boron, Xenon | nRF52840 | Cortex-M4F | 64MHz | 1 MB | 256KB +Particle Photon, Electron | STM32F205 | Cortex-M3 | 120Mhz | 1 MB | 128KB +Sparkfun Photon RedBoard | STM32F205 | Cortex-M3 | 120Mhz | 1 MB | 128KB +Air602 | WM W600 | Cortex-M3 | 80MHz | 1 MB | 160KB+128KB +Adafruit PyBadge | ATSAMD51J19 | Cortex-M4F | 120MHz | 512KB | 192KB +Realtek RTL8711 | | Cortex-M3 | 166MHz | 2 MB | 2 MB+512KB +Nordic nRF52840 | | Cortex-M4F | 64MHz | 1 MB | 256KB +Nordic nRF52833 | | Cortex-M4F | 64MHz | 512KB | 128KB +P-Nucleo WB55RG | STM32WB55RG | Cortex-M4F | 64MHz | 1 MB | 256KB +Teensy 4.0 | NXP iMXRT1062 | Cortex-M7 | 600MHz | 2 MB | 1 MB +Teensy 3.5 | MK64FX512 | Cortex-M4F | 120MHz | 512KB | 192KB +MXChip AZ3166 | EMW3166 | Cortex-M4 | 100MHz | 1 MB+2 MB | 256KB +Arduino Due | AT91SAM3X8E | Cortex-M3 | 84MHz | 512KB | 96KB +Sipeed MAIX | Kendryte K210 | RV64IMAFDC | 400MHz | 16 MB | 8 MB +Fomu (soft CPU) | Lattice ICE40UP5K | RV32I | 12MHz | 2 MB | 128KB + +## Limited support + +The following devices can run Wasm3, however they cannot afford to allocate even a single Linear Memory page (64KB). +This means `memoryLimit` should be set to the actual amount of RAM available, and that in turn usually breaks the allocator of the hosted Wasm application (which still assumes the page is 64KB and performs OOB access). + +Device | Chipset | Architecture | Clock | Flash | RAM +--- |:---: | --- | -----:| --- | --- +Espressif ESP8266 | | Xtensa L106 ⚠️ | 160MHz | 4 MB | ~50KB (available) +Teensy 3.1/3.2 | NXP MK20DX256 | Cortex-M4 | 72MHz | 288KB | 64KB +Blue Pill | STM32F103 | Cortex-M3 | 72MHz | 64KB | 20KB +Arduino MKR* | SAMD21 | Cortex-M0+ ⚠️ | 48MHz | 256KB | 32KB +Arduino 101 | Intel Curie | ARC32 | 32MHz | 196KB | 24KB +SiFive HiFive1 | Freedom E310 | RV32IMAC | 320MHz | 16 MB | 16KB +Nordic nRF52832 | | Cortex-M4F | 64MHz | 256/512KB | 32/64KB +Nordic nRF51822 | | Cortex-M0 ⚠️ | 16MHz | 128/256KB | 16/32KB +Wicked Device WildFire | ATmega1284 | 8-bit AVR ⚠️ | 20MHz | 128KB | 16KB + +### Legend: + ⚠️ This architecture/compiler currently fails to perform TCO (Tail Call Optimization/Elimination), which leads to sub-optimal interpreter behaviour (intense native stack usage, lower performance). +There are plans to improve this in future 🦄. diff --git a/wasm3-sys/wasm3/docs/Installation.md b/wasm3-sys/wasm3/docs/Installation.md new file mode 100644 index 0000000..651cdf3 --- /dev/null +++ b/wasm3-sys/wasm3/docs/Installation.md @@ -0,0 +1,26 @@ +# Wasm3 installation + +## Windows +Download `wasm3-win-x64.exe` or `wasm3-win-x86.exe` from the [latest release page](https://github.com/wasm3/wasm3/releases/latest). + +## macOS +Use [Homebrew](https://brew.sh) to build and install automatically: +```sh +brew install wasm3 +``` + +## Cosmopolitan / Actually Portable Executable +[APE](https://justine.lol/cosmopolitan/index.html) is a polyglot format that runs natively on Linux + Mac + Windows + FreeBSD + OpenBSD + NetBSD + BIOS. +Download `wasm3-cosmopolitan.com` from the [latest release page](https://github.com/wasm3/wasm3/releases/latest) + +## OpenWRT +Follow instructions [here](https://github.com/wasm3/wasm3-openwrt-packages). + +## Arduino / PlatformIO / Particle.io library +Find `Wasm3` in the `Library Manager` and install it. + +## Python module +```sh +pip3 install pywasm3 +``` + diff --git a/wasm3-sys/wasm3/docs/Interpreter.md b/wasm3-sys/wasm3/docs/Interpreter.md new file mode 100644 index 0000000..67f2688 --- /dev/null +++ b/wasm3-sys/wasm3/docs/Interpreter.md @@ -0,0 +1,166 @@ +# M3 + +This is a WebAssembly interpreter written in C using a novel, high performance interpreter topology. The interpreter strategy (named M3) was developed prior to this particular Wasm project and is described some below. + +## Purpose + +I don't know. I just woke up one day and started hacking this out after realizing my interpreter was well suited for the Wasm bytecode structure. Some ideas: + +* It could be useful for embedded systems. +* It might be a good start-up, pre-JIT interpreter in a more complex Wasm compiler system. +* It could serve as a Wasm validation library. +* The interpreter topology might be inspiring to others. + + +## Benchmarks + +It's at least fleshed out enough to run some simple benchmarks. + +Tested on a 4 GHz Intel Core i7 iMac (Retina 5K, 27-inch, Late 2014). M3 was compiled with Clang -Os. C benchmarks were compiled with gcc with -O3 + +### Mandelbrot + +C code lifted from: https://github.com/ColinEberhardt/wasm-mandelbrot + +|Interpreter|Execution Time|Relative to GCC| | +|-----------|--------------|---------------|----| +|Life |547 s |133 x | https://github.com/perlin-network/life +|Lua |122 s |30 x | This isn't Lua running some weird Wasm transcoding; a manual Lua conversion of the C benchmark as an additional reference point. +|M3 |17.9 s |4.4 x | (3.7 x on my 2016 MacBook Pro) +|GCC |4.1 s | | + +### CRC32 + +|Interpreter|Execution Time|Relative to GCC| +|-----------|--------------|---------------| +|Life |153 s |254 x | +|M3 |5.1 s |8.5 x | +|GCC |600 ms | | + + +In general, the M3 strategy seems capable of executing code around 4-15X slower than compiled code on a modern x86 processor. (Older CPUs don't fare as well. I suspect branch predictor differences.) I have yet to test on anything ARM. + +## M3: Massey Meta Machine + +Over the years, I've mucked around with creating my own personal programming language. It's called Gestalt. The yet unreleased repository will be here: https://github.com/soundandform/gestalt + +Early on I decided I needed an efficient interpreter to achieve the instant-feedback, live-coding environment I desire. Deep traditional compilation is too slow and totally unnecessary during development. And, most importantly, compilation latency destroys creative flow. + +I briefly considered retooling something extant. The Lua virtual machine, one of the faster interpreters, is too Lua centric. And everything else is too slow. + +I've also always felt that the "spin in a loop around a giant switch statement" thing most interpreters do was clumsy and boring. My intuition said there was something more elegant to be found. + +The structure that emerged I named a "meta machine" since it mirrors the execution of compiled code much more closely than the switch-based virtual machine. + +I set out with a goal of approximating Lua's performance. But this interpreter appears to beat Lua by 3X and more on basic benchmarks -- whatever they're worth! + +### How it works + +This rough information might not be immediately intelligible without referencing the source code. + +#### Reduce bytecode decoding overhead + +* Bytecode/opcodes are translated into more efficient "operations" during a compilation pass, generating pages of meta-machine code + * M3 trades some space for time. Opcodes map to up to 3 different operations depending on the number of source operands and commutative-ness. +* Commonly occurring sequences of operations can can also be optimized into a "fused" operation. This *sometimes* results in improved performance. + * the modern CPU pipeline is a mysterious beast +* In M3/Wasm, the stack machine model is translated into a more direct and efficient "register file" approach. + +#### Tightly Chained Operations + +* M3 operations are C functions with a single, fixed function signature. + + ```C + void * Operation_Whatever (pc_t pc, u64 * sp, u8 * mem, reg_t r0, f64 fp0); + ``` + +* The arguments of the operation are the M3's virtual machine registers + * program counter, stack pointer, etc. +* The return argument is a trap/exception and program flow control signal +* The M3 program code is traversed by each operation calling the next. The operations themselves drive execution forward. There is no outer control structure. + * Because operations end with a call to the next function, the C compiler will tail-call optimize most operations. +* Finally, note that x86/ARM calling conventions pass initial arguments through registers, and the indirect jumps between operations are branch predicted. + +#### The End Result + +Since operations all have a standardized signature and arguments are tail-call passed through to the next, the M3 "virtual" machine registers end up mapping directly to real CPU registers. It's not virtual! Instead, it's a meta machine with very low execution impedance. + +|M3 Register |x86 Register| +|-----------------------------|------------| +|program counter (pc) |rdi | +|stack pointer (sp) |rsi | +|linear memory (mem) |rdx | +|integer register (r0) |rcx | +|floating-point register (fp0)|xmm0 | + + +For example, here's a bitwise-or operation in the M3 compiled on x86. + +```assembly +m3`op_u64_Or_sr: + 0x1000062c0 <+0>: movslq (%rdi), %rax ; load operand stack offset + 0x1000062c3 <+3>: orq (%rsi,%rax,8), %rcx ; or r0 with stack operand + 0x1000062c7 <+7>: movq 0x8(%rdi), %rax ; fetch next operation + 0x1000062cb <+11>: addq $0x10, %rdi ; increment program counter + 0x1000062cf <+15>: jmpq *%rax ; jump to next operation +``` + + +#### Registers and Operational Complexity + +* The conventional Windows calling convention isn't compatible with M3, as-is, since it only passes 4 arguments through registers. Applying the vectorcall calling convention (https://docs.microsoft.com/en-us/cpp/cpp/vectorcall) resolves this problem. + +* It's possible to use more CPU registers. For example, adding an additional floating-point register to the meta-machine did marginally increase performance in prior tests. However, the operation space increases exponentially. With one register, there are up to 3 operations per opcode (e.g. a non-commutative math operation). Adding another register increases the operation count to 10. However, as you can see above, operations tend to be tiny. + +#### Stack Usage + +* Looking at the above assembly code, you'll notice that once an M3 operation is optimized, it doesn't need the regular stack (no mucking with the ebp/esp registers). This is the case for 90% of the opcodes. Branching and call operations do require stack variables. Therefore, execution can't march forward indefinitely; the stack would eventually overflow. + + Therefore, loops unwind the stack. When a loop is continued, the Continue operation returns, unwinding the stack. Its return value is a pointer to the loop opcode it wants to unwind to. The Loop operations checks for its pointer and responds appropriately, either calling back into the loop code or returning the loop pointer back down the call stack. + +* Traps/Exceptions work similarly. A trap pointer is returned from the trap operation which has the effect of unwinding the entire stack. + +* Returning from a Wasm function also unwinds the stack, back to the point of the Call operation. + +* But, because M3 execution leans heavily on the native stack, this does create one runtime usage issue. + + A conventional interpreter can save its state, break out of its processing loop and return program control to the client code. This is not the case in M3 since the C stack might be wound up in a loop for long periods of time. + + With Gestalt, I resolved this problem with fibers (built with Boost Context). M3 execution occurs in a fiber so that control can effortlessly switch to the "main" fiber. No explicit saving of state is necessary since that's the whole purpose of a fiber. + + More simplistically, the interpreter runtime can also periodically call back to the client (in the either the Loop or LoopContinue operation). This is necessary, regardless, to detect hangs and break out of infinite loops. + + +## The M3 strategy for other languages (is rad) + +The Gestalt M3 interpreter works slightly differently than this Wasm version. With Gestalt, blocks of all kind (if/else/try), not just loops, unwind the native stack. (This somewhat degrades raw x86 performance.) + +But, this adds a really beautiful property to the interpreter. The lexical scoping of a block in the language source code maps directly into the interpreter. All opcodes/operations end up having an optional prologue/epilogue structure. This made things like reference-counting objects in Gestalt effortless. Without this property, the compiler itself would have to track scope and insert dererence opcodes intentionally. Instead, the "CreateObject" operation is also the "DestroyObject" operation on the exit/return pathway. + +Here's some pseudocode to make this more concrete: + +``` +return_t Operation_NewObject (registers...) +{ + Object o = runtime->CreateObject (registers...); + + * stack [index] = o; + + return_t r = CallNextOperation (registers...); // executes to the end of the scope/block/curly-brace & returns + + if (o->ReferenceCount () == 0) + runtime->DestroyObject (registers..., o); // calls o's destructor and frees memory + + return r; +} +``` + +Likewise, a "defer" function (like in Go) becomes absolutely effortless to implement. Exceptions (try/catch) as well. + + +## Prior Art + +After the Wasm3 project was posted to Hacker News (https://news.ycombinator.com/item?id=22024758), I finally discovered precedent for this tail-call interpreter design. It has previously been called "threaded code". See the "Continuation-passing style" section: http://www.complang.tuwien.ac.at/forth/threaded-code.html). + +If this style of interpreter was discussed back in the 70's, why hasn't it been more popular? I suspect because there was no benefit until more recently. Older calling conventions only used the stack to pass arguments, older CPUs didn't have branch prediction and compiler tail-call optimization maybe weren't ubiqutous. + diff --git a/wasm3-sys/wasm3/docs/Performance.md b/wasm3-sys/wasm3/docs/Performance.md new file mode 100644 index 0000000..4b52a74 --- /dev/null +++ b/wasm3-sys/wasm3/docs/Performance.md @@ -0,0 +1,91 @@ +# Performance + +## CoreMark 1.0 results + +```log +# Intel i5-8250U x64 (1.6-3.4GHz) + +Node v13.0.1 (interpreter) 28.544923 57.0x +wac (wax) 101.864113 16.0x +wasm-micro-runtime 201.612903 8.1x ▲ slower +wasm3 1627.869119 1.0 +Wasmer 0.13.1 singlepass 4065.591544 2.5x ▼ faster +wasmtime 0.8.0 (--optimize) 6453.505427 4.0x +Wasmer 0.13.1 cranelift 6467.164442 4.0x +Webassembly.sh (Chromium 78) 6914.325225 4.2x +Webassembly.sh (Firefox 70) 7251.153593 4.5x +wasmer-js (Node v13.0.1) 10043.827611 6.2x +Wasmer 0.13.1 llvm 12450.199203 7.6x +WAVM 14946.566026 9.2x +Native (GCC 7.4.0, 32-bit) 18070.112035 11.1x +Native (GCC 7.4.0, 64-bit) 19144.862795 11.8x +``` + +**Note:** Here is more info on [how to run CoreMark benchmark](https://github.com/wasm3/wasm-coremark). + +## Simple recursive Fibonacci calculation test + +```log + fib(40) +----------------------------------------------------------------------------------------- +# Intel i5-8250U x64 (1.6-3.4GHz) +Native C implementation 0.23s +Linux 3.83s +Win 10 5.35s +wasm3 on V8 (Emscripten 1.38, node v13.0.1) 17.98s + +# Raspberry Pi 4 BCM2711B0 armv7l (A72 @ 1.5GHz) +Native C implementation 1.11s +Linux 22.97s + +# Orange Pi Zero Plus2 H5 aarch64 (A53 @ 1GHz) +Native C implementation 2.55s +Linux 50.00s + +# VoCore2 mips32r2 (MT7628AN @ 580MHz) +Native C implementation 6.21s +OpenWRT 2m 38s + +# Xiaomi Mi Router 3G mips32r2 (MT7621AT @ 880MHz) +Native C implementation 8.83s +OpenWRT 3m 20s +``` + +## Wasm3 on MCUs + +```log + fib(24) comments +----------------------------------------------------------------------------------------- +Maix (K210) rv64imafc @ 400MHz 77ms +ESP8266 LX106 @ 160MHz 308ms TCO failed, stack used: 9024 +ESP32 LX6 @ 240MHz 297ms TCO failed, stack used: 10600 +ESP32-s2 (beta) LX6 @ 240MHz 297ms TCO failed +Particle Photon Arm M3 @ 120MHz 536ms +MXChip AZ3166 Arm M4 @ 100MHz ms +WM W600 Arm M3 @ 80MHz 698ms TCO enabled, stack used: 1325 +WM W600 Arm M3 @ 80MHz 826ms TCO disabled, stack used: 8109 +Arduino DUE (SAM3X8E) Arm M3 @ 84MHz 754ms +BleNano2 (nRF52) Arm M4 @ 64MHz 1.19s +Arduino MKR1000 Arm M0+ @ 48MHz 1.93s TCO failed +TinyBLE (nRF51) Arm M0 @ 16MHz 5.69s TCO failed +BluePill Arm M3 @ 72MHz 7.62s +HiFive1 (FE310) rv32imac @ 320MHz 9.10s <- something wrong here? +ATmega1284 avr @ 16MHz 12.99s TCO failed +Fomu rv32i @ 12MHz 25.20s +``` + +## Wasm3 vs other languages + +```log + fib(40) +----------------------------------------------------------------------------------------- +LuaJIT jit 1.15s +Node v10.15 jit 2.97s ▲ faster +Wasm3 interp 3.83s +Lua 5.1 interp 16.65s ▼ slower +Python 2.7 interp 34.08s +Python 3.4 interp 35.67s +Micropython v1.11 interp 85,00s +Espruino 2v04 interp >20m +``` + diff --git a/wasm3-sys/wasm3/docs/Testing.md b/wasm3-sys/wasm3/docs/Testing.md new file mode 100644 index 0000000..b38820c --- /dev/null +++ b/wasm3-sys/wasm3/docs/Testing.md @@ -0,0 +1,61 @@ +# Wasm3 tests + +## Running WebAssembly spec tests + +To run spec tests, you need `python3` + +```sh +# In test directory: +python3 ./run-spec-test.py +``` + +It will automatically download, extract, run the WebAssembly core test suite. + +## Running WASI test + +Wasm3 comes with a set of benchmarks and test programs (prebuilt as `WASI` apps) including `CoreMark`, `C-Ray`, `Brotli`, `mandelbrot`, `smallpt` and `wasm3` itself. + +This test will run all of them and verify the output: + +```sh +# In test directory: +python3 ./run-wasi-test.py +``` + +It can be run against other engines as well: + +```sh +./run-wasi-test.py --exec wasmtime # [PASS] +./run-wasi-test.py --exec "wavm run" # [PASS] +./run-wasi-test.py --exec "wasmer run" # [PASS] +./run-wasi-test.py --exec "wasmer-js run" # [PASS] +./run-wasi-test.py --exec $WAMR/iwasm --timeout=300 # [PASS, but very slow] +./run-wasi-test.py --exec $WAC/wax --timeout=300 # [FAIL, crashes on most tests] +``` + +## Running coverage-guided fuzz testing with libFuzzer + +You need to produce a fuzzer build first (use your version of Clang): + +```sh +# In wasm3 root: +mkdir build-fuzzer +cd build-fuzzer +cmake -GNinja -DCLANG_SUFFIX="-9" .. +cmake -DBUILD_FUZZ:BOOL=TRUE .. +ninja +``` + +```sh +# In test directory: +../build-fuzzer/wasm3-fuzzer -detect_leaks=0 ./fuzz/corpus +``` + +Read [more on libFuzzer](https://llvm.org/docs/LibFuzzer.html) and it's options. + +Note: to catch fuzzer errors in debugger, you need to define: +```sh +export ASAN_OPTIONS=abort_on_error=1 +export UBSAN_OPTIONS=abort_on_error=1 +``` + diff --git a/wasm3-sys/wasm3/docs/Troubleshooting.md b/wasm3-sys/wasm3/docs/Troubleshooting.md new file mode 100644 index 0000000..9b95b12 --- /dev/null +++ b/wasm3-sys/wasm3/docs/Troubleshooting.md @@ -0,0 +1,26 @@ +# Wasm3 troubleshooting + +### `Error: [trap] stack overflow` + +Increase the stack size: +```sh +wasm3 --stack-size 1000000 file.wasm +``` + +### `Error: missing imported function` + +This means that the runtime doesn't provide a specific function, needed for your module execution. +You need to implement the required functions, and re-build Wasm3. +Alternatively, you can use Python to define your environment. Check out [`pywasm3`](https://pypi.org/project/pywasm3/) module. + +**Note:** If this happens with `WASI` functions like `wasi_unstable.*` or `wasi_snapshot_preview1.*`, please report as a bug. + +### `Error: compiling function overran its stack height limit` + +Try increasing `d_m3MaxFunctionStackHeight` in `m3_config.h` and rebuilding Wasm3. + +### `Error: [Fatal] repl_load: unallocated linear memory` + +Your module requires some `Memory`, but doesn't define/export it by itself. +This happens if module is built by `Emscripten`, or it's a library that is intended to be linked to some other modules. +Wasm3 currently doesn't support running such modules directly, but you can remove this limitation when embedding Wasm3 into your own app. diff --git a/wasm3-sys/wasm3/extra/blynk.png b/wasm3-sys/wasm3/extra/blynk.png new file mode 100644 index 0000000..000fde8 Binary files /dev/null and b/wasm3-sys/wasm3/extra/blynk.png differ diff --git a/wasm3-sys/wasm3/extra/button.png b/wasm3-sys/wasm3/extra/button.png new file mode 100644 index 0000000..85bceaf Binary files /dev/null and b/wasm3-sys/wasm3/extra/button.png differ diff --git a/wasm3-sys/wasm3/extra/disasm-func.sh b/wasm3-sys/wasm3/extra/disasm-func.sh new file mode 100755 index 0000000..188f3ff --- /dev/null +++ b/wasm3-sys/wasm3/extra/disasm-func.sh @@ -0,0 +1,17 @@ +# +# Utility to disassemble a specific function. +# Usage: +# ./disasm-func.sh ../build/wasm3 i32_Divide_sr +# + +FILE="$1" +FUNC="$2" + +# get starting address and size of function fact from nm +ADDR=$(nm --print-size --radix=d $FILE | grep $FUNC | cut -d ' ' -f 1,2) +# strip leading 0's to avoid being interpreted by objdump as octal addresses +STARTADDR=$(echo $ADDR | cut -d ' ' -f 1 | sed 's/^0*\(.\)/\1/') +SIZE=$(echo $ADDR | cut -d ' ' -f 2 | sed 's/^0*//') +STOPADDR=$(( $STARTADDR + $SIZE )) + +objdump --disassemble $FILE --start-address=$STARTADDR --stop-address=$STOPADDR -M suffix diff --git a/wasm3-sys/wasm3/extra/iden3.svg b/wasm3-sys/wasm3/extra/iden3.svg new file mode 100644 index 0000000..975144f --- /dev/null +++ b/wasm3-sys/wasm3/extra/iden3.svg @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/wasm3-sys/wasm3/extra/logo.png b/wasm3-sys/wasm3/extra/logo.png new file mode 100644 index 0000000..c1cf38d Binary files /dev/null and b/wasm3-sys/wasm3/extra/logo.png differ diff --git a/wasm3-sys/wasm3/extra/scailable.png b/wasm3-sys/wasm3/extra/scailable.png new file mode 100644 index 0000000..eb997b8 Binary files /dev/null and b/wasm3-sys/wasm3/extra/scailable.png differ diff --git a/wasm3-sys/wasm3/extra/screenshot-android.png b/wasm3-sys/wasm3/extra/screenshot-android.png new file mode 100644 index 0000000..885bbdd Binary files /dev/null and b/wasm3-sys/wasm3/extra/screenshot-android.png differ diff --git a/wasm3-sys/wasm3/extra/screenshot-ios.png b/wasm3-sys/wasm3/extra/screenshot-ios.png new file mode 100644 index 0000000..8bfe5b4 Binary files /dev/null and b/wasm3-sys/wasm3/extra/screenshot-ios.png differ diff --git a/wasm3-sys/wasm3/extra/shareup_app.svg b/wasm3-sys/wasm3/extra/shareup_app.svg new file mode 100644 index 0000000..875a8b1 --- /dev/null +++ b/wasm3-sys/wasm3/extra/shareup_app.svg @@ -0,0 +1 @@ +Shareup \ No newline at end of file diff --git a/wasm3-sys/wasm3/extra/testutils.py b/wasm3-sys/wasm3/extra/testutils.py new file mode 100755 index 0000000..97eccc6 --- /dev/null +++ b/wasm3-sys/wasm3/extra/testutils.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +# Author: Volodymyr Shymanskyy + +import os +import re, fnmatch +import pathlib + +class ansi: + ENDC = '\033[0m' + HEADER = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + +class dotdict(dict): + def __init__(self, *args, **kwargs): + super(dotdict, self).__init__(*args, **kwargs) + for arg in args: + if isinstance(arg, dict): + for k, v in arg.items(): + self[k] = v + if kwargs: + for k, v in kwargs.items(): + self[k] = v + + __getattr__ = dict.get + __setattr__ = dict.__setitem__ + __delattr__ = dict.__delitem__ + +class Blacklist(): + def __init__(self, patterns): + self._patterns = list(map(fnmatch.translate, patterns)) + self.update() + + def add(self, patterns): + self._patterns += list(map(fnmatch.translate, patterns)) + self.update() + + def update(self): + self._regex = re.compile('|'.join(self._patterns)) + + def __contains__(self, item): + return self._regex.match(item) is not None + +def filename(p): + _, fn = os.path.split(p) + return fn + +def pathname(p): + pn, _ = os.path.split(p) + return pn + +def ensure_path(p): + pathlib.Path(p).mkdir(parents=True, exist_ok=True) diff --git a/wasm3-sys/wasm3/extra/txiki_js.png b/wasm3-sys/wasm3/extra/txiki_js.png new file mode 100644 index 0000000..45cdb91 Binary files /dev/null and b/wasm3-sys/wasm3/extra/txiki_js.png differ diff --git a/wasm3-sys/wasm3/extra/utils.mk b/wasm3-sys/wasm3/extra/utils.mk new file mode 100644 index 0000000..f5ce9ea --- /dev/null +++ b/wasm3-sys/wasm3/extra/utils.mk @@ -0,0 +1,39 @@ +.PHONY: format + +all: + +format: + # Convert tabs to spaces + find ./source -type f -iname '*.[cpp\|c\|h]' -exec bash -c 'expand -t 4 "$$0" | sponge "$$0"' {} \; + # Remove trailing whitespaces + find ./source -type f -iname '*.[cpp\|c\|h]' -exec sed -i 's/ *$$//' {} \; + +preprocess: preprocess_restore + cp ./source/m3_exec.h ./source/m3_exec.h.bak + cp ./source/m3_compile.c ./source/m3_compile.c.bak + awk 'BEGIN {RS=""}{gsub(/\\\n/,"\\\n__NL__ ")}1' ./source/m3_exec.h | sponge ./source/m3_exec.h + cpp -I./source -P ./source/m3_compile.c | sponge ./source/m3_compile.c + awk '{gsub(/__NL__/,"\n")}1' ./source/m3_compile.c | sponge ./source/m3_compile.c + mv ./source/m3_exec.h.bak ./source/m3_exec.h + +preprocess_restore: + -mv source/m3_compile.c.bak source/m3_compile.c + touch source/m3_compile.c + + +test_rv64: + riscv64-linux-gnu-gcc -DDEBUG -Dd_m3HasWASI \ + -I./source ./source/*.c ./platforms/app/main.c \ + -O3 -g0 -flto -lm -static \ + -o wasm3-rv64 + + cd test; python3 run-wasi-test.py --fast --exec "qemu-riscv64-static ../wasm3-rv64" + rm ./wasm3-rv64 + +test_cpp: + clang -xc++ -Dd_m3HasWASI \ + -I./source ./source/*.c ./platforms/app/main.c \ + -O3 -g0 -flto -lm -static \ + -o wasm3-cpp + cd test; python3 run-wasi-test.py --fast --exec "../wasm3-cpp" + rm ./wasm3-cpp diff --git a/wasm3-sys/wasm3/extra/wapm-package/README.md b/wasm3-sys/wasm3/extra/wapm-package/README.md new file mode 100644 index 0000000..0174c86 --- /dev/null +++ b/wasm3-sys/wasm3/extra/wapm-package/README.md @@ -0,0 +1,105 @@ +# Wasm3 + +[Wasm3](https://github.com/wasm3/wasm3) is the fastest WebAssembly interpreter, and the most universal runtime. +It's packaged into a `WebAssembly` package, so you can finally run `WebAssembly` on `WebAssembly` 😆 + +## Running on WebAssembly.sh + +Open [**WebAssembly.sh**](https://webassembly.sh) + +First you need to fetch a wasm file you'd like to run: + +```sh +$ curl https://raw.githubusercontent.com/wasm3/wasm3/main/test/lang/fib32.wasm -o /tmp/fib32.wasm + +$ ls -l /tmp/fib32.wasm +---------- 1 somebody somegroup 62 1970-01-19 05:45 /tmp/fib32.wasm +``` + +Now we can run `wasm3` in interactive mode: + +```sh +$ wasm3 --repl /tmp/fib32.wasm +wasm3> fib 20 +Result: 6765 +wasm3> fib 30 +Result: 832040 +wasm3> ^C +$ +``` + +Or run a specific function directly: + +```sh +$ wasm3 --func fib /tmp/fib32.wasm 30 +Result: 832040 +``` + +`wasm3` also supports `WASI`, so you can run: + +```sh +$ curl https://raw.githubusercontent.com/wasm3/wasm3/main/test/wasi/simple/test.wasm -o /tmp/test.wasm +$ wasm3 /tmp/test.wasm +``` + +or even... run wasm3 inside wasm3: + +```sh +$ curl https://registry-cdn.wapm.io/contents/vshymanskyy/wasm3/0.5.0/build/wasm3-wasi.wasm -o /tmp/wasm3.wasm +$ wasm3 --stack-size 100000 /tmp/wasm3.wasm /tmp/test.wasm +``` + +## Tracing + +You can also get structured traces of arbitrary WASM file execution (and this requires no specific support from the runtime): + +```sh +$ wasm3-strace --repl /tmp/fib32.wasm +wasm3> fib 3 +fib (i32: 3) { + fib (i32: 1) { + } = 1 + fib (i32: 2) { + fib (i32: 0) { + } = 0 + fib (i32: 1) { + } = 1 + } = 1 +} = 2 +Result: 2 +``` + +WASI apps tracing is also supported: + +```sh +$ wasm3-strace /tmp/test.wasm trap +_start () { + __wasm_call_ctors () { + __wasilibc_populate_preopens () { + wasi_snapshot_preview1!fd_prestat_get(3, 65528) { } = 0 + malloc (i32: 2) { + dlmalloc (i32: 2) { + sbrk (i32: 0) { + } = 131072 + } = 70016 + } = 70016 +... + strcmp (i32: 70127, i32: 32) { + } = 0 + test_trap () { + a () { + b () { + c () { + } !trap = [trap] unreachable executed +... +==== wasm backtrace: + 0: 0x000c59 - .unnamed!c + 1: 0x000c5e - .unnamed!b + 2: 0x000c68 - .unnamed!a + 3: 0x000c72 - .unnamed!test_trap + 4: 0x000d2c - .unnamed!main + 5: 0x0037c9 - .unnamed!__main_void + 6: 0x000edb - .unnamed!__original_main + 7: 0x0002f3 - .unnamed!_start +Error: [trap] unreachable executed +``` diff --git a/wasm3-sys/wasm3/extra/wapm-package/build/.gitignore b/wasm3-sys/wasm3/extra/wapm-package/build/.gitignore new file mode 100644 index 0000000..86d0cb2 --- /dev/null +++ b/wasm3-sys/wasm3/extra/wapm-package/build/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/wasm3-sys/wasm3/extra/wapm-package/wapm.toml b/wasm3-sys/wasm3/extra/wapm-package/wapm.toml new file mode 100644 index 0000000..54b6b27 --- /dev/null +++ b/wasm3-sys/wasm3/extra/wapm-package/wapm.toml @@ -0,0 +1,25 @@ +[package] +name = "vshymanskyy/wasm3" +version = "0.5.0" +description = "🚀 The fastest WebAssembly interpreter. You can finally run WebAssembly on WebAssembly 😆" +readme = "README.md" +repository = "https://github.com/wasm3/wasm3" +homepage = "https://github.com/wasm3/wasm3" + +[[module]] +name = "wasm3" +source = "build/wasm3-wasi.wasm" +abi = "wasi" + +[[module]] +name = "wasm3-strace" +source = "build/wasm3-strace.wasm" +abi = "wasi" + +[[command]] +name = "wasm3" +module = "wasm3" + +[[command]] +name = "wasm3-strace" +module = "wasm3-strace" diff --git a/wasm3-sys/wasm3/extra/wasm-symbol.svg b/wasm3-sys/wasm3/extra/wasm-symbol.svg new file mode 100644 index 0000000..1323482 --- /dev/null +++ b/wasm3-sys/wasm3/extra/wasm-symbol.svg @@ -0,0 +1,71 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/wasm3-sys/wasm3/extra/wowcube.png b/wasm3-sys/wasm3/extra/wowcube.png new file mode 100644 index 0000000..f6c069c Binary files /dev/null and b/wasm3-sys/wasm3/extra/wowcube.png differ diff --git a/wasm3-sys/wasm3/platforms/android/.gitignore b/wasm3-sys/wasm3/platforms/android/.gitignore new file mode 100644 index 0000000..11b5322 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/.gitignore @@ -0,0 +1,9 @@ +.gradle +# Build output directies +*/.externalNativeBuild +/target +*/target +/build +*/build +*/.cxx + diff --git a/wasm3-sys/wasm3/platforms/android/README.md b/wasm3-sys/wasm3/platforms/android/README.md new file mode 100644 index 0000000..0d6c852 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/README.md @@ -0,0 +1,26 @@ +## Build for Android + +

+ +Install Android SDK Tools, then: + +```sh +export ANDROID_HOME=/opt/android-sdk/ +export PATH=$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools:$PATH +``` + +Install NDK: +```sh +sdkmanager --install ndk-bundle +``` + +Build: +```sh +./gradlew build +``` + +Install on device: +``` +adb install -r ./app/build/outputs/apk/debug/app-debug.apk +``` + diff --git a/wasm3-sys/wasm3/platforms/android/app/build.gradle b/wasm3-sys/wasm3/platforms/android/app/build.gradle new file mode 100644 index 0000000..e48af94 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/build.gradle @@ -0,0 +1,33 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + ndkVersion '22.1.7171670' + + defaultConfig { + applicationId 'com.example.hellojni' + minSdkVersion 23 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), + 'proguard-rules.pro' + } + } + externalNativeBuild { + cmake { + version '3.10.2+' + path "src/main/cpp/CMakeLists.txt" + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' +} diff --git a/wasm3-sys/wasm3/platforms/android/app/proguard-rules.pro b/wasm3-sys/wasm3/platforms/android/app/proguard-rules.pro new file mode 100644 index 0000000..b7420a7 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/gfan/dev/sdk_current/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/AndroidManifest.xml b/wasm3-sys/wasm3/platforms/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2081ab0 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/CMakeLists.txt b/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000..d4d63ec --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.4.1) + +add_definitions(-DANDROID -Wno-format-security -O3 + #-fno-optimize-sibling-calls + -flto -fomit-frame-pointer -fno-stack-check -fno-stack-protector) + +file(GLOB M3_SRC FOLLOW_SYMLINKS "m3/*.c" "*.c") + +add_library(wasm3-jni SHARED ${M3_SRC}) + +set_target_properties(wasm3-jni PROPERTIES LINK_FLAGS "-flto -O3") + +# Include libraries needed for wasm3-jni lib +target_link_libraries(wasm3-jni + android + log) diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/jni.c b/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/jni.c new file mode 100644 index 0000000..115c6a4 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/jni.c @@ -0,0 +1,96 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include + +extern int main(); + +/* + * JNI init + */ + +JavaVM* javaVM; +JNIEnv* jniEnv; +jclass activityClz; +jobject activityObj; + +JNIEXPORT jint JNICALL +JNI_OnLoad(JavaVM* vm, void* reserved) +{ + if ((*vm)->GetEnv(vm, (void**)&jniEnv, JNI_VERSION_1_6) != JNI_OK) { + return JNI_ERR; // JNI version not supported + } + javaVM = vm; + return JNI_VERSION_1_6; +} + +static int pfd[2]; +static pthread_t pumpThread; +static pthread_t mainThread; + +static void* runOutputPump(void* ctx) +{ + int readSize; + char buff[128]; + + JNIEnv* env; + (*javaVM)->AttachCurrentThread(javaVM, &env, NULL); + + jmethodID outputTextId = (*env)->GetMethodID(env, activityClz, + "outputText", + "(Ljava/lang/String;)V"); + + while ((readSize = read(pfd[0], buff, sizeof(buff) - 1)) > 0) + { + buff[readSize] = '\0'; + + jstring javaMsg = (*env)->NewStringUTF(env, buff); + (*env)->CallVoidMethod(env, activityObj, outputTextId, javaMsg); + (*env)->DeleteLocalRef(env, javaMsg); + } + + return 0; +} + +static void* runMain(void* ctx) +{ + (*javaVM)->AttachCurrentThread(javaVM, &jniEnv, NULL); + main(); + return NULL; +} + +JNIEXPORT void JNICALL +Java_com_example_wasm3_MainActivity_runMain(JNIEnv* env, jobject instance) +{ + setvbuf(stdout, 0, _IOLBF, 0); // stdout: line-buffered + setvbuf(stderr, 0, _IONBF, 0); // stderr: unbuffered + + // create the pipe and redirect stdout and stderr + pipe(pfd); + dup2(pfd[1], 1); + dup2(pfd[1], 2); + + jclass clz = (*env)->GetObjectClass(env, instance); + activityClz = (*env)->NewGlobalRef(env, clz); + activityObj = (*env)->NewGlobalRef(env, instance); + + pthread_attr_t threadAttr; + pthread_attr_init(&threadAttr); + pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED); + + pthread_create( &pumpThread, &threadAttr, runOutputPump, NULL); + + pthread_create( &mainThread, &threadAttr, runMain, NULL); + + pthread_attr_destroy(&threadAttr); +} diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/m3 b/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/m3 new file mode 120000 index 0000000..f70c2e0 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/m3 @@ -0,0 +1 @@ +../../../../../../source \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/main.c b/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/main.c new file mode 100644 index 0000000..a1bb331 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/cpp/main.c @@ -0,0 +1,70 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include + +#include "m3/wasm3.h" +#include "m3/m3_api_libc.h" + +#include "m3/extra/coremark_minimal.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)coremark_minimal_wasm; + size_t fsize = coremark_minimal_wasm_len; + + printf("Loading WebAssembly...\n"); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 8192, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + result = m3_LinkLibC (module); + if (result) FATAL("m3_LinkLibC: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "run"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running CoreMark 1.0...\n"); + + result = m3_CallV (f); + if (result) FATAL("m3_Call: %s", result); + + float value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %0.3f\n", value); +} + +int main() +{ + printf("Wasm3 v" M3_VERSION " on Android (" M3_ARCH ")\n"); + printf("Build " __DATE__ " " __TIME__ "\n"); + + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + printf("Elapsed: %ld ms\n", (end - start)*1000 / CLOCKS_PER_SEC); +} diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/java/com/example/wasm3/MainActivity.java b/wasm3-sys/wasm3/platforms/android/app/src/main/java/com/example/wasm3/MainActivity.java new file mode 100644 index 0000000..88e3326 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/java/com/example/wasm3/MainActivity.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.example.wasm3; + +import androidx.annotation.Keep; +import androidx.appcompat.app.AppCompatActivity; +import android.os.Bundle; +import android.widget.TextView; + +public class MainActivity extends AppCompatActivity { + + TextView tv; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_main); + tv = (TextView)findViewById(R.id.console); + + runMain(); + } + + @Keep + private void outputText(final String s) { + runOnUiThread(new Runnable() { + @Override + public void run() { + MainActivity.this.tv.append(s); + } + }); + } + + static { + System.loadLibrary("wasm3-jni"); + } + public native void runMain(); +} + diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/drawable/ic_launcher.png b/wasm3-sys/wasm3/platforms/android/app/src/main/res/drawable/ic_launcher.png new file mode 100644 index 0000000..842fcc8 Binary files /dev/null and b/wasm3-sys/wasm3/platforms/android/app/src/main/res/drawable/ic_launcher.png differ diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/layout/activity_main.xml b/wasm3-sys/wasm3/platforms/android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..15e83f8 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..c68f603 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..ae9968a Binary files /dev/null and b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..7ed0c12 Binary files /dev/null and b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..68bb899 Binary files /dev/null and b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..f51427e Binary files /dev/null and b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..85c1d06 Binary files /dev/null and b/wasm3-sys/wasm3/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/values-w820dp/dimens.xml b/wasm3-sys/wasm3/platforms/android/app/src/main/res/values-w820dp/dimens.xml new file mode 100644 index 0000000..63fc816 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ + + + 64dp + diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/colors.xml b/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..932a251 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #654ff0 + #4b3bb3 + #bfd9cc + diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/dimens.xml b/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..47c8224 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + 16dp + 16dp + diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/strings.xml b/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..8d2f0bf --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Wasm3 + diff --git a/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/styles.xml b/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..5885930 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/wasm3-sys/wasm3/platforms/android/build.gradle b/wasm3-sys/wasm3/platforms/android/build.gradle new file mode 100644 index 0000000..4dc1795 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/build.gradle @@ -0,0 +1,25 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:4.0.0' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/wasm3-sys/wasm3/platforms/android/gradle.properties b/wasm3-sys/wasm3/platforms/android/gradle.properties new file mode 100644 index 0000000..8c31d11 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/gradle.properties @@ -0,0 +1,21 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +android.enableJetifier=true +android.useAndroidX=true + diff --git a/wasm3-sys/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.jar b/wasm3-sys/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..490fda8 Binary files /dev/null and b/wasm3-sys/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/wasm3-sys/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.properties b/wasm3-sys/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..8cf6eb5 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/wasm3-sys/wasm3/platforms/android/gradlew b/wasm3-sys/wasm3/platforms/android/gradlew new file mode 100755 index 0000000..2fe81a7 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/wasm3-sys/wasm3/platforms/android/gradlew.bat b/wasm3-sys/wasm3/platforms/android/gradlew.bat new file mode 100644 index 0000000..9109989 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/gradlew.bat @@ -0,0 +1,103 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/wasm3-sys/wasm3/platforms/android/override.txt b/wasm3-sys/wasm3/platforms/android/override.txt new file mode 100644 index 0000000..670531e --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/override.txt @@ -0,0 +1,43 @@ + +/* + * Override printf, puts, putchar + */ + +JNIEnv* jniEnv; + +void callOutputText(const char* text) { + JNIEnv *env = jniEnv; + + jstring javaMsg = (*env)->NewStringUTF(env, text); + (*env)->CallVoidMethod(env, activityObj, outputTextId, javaMsg); + (*env)->DeleteLocalRef(env, javaMsg); +} + +int printf(const char * format, ... ) +{ + char buff[256] = {}; + + va_list args; + va_start (args, format); + const int result = vsnprintf(buff, sizeof(buff), format, args); + va_end (args); + + if (result > 0) { + callOutputText(buff); + } + return result; +} + +int puts(const char *s) +{ + callOutputText(s); + callOutputText("\n"); + return strlen(s); +} + +int putchar(int c) +{ + char buff[2] = { c, '\0' }; + callOutputText(buff); + return c; +} diff --git a/wasm3-sys/wasm3/platforms/android/settings.gradle b/wasm3-sys/wasm3/platforms/android/settings.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/wasm3-sys/wasm3/platforms/android/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/wasm3-sys/wasm3/platforms/app/README.md b/wasm3-sys/wasm3/platforms/app/README.md new file mode 100644 index 0000000..17587ba --- /dev/null +++ b/wasm3-sys/wasm3/platforms/app/README.md @@ -0,0 +1 @@ +This is the main file for Linux, Windows, Mac OS, OpenWRT builds diff --git a/wasm3-sys/wasm3/platforms/app/main.c b/wasm3-sys/wasm3/platforms/app/main.c new file mode 100644 index 0000000..84e77db --- /dev/null +++ b/wasm3-sys/wasm3/platforms/app/main.c @@ -0,0 +1,714 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include +#include + +#include "wasm3.h" +#include "m3_api_libc.h" + +#if defined(d_m3HasWASI) || defined(d_m3HasMetaWASI) || defined(d_m3HasUVWASI) +#include "m3_api_wasi.h" +#define LINK_WASI +#endif + +#if defined(d_m3HasTracer) +#include "m3_api_tracer.h" +#endif + +// TODO: remove +#include "m3_env.h" + +/* + * NOTE: Gas metering/limit only applies to pre-instrumented modules. + * You can generate a metered version from any wasm file automatically, using + * https://github.com/ewasm/wasm-metering + */ +#define GAS_LIMIT 500000000 +#define GAS_FACTOR 10000LL + +#define MAX_MODULES 16 + +#define FATAL(msg, ...) { fprintf(stderr, "Error: [Fatal] " msg "\n", ##__VA_ARGS__); goto _onfatal; } + + +static IM3Environment env; +static IM3Runtime runtime; + +static u8* wasm_bins[MAX_MODULES]; +static int wasm_bins_qty = 0; + +#if defined(GAS_LIMIT) + +static int64_t initial_gas = GAS_FACTOR * GAS_LIMIT; +static int64_t current_gas = GAS_FACTOR * GAS_LIMIT; +static bool is_gas_metered = false; + +m3ApiRawFunction(metering_usegas) +{ + m3ApiGetArg (int32_t, gas) + + current_gas -= gas; + + if (UNLIKELY(current_gas < 0)) { + m3ApiTrap("[trap] Out of gas"); + } + m3ApiSuccess(); +} + +#endif // GAS_LIMIT + + +M3Result link_all (IM3Module module) +{ + M3Result res; + res = m3_LinkSpecTest (module); + if (res) return res; + + res = m3_LinkLibC (module); + if (res) return res; + +#if defined(LINK_WASI) + res = m3_LinkWASI (module); + if (res) return res; +#endif + +#if defined(d_m3HasTracer) + res = m3_LinkTracer (module); + if (res) return res; +#endif + +#if defined(GAS_LIMIT) + res = m3_LinkRawFunction (module, "metering", "usegas", "v(i)", &metering_usegas); + if (!res) { + fprintf(stderr, "Warning: Gas is limited to %0.4f\n", (double)(current_gas) / GAS_FACTOR); + is_gas_metered = true; + } + if (res == m3Err_functionLookupFailed) { res = NULL; } +#endif + + return res; +} + +const char* modname_from_fn(const char* fn) +{ + const char* sep = "/\\:*?"; + char c; + while ((c = *sep++)) { + const char* off = strrchr(fn, c) + 1; + fn = (fn < off) ? off : fn; + } + return fn; +} + +M3Result repl_load (const char* fn) +{ + M3Result result = m3Err_none; + IM3Module module = NULL; + + u8* wasm = NULL; + u32 fsize = 0; + + FILE* f = fopen (fn, "rb"); + if (!f) { + return "cannot open file"; + } + fseek (f, 0, SEEK_END); + fsize = ftell(f); + fseek (f, 0, SEEK_SET); + + if (fsize < 8) { + result = "file is too small"; + goto on_error; + } else if (fsize > 64*1024*1024) { + result = "file is too big"; + goto on_error; + } + + wasm = (u8*) malloc(fsize); + if (!wasm) { + result = "cannot allocate memory for wasm binary"; + goto on_error; + } + + if (fread (wasm, 1, fsize, f) != fsize) { + result = "cannot read file"; + goto on_error; + } + fclose (f); + f = NULL; + + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) goto on_error; + + result = m3_LoadModule (runtime, module); + if (result) goto on_error; + + m3_SetModuleName(module, modname_from_fn(fn)); + + result = link_all (module); + if (result) goto on_error; + + if (wasm_bins_qty < MAX_MODULES) { + wasm_bins[wasm_bins_qty++] = wasm; + } + + return result; + +on_error: + m3_FreeModule(module); + if (wasm) free(wasm); + if (f) fclose(f); + + return result; +} + +M3Result repl_load_hex (u32 fsize) +{ + M3Result result = m3Err_none; + + if (fsize < 8) { + return "file is too small"; + } else if (fsize > 10*1024*1024) { + return "file too big"; + } + + u8* wasm = (u8*) malloc(fsize); + if (!wasm) { + return "cannot allocate memory for wasm binary"; + } + + { // Load hex data from stdin + u32 wasm_idx = 0; + char hex[3] = { 0, }; + int hex_idx = 0; + while (wasm_idx < fsize) { + int c = fgetc(stdin); + if (!isxdigit(c)) continue; // Skip non-hex chars + hex[hex_idx++] = c; + if (hex_idx == 2) { + int val = strtol(hex, NULL, 16); + wasm[wasm_idx++] = val; + hex_idx = 0; + } + } + if (!fgets(hex, 3, stdin)) // Consume a newline + return "cannot read EOL"; + } + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) return result; + + result = m3_LoadModule (runtime, module); + if (result) return result; + + result = link_all (module); + + return result; +} + +void print_gas_used() +{ +#if defined(GAS_LIMIT) + if (is_gas_metered) { + fprintf(stderr, "Gas used: %0.4f\n", (double)(initial_gas - current_gas) / GAS_FACTOR); + } +#endif +} + +void print_backtrace() +{ + IM3BacktraceInfo info = m3_GetBacktrace(runtime); + if (!info) { + return; + } + + fprintf(stderr, "==== wasm backtrace:"); + + int frameCount = 0; + IM3BacktraceFrame curr = info->frames; + while (curr) + { + fprintf(stderr, "\n %d: 0x%06x - %s!%s", + frameCount, curr->moduleOffset, + m3_GetModuleName (m3_GetFunctionModule(curr->function)), + m3_GetFunctionName (curr->function) + ); + curr = curr->next; + frameCount++; + } + if (info->lastFrame == M3_BACKTRACE_TRUNCATED) { + fprintf(stderr, "\n (truncated)"); + } + fprintf(stderr, "\n"); +} + +M3Result repl_call (const char* name, int argc, const char* argv[]) +{ + IM3Function func; + M3Result result = m3_FindFunction (&func, runtime, name); + if (result) return result; + + if (argc && (!strcmp(name, "main") || !strcmp(name, "_main"))) { + return "passing arguments to libc main() not implemented"; + } + + if (!strcmp(name, "_start")) { +#if defined(LINK_WASI) + // Strip wasm file path + if (argc > 0) { + argv[0] = modname_from_fn(argv[0]); + } + + m3_wasi_context_t* wasi_ctx = m3_GetWasiContext(); + wasi_ctx->argc = argc; + wasi_ctx->argv = argv; + + result = m3_CallArgv(func, 0, NULL); + + print_gas_used(); + + if (result == m3Err_trapExit) { + exit(wasi_ctx->exit_code); + } + + return result; +#else + return "WASI not linked"; +#endif + } + + int arg_count = m3_GetArgCount(func); + int ret_count = m3_GetRetCount(func); + if (argc < arg_count) { + return "not enough arguments"; + } else if (argc > arg_count) { + return "too many arguments"; + } + + result = m3_CallArgv (func, argc, argv); + + print_gas_used(); + + if (result) return result; + + static uint64_t valbuff[128]; + static const void* valptrs[128]; + memset(valbuff, 0, sizeof(valbuff)); + for (int i = 0; i < ret_count; i++) { + valptrs[i] = &valbuff[i]; + } + result = m3_GetResults (func, ret_count, valptrs); + if (result) return result; + + if (ret_count <= 0) { + fprintf (stderr, "Result: \n"); + } + for (int i = 0; i < ret_count; i++) { + switch (m3_GetRetType(func, i)) { + case c_m3Type_i32: fprintf (stderr, "Result: %" PRIi32 "\n", *(i32*)valptrs[i]); break; + case c_m3Type_i64: fprintf (stderr, "Result: %" PRIi64 "\n", *(i64*)valptrs[i]); break; +# if d_m3HasFloat + case c_m3Type_f32: fprintf (stderr, "Result: %" PRIf32 "\n", *(f32*)valptrs[i]); break; + case c_m3Type_f64: fprintf (stderr, "Result: %" PRIf64 "\n", *(f64*)valptrs[i]); break; +# endif + default: return "unknown return type"; + } + } + + return result; +} + +// :invoke is used by spec tests, so it treats floats as raw data +M3Result repl_invoke (const char* name, int argc, const char* argv[]) +{ + IM3Function func; + M3Result result = m3_FindFunction (&func, runtime, name); + if (result) return result; + + int arg_count = m3_GetArgCount(func); + int ret_count = m3_GetRetCount(func); + + if (argc > 128) { + return "arguments limit reached"; + } else if (argc < arg_count) { + return "not enough arguments"; + } else if (argc > arg_count) { + return "too many arguments"; + } + + static uint64_t valbuff[128]; + static const void* valptrs[128]; + memset(valbuff, 0, sizeof(valbuff)); + memset(valptrs, 0, sizeof(valptrs)); + + for (int i = 0; i < argc; i++) { + u64* s = &valbuff[i]; + valptrs[i] = s; + switch (m3_GetArgType(func, i)) { + case c_m3Type_i32: + case c_m3Type_f32: *(u32*)(s) = strtoul(argv[i], NULL, 10); break; + case c_m3Type_i64: + case c_m3Type_f64: *(u64*)(s) = strtoull(argv[i], NULL, 10); break; + default: return "unknown argument type"; + } + } + + result = m3_Call (func, argc, valptrs); + if (result) return result; + + // reuse valbuff for return values + memset(valbuff, 0, sizeof(valbuff)); + for (int i = 0; i < ret_count; i++) { + valptrs[i] = &valbuff[i]; + } + result = m3_GetResults (func, ret_count, valptrs); + if (result) return result; + + fprintf (stderr, "Result: "); + if (ret_count <= 0) { + fprintf (stderr, ""); + } + for (int i = 0; i < ret_count; i++) { + switch (m3_GetRetType(func, i)) { + case c_m3Type_i32: fprintf (stderr, "%" PRIu32 ":i32", *(u32*)valptrs[i]); break; + case c_m3Type_f32: fprintf (stderr, "%" PRIu32 ":f32", *(u32*)valptrs[i]); break; + case c_m3Type_i64: fprintf (stderr, "%" PRIu64 ":i64", *(u64*)valptrs[i]); break; + case c_m3Type_f64: fprintf (stderr, "%" PRIu64 ":f64", *(u64*)valptrs[i]); break; + default: return "unknown return type"; + } + if (i != ret_count-1) { + fprintf (stderr, ", "); + } + } + fprintf (stderr, "\n"); + + return result; +} + +M3Result repl_global_get (const char* name) +{ + IM3Global g = m3_FindGlobal(runtime->modules, name); + + M3TaggedValue tagged; + M3Result err = m3_GetGlobal (g, &tagged); + if (err) return err; + + switch (tagged.type) { + case c_m3Type_i32: fprintf (stderr, "%" PRIu32 ":i32\n", tagged.value.i32); break; + case c_m3Type_i64: fprintf (stderr, "%" PRIu64 ":i64\n", tagged.value.i64); break; + case c_m3Type_f32: fprintf (stderr, "%" PRIf32 ":f32\n", tagged.value.f32); break; + case c_m3Type_f64: fprintf (stderr, "%" PRIf64 ":f64\n", tagged.value.f64); break; + default: return m3Err_invalidTypeId; + } + return m3Err_none; +} + +M3Result repl_global_set (const char* name, const char* value) +{ + IM3Global g = m3_FindGlobal(runtime->modules, name); + + M3TaggedValue tagged = { + .type = m3_GetGlobalType(g) + }; + + switch (tagged.type) { + case c_m3Type_i32: tagged.value.i32 = strtoul(value, NULL, 10); break; + case c_m3Type_i64: tagged.value.i64 = strtoull(value, NULL, 10); break; + case c_m3Type_f32: tagged.value.f32 = strtod(value, NULL); break; + case c_m3Type_f64: tagged.value.f64 = strtod(value, NULL); break; + default: return m3Err_invalidTypeId; + } + + return m3_SetGlobal (g, &tagged); +} + +M3Result repl_compile () +{ + return m3_CompileModule(runtime->modules); +} + +M3Result repl_dump () +{ + uint32_t len; + uint8_t* mem = m3_GetMemory(runtime, &len, 0); + if (mem) { + FILE* f = fopen ("wasm3_dump.bin", "wb"); + if (!f) { + return "cannot open file"; + } + if (fwrite (mem, 1, len, f) != len) { + return "cannot write file"; + } + fclose (f); + } + return m3Err_none; +} + +void repl_free () +{ + if (runtime) { + m3_FreeRuntime (runtime); + runtime = NULL; + } + + for (int i = 0; i < wasm_bins_qty; i++) { + free (wasm_bins[i]); + wasm_bins[i] = NULL; + } +} + +M3Result repl_init (unsigned stack) +{ + repl_free(); + runtime = m3_NewRuntime (env, stack, NULL); + if (runtime == NULL) { + return "m3_NewRuntime failed"; + } + return m3Err_none; +} + +static +void unescape(char* buff) +{ + char* outp = buff; + while (*buff) { + if (*buff == '\\') { + switch (*(buff+1)) { + case '0': *outp++ = '\0'; break; + case 'b': *outp++ = '\b'; break; + case 'n': *outp++ = '\n'; break; + case 'r': *outp++ = '\r'; break; + case 't': *outp++ = '\t'; break; + case 'x': { + char hex[3] = { *(buff+2), *(buff+3), '\0' }; + *outp = strtol(hex, NULL, 16); + buff += 2; outp += 1; + break; + } + // Otherwise just pass the letter + // Also handles '\\' + default: *outp++ = *(buff+1); break; + } + buff += 2; + } else { + *outp++ = *buff++; + } + } + *outp = '\0'; +} + +static +int split_argv(char *str, char** argv) +{ + int result = 0; + char* curr = str; + int len = 0; + for (int i = 0; str[i] != '\0'; i++) { + if (strchr(" \n\r\t", str[i])) { + if (len) { // Found space after non-space + str[i] = '\0'; + //unescape(curr); // TODO: breaks windows build? + argv[result++] = curr; + len = 0; + } + } else { + if (!len) { // Found non-space after space + curr = &str[i]; + } + len++; + } + } + argv[result] = NULL; + return result; +} + +void print_version() { + const char* wasm3_env = getenv("WASM3"); + const char* wasm3_arch = getenv("WASM3_ARCH"); + + printf("Wasm3 v" M3_VERSION "%s on %s\n", + (wasm3_arch || wasm3_env) ? " self-hosting" : "", + wasm3_arch ? wasm3_arch : M3_ARCH); + + printf("Build: " __DATE__ " " __TIME__ ", " M3_COMPILER_VER "\n"); +} + +void print_usage() { + puts("Usage:"); + puts(" wasm3 [options] [args...]"); + puts(" wasm3 --repl [file]"); + puts("Options:"); + puts(" --func function to run default: _start"); + puts(" --stack-size stack size in bytes default: 64KB"); + puts(" --dump-on-trap dump wasm memory"); +} + +#define ARGV_SHIFT() { i_argc--; i_argv++; } +#define ARGV_SET(x) { if (i_argc > 0) { x = i_argv[0]; ARGV_SHIFT(); } } + +int main (int i_argc, const char* i_argv[]) +{ + M3Result result = m3Err_none; + env = m3_NewEnvironment (); + runtime = NULL; + + bool argRepl = false; + bool argDumpOnTrap = false; + const char* argFile = NULL; + const char* argFunc = "_start"; + unsigned argStackSize = 64*1024; + +// m3_PrintM3Info (); + + ARGV_SHIFT(); // Skip executable name + + while (i_argc > 0) + { + const char* arg = i_argv[0]; + if (arg[0] != '-') break; + + ARGV_SHIFT(); + if (!strcmp("--help", arg) or !strcmp("-h", arg)) { + print_usage(); + return 0; + } else if (!strcmp("--version", arg)) { + print_version(); + return 0; + } else if (!strcmp("--repl", arg)) { + argRepl = true; + } else if (!strcmp("--dump-on-trap", arg)) { + argDumpOnTrap = true; + } else if (!strcmp("--stack-size", arg)) { + const char* tmp = "65536"; + ARGV_SET(tmp); + argStackSize = atol(tmp); + } else if (!strcmp("--gas-limit", arg)) { + const char* tmp = "0"; + ARGV_SET(tmp); + initial_gas = current_gas = GAS_FACTOR * atol(tmp); + } else if (!strcmp("--dir", arg)) { + const char* argDir; + ARGV_SET(argDir); + (void)argDir; + } else if (!strcmp("--func", arg) or !strcmp("-f", arg)) { + ARGV_SET(argFunc); + } + } + + if ((argRepl and (i_argc > 1)) or // repl supports 0 or 1 args + (not argRepl and (i_argc < 1)) // normal expects at least 1 + ) { + print_usage(); + return 1; + } + + ARGV_SET(argFile); + + result = repl_init(argStackSize); + if (result) FATAL("repl_init: %s", result); + + if (argFile) { + result = repl_load(argFile); + if (result) FATAL("repl_load: %s", result); + + if (argFunc and not argRepl) { + if (!strcmp(argFunc, "_start")) { + // When passing args to WASI, include wasm filename as argv[0] + result = repl_call(argFunc, i_argc+1, i_argv-1); + } else { + result = repl_call(argFunc, i_argc, i_argv); + } + + if (result) { + if (argDumpOnTrap) { + repl_dump(); + } + print_backtrace(); + goto _onfatal; + } + } + } + + while (argRepl) + { + char cmd_buff[2048] = { 0, }; + char* argv[32] = { 0, }; + fprintf(stdout, "wasm3> "); + fflush(stdout); + if (!fgets(cmd_buff, sizeof(cmd_buff), stdin)) { + return 0; + } + int argc = split_argv(cmd_buff, argv); + if (argc <= 0) { + continue; + } + result = m3Err_none; + if (!strcmp(":init", argv[0])) { + result = repl_init(argStackSize); + } else if (!strcmp(":version", argv[0])) { + print_version(); + } else if (!strcmp(":exit", argv[0])) { + repl_free(); + return 0; + } else if (!strcmp(":load", argv[0])) { // :load + result = repl_load(argv[1]); + } else if (!strcmp(":load-hex", argv[0])) { // :load-hex \n + result = repl_load_hex(atol(argv[1])); + } else if (!strcmp(":get-global", argv[0])) { + result = repl_global_get(argv[1]); + } else if (!strcmp(":set-global", argv[0])) { + result = repl_global_set(argv[1], argv[2]); + } else if (!strcmp(":dump", argv[0])) { + result = repl_dump(); + } else if (!strcmp(":compile", argv[0])) { + result = repl_compile(); + } else if (!strcmp(":invoke", argv[0])) { + unescape(argv[1]); + result = repl_invoke(argv[1], argc-2, (const char**)(argv+2)); + } else if (argv[0][0] == ':') { + result = "no such command"; + } else { + unescape(argv[0]); + result = repl_call(argv[0], argc-1, (const char**)(argv+1)); + if (result) { + print_backtrace(); + } + } + + if (result == m3Err_trapExit) { + //TODO: fprintf(stderr, M3_ARCH "-wasi: exit(%d)\n", runtime->exit_code); + } else if (result) { + fprintf (stderr, "Error: %s", result); + M3ErrorInfo info; + m3_GetErrorInfo (runtime, &info); + fprintf (stderr, " (%s)\n", info.message); + } + } + +_onfatal: + if (result) { + fprintf (stderr, "Error: %s", result); + if (runtime) + { + M3ErrorInfo info; + m3_GetErrorInfo (runtime, &info); + if (strlen(info.message)) { + fprintf (stderr, " (%s)", info.message); + } + } + fprintf (stderr, "\n"); + } + + m3_FreeRuntime (runtime); + m3_FreeEnvironment (env); + + return result ? 1 : 0; +} diff --git a/wasm3-sys/wasm3/platforms/app_fuzz/fuzzer.c b/wasm3-sys/wasm3/platforms/app_fuzz/fuzzer.c new file mode 100644 index 0000000..b97d649 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/app_fuzz/fuzzer.c @@ -0,0 +1,49 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include + +#include "wasm3.h" + +#define FATAL(...) __builtin_trap() + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + M3Result result = m3Err_none; + + if (size < 8 || size > 256*1024) { + return 0; + } + + IM3Environment env = m3_NewEnvironment (); + if (env) { + IM3Runtime runtime = m3_NewRuntime (env, 128, NULL); + if (runtime) { + IM3Module module = NULL; + result = m3_ParseModule (env, &module, data, size); + if (module) { + result = m3_LoadModule (runtime, module); + if (result == 0) { + IM3Function f = NULL; + result = m3_FindFunction (&f, runtime, "fib"); + /* TODO: + if (f) { + m3_CallV (f, 10); + }*/ + } else { + m3_FreeModule (module); + } + } + + m3_FreeRuntime(runtime); + } + m3_FreeEnvironment(env); + } + + return 0; +} diff --git a/wasm3-sys/wasm3/platforms/cosmopolitan/.gitignore b/wasm3-sys/wasm3/platforms/cosmopolitan/.gitignore new file mode 100644 index 0000000..8352c97 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/cosmopolitan/.gitignore @@ -0,0 +1,4 @@ +cosmopolitan/ +wasm3.com +wasm3.com.dbg + diff --git a/wasm3-sys/wasm3/platforms/cosmopolitan/build.sh b/wasm3-sys/wasm3/platforms/cosmopolitan/build.sh new file mode 100755 index 0000000..b84f995 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/cosmopolitan/build.sh @@ -0,0 +1,41 @@ + +COSMOPOLITAN_VERSION=1.0 +COSMOPOLITAN_URL=https://github.com/jart/cosmopolitan/releases/download/$COSMOPOLITAN_VERSION/cosmopolitan-amalgamation-$COSMOPOLITAN_VERSION.zip + +SOURCE_DIR=../../source + +EXTRA_FLAGS="-Dd_m3PreferStaticAlloc -Dd_m3HasWASI" + +STD=./cosmopolitan/std + +if [ ! -d "./cosmopolitan" ]; then + echo "Downloading Cosmopolitan..." + curl -L -o cosmopolitan.zip $COSMOPOLITAN_URL + unzip cosmopolitan.zip -d cosmopolitan + rm cosmopolitan.zip +fi + +if [ ! -d "$STD/sys" ]; then + # Generate header stubs + mkdir -p $STD/sys + touch $STD/assert.h $STD/limits.h $STD/ctype.h $STD/time.h $STD/errno.h \ + $STD/inttypes.h $STD/fcntl.h $STD/math.h $STD/stdarg.h $STD/stdbool.h \ + $STD/stdint.h $STD/stdio.h $STD/stdlib.h $STD/string.h $STD/stddef.h \ + $STD/sys/types.h $STD/sys/stat.h $STD/unistd.h $STD/sys/uio.h \ + $STD/sys/random.h +fi + +echo "Building Wasm3..." + +# TODO: remove -fno-strict-aliasing + +gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \ + -Wl,--gc-sections -Wl,-z,max-page-size=0x1000 -fuse-ld=bfd \ + -Wl,-T,cosmopolitan/ape.lds -include cosmopolitan/cosmopolitan.h \ + -Wno-format-security -Wfatal-errors -fno-strict-aliasing $EXTRA_FLAGS \ + -fomit-frame-pointer -fno-stack-check -fno-stack-protector \ + -o wasm3.com.dbg -DAPE -I$STD -I$SOURCE_DIR $SOURCE_DIR/*.c ../app/main.c \ + cosmopolitan/crt.o cosmopolitan/ape.o cosmopolitan/cosmopolitan.a + +objcopy -SO binary wasm3.com.dbg wasm3.com + diff --git a/wasm3-sys/wasm3/platforms/cpp/.gitignore b/wasm3-sys/wasm3/platforms/cpp/.gitignore new file mode 100644 index 0000000..6be3b8f --- /dev/null +++ b/wasm3-sys/wasm3/platforms/cpp/.gitignore @@ -0,0 +1,2 @@ +build +cmake-build-debug diff --git a/wasm3-sys/wasm3/platforms/cpp/CMakeLists.txt b/wasm3-sys/wasm3/platforms/cpp/CMakeLists.txt new file mode 100644 index 0000000..1230a33 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/cpp/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.9) +project(wasm3_cpp_example) + +set(target ${CMAKE_PROJECT_NAME}) + +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../../source ${CMAKE_BINARY_DIR}/m3) + +add_executable(${target} main.cpp) +target_link_libraries(${target} PRIVATE m3) + +add_subdirectory(wasm3_cpp) +target_link_libraries(${target} PRIVATE wasm3_cpp) + +target_compile_options(${target} PUBLIC -g) +target_compile_options(m3 PUBLIC -g) + +# Copy the 'wasm' directory into the build directory, so that +# wasm/test_prog.wasm is found even if wasm3_cpp_example is executed +# from the build directory. +add_custom_target(copy_wasm ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/wasm + ${CMAKE_BINARY_DIR}/wasm +) +add_dependencies(${CMAKE_PROJECT_NAME} copy_wasm) diff --git a/wasm3-sys/wasm3/platforms/cpp/README.md b/wasm3-sys/wasm3/platforms/cpp/README.md new file mode 100644 index 0000000..3ab4ecc --- /dev/null +++ b/wasm3-sys/wasm3/platforms/cpp/README.md @@ -0,0 +1,77 @@ +## C++ wrapper + +This example shows how to embed WASM3 into a C++ application. It uses a header-only library, `wasm3_cpp.h`, provided in `wasm3_cpp` subdirectory. Like WASM3 itself, this library can be included into CMake projects using `add_subdirectory` function. + +The main code of the example in `main.cpp` initializes WASM3, loads a WebAssembly module, links two external functions to the module, and executes two functions defined in WebAssembly. + +The WebAssembly module source code is inside `wasm` subdirectory. + +### `wasm3_cpp.h` reference + +All the classes are located in `wasm3` namespace. + +#### Class `environment` + +`environment::environment()` — create a new WASM3 environment. Runtimes, modules are owned by an environment. + +`runtime environment::new_runtime(size_t stack_size_bytes)` — create new runtime inside the environment. + +`module environment::parse_module(std::istream &in)` or `module environment::parse_module(const uint8_t *data, size_t size)` — parse a WASM binary module. + +#### Class `runtime` + +`runtime` objects are created using `environment::new_runtime` method, see above. + +`void runtime::load(module &m)` — load a parsed module into the runtime. + +`function runtime::find_function(const char *name)` — find a function defined in one of the loaded modules, by name. Raises a `wasm3::error` exception if the function is not found. + +#### Class `module` + +`module` objects are created by `environment::parse_module`. Parsed modules can be loaded into a `runtime` object. One module can only be loaded into one runtime. + +Before loading a module, you may need to link some external functions to it: + +`template void module::link(const char *mod, Func *function, const char *function_name)` — link a function `function` to module named `mod` under the name `function_name`. To link to any module, use `mod="*"`. + +`function` has to be either a non-member function or a static member function. + +Currently, the following types of arguments can be passed to functions linked this way: + +* int32_t +* int64_t +* float +* double +* const/non-const pointers + +Automatic conversion of other integral types may be implemented in the future. + +If the module doesn't reference an imported function named `func`, an exception is thrown. To link a function "optionally", i.e. without throwing an exception if the function is not imported, use `module::link_optional` instead. + +#### Class `function` + +`function` object can be obtained from a `runtime`, looking up the function by name. Function objects are used to call WebAssembly functions. + +`template Ret function::call()` — call a WebAssembly function which doesn't take any arguments. The return value of the function is automatically converted to the type `Ret`. Note that you need to specify the return type when using this template function, and the type has to match the type returned by the WebAssembly function. + +`template Ret function::call(Args...)` — same as above, but also allows passing arguments to the WebAssembly function. + +`template Ret function::call_argv(Args...)` — same as above, except that this function takes arguments as C strings (`const char*`). + +### Building and running + +This directory is a CMake project, and can be built as follows: + +```bash +mkdir build +cd build +cmake .. +cmake --build . +``` + +Then run the example: + +```bash +./wasm3_cpp_example +``` + diff --git a/wasm3-sys/wasm3/platforms/cpp/main.cpp b/wasm3-sys/wasm3/platforms/cpp/main.cpp new file mode 100644 index 0000000..25f8ba8 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/cpp/main.cpp @@ -0,0 +1,66 @@ +#include +#include +#include + +#include "wasm3_cpp.h" +#include "wasm/test_prog.wasm.h" + +int sum(int a, int b) +{ + return a + b; +} + +void * ext_memcpy (void* dst, const void* arg, int32_t size) +{ + return memcpy(dst, arg, (size_t) size); +} + +int main(void) +{ + std::cout << "Loading WebAssembly..." << std::endl; + + /* Wasm module can be loaded from a file */ + try { + wasm3::environment env; + wasm3::runtime runtime = env.new_runtime(1024); + const char* file_name = "wasm/test_prog.wasm"; + std::ifstream wasm_file(file_name, std::ios::binary | std::ios::in); + if (!wasm_file.is_open()) { + throw std::runtime_error("Failed to open wasm file"); + } + wasm3::module mod = env.parse_module(wasm_file); + runtime.load(mod); + } + catch(std::runtime_error &e) { + std::cerr << "WASM3 error: " << e.what() << std::endl; + return 1; + } + + /* Wasm module can also be loaded from an array */ + try { + wasm3::environment env; + wasm3::runtime runtime = env.new_runtime(1024); + wasm3::module mod = env.parse_module(test_prog_wasm, test_prog_wasm_len); + runtime.load(mod); + + mod.link("*", "sum", sum); + mod.link("*", "ext_memcpy", ext_memcpy); + + { + wasm3::function test_fn = runtime.find_function("test"); + auto res = test_fn.call(20, 10); + std::cout << "result: " << res << std::endl; + } + { + wasm3::function memcpy_test_fn = runtime.find_function("test_memcpy"); + auto res = memcpy_test_fn.call(); + std::cout << "result: 0x" << std::hex << res << std::dec << std::endl; + } + } + catch(wasm3::error &e) { + std::cerr << "WASM3 error: " << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/wasm3-sys/wasm3/platforms/cpp/wasm/Makefile b/wasm3-sys/wasm3/platforms/cpp/wasm/Makefile new file mode 100644 index 0000000..acdf6e1 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/cpp/wasm/Makefile @@ -0,0 +1,18 @@ +NAME=test_prog +SRC=$(NAME).c +WASM=$(NAME).wasm +HEADER=$(NAME).wasm.h +EMCC_FLAGS=-s STANDALONE_WASM -s ERROR_ON_UNDEFINED_SYMBOLS=0 -O3 + +all: $(HEADER) + +clean: + rm -f $(HEADER) $(WASM) + +.PHONY: all clean + +$(WASM): $(SRC) + emcc $< -o $@ $(EMCC_FLAGS) + +$(HEADER): $(WASM) + xxd -i $< >$@ diff --git a/wasm3-sys/wasm3/platforms/cpp/wasm/test_prog.c b/wasm3-sys/wasm3/platforms/cpp/wasm/test_prog.c new file mode 100644 index 0000000..a2250c8 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/cpp/wasm/test_prog.c @@ -0,0 +1,24 @@ +#include +#include + +extern int sum(int, int); +extern int ext_memcpy(void*, const void*, size_t); + +#define WASM_EXPORT __attribute__((used)) __attribute__((visibility ("default"))) + +int WASM_EXPORT test(int32_t arg1, int32_t arg2) +{ + int x = arg1 + arg2; + int y = arg1 - arg2; + return sum(x, y) / 2; +} + +int64_t WASM_EXPORT test_memcpy(void) +{ + int64_t x = 0; + int32_t low = 0x01234567; + int32_t high = 0x89abcdef; + ext_memcpy(&x, &low, 4); + ext_memcpy(((uint8_t*)&x) + 4, &high, 4); + return x; +} diff --git a/wasm3-sys/wasm3/platforms/cpp/wasm/test_prog.wasm b/wasm3-sys/wasm3/platforms/cpp/wasm/test_prog.wasm new file mode 100644 index 0000000..eeb49b0 Binary files /dev/null and b/wasm3-sys/wasm3/platforms/cpp/wasm/test_prog.wasm differ diff --git a/wasm3-sys/wasm3/platforms/cpp/wasm/test_prog.wasm.h b/wasm3-sys/wasm3/platforms/cpp/wasm/test_prog.wasm.h new file mode 100644 index 0000000..cfc8003 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/cpp/wasm/test_prog.wasm.h @@ -0,0 +1,25 @@ +unsigned char test_prog_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x15, 0x04, 0x60, + 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x00, 0x60, 0x03, 0x7f, 0x7f, + 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x7e, 0x02, 0x1c, 0x02, 0x03, 0x65, + 0x6e, 0x76, 0x0a, 0x65, 0x78, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x63, 0x70, + 0x79, 0x00, 0x02, 0x03, 0x65, 0x6e, 0x76, 0x03, 0x73, 0x75, 0x6d, 0x00, + 0x00, 0x03, 0x04, 0x03, 0x01, 0x03, 0x00, 0x05, 0x06, 0x01, 0x01, 0x80, + 0x02, 0x80, 0x02, 0x06, 0x09, 0x01, 0x7f, 0x01, 0x41, 0x80, 0x8c, 0xc0, + 0x02, 0x0b, 0x07, 0x28, 0x04, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, + 0x02, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x00, 0x04, 0x0b, 0x74, 0x65, + 0x73, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x63, 0x70, 0x79, 0x00, 0x03, 0x06, + 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x02, 0x0a, 0x71, 0x03, 0x03, + 0x00, 0x01, 0x0b, 0x59, 0x02, 0x01, 0x7f, 0x01, 0x7e, 0x23, 0x00, 0x41, + 0x10, 0x6b, 0x22, 0x00, 0x24, 0x00, 0x20, 0x00, 0x42, 0x00, 0x37, 0x03, + 0x08, 0x20, 0x00, 0x41, 0xe7, 0x8a, 0x8d, 0x09, 0x36, 0x02, 0x04, 0x20, + 0x00, 0x41, 0xef, 0x9b, 0xaf, 0xcd, 0x78, 0x36, 0x02, 0x00, 0x20, 0x00, + 0x41, 0x08, 0x6a, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x41, 0x04, 0x10, 0x00, + 0x1a, 0x20, 0x00, 0x41, 0x08, 0x6a, 0x41, 0x04, 0x72, 0x20, 0x00, 0x41, + 0x04, 0x10, 0x00, 0x1a, 0x20, 0x00, 0x29, 0x03, 0x08, 0x21, 0x01, 0x20, + 0x00, 0x41, 0x10, 0x6a, 0x24, 0x00, 0x20, 0x01, 0x0b, 0x11, 0x00, 0x20, + 0x00, 0x20, 0x01, 0x6a, 0x20, 0x00, 0x20, 0x01, 0x6b, 0x10, 0x01, 0x41, + 0x02, 0x6d, 0x0b, 0x0b, 0x0a, 0x01, 0x00, 0x41, 0x80, 0x0c, 0x0b, 0x03, + 0xa0, 0x06, 0x50 +}; +unsigned int test_prog_wasm_len = 255; diff --git a/wasm3-sys/wasm3/platforms/cpp/wasm3_cpp/CMakeLists.txt b/wasm3-sys/wasm3/platforms/cpp/wasm3_cpp/CMakeLists.txt new file mode 100644 index 0000000..1cd3216 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/cpp/wasm3_cpp/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.5) +add_library(wasm3_cpp INTERFACE) +target_include_directories(wasm3_cpp INTERFACE include) +target_compile_features(wasm3_cpp INTERFACE cxx_std_17) diff --git a/wasm3-sys/wasm3/platforms/cpp/wasm3_cpp/include/wasm3_cpp.h b/wasm3-sys/wasm3/platforms/cpp/wasm3_cpp/include/wasm3_cpp.h new file mode 100644 index 0000000..4f00505 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/cpp/wasm3_cpp/include/wasm3_cpp.h @@ -0,0 +1,398 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wasm3.h" + + +namespace wasm3 { + /** @cond */ + namespace detail { + typedef uint64_t *stack_type; + typedef void *mem_type; + template struct first_type { typedef T type; }; + + typedef const void *(*m3_api_raw_fn)(IM3Runtime, uint64_t *, void *); + + template + void arg_from_stack(T &dest, stack_type &_sp, mem_type mem) { + m3ApiGetArg(T, tmp); + dest = tmp; + } + + template + void arg_from_stack(T* &dest, stack_type &_sp, mem_type _mem) { + m3ApiGetArgMem(T*, tmp); + dest = tmp; + }; + + template + void arg_from_stack(const T* &dest, stack_type &_sp, mem_type _mem) { + m3ApiGetArgMem(const T*, tmp); + dest = tmp; + }; + + template + struct m3_sig { + static const char value = c; + }; + template struct m3_type_to_sig; + template<> struct m3_type_to_sig : m3_sig<'i'> {}; + template<> struct m3_type_to_sig : m3_sig<'I'> {}; + template<> struct m3_type_to_sig : m3_sig<'f'> {}; + template<> struct m3_type_to_sig : m3_sig<'F'> {}; + template<> struct m3_type_to_sig : m3_sig<'v'> {}; + template<> struct m3_type_to_sig : m3_sig<'*'> {}; + template<> struct m3_type_to_sig : m3_sig<'*'> {}; + + + template + struct m3_signature { + constexpr static size_t n_args = sizeof...(Args); + constexpr static const char value[n_args + 4] = { + m3_type_to_sig::value, + '(', + m3_type_to_sig::value..., + ')', + 0 + }; + }; + + template + static void get_args_from_stack(stack_type &sp, mem_type mem, std::tuple &tuple) { + std::apply([&](auto &... item) { + (arg_from_stack(item, sp, mem), ...); + }, tuple); + } + + template + struct wrap_helper; + + template + struct wrap_helper { + using Func = Ret(Args...); + static const void *wrap_fn(IM3Runtime rt, IM3ImportContext _ctx, stack_type _sp, mem_type mem) { + std::tuple args; + // The order here matters: m3ApiReturnType should go before calling get_args_from_stack, + // since both modify `_sp`, and the return value on the stack is reserved before the arguments. + m3ApiReturnType(Ret); + get_args_from_stack(_sp, mem, args); + Func* function = reinterpret_cast(_ctx->userdata); + Ret r = std::apply(function, args); + m3ApiReturn(r); + } + }; + + template + struct wrap_helper { + using Func = void(Args...); + static const void *wrap_fn(IM3Runtime rt, IM3ImportContext _ctx, stack_type sp, mem_type mem) { + std::tuple args; + get_args_from_stack(sp, mem, args); + Func* function = reinterpret_cast(_ctx->userdata); + std::apply(function, args); + m3ApiSuccess(); + } + }; + + template + class m3_wrapper; + + template + class m3_wrapper { + public: + static M3Result link(IM3Module io_module, + const char *const i_moduleName, + const char *const i_functionName, + Ret (*function)(Args...)) { + + return m3_LinkRawFunctionEx(io_module, i_moduleName, i_functionName, + m3_signature::value, + &wrap_helper::wrap_fn, + reinterpret_cast(function)); + } + }; + } // namespace detail + /** @endcond */ + + class module; + class runtime; + class function; + + /** + * Exception thrown for wasm3 errors. + * + * Use error:what() to get the reason as a string. + */ + class error : public std::runtime_error { + public: + explicit error(M3Result err) : std::runtime_error(err) {} + }; + + /** @cond */ + namespace detail { + void check_error(M3Result err) { + if (err != m3Err_none) { + throw error(err); + } + } + } // namespace detail + /** @endcond */ + + + /** + * Wrapper for WASM3 environment. + * + * Runtimes, modules are owned by an environment. + */ + class environment { + public: + environment() { + m_env.reset(m3_NewEnvironment(), m3_FreeEnvironment); + if (m_env == nullptr) { + throw std::bad_alloc(); + } + } + + /** + * Create new runtime + * + * @param stack_size_bytes size of the WASM stack for this runtime + * @return runtime object + */ + runtime new_runtime(size_t stack_size_bytes); + + /** + * Parse a WASM module from file + * + * The parsed module is not loaded into any runtime. Use runtime::load to + * load the module after parsing it. + * + * @param in file (WASM binary) + * @return module object + */ + module parse_module(std::istream &in); + + /** + * Parse a WASM module from binary data + * + * @param data pointer to the start of the binary + * @param size size of the binary + * @return module object + */ + module parse_module(const uint8_t *data, size_t size); + + protected: + std::shared_ptr m_env; + }; + + /** + * Wrapper for the runtime, where modules are loaded and executed. + */ + class runtime { + public: + /** + * Load the module into runtime + * @param mod module parsed by environment::parse_module + */ + void load(module &mod); + + /** + * Get a function handle by name + * + * If the function is not found, throws an exception. + * @param name name of a function, c-string + * @return function object + */ + function find_function(const char *name); + + protected: + friend class environment; + + runtime(const std::shared_ptr &env, size_t stack_size_bytes) + : m_env(env) { + m_runtime.reset(m3_NewRuntime(env.get(), stack_size_bytes, nullptr), &m3_FreeRuntime); + if (m_runtime == nullptr) { + throw std::bad_alloc(); + } + } + + /* runtime extends the lifetime of the environment */ + std::shared_ptr m_env; + std::shared_ptr m_runtime; + }; + + /** + * Module object holds a webassembly module + * + * It can be constructed by parsing a WASM binary using environment::parse_module. + * Functions can be linked to the loaded module. + * Once constructed, modules can be loaded into the runtime. + */ + class module { + public: + /** + * Link an external function. + * + * Throws an exception if the module doesn't reference a function with the given name. + * + * @tparam Func Function type (signature) + * @param module Name of the module to link the function to, or "*" to link to any module + * @param function_name Name of the function (as referenced by the module) + * @param function Function to link (a function pointer) + */ + template + void link(const char *module, const char *function_name, Func *function); + + /** + * Same as module::link, but doesn't throw an exception if the function is not referenced. + */ + template + void link_optional(const char *module, const char *function_name, Func *function); + + + protected: + friend class environment; + friend class runtime; + + module(const std::shared_ptr &env, std::istream &in_wasm) { + in_wasm.unsetf(std::ios::skipws); + std::vector in_bytes; + std::copy(std::istream_iterator(in_wasm), + std::istream_iterator(), + std::back_inserter(in_bytes)); + parse(env.get(), in_bytes.data(), in_bytes.size()); + } + + module(const std::shared_ptr &env, const uint8_t *data, size_t size) : m_env(env) { + parse(env.get(), data, size); + } + + void parse(IM3Environment env, const uint8_t *data, size_t size) { + IM3Module p; + M3Result err = m3_ParseModule(env, &p, data, size); + detail::check_error(err); + m_module.reset(p, [this](IM3Module module) { + if (!m_loaded) { + m3_FreeModule(module); + } + }); + } + + void load_into(IM3Runtime runtime) { + M3Result err = m3_LoadModule(runtime, m_module.get()); + detail::check_error(err); + m_loaded = true; + } + + std::shared_ptr m_env; + std::shared_ptr m_module; + bool m_loaded = false; + }; + + + /** + * Handle of a function. Can be obtained from runtime::find_function method by name. + */ + class function { + public: + /** + * Call the function with the provided arguments, expressed as strings. + * + * Arguments are passed as strings. WASM3 automatically converts them into the types expected + * by the function being called. + * + * Note that the type of the return value must be explicitly specified as a template argument. + * + * @return the return value of the function. + */ + template + typename detail::first_type::value>::type...>::type + call_argv(Args... args) { + /* std::enable_if above checks that all argument types are convertible const char* */ + const char* argv[] = {args...}; + M3Result res = m3_CallArgv(m_func, sizeof...(args), argv); + detail::check_error(res); + Ret ret; + res = m3_GetResults(m_func, 1, &ret); + detail::check_error(res); + return ret; + } + + /** + * Call the function with the provided arguments (int/float types). + * + * Note that the type of the return value must be explicitly specified as a template argument. + * + * @return the return value of the function. + */ + template + Ret call(Args... args) { + const void *arg_ptrs[] = { reinterpret_cast(&args)... }; + M3Result res = m3_Call(m_func, sizeof...(args), arg_ptrs); + detail::check_error(res); + Ret ret; + const void* ret_ptrs[] = { &ret }; + res = m3_GetResults(m_func, 1, ret_ptrs); + detail::check_error(res); + return ret; + } + + protected: + friend class runtime; + + function(const std::shared_ptr &runtime, const char *name) : m_runtime(runtime) { + M3Result err = m3_FindFunction(&m_func, runtime.get(), name); + detail::check_error(err); + assert(m_func != nullptr); + } + + std::shared_ptr m_runtime; + M3Function *m_func = nullptr; + }; + + runtime environment::new_runtime(size_t stack_size_bytes) { + return runtime(m_env, stack_size_bytes); + } + + module environment::parse_module(std::istream &in) { + return module(m_env, in); + } + + module environment::parse_module(const uint8_t *data, size_t size) { + return module(m_env, data, size); + } + + void runtime::load(module &mod) { + mod.load_into(m_runtime.get()); + } + + function runtime::find_function(const char *name) { + return function(m_runtime, name); + } + + template + void module::link(const char *module, const char *function_name, Func *function) { + M3Result ret = detail::m3_wrapper::link(m_module.get(), module, function_name, function); + detail::check_error(ret); + } + + template + void module::link_optional(const char *module, const char *function_name, Func *function) { + M3Result ret = detail::m3_wrapper::link(m_module.get(), module, function_name, function); + if (ret == m3Err_functionLookupFailed) { + return; + } + detail::check_error(ret); + } + +} // namespace wasm3 diff --git a/wasm3-sys/wasm3/platforms/embedded/arduino/.gitignore b/wasm3-sys/wasm3/platforms/embedded/arduino/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/arduino/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/wasm3-sys/wasm3/platforms/embedded/arduino/lib/wasm3 b/wasm3-sys/wasm3/platforms/embedded/arduino/lib/wasm3 new file mode 120000 index 0000000..17056a9 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/arduino/lib/wasm3 @@ -0,0 +1 @@ +../../../../source \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/arduino/platformio.ini b/wasm3-sys/wasm3/platforms/embedded/arduino/platformio.ini new file mode 100644 index 0000000..dceda85 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/arduino/platformio.ini @@ -0,0 +1,137 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +default_envs = + mkr1000 + due + mega1284 + tinyBLE + blenano + blenano2 + teensy31 + bluepill-mapple + bluepill + az3166 + maix + #titiva TODO: undefined reference to `_exit' + +[env] +framework = arduino +monitor_speed = 115200 + +src_filter = + +<*> + - + +[env:mkr1000] +platform = atmelsam +board = mkr1000USB + +src_build_flags = + -O3 -Wfatal-errors + -flto + #-fPIC -fomit-frame-pointer -foptimize-sibling-calls + +[env:due] +platform = atmelsam +board = due + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:mega1284] +platform = atmelavr +board = wildfirev3 + +src_build_flags = + -Dd_m3CodePageAlignSize=512 + -Os -Wfatal-errors + -flto + +[env:tinyBLE] +platform = nordicnrf51 +board = seeedTinyBLE + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:blenano] +platform = nordicnrf51 +board = redBearLabBLENano + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:blenano2] +platform = nordicnrf52 +board = redbear_blenano2 + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:teensy31] +platform = teensy +board = teensy31 +upload_protocol = teensy-cli + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:bluepill-mapple] +platform = ststm32 +board = bluepill_f103c8_128k +board_build.core = maple +upload_protocol = stlink +#upload_protocol = dfu + +src_build_flags = + -Dd_m3FixedHeap=8192 + -Os -Wfatal-errors + -flto + +[env:bluepill] +platform = ststm32 +board = bluepill_f103c8 +upload_protocol = stlink + +src_build_flags = + -Dd_m3FixedHeap=8192 + -Os -Wfatal-errors + -flto + +[env:az3166] +platform = ststm32 +board = mxchip_az3166 + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:maix] +platform = kendryte210 +board = sipeed-maix-one-dock + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:titiva] +platform = titiva +board = lptm4c1294ncpdt + +src_build_flags = + -DLED_BUILTIN=13 + -O3 -Wfatal-errors diff --git a/wasm3-sys/wasm3/platforms/embedded/arduino/src/main.cpp b/wasm3-sys/wasm3/platforms/embedded/arduino/src/main.cpp new file mode 100644 index 0000000..f14d4f6 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/arduino/src/main.cpp @@ -0,0 +1,82 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "Arduino.h" + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(func, msg) { \ + Serial.print("Fatal: " func ": "); \ + Serial.println(msg); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + size_t fsize = fib32_wasm_len; + + Serial.println("Loading WebAssembly..."); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment", "failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime", "failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction", result); + + Serial.println("Running..."); + + result = m3_CallV(f, 24); + if (result) FATAL("m3_Call", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + Serial.print("Result: "); + Serial.println(value); +} + +void setup() +{ + pinMode(LED_BUILTIN, OUTPUT); + + Serial.begin(115200); + delay(10); + while (!Serial) {} + + Serial.println(); + Serial.println("Wasm3 v" M3_VERSION " on Arduino (" M3_ARCH "), build " __DATE__ " " __TIME__); + + digitalWrite(LED_BUILTIN, HIGH); + uint32_t start = millis(); + run_wasm(); + uint32_t end = millis(); + digitalWrite(LED_BUILTIN, LOW); + + Serial.print("Elapsed: "); + Serial.print(end - start); + Serial.println(" ms"); +} + +void loop() +{ + delay(100); +} diff --git a/wasm3-sys/wasm3/platforms/embedded/bluepill/.gitignore b/wasm3-sys/wasm3/platforms/embedded/bluepill/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/bluepill/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/wasm3-sys/wasm3/platforms/embedded/bluepill/lib/wasm3/library.json b/wasm3-sys/wasm3/platforms/embedded/bluepill/lib/wasm3/library.json new file mode 100644 index 0000000..38cdf08 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/bluepill/lib/wasm3/library.json @@ -0,0 +1,7 @@ +{ + "build" : { + "flags": "-Os -fomit-frame-pointer -fno-stack-check -fno-stack-protector -Wfatal-errors -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers", + "srcFilter": ["+<*>", "-"], + "libArchive": false + } +} diff --git a/wasm3-sys/wasm3/platforms/embedded/bluepill/lib/wasm3/src b/wasm3-sys/wasm3/platforms/embedded/bluepill/lib/wasm3/src new file mode 120000 index 0000000..e3e41d7 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/bluepill/lib/wasm3/src @@ -0,0 +1 @@ +../../../../../source \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/bluepill/platformio.ini b/wasm3-sys/wasm3/platforms/embedded/bluepill/platformio.ini new file mode 100644 index 0000000..6b3199b --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/bluepill/platformio.ini @@ -0,0 +1,10 @@ +[env:bluepill] +platform = ststm32 +board = bluepill_f103c8 +framework = stm32cube +upload_protocol = stlink +lib_deps = jeeh + +build_flags = + -Dd_m3FixedHeap=8192 + -Os -Wfatal-errors diff --git a/wasm3-sys/wasm3/platforms/embedded/bluepill/src/main.cpp b/wasm3-sys/wasm3/platforms/embedded/bluepill/src/main.cpp new file mode 100644 index 0000000..120af16 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/bluepill/src/main.cpp @@ -0,0 +1,75 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#include +#include + +#define FATAL(func, msg) { \ + puts("Fatal: " func ": "); \ + puts(msg); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + size_t fsize = fib32_wasm_len; + + puts("Loading WebAssembly..."); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment", "failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime", "failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction", result); + + puts("Running..."); + + result = m3_CallV (f, 24); + if (result) FATAL("m3_Call", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults", result); + + char buff[32]; + itoa(value, buff, 10); + + puts("Result: "); + puts(buff); + puts("\n"); +} + +PinC<13> led; + +int main() +{ + enableSysTick(); + led.mode(Pinmode::out); + + puts("Wasm3 v" M3_VERSION " on BluePill, build " __DATE__ " " __TIME__ "\n"); + + led = 0; + run_wasm(); + led = 1; + +} diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/.gitignore b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/.gitignore new file mode 100644 index 0000000..d054d84 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/.gitignore @@ -0,0 +1,3 @@ +build +sdkconfig +sdkconfig.old diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/.old/Makefile b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/.old/Makefile new file mode 100644 index 0000000..2f23716 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/.old/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := wasm3 + +include $(IDF_PATH)/make/project.mk + diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/.old/component.mk b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/.old/component.mk new file mode 100644 index 0000000..0b9d758 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/.old/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/CMakeLists.txt b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/CMakeLists.txt new file mode 100644 index 0000000..d88e541 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(wasm3) diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/README.md b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/README.md new file mode 100644 index 0000000..616de06 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/README.md @@ -0,0 +1,24 @@ +## Build for ESP-IDF, with minimal WASI support + +**Note:** Currently, to run this example you need a PSRAM-enabled ESP32 module (this might be improved in future). + +Download and install ESP-IDF v4.0 + +```sh +export IDF_PATH=/opt/esp32/esp-idf + +# Set tools path if needed: +#export IDF_TOOLS_PATH=/opt/esp32 + +source $IDF_PATH/export.sh + +idf.py menuconfig + +# Select target: +idf.py set-target esp32s2beta # or esp32 + +idf.py build + +idf.py -p /dev/ttyUSB0 flash monitor + +``` diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/CMakeLists.txt b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/CMakeLists.txt new file mode 100644 index 0000000..59c8747 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/CMakeLists.txt @@ -0,0 +1,11 @@ +file(GLOB_RECURSE M3_SOURCES "m3/*.c") + +set(APP_SOURCES "main.cpp" "m3_api_esp_wasi.c") + +idf_component_register(SRCS ${APP_SOURCES} ${M3_SOURCES} + INCLUDE_DIRS "") + +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error -O3 -DESP32 -Dd_m3MaxFunctionStackHeight=256) + +# Disable harmless warnings +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers) diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/m3 b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/m3 new file mode 120000 index 0000000..17056a9 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/m3 @@ -0,0 +1 @@ +../../../../source \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.c b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.c new file mode 100644 index 0000000..c90e3f9 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.c @@ -0,0 +1,536 @@ +// +// m3_api_esp_wasi.c +// +// Created by Volodymyr Shymanskyy on 01/07/20. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#define _POSIX_C_SOURCE 200809L + +#include "m3_api_esp_wasi.h" + +#include "m3/m3_env.h" +#include "m3/m3_exception.h" + +#if defined(ESP32) + +typedef uint32_t __wasi_size_t; +#include "m3/extra/wasi_core.h" + +#include +#include +#include +#include +#include +#include +#include + +typedef struct wasi_iovec_t +{ + __wasi_size_t buf; + __wasi_size_t buf_len; +} wasi_iovec_t; + +#define PREOPEN_CNT 3 + +typedef struct Preopen { + int fd; + char* path; +} Preopen; + +Preopen preopen[PREOPEN_CNT] = { + { 0, "" }, + { 1, "" }, + { 2, "" }, +}; + +static +__wasi_errno_t errno_to_wasi(int errnum) { + switch (errnum) { + case EPERM: return __WASI_EPERM; break; + case ENOENT: return __WASI_ENOENT; break; + case ESRCH: return __WASI_ESRCH; break; + case EINTR: return __WASI_EINTR; break; + case EIO: return __WASI_EIO; break; + case ENXIO: return __WASI_ENXIO; break; + case E2BIG: return __WASI_E2BIG; break; + case ENOEXEC: return __WASI_ENOEXEC; break; + case EBADF: return __WASI_EBADF; break; + case ECHILD: return __WASI_ECHILD; break; + case EAGAIN: return __WASI_EAGAIN; break; + case ENOMEM: return __WASI_ENOMEM; break; + case EACCES: return __WASI_EACCES; break; + case EFAULT: return __WASI_EFAULT; break; + case EBUSY: return __WASI_EBUSY; break; + case EEXIST: return __WASI_EEXIST; break; + case EXDEV: return __WASI_EXDEV; break; + case ENODEV: return __WASI_ENODEV; break; + case ENOTDIR: return __WASI_ENOTDIR; break; + case EISDIR: return __WASI_EISDIR; break; + case EINVAL: return __WASI_EINVAL; break; + case ENFILE: return __WASI_ENFILE; break; + case EMFILE: return __WASI_EMFILE; break; + case ENOTTY: return __WASI_ENOTTY; break; + case ETXTBSY: return __WASI_ETXTBSY; break; + case EFBIG: return __WASI_EFBIG; break; + case ENOSPC: return __WASI_ENOSPC; break; + case ESPIPE: return __WASI_ESPIPE; break; + case EROFS: return __WASI_EROFS; break; + case EMLINK: return __WASI_EMLINK; break; + case EPIPE: return __WASI_EPIPE; break; + case EDOM: return __WASI_EDOM; break; + case ERANGE: return __WASI_ERANGE; break; + default: return __WASI_EINVAL; + } +} + +static inline +int convert_clockid(__wasi_clockid_t in) { + switch (in) { + case __WASI_CLOCK_MONOTONIC: return CLOCK_MONOTONIC; + //case __WASI_CLOCK_PROCESS_CPUTIME_ID: return CLOCK_PROCESS_CPUTIME_ID; + case __WASI_CLOCK_REALTIME: return CLOCK_REALTIME; + //case __WASI_CLOCK_THREAD_CPUTIME_ID: return CLOCK_THREAD_CPUTIME_ID; + default: return -1; + } +} + +static inline +__wasi_timestamp_t convert_timespec(const struct timespec *ts) { + if (ts->tv_sec < 0) + return 0; + if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000) + return UINT64_MAX; + return (__wasi_timestamp_t)ts->tv_sec * 1000000000 + ts->tv_nsec; +} + + +/* + * WASI API implementation + */ + +m3ApiRawFunction(m3_wasi_unstable_args_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , argv) + m3ApiGetArgMem (char * , argv_buf) + + if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); } + + for (u32 i = 0; i < runtime->argc; ++i) + { + m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf)); + + size_t len = strlen (runtime->argv[i]); + memcpy (argv_buf, runtime->argv[i], len); + argv_buf += len; + * argv_buf++ = 0; + } + + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_args_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , argc) + m3ApiGetArgMem (__wasi_size_t * , argv_buf_size) + + if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); } + + __wasi_size_t buflen = 0; + for (u32 i = 0; i < runtime->argc; ++i) + { + buflen += strlen (runtime->argv[i]) + 1; + } + + m3ApiWriteMem32(argc, runtime->argc); + m3ApiWriteMem32(argv_buf_size, buflen); + + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_environ_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , env) + m3ApiGetArgMem (char * , env_buf) + + if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); } + // TODO + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_environ_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , env_count) + m3ApiGetArgMem (__wasi_size_t * , env_buf_size) + + if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); } + + // TODO + m3ApiWriteMem32(env_count, 0); + m3ApiWriteMem32(env_buf_size, 0); + + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_prestat_dir_name) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); } + if (fd < 3 || fd >= PREOPEN_CNT) { m3ApiReturn(__WASI_EBADF); } + size_t slen = strlen(preopen[fd].path); + memcpy(path, preopen[fd].path, M3_MIN(slen, path_len)); + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_prestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (uint32_t * , buf) // TODO: use actual struct + + if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); } + if (fd < 3 || fd >= PREOPEN_CNT) { m3ApiReturn(__WASI_EBADF); } + m3ApiWriteMem32(buf, __WASI_PREOPENTYPE_DIR); + m3ApiWriteMem32(buf+1, strlen(preopen[fd].path)); + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_fdstat_t * , fdstat) + + if (runtime == NULL || fdstat == NULL) { m3ApiReturn(__WASI_EINVAL); } + + struct stat fd_stat; + int fl = fcntl(fd, F_GETFL); + if (fl < 0) { m3ApiReturn(errno_to_wasi(errno)); } + fstat(fd, &fd_stat); + int mode = fd_stat.st_mode; + fdstat->fs_filetype = (S_ISBLK(mode) ? __WASI_FILETYPE_BLOCK_DEVICE : 0) | + (S_ISCHR(mode) ? __WASI_FILETYPE_CHARACTER_DEVICE : 0) | + (S_ISDIR(mode) ? __WASI_FILETYPE_DIRECTORY : 0) | + (S_ISREG(mode) ? __WASI_FILETYPE_REGULAR_FILE : 0) | + //(S_ISSOCK(mode) ? __WASI_FILETYPE_SOCKET_STREAM : 0) | + (S_ISLNK(mode) ? __WASI_FILETYPE_SYMBOLIC_LINK : 0); + m3ApiWriteMem16(&fdstat->fs_flags, + ((fl & O_APPEND) ? __WASI_FDFLAG_APPEND : 0) | + //((fl & O_DSYNC) ? __WASI_FDFLAG_DSYNC : 0) | + ((fl & O_NONBLOCK) ? __WASI_FDFLAG_NONBLOCK : 0) | + //((fl & O_RSYNC) ? __WASI_FDFLAG_RSYNC : 0) | + ((fl & O_SYNC) ? __WASI_FDFLAG_SYNC : 0)); + fdstat->fs_rights_base = (uint64_t)-1; // all rights + fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_set_flags) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_fdflags_t , flags) + + // TODO + + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_filedelta_t , offset) + m3ApiGetArg (__wasi_whence_t , wasi_whence) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + if (runtime == NULL || result == NULL) { m3ApiReturn(__WASI_EINVAL); } + + int whence; + switch (wasi_whence) { + case __WASI_WHENCE_CUR: whence = SEEK_CUR; break; + case __WASI_WHENCE_END: whence = SEEK_END; break; + case __WASI_WHENCE_SET: whence = SEEK_SET; break; + default: m3ApiReturn(__WASI_EINVAL); + } + + int64_t ret; + ret = lseek(fd, offset, whence); + if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } + m3ApiWriteMem64(result, ret); + m3ApiReturn(__WASI_ESUCCESS); +} + + +m3ApiRawFunction(m3_wasi_unstable_path_open) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , dirfd) + m3ApiGetArg (__wasi_lookupflags_t , dirflags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + m3ApiGetArg (__wasi_oflags_t , oflags) + m3ApiGetArg (__wasi_rights_t , fs_rights_base) + m3ApiGetArg (__wasi_rights_t , fs_rights_inheriting) + m3ApiGetArg (__wasi_fdflags_t , fs_flags) + m3ApiGetArgMem (__wasi_fd_t * , fd) + + if (path_len >= 512) + m3ApiReturn(__WASI_EINVAL); + + // copy path so we can ensure it is NULL terminated + char host_path [path_len+1]; + + memcpy (host_path, path, path_len); + host_path[path_len] = '\0'; // NULL terminator + + // TODO + m3ApiReturn(__WASI_ENOSYS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_read) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nread) + + if (runtime == NULL || nread == NULL) { m3ApiReturn(__WASI_EINVAL); } + + ssize_t res = 0; + for (__wasi_size_t i = 0; i < iovs_len; i++) { + void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + if (len == 0) continue; + + int ret = read (fd, addr, len); + if (ret < 0) m3ApiReturn(errno_to_wasi(errno)); + res += ret; + if ((size_t)ret < len) break; + } + m3ApiWriteMem32(nread, res); + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_write) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nwritten) + + if (runtime == NULL || nwritten == NULL) { m3ApiReturn(__WASI_EINVAL); } + + ssize_t res = 0; + for (__wasi_size_t i = 0; i < iovs_len; i++) { + void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + if (len == 0) continue; + + int ret = write (fd, addr, len); + if (ret < 0) m3ApiReturn(errno_to_wasi(errno)); + res += ret; + if ((size_t)ret < len) break; + } + m3ApiWriteMem32(nwritten, res); + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_close) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + + int ret = close(fd); + m3ApiReturn(ret == 0 ? __WASI_ESUCCESS : ret); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_datasync) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + + // TODO + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_random_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint8_t * , buf) + m3ApiGetArg (__wasi_size_t , buflen) + + while (1) { + ssize_t retlen = 0; + +#if defined(__wasi__) || defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__) + size_t reqlen = M3_MIN (buflen, 256); +# if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + retlen = SecRandomCopyBytes(kSecRandomDefault, reqlen, buf) < 0 ? -1 : reqlen; +# else + retlen = getentropy(buf, reqlen) < 0 ? -1 : reqlen; +# endif +#elif defined(__FreeBSD__) || defined(__linux__) + retlen = getrandom(buf, buflen, 0); +#elif defined(_WIN32) + if (RtlGenRandom(buf, buflen) == TRUE) { + m3ApiReturn(__WASI_ESUCCESS); + } +#else + m3ApiReturn(__WASI_ENOSYS); +#endif + if (retlen < 0) { + if (errno == EINTR || errno == EAGAIN) { + continue; + } + m3ApiReturn(errno_to_wasi(errno)); + } else if (retlen == buflen) { + m3ApiReturn(__WASI_ESUCCESS); + } else { + buf += retlen; + buflen -= retlen; + } + } +} + +m3ApiRawFunction(m3_wasi_unstable_clock_res_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArgMem (__wasi_timestamp_t * , resolution) + + if (runtime == NULL || resolution == NULL) { m3ApiReturn(__WASI_EINVAL); } + + int clk = convert_clockid(wasi_clk_id); + if (clk < 0) m3ApiReturn(__WASI_EINVAL); + + struct timespec tp; + if (clock_getres(clk, &tp) != 0) { + m3ApiWriteMem64(resolution, 1000000); + } else { + m3ApiWriteMem64(resolution, convert_timespec(&tp)); + } + + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_clock_time_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArg (__wasi_timestamp_t , precision) + m3ApiGetArgMem (__wasi_timestamp_t * , time) + + if (runtime == NULL || time == NULL) { m3ApiReturn(__WASI_EINVAL); } + + int clk = convert_clockid(wasi_clk_id); + if (clk < 0) m3ApiReturn(__WASI_EINVAL); + + struct timespec tp; + if (clock_gettime(clk, &tp) != 0) { + m3ApiReturn(errno_to_wasi(errno)); + } + + m3ApiWriteMem64(time, convert_timespec(&tp)); + m3ApiReturn(__WASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_proc_exit) +{ + m3ApiGetArg (uint32_t, code) + + runtime->exit_code = code; + + m3ApiTrap(m3Err_trapExit); +} + + +static +M3Result SuppressLookupFailure(M3Result i_result) +{ + if (i_result == m3Err_functionLookupFailed) + return m3Err_none; + else + return i_result; +} + + +M3Result m3_LinkEspWASI (IM3Module module) +{ + M3Result result = m3Err_none; + + // TODO: Preopen dirs + + static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" }; + + for (int i=0; i<2; i++) + { + const char* wasi = namespaces[i]; + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_get", "i(**)", &m3_wasi_unstable_args_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_unstable_args_sizes_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_unstable_clock_res_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(iI*)", &m3_wasi_unstable_clock_time_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_unstable_environ_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get", "i(**)", &m3_wasi_unstable_environ_sizes_get))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_advise", "i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_allocate", "i(iII)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close", "i(i)", &m3_wasi_unstable_fd_close))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync", "i(i)", &m3_wasi_unstable_fd_datasync))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get", "i(i*)", &m3_wasi_unstable_fd_fdstat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_flags", "i(ii)", &m3_wasi_unstable_fd_fdstat_set_flags))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_rights", "i(iII)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_get", "i(i*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_size", "i(iI)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_times","i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pread", "i(i*iI*)",))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get", "i(i*)", &m3_wasi_unstable_fd_prestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name", "i(i*i)", &m3_wasi_unstable_fd_prestat_dir_name))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pwrite", "i(i*iI*)",))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read", "i(i*i*)", &m3_wasi_unstable_fd_read))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_readdir", "i(i*iI*)",))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_renumber", "i(ii)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_seek", "i(iIi*)", &m3_wasi_unstable_fd_seek))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_sync", "i(i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_tell", "i(i*)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write", "i(i*i*)", &m3_wasi_unstable_fd_write))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_create_directory", "i(i*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_get", "i(ii*i*)", &m3_wasi_unstable_path_filestat_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_set_times", "i(ii*iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_link", "i(ii*ii*i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", "i(ii*iiIIi*)", &m3_wasi_unstable_path_open))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_readlink", "i(i*i*i*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_remove_directory", "i(i*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_rename", "i(i*ii*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_symlink", "i(*ii*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file", "i(i*i)", ))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff", "i(**i*)", &m3_wasi_unstable_poll_oneoff))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_exit", "v(i)", &m3_wasi_unstable_proc_exit))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise", "i(i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_unstable_random_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield", "i()", ))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv", "i(i*ii**)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send", "i(i*ii*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_shutdown", "i(ii)", ))); + } + +_catch: + return result; +} + +#endif // ESP32 + diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.h b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.h new file mode 100644 index 0000000..838129a --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.h @@ -0,0 +1,23 @@ +// +// m3_api_esp_wasi.h +// +// Created by Volodymyr Shymanskyy on 01/07/20. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef m3_api_esp_wasi_h +#define m3_api_esp_wasi_h + +#include "m3/m3_core.h" + +# if defined(__cplusplus) +extern "C" { +# endif + + M3Result m3_LinkEspWASI (IM3Module io_module); + +#if defined(__cplusplus) +} +# endif + +#endif /* m3_api_esp_wasi_h */ diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/main.cpp b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/main.cpp new file mode 100644 index 0000000..1213420 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/main.cpp @@ -0,0 +1,69 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "esp_system.h" + +#include +#include +#include + +#include "m3/wasm3.h" + +#include "m3_api_esp_wasi.h" +#include "wasi_test.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +static void run_wasm(void) +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)wasi_test_wasm; + uint32_t fsize = wasi_test_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 8*1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + result = m3_LinkEspWASI (runtime->modules); + if (result) FATAL("m3_LinkEspWASI: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "_start"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + const char* i_argv[2] = { "test.wasm", NULL }; + result = m3_CallArgv (f, 1, i_argv); + if (result) FATAL("m3_Call: %s", result); +} + +extern "C" void app_main(void) +{ + printf("\nWasm3 v" M3_VERSION " on " CONFIG_IDF_TARGET ", build " __DATE__ " " __TIME__ "\n"); + + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + printf("Elapsed: %ld ms\n", (end - start)*1000 / CLOCKS_PER_SEC); + + sleep(3); + printf("Restarting...\n\n\n"); + esp_restart(); +} diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/wasi_test.wasm.h b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/wasi_test.wasm.h new file mode 100644 index 0000000..6dbdab3 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/main/wasi_test.wasm.h @@ -0,0 +1,2307 @@ +unsigned char wasi_test_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x0e, 0x60, + 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, + 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, 0x7e, + 0x60, 0x00, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60, 0x02, 0x7f, 0x7f, 0x00, + 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x00, 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f, + 0x01, 0x7f, 0x60, 0x05, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, + 0x09, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x01, 0x7f, + 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, 0x7f, 0x60, 0x04, 0x7f, 0x7e, 0x7f, + 0x7f, 0x01, 0x7f, 0x60, 0x02, 0x7c, 0x7f, 0x01, 0x7c, 0x02, 0xa8, 0x03, + 0x0f, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x0e, 0x66, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, 0x61, 0x73, + 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x13, 0x66, + 0x64, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x64, 0x69, + 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x0d, 0x77, 0x61, 0x73, + 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x11, 0x65, + 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x73, + 0x5f, 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, + 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0b, 0x65, 0x6e, 0x76, + 0x69, 0x72, 0x6f, 0x6e, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, + 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x0e, 0x61, 0x72, 0x67, 0x73, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x73, 0x5f, + 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, + 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x08, 0x61, 0x72, 0x67, 0x73, + 0x5f, 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, + 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0e, 0x63, 0x6c, 0x6f, + 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x67, 0x65, 0x74, 0x00, + 0x0b, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x5f, 0x65, 0x78, 0x69, + 0x74, 0x00, 0x05, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x08, 0x66, 0x64, 0x5f, 0x63, 0x6c, 0x6f, + 0x73, 0x65, 0x00, 0x01, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, + 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x07, 0x66, 0x64, 0x5f, 0x72, 0x65, + 0x61, 0x64, 0x00, 0x08, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, + 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0d, 0x66, 0x64, 0x5f, 0x66, 0x64, + 0x73, 0x74, 0x61, 0x74, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, + 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x09, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x00, 0x0a, + 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x0a, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x5f, 0x67, 0x65, + 0x74, 0x00, 0x02, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x07, 0x66, 0x64, 0x5f, 0x73, 0x65, 0x65, + 0x6b, 0x00, 0x0c, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x08, 0x66, 0x64, 0x5f, 0x77, 0x72, 0x69, + 0x74, 0x65, 0x00, 0x08, 0x03, 0x32, 0x31, 0x04, 0x01, 0x04, 0x05, 0x02, + 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, 0x02, 0x02, 0x01, 0x06, 0x05, 0x04, + 0x02, 0x01, 0x06, 0x01, 0x01, 0x06, 0x09, 0x07, 0x04, 0x02, 0x04, 0x01, + 0x03, 0x03, 0x01, 0x00, 0x04, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x07, 0x01, 0x02, 0x02, 0x02, 0x0d, 0x04, 0x05, 0x01, 0x70, + 0x01, 0x05, 0x05, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f, + 0x01, 0x41, 0xa0, 0xaa, 0x04, 0x0b, 0x07, 0x19, 0x03, 0x06, 0x6d, 0x65, + 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x00, 0x0f, 0x03, 0x66, 0x69, 0x62, 0x00, 0x10, 0x09, 0x0a, 0x01, + 0x00, 0x41, 0x01, 0x0b, 0x04, 0x2b, 0x2f, 0x2d, 0x36, 0x0a, 0xd2, 0xbf, + 0x01, 0x31, 0xf7, 0x02, 0x01, 0x04, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, + 0x22, 0x01, 0x24, 0x00, 0x10, 0x1f, 0x41, 0x03, 0x21, 0x00, 0x02, 0x40, + 0x03, 0x40, 0x20, 0x00, 0x20, 0x01, 0x10, 0x00, 0x22, 0x02, 0x41, 0x08, + 0x4b, 0x0d, 0x01, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x41, 0x01, 0x6b, + 0x0e, 0x08, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x0b, + 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x04, 0x40, 0x20, 0x01, 0x28, 0x02, + 0x04, 0x41, 0x01, 0x6a, 0x10, 0x14, 0x22, 0x02, 0x45, 0x0d, 0x03, 0x20, + 0x00, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x04, 0x10, 0x01, 0x04, 0x40, + 0x20, 0x02, 0x10, 0x15, 0x0c, 0x04, 0x0b, 0x20, 0x02, 0x20, 0x01, 0x28, + 0x02, 0x04, 0x6a, 0x41, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x20, 0x02, + 0x10, 0x20, 0x20, 0x02, 0x10, 0x15, 0x0d, 0x03, 0x0b, 0x20, 0x00, 0x41, + 0x01, 0x6a, 0x22, 0x02, 0x20, 0x00, 0x49, 0x20, 0x02, 0x21, 0x00, 0x45, + 0x0d, 0x01, 0x0b, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, + 0x20, 0x01, 0x41, 0x0c, 0x6a, 0x10, 0x02, 0x0d, 0x00, 0x41, 0xe8, 0x1f, + 0x20, 0x01, 0x28, 0x02, 0x00, 0x41, 0x02, 0x74, 0x41, 0x04, 0x6a, 0x10, + 0x14, 0x36, 0x02, 0x00, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x10, 0x14, 0x22, + 0x00, 0x45, 0x0d, 0x00, 0x41, 0xe8, 0x1f, 0x28, 0x02, 0x00, 0x22, 0x02, + 0x45, 0x0d, 0x00, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x00, 0x41, 0x02, + 0x74, 0x6a, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, 0xe8, 0x1f, 0x28, 0x02, + 0x00, 0x20, 0x00, 0x10, 0x03, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x0c, 0x6a, + 0x20, 0x01, 0x10, 0x04, 0x0d, 0x01, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x22, + 0x00, 0x04, 0x40, 0x20, 0x00, 0x41, 0x02, 0x74, 0x41, 0x04, 0x6a, 0x10, + 0x14, 0x21, 0x00, 0x20, 0x01, 0x28, 0x02, 0x00, 0x10, 0x14, 0x21, 0x02, + 0x20, 0x00, 0x45, 0x0d, 0x02, 0x20, 0x02, 0x45, 0x0d, 0x02, 0x20, 0x00, + 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x02, 0x10, 0x05, 0x0d, + 0x02, 0x0b, 0x41, 0xe8, 0x1b, 0x41, 0x88, 0x08, 0x29, 0x03, 0x00, 0x37, + 0x03, 0x00, 0x41, 0xe0, 0x1b, 0x41, 0x80, 0x08, 0x29, 0x03, 0x00, 0x37, + 0x03, 0x00, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x20, 0x00, 0x10, 0x13, 0x21, + 0x00, 0x10, 0x30, 0x20, 0x00, 0x0d, 0x02, 0x20, 0x01, 0x41, 0x10, 0x6a, + 0x24, 0x00, 0x0f, 0x0b, 0x41, 0xc7, 0x00, 0x10, 0x18, 0x00, 0x0b, 0x41, + 0xc7, 0x00, 0x10, 0x18, 0x00, 0x0b, 0x20, 0x00, 0x10, 0x18, 0x00, 0x0b, + 0x41, 0xc7, 0x00, 0x10, 0x18, 0x00, 0x0b, 0x1c, 0x00, 0x20, 0x00, 0x41, + 0x02, 0x4f, 0x04, 0x40, 0x20, 0x00, 0x41, 0x7f, 0x6a, 0x10, 0x10, 0x20, + 0x00, 0x41, 0x7e, 0x6a, 0x10, 0x10, 0x6a, 0x0f, 0x0b, 0x20, 0x00, 0x0b, + 0xb0, 0x01, 0x02, 0x04, 0x7f, 0x01, 0x7e, 0x23, 0x00, 0x41, 0x40, 0x6a, + 0x22, 0x00, 0x24, 0x00, 0x20, 0x00, 0x41, 0x14, 0x36, 0x02, 0x10, 0x41, + 0xe0, 0x08, 0x20, 0x00, 0x41, 0x10, 0x6a, 0x10, 0x22, 0x41, 0xd8, 0x1b, + 0x28, 0x02, 0x00, 0x10, 0x23, 0x1a, 0x20, 0x00, 0x41, 0x30, 0x6a, 0x10, + 0x17, 0x41, 0x14, 0x10, 0x10, 0x21, 0x03, 0x20, 0x00, 0x41, 0x20, 0x6a, + 0x10, 0x17, 0x20, 0x00, 0x29, 0x03, 0x20, 0x20, 0x00, 0x29, 0x03, 0x30, + 0x7d, 0x21, 0x04, 0x02, 0x7f, 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, 0x01, + 0x20, 0x00, 0x28, 0x02, 0x38, 0x22, 0x02, 0x48, 0x04, 0x40, 0x20, 0x04, + 0x42, 0x7f, 0x7c, 0x21, 0x04, 0x20, 0x01, 0x20, 0x02, 0x6b, 0x41, 0x80, + 0x94, 0xeb, 0xdc, 0x03, 0x6a, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x20, 0x02, + 0x6b, 0x0b, 0x21, 0x01, 0x20, 0x00, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, + 0x00, 0x20, 0x04, 0xb9, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8f, + 0x40, 0xa2, 0x20, 0x01, 0xb7, 0x44, 0x00, 0x00, 0x00, 0x00, 0x80, 0x84, + 0x2e, 0x41, 0xa3, 0xa0, 0x39, 0x03, 0x08, 0x41, 0xeb, 0x08, 0x20, 0x00, + 0x10, 0x22, 0x20, 0x00, 0x41, 0x40, 0x6b, 0x24, 0x00, 0x0b, 0x75, 0x01, + 0x02, 0x7f, 0x23, 0x00, 0x41, 0x20, 0x6b, 0x22, 0x01, 0x24, 0x00, 0x02, + 0x40, 0x20, 0x00, 0x10, 0x1c, 0x22, 0x02, 0x41, 0x00, 0x4e, 0x04, 0x40, + 0x20, 0x01, 0x41, 0x00, 0x3a, 0x00, 0x1f, 0x20, 0x02, 0x20, 0x01, 0x41, + 0x1f, 0x6a, 0x10, 0x1a, 0x41, 0x01, 0x4e, 0x04, 0x40, 0x03, 0x40, 0x20, + 0x01, 0x20, 0x01, 0x2c, 0x00, 0x1f, 0x36, 0x02, 0x00, 0x41, 0xf9, 0x08, + 0x20, 0x01, 0x10, 0x22, 0x20, 0x02, 0x20, 0x01, 0x41, 0x1f, 0x6a, 0x10, + 0x1a, 0x41, 0x00, 0x4a, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x02, 0x10, 0x19, + 0x1a, 0x10, 0x28, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x20, 0x00, 0x36, 0x02, + 0x10, 0x41, 0xff, 0x08, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x10, 0x22, 0x0b, + 0x20, 0x01, 0x41, 0x20, 0x6a, 0x24, 0x00, 0x0b, 0xdd, 0x02, 0x02, 0x02, + 0x7f, 0x01, 0x7e, 0x23, 0x00, 0x41, 0xd0, 0x00, 0x6b, 0x22, 0x02, 0x24, + 0x00, 0x41, 0x90, 0x08, 0x41, 0x0c, 0x41, 0xd8, 0x1b, 0x28, 0x02, 0x00, + 0x22, 0x03, 0x10, 0x34, 0x1a, 0x41, 0xe0, 0x1b, 0x41, 0x0f, 0x20, 0x03, + 0x10, 0x34, 0x1a, 0x20, 0x02, 0x41, 0xa8, 0x08, 0x36, 0x02, 0x30, 0x41, + 0x9d, 0x08, 0x20, 0x02, 0x41, 0x30, 0x6a, 0x10, 0x22, 0x41, 0xaf, 0x08, + 0x41, 0x00, 0x10, 0x22, 0x20, 0x00, 0x41, 0x01, 0x4e, 0x04, 0x40, 0x20, + 0x01, 0x21, 0x03, 0x03, 0x40, 0x20, 0x02, 0x20, 0x03, 0x28, 0x02, 0x00, + 0x36, 0x02, 0x20, 0x41, 0xb6, 0x08, 0x20, 0x02, 0x41, 0x20, 0x6a, 0x10, + 0x22, 0x20, 0x03, 0x41, 0x04, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x7f, + 0x6a, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x0b, 0x10, 0x28, 0x20, 0x02, 0x41, + 0x40, 0x6b, 0x10, 0x17, 0x20, 0x02, 0x20, 0x02, 0x29, 0x03, 0x40, 0x37, + 0x03, 0x10, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x48, 0x36, 0x02, 0x18, + 0x41, 0xc9, 0x08, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x10, 0x22, 0x20, 0x02, + 0x41, 0x40, 0x6b, 0x41, 0x04, 0x10, 0x0c, 0x22, 0x00, 0x04, 0x40, 0x41, + 0xe0, 0x1f, 0x20, 0x00, 0x36, 0x02, 0x00, 0x0b, 0x41, 0xa8, 0x28, 0x20, + 0x02, 0x28, 0x02, 0x40, 0x41, 0x7f, 0x6a, 0xad, 0x37, 0x03, 0x00, 0x41, + 0xa8, 0x28, 0x41, 0xa8, 0x28, 0x29, 0x03, 0x00, 0x42, 0xad, 0xfe, 0xd5, + 0xe4, 0xd4, 0x85, 0xfd, 0xa8, 0xd8, 0x00, 0x7e, 0x42, 0x01, 0x7c, 0x22, + 0x04, 0x37, 0x03, 0x00, 0x20, 0x04, 0x42, 0x21, 0x88, 0xa7, 0x21, 0x00, + 0x41, 0xa8, 0x28, 0x41, 0xa8, 0x28, 0x29, 0x03, 0x00, 0x42, 0xad, 0xfe, + 0xd5, 0xe4, 0xd4, 0x85, 0xfd, 0xa8, 0xd8, 0x00, 0x7e, 0x42, 0x01, 0x7c, + 0x22, 0x04, 0x37, 0x03, 0x00, 0x20, 0x04, 0x42, 0x21, 0x88, 0xa7, 0x21, + 0x03, 0x20, 0x02, 0x20, 0x00, 0x41, 0xbb, 0xd1, 0x8b, 0xdd, 0x00, 0x6d, + 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x02, 0x20, 0x03, 0x41, 0xbb, 0xd1, + 0x8b, 0xdd, 0x00, 0x6d, 0x22, 0x03, 0x36, 0x02, 0x04, 0x20, 0x02, 0x20, + 0x00, 0x20, 0x03, 0x6a, 0x36, 0x02, 0x08, 0x41, 0xbb, 0x08, 0x20, 0x02, + 0x10, 0x22, 0x10, 0x11, 0x20, 0x01, 0x28, 0x02, 0x04, 0x10, 0x3b, 0x45, + 0x04, 0x40, 0x20, 0x01, 0x28, 0x02, 0x08, 0x10, 0x12, 0x0b, 0x10, 0x32, + 0x20, 0x02, 0x41, 0xd0, 0x00, 0x6a, 0x24, 0x00, 0x41, 0x00, 0x0b, 0xb9, + 0x2e, 0x01, 0x0b, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x0b, 0x24, + 0x00, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, + 0x00, 0x41, 0xec, 0x01, 0x4d, 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x28, 0x02, + 0x00, 0x22, 0x05, 0x41, 0x10, 0x20, 0x00, 0x41, 0x13, 0x6a, 0x41, 0x70, + 0x71, 0x20, 0x00, 0x41, 0x0b, 0x49, 0x1b, 0x22, 0x06, 0x41, 0x03, 0x76, + 0x22, 0x00, 0x76, 0x22, 0x01, 0x41, 0x03, 0x71, 0x04, 0x40, 0x20, 0x01, + 0x41, 0x01, 0x71, 0x20, 0x00, 0x72, 0x41, 0x01, 0x73, 0x22, 0x02, 0x41, + 0x03, 0x74, 0x22, 0x04, 0x41, 0xa0, 0x1c, 0x6a, 0x28, 0x02, 0x00, 0x22, + 0x01, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x02, 0x40, 0x20, 0x01, 0x28, 0x02, + 0x08, 0x22, 0x03, 0x20, 0x04, 0x41, 0x98, 0x1c, 0x6a, 0x22, 0x04, 0x46, + 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x05, 0x41, 0x7e, 0x20, 0x02, 0x77, + 0x71, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x41, 0x80, 0x1c, 0x28, 0x02, + 0x00, 0x1a, 0x20, 0x04, 0x20, 0x03, 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, + 0x04, 0x36, 0x02, 0x0c, 0x0b, 0x20, 0x01, 0x20, 0x02, 0x41, 0x03, 0x74, + 0x22, 0x02, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, 0x01, 0x20, 0x02, + 0x6a, 0x22, 0x01, 0x20, 0x01, 0x28, 0x02, 0x04, 0x41, 0x01, 0x72, 0x36, + 0x02, 0x04, 0x0c, 0x0c, 0x0b, 0x20, 0x06, 0x41, 0xf8, 0x1b, 0x28, 0x02, + 0x00, 0x22, 0x08, 0x4d, 0x0d, 0x01, 0x20, 0x01, 0x04, 0x40, 0x02, 0x40, + 0x41, 0x02, 0x20, 0x00, 0x74, 0x22, 0x02, 0x41, 0x00, 0x20, 0x02, 0x6b, + 0x72, 0x20, 0x01, 0x20, 0x00, 0x74, 0x71, 0x22, 0x00, 0x41, 0x00, 0x20, + 0x00, 0x6b, 0x71, 0x41, 0x7f, 0x6a, 0x22, 0x00, 0x20, 0x00, 0x41, 0x0c, + 0x76, 0x41, 0x10, 0x71, 0x22, 0x00, 0x76, 0x22, 0x01, 0x41, 0x05, 0x76, + 0x41, 0x08, 0x71, 0x22, 0x02, 0x20, 0x00, 0x72, 0x20, 0x01, 0x20, 0x02, + 0x76, 0x22, 0x00, 0x41, 0x02, 0x76, 0x41, 0x04, 0x71, 0x22, 0x01, 0x72, + 0x20, 0x00, 0x20, 0x01, 0x76, 0x22, 0x00, 0x41, 0x01, 0x76, 0x41, 0x02, + 0x71, 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, 0x76, 0x22, 0x00, 0x41, + 0x01, 0x76, 0x41, 0x01, 0x71, 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, + 0x76, 0x6a, 0x22, 0x02, 0x41, 0x03, 0x74, 0x22, 0x03, 0x41, 0xa0, 0x1c, + 0x6a, 0x28, 0x02, 0x00, 0x22, 0x01, 0x28, 0x02, 0x08, 0x22, 0x00, 0x20, + 0x03, 0x41, 0x98, 0x1c, 0x6a, 0x22, 0x03, 0x46, 0x04, 0x40, 0x41, 0xf0, + 0x1b, 0x20, 0x05, 0x41, 0x7e, 0x20, 0x02, 0x77, 0x71, 0x22, 0x05, 0x36, + 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, 0x1a, + 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x08, 0x20, 0x00, 0x20, 0x03, 0x36, + 0x02, 0x0c, 0x0b, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x20, 0x01, + 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, 0x01, 0x20, 0x02, + 0x41, 0x03, 0x74, 0x22, 0x02, 0x6a, 0x20, 0x02, 0x20, 0x06, 0x6b, 0x22, + 0x04, 0x36, 0x02, 0x00, 0x20, 0x01, 0x20, 0x06, 0x6a, 0x22, 0x06, 0x20, + 0x04, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x08, 0x04, 0x40, 0x20, + 0x08, 0x41, 0x03, 0x76, 0x22, 0x03, 0x41, 0x03, 0x74, 0x41, 0x98, 0x1c, + 0x6a, 0x21, 0x01, 0x41, 0x84, 0x1c, 0x28, 0x02, 0x00, 0x21, 0x02, 0x02, + 0x7f, 0x20, 0x05, 0x41, 0x01, 0x20, 0x03, 0x74, 0x22, 0x03, 0x71, 0x45, + 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x03, 0x20, 0x05, 0x72, 0x36, 0x02, + 0x00, 0x20, 0x01, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x08, 0x0b, + 0x22, 0x03, 0x20, 0x02, 0x36, 0x02, 0x0c, 0x20, 0x01, 0x20, 0x02, 0x36, + 0x02, 0x08, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x02, 0x20, + 0x03, 0x36, 0x02, 0x08, 0x0b, 0x41, 0x84, 0x1c, 0x20, 0x06, 0x36, 0x02, + 0x00, 0x41, 0xf8, 0x1b, 0x20, 0x04, 0x36, 0x02, 0x00, 0x0c, 0x0c, 0x0b, + 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, 0x22, 0x0a, 0x45, 0x0d, 0x01, 0x20, + 0x0a, 0x41, 0x00, 0x20, 0x0a, 0x6b, 0x71, 0x41, 0x7f, 0x6a, 0x22, 0x00, + 0x20, 0x00, 0x41, 0x0c, 0x76, 0x41, 0x10, 0x71, 0x22, 0x00, 0x76, 0x22, + 0x01, 0x41, 0x05, 0x76, 0x41, 0x08, 0x71, 0x22, 0x02, 0x20, 0x00, 0x72, + 0x20, 0x01, 0x20, 0x02, 0x76, 0x22, 0x00, 0x41, 0x02, 0x76, 0x41, 0x04, + 0x71, 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, 0x76, 0x22, 0x00, 0x41, + 0x01, 0x76, 0x41, 0x02, 0x71, 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, + 0x76, 0x22, 0x00, 0x41, 0x01, 0x76, 0x41, 0x01, 0x71, 0x22, 0x01, 0x72, + 0x20, 0x00, 0x20, 0x01, 0x76, 0x6a, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, + 0x6a, 0x28, 0x02, 0x00, 0x22, 0x01, 0x28, 0x02, 0x04, 0x41, 0x78, 0x71, + 0x20, 0x06, 0x6b, 0x21, 0x02, 0x20, 0x01, 0x21, 0x04, 0x03, 0x40, 0x02, + 0x40, 0x20, 0x04, 0x28, 0x02, 0x10, 0x22, 0x00, 0x45, 0x04, 0x40, 0x20, + 0x04, 0x41, 0x14, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x01, + 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x41, 0x78, 0x71, 0x20, 0x06, 0x6b, + 0x22, 0x03, 0x20, 0x02, 0x20, 0x03, 0x20, 0x02, 0x49, 0x22, 0x03, 0x1b, + 0x21, 0x02, 0x20, 0x00, 0x20, 0x01, 0x20, 0x03, 0x1b, 0x21, 0x01, 0x20, + 0x00, 0x21, 0x04, 0x0c, 0x01, 0x0b, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x18, + 0x21, 0x09, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x22, 0x03, 0x47, + 0x04, 0x40, 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, 0x20, 0x01, 0x28, 0x02, + 0x08, 0x22, 0x00, 0x4d, 0x04, 0x40, 0x20, 0x00, 0x28, 0x02, 0x0c, 0x1a, + 0x0b, 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x08, 0x20, 0x00, 0x20, 0x03, + 0x36, 0x02, 0x0c, 0x0c, 0x0b, 0x0b, 0x20, 0x01, 0x41, 0x14, 0x6a, 0x22, + 0x04, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x04, 0x40, 0x20, 0x01, 0x28, + 0x02, 0x10, 0x22, 0x00, 0x45, 0x0d, 0x03, 0x20, 0x01, 0x41, 0x10, 0x6a, + 0x21, 0x04, 0x0b, 0x03, 0x40, 0x20, 0x04, 0x21, 0x07, 0x20, 0x00, 0x22, + 0x03, 0x41, 0x14, 0x6a, 0x22, 0x04, 0x28, 0x02, 0x00, 0x22, 0x00, 0x0d, + 0x00, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x21, 0x04, 0x20, 0x03, 0x28, 0x02, + 0x10, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x41, 0x00, 0x36, 0x02, + 0x00, 0x0c, 0x0a, 0x0b, 0x41, 0x7f, 0x21, 0x06, 0x20, 0x00, 0x41, 0xbf, + 0x7f, 0x4b, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x13, 0x6a, 0x22, 0x00, 0x41, + 0x70, 0x71, 0x21, 0x06, 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, 0x22, 0x08, + 0x45, 0x0d, 0x00, 0x41, 0x00, 0x20, 0x06, 0x6b, 0x21, 0x04, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, 0x41, 0x00, 0x20, 0x00, 0x41, 0x08, + 0x76, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x41, 0x1f, 0x20, 0x06, 0x41, + 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x00, 0x1a, 0x20, 0x00, 0x20, 0x00, + 0x41, 0x80, 0xfe, 0x3f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x08, 0x71, 0x22, + 0x00, 0x74, 0x22, 0x01, 0x20, 0x01, 0x41, 0x80, 0xe0, 0x1f, 0x6a, 0x41, + 0x10, 0x76, 0x41, 0x04, 0x71, 0x22, 0x01, 0x74, 0x22, 0x02, 0x20, 0x02, + 0x41, 0x80, 0x80, 0x0f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x02, 0x71, 0x22, + 0x02, 0x74, 0x41, 0x0f, 0x76, 0x20, 0x00, 0x20, 0x01, 0x72, 0x20, 0x02, + 0x72, 0x6b, 0x22, 0x00, 0x41, 0x01, 0x74, 0x20, 0x06, 0x20, 0x00, 0x41, + 0x15, 0x6a, 0x76, 0x41, 0x01, 0x71, 0x72, 0x41, 0x1c, 0x6a, 0x0b, 0x22, + 0x07, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, 0x28, 0x02, 0x00, 0x22, + 0x02, 0x45, 0x04, 0x40, 0x41, 0x00, 0x21, 0x00, 0x0c, 0x01, 0x0b, 0x20, + 0x06, 0x41, 0x00, 0x41, 0x19, 0x20, 0x07, 0x41, 0x01, 0x76, 0x6b, 0x20, + 0x07, 0x41, 0x1f, 0x46, 0x1b, 0x74, 0x21, 0x01, 0x41, 0x00, 0x21, 0x00, + 0x03, 0x40, 0x02, 0x40, 0x20, 0x02, 0x28, 0x02, 0x04, 0x41, 0x78, 0x71, + 0x20, 0x06, 0x6b, 0x22, 0x05, 0x20, 0x04, 0x4f, 0x0d, 0x00, 0x20, 0x02, + 0x21, 0x03, 0x20, 0x05, 0x22, 0x04, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x04, + 0x20, 0x02, 0x21, 0x00, 0x0c, 0x03, 0x0b, 0x20, 0x00, 0x20, 0x02, 0x41, + 0x14, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x05, 0x20, 0x05, 0x20, 0x02, 0x20, + 0x01, 0x41, 0x1d, 0x76, 0x41, 0x04, 0x71, 0x6a, 0x41, 0x10, 0x6a, 0x28, + 0x02, 0x00, 0x22, 0x02, 0x46, 0x1b, 0x20, 0x00, 0x20, 0x05, 0x1b, 0x21, + 0x00, 0x20, 0x01, 0x20, 0x02, 0x41, 0x00, 0x47, 0x74, 0x21, 0x01, 0x20, + 0x02, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x20, 0x03, 0x72, 0x45, 0x04, + 0x40, 0x41, 0x02, 0x20, 0x07, 0x74, 0x22, 0x00, 0x41, 0x00, 0x20, 0x00, + 0x6b, 0x72, 0x20, 0x08, 0x71, 0x22, 0x00, 0x45, 0x0d, 0x03, 0x20, 0x00, + 0x41, 0x00, 0x20, 0x00, 0x6b, 0x71, 0x41, 0x7f, 0x6a, 0x22, 0x00, 0x20, + 0x00, 0x41, 0x0c, 0x76, 0x41, 0x10, 0x71, 0x22, 0x00, 0x76, 0x22, 0x01, + 0x41, 0x05, 0x76, 0x41, 0x08, 0x71, 0x22, 0x02, 0x20, 0x00, 0x72, 0x20, + 0x01, 0x20, 0x02, 0x76, 0x22, 0x00, 0x41, 0x02, 0x76, 0x41, 0x04, 0x71, + 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, 0x76, 0x22, 0x00, 0x41, 0x01, + 0x76, 0x41, 0x02, 0x71, 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, 0x76, + 0x22, 0x00, 0x41, 0x01, 0x76, 0x41, 0x01, 0x71, 0x22, 0x01, 0x72, 0x20, + 0x00, 0x20, 0x01, 0x76, 0x6a, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, + 0x28, 0x02, 0x00, 0x21, 0x00, 0x0b, 0x20, 0x00, 0x45, 0x0d, 0x01, 0x0b, + 0x03, 0x40, 0x20, 0x00, 0x28, 0x02, 0x04, 0x41, 0x78, 0x71, 0x20, 0x06, + 0x6b, 0x22, 0x05, 0x20, 0x04, 0x49, 0x21, 0x01, 0x20, 0x05, 0x20, 0x04, + 0x20, 0x01, 0x1b, 0x21, 0x04, 0x20, 0x00, 0x20, 0x03, 0x20, 0x01, 0x1b, + 0x21, 0x03, 0x20, 0x00, 0x28, 0x02, 0x10, 0x22, 0x02, 0x04, 0x7f, 0x20, + 0x02, 0x05, 0x20, 0x00, 0x41, 0x14, 0x6a, 0x28, 0x02, 0x00, 0x0b, 0x22, + 0x00, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x03, 0x45, 0x0d, 0x00, 0x20, 0x04, + 0x41, 0xf8, 0x1b, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6b, 0x4f, 0x0d, 0x00, + 0x20, 0x03, 0x28, 0x02, 0x18, 0x21, 0x07, 0x20, 0x03, 0x20, 0x03, 0x28, + 0x02, 0x0c, 0x22, 0x01, 0x47, 0x04, 0x40, 0x41, 0x80, 0x1c, 0x28, 0x02, + 0x00, 0x20, 0x03, 0x28, 0x02, 0x08, 0x22, 0x00, 0x4d, 0x04, 0x40, 0x20, + 0x00, 0x28, 0x02, 0x0c, 0x1a, 0x0b, 0x20, 0x01, 0x20, 0x00, 0x36, 0x02, + 0x08, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x0c, 0x09, 0x0b, 0x20, + 0x03, 0x41, 0x14, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, + 0x04, 0x40, 0x20, 0x03, 0x28, 0x02, 0x10, 0x22, 0x00, 0x45, 0x0d, 0x03, + 0x20, 0x03, 0x41, 0x10, 0x6a, 0x21, 0x02, 0x0b, 0x03, 0x40, 0x20, 0x02, + 0x21, 0x05, 0x20, 0x00, 0x22, 0x01, 0x41, 0x14, 0x6a, 0x22, 0x02, 0x28, + 0x02, 0x00, 0x22, 0x00, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x21, + 0x02, 0x20, 0x01, 0x28, 0x02, 0x10, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x20, + 0x05, 0x41, 0x00, 0x36, 0x02, 0x00, 0x0c, 0x08, 0x0b, 0x41, 0xf8, 0x1b, + 0x28, 0x02, 0x00, 0x22, 0x01, 0x20, 0x06, 0x4f, 0x04, 0x40, 0x41, 0x84, + 0x1c, 0x28, 0x02, 0x00, 0x21, 0x00, 0x02, 0x40, 0x20, 0x01, 0x20, 0x06, + 0x6b, 0x22, 0x02, 0x41, 0x10, 0x4f, 0x04, 0x40, 0x20, 0x00, 0x20, 0x06, + 0x6a, 0x22, 0x03, 0x20, 0x02, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x41, + 0xf8, 0x1b, 0x20, 0x02, 0x36, 0x02, 0x00, 0x41, 0x84, 0x1c, 0x20, 0x03, + 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x20, 0x02, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x0c, + 0x01, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, + 0x20, 0x00, 0x20, 0x01, 0x6a, 0x22, 0x01, 0x20, 0x01, 0x28, 0x02, 0x04, + 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x41, 0x84, 0x1c, 0x41, 0x00, 0x36, + 0x02, 0x00, 0x41, 0xf8, 0x1b, 0x41, 0x00, 0x36, 0x02, 0x00, 0x0b, 0x20, + 0x00, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x0c, 0x0a, 0x0b, 0x41, 0xfc, 0x1b, + 0x28, 0x02, 0x00, 0x22, 0x01, 0x20, 0x06, 0x4b, 0x04, 0x40, 0x41, 0x88, + 0x1c, 0x28, 0x02, 0x00, 0x22, 0x00, 0x20, 0x06, 0x6a, 0x22, 0x02, 0x20, + 0x01, 0x20, 0x06, 0x6b, 0x22, 0x01, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, + 0x41, 0xfc, 0x1b, 0x20, 0x01, 0x36, 0x02, 0x00, 0x41, 0x88, 0x1c, 0x20, + 0x02, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, + 0x02, 0x04, 0x20, 0x00, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x0c, 0x0a, 0x0b, + 0x41, 0x00, 0x21, 0x00, 0x20, 0x06, 0x41, 0xc7, 0x00, 0x6a, 0x22, 0x04, + 0x02, 0x7f, 0x41, 0xc8, 0x1f, 0x28, 0x02, 0x00, 0x04, 0x40, 0x41, 0xd0, + 0x1f, 0x28, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x41, 0xd4, 0x1f, 0x42, 0x7f, + 0x37, 0x02, 0x00, 0x41, 0xcc, 0x1f, 0x42, 0x80, 0x80, 0x84, 0x80, 0x80, + 0x80, 0xc0, 0x00, 0x37, 0x02, 0x00, 0x41, 0xc8, 0x1f, 0x20, 0x0b, 0x41, + 0x0c, 0x6a, 0x41, 0x70, 0x71, 0x41, 0xd8, 0xaa, 0xd5, 0xaa, 0x05, 0x73, + 0x36, 0x02, 0x00, 0x41, 0xdc, 0x1f, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, + 0xac, 0x1f, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, 0x80, 0x80, 0x04, 0x0b, + 0x22, 0x02, 0x6a, 0x22, 0x05, 0x41, 0x00, 0x20, 0x02, 0x6b, 0x22, 0x07, + 0x71, 0x22, 0x02, 0x20, 0x06, 0x4d, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, + 0x30, 0x36, 0x02, 0x00, 0x0c, 0x0a, 0x0b, 0x02, 0x40, 0x41, 0xa8, 0x1f, + 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x41, 0xa0, 0x1f, 0x28, + 0x02, 0x00, 0x22, 0x03, 0x20, 0x02, 0x6a, 0x22, 0x08, 0x20, 0x03, 0x4b, + 0x41, 0x00, 0x20, 0x08, 0x20, 0x00, 0x4d, 0x1b, 0x0d, 0x00, 0x41, 0x00, + 0x21, 0x00, 0x41, 0xe0, 0x1f, 0x41, 0x30, 0x36, 0x02, 0x00, 0x0c, 0x0a, + 0x0b, 0x41, 0xac, 0x1f, 0x2d, 0x00, 0x00, 0x41, 0x04, 0x71, 0x0d, 0x04, + 0x02, 0x40, 0x02, 0x40, 0x41, 0x88, 0x1c, 0x28, 0x02, 0x00, 0x22, 0x03, + 0x04, 0x40, 0x41, 0xb0, 0x1f, 0x21, 0x00, 0x03, 0x40, 0x20, 0x00, 0x28, + 0x02, 0x00, 0x22, 0x08, 0x20, 0x03, 0x4d, 0x04, 0x40, 0x20, 0x08, 0x20, + 0x00, 0x28, 0x02, 0x04, 0x6a, 0x20, 0x03, 0x4b, 0x0d, 0x03, 0x0b, 0x20, + 0x00, 0x28, 0x02, 0x08, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x0b, 0x41, 0x00, + 0x10, 0x21, 0x22, 0x01, 0x41, 0x7f, 0x46, 0x0d, 0x05, 0x20, 0x02, 0x21, + 0x05, 0x41, 0xcc, 0x1f, 0x28, 0x02, 0x00, 0x22, 0x00, 0x41, 0x7f, 0x6a, + 0x22, 0x03, 0x20, 0x01, 0x71, 0x04, 0x40, 0x20, 0x02, 0x20, 0x01, 0x6b, + 0x20, 0x01, 0x20, 0x03, 0x6a, 0x41, 0x00, 0x20, 0x00, 0x6b, 0x71, 0x6a, + 0x21, 0x05, 0x0b, 0x20, 0x05, 0x20, 0x06, 0x4d, 0x0d, 0x05, 0x20, 0x05, + 0x41, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x05, 0x41, 0xa8, 0x1f, + 0x28, 0x02, 0x00, 0x22, 0x00, 0x04, 0x40, 0x41, 0xa0, 0x1f, 0x28, 0x02, + 0x00, 0x22, 0x03, 0x20, 0x05, 0x6a, 0x22, 0x07, 0x20, 0x03, 0x4d, 0x0d, + 0x06, 0x20, 0x07, 0x20, 0x00, 0x4b, 0x0d, 0x06, 0x0b, 0x20, 0x05, 0x10, + 0x21, 0x22, 0x00, 0x20, 0x01, 0x47, 0x0d, 0x01, 0x0c, 0x07, 0x0b, 0x20, + 0x05, 0x20, 0x01, 0x6b, 0x20, 0x07, 0x71, 0x22, 0x05, 0x41, 0xfe, 0xff, + 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x04, 0x20, 0x05, 0x10, 0x21, 0x22, 0x01, + 0x20, 0x00, 0x28, 0x02, 0x00, 0x20, 0x00, 0x28, 0x02, 0x04, 0x6a, 0x46, + 0x0d, 0x03, 0x20, 0x01, 0x21, 0x00, 0x0b, 0x20, 0x00, 0x21, 0x01, 0x02, + 0x40, 0x20, 0x06, 0x41, 0xc8, 0x00, 0x6a, 0x20, 0x05, 0x4d, 0x0d, 0x00, + 0x20, 0x05, 0x41, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x00, 0x20, + 0x01, 0x41, 0x7f, 0x46, 0x0d, 0x00, 0x41, 0xd0, 0x1f, 0x28, 0x02, 0x00, + 0x22, 0x00, 0x20, 0x04, 0x20, 0x05, 0x6b, 0x6a, 0x41, 0x00, 0x20, 0x00, + 0x6b, 0x71, 0x22, 0x00, 0x41, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, + 0x06, 0x20, 0x00, 0x10, 0x21, 0x41, 0x7f, 0x47, 0x04, 0x40, 0x20, 0x00, + 0x20, 0x05, 0x6a, 0x21, 0x05, 0x0c, 0x07, 0x0b, 0x41, 0x00, 0x20, 0x05, + 0x6b, 0x10, 0x21, 0x1a, 0x0c, 0x04, 0x0b, 0x20, 0x01, 0x41, 0x7f, 0x47, + 0x0d, 0x05, 0x0c, 0x03, 0x0b, 0x41, 0x00, 0x21, 0x03, 0x0c, 0x07, 0x0b, + 0x41, 0x00, 0x21, 0x01, 0x0c, 0x05, 0x0b, 0x20, 0x01, 0x41, 0x7f, 0x47, + 0x0d, 0x02, 0x0b, 0x41, 0xac, 0x1f, 0x41, 0xac, 0x1f, 0x28, 0x02, 0x00, + 0x41, 0x04, 0x72, 0x36, 0x02, 0x00, 0x0b, 0x20, 0x02, 0x41, 0xfe, 0xff, + 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x01, 0x20, 0x02, 0x10, 0x21, 0x22, 0x01, + 0x41, 0x00, 0x10, 0x21, 0x22, 0x00, 0x4f, 0x0d, 0x01, 0x20, 0x01, 0x41, + 0x7f, 0x46, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x7f, 0x46, 0x0d, 0x01, 0x20, + 0x00, 0x20, 0x01, 0x6b, 0x22, 0x05, 0x20, 0x06, 0x41, 0x38, 0x6a, 0x4d, + 0x0d, 0x01, 0x0b, 0x41, 0xa0, 0x1f, 0x41, 0xa0, 0x1f, 0x28, 0x02, 0x00, + 0x20, 0x05, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, 0xa4, + 0x1f, 0x28, 0x02, 0x00, 0x4b, 0x04, 0x40, 0x41, 0xa4, 0x1f, 0x20, 0x00, + 0x36, 0x02, 0x00, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x41, 0x88, + 0x1c, 0x28, 0x02, 0x00, 0x22, 0x07, 0x04, 0x40, 0x41, 0xb0, 0x1f, 0x21, + 0x00, 0x03, 0x40, 0x20, 0x01, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x02, + 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x03, 0x6a, 0x46, 0x0d, 0x02, 0x20, + 0x00, 0x28, 0x02, 0x08, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x0c, 0x02, 0x0b, + 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, 0x22, 0x00, 0x41, 0x00, 0x20, 0x01, + 0x20, 0x00, 0x4f, 0x1b, 0x45, 0x04, 0x40, 0x41, 0x80, 0x1c, 0x20, 0x01, + 0x36, 0x02, 0x00, 0x0b, 0x41, 0x00, 0x21, 0x00, 0x41, 0xb4, 0x1f, 0x20, + 0x05, 0x36, 0x02, 0x00, 0x41, 0xb0, 0x1f, 0x20, 0x01, 0x36, 0x02, 0x00, + 0x41, 0x90, 0x1c, 0x41, 0x7f, 0x36, 0x02, 0x00, 0x41, 0x94, 0x1c, 0x41, + 0xc8, 0x1f, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x41, 0xbc, 0x1f, 0x41, + 0x00, 0x36, 0x02, 0x00, 0x03, 0x40, 0x20, 0x00, 0x41, 0xa0, 0x1c, 0x6a, + 0x20, 0x00, 0x41, 0x98, 0x1c, 0x6a, 0x22, 0x02, 0x36, 0x02, 0x00, 0x20, + 0x00, 0x41, 0xa4, 0x1c, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x00, + 0x41, 0x08, 0x6a, 0x22, 0x00, 0x41, 0x80, 0x02, 0x47, 0x0d, 0x00, 0x0b, + 0x20, 0x01, 0x41, 0x78, 0x20, 0x01, 0x6b, 0x41, 0x0f, 0x71, 0x41, 0x00, + 0x20, 0x01, 0x41, 0x08, 0x6a, 0x41, 0x0f, 0x71, 0x1b, 0x22, 0x00, 0x6a, + 0x22, 0x02, 0x20, 0x05, 0x41, 0x48, 0x6a, 0x22, 0x03, 0x20, 0x00, 0x6b, + 0x22, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x41, 0x8c, 0x1c, 0x41, + 0xd8, 0x1f, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x41, 0xfc, 0x1b, 0x20, + 0x00, 0x36, 0x02, 0x00, 0x41, 0x88, 0x1c, 0x20, 0x02, 0x36, 0x02, 0x00, + 0x20, 0x01, 0x20, 0x03, 0x6a, 0x41, 0x38, 0x36, 0x02, 0x04, 0x0c, 0x02, + 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x0c, 0x41, 0x08, 0x71, 0x0d, 0x00, 0x20, + 0x01, 0x20, 0x07, 0x4d, 0x0d, 0x00, 0x20, 0x02, 0x20, 0x07, 0x4b, 0x0d, + 0x00, 0x20, 0x07, 0x41, 0x78, 0x20, 0x07, 0x6b, 0x41, 0x0f, 0x71, 0x41, + 0x00, 0x20, 0x07, 0x41, 0x08, 0x6a, 0x41, 0x0f, 0x71, 0x1b, 0x22, 0x01, + 0x6a, 0x22, 0x02, 0x41, 0xfc, 0x1b, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, + 0x22, 0x04, 0x20, 0x01, 0x6b, 0x22, 0x01, 0x41, 0x01, 0x72, 0x36, 0x02, + 0x04, 0x20, 0x00, 0x20, 0x03, 0x20, 0x05, 0x6a, 0x36, 0x02, 0x04, 0x41, + 0x8c, 0x1c, 0x41, 0xd8, 0x1f, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x41, + 0xfc, 0x1b, 0x20, 0x01, 0x36, 0x02, 0x00, 0x41, 0x88, 0x1c, 0x20, 0x02, + 0x36, 0x02, 0x00, 0x20, 0x04, 0x20, 0x07, 0x6a, 0x41, 0x38, 0x36, 0x02, + 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, + 0x22, 0x03, 0x49, 0x04, 0x40, 0x41, 0x80, 0x1c, 0x20, 0x01, 0x36, 0x02, + 0x00, 0x20, 0x01, 0x21, 0x03, 0x0b, 0x20, 0x01, 0x20, 0x05, 0x6a, 0x21, + 0x02, 0x41, 0xb0, 0x1f, 0x21, 0x00, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0x40, 0x20, 0x02, 0x20, 0x00, + 0x28, 0x02, 0x00, 0x47, 0x04, 0x40, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, + 0x00, 0x0d, 0x01, 0x0c, 0x02, 0x0b, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x0c, + 0x41, 0x08, 0x71, 0x45, 0x0d, 0x01, 0x0b, 0x41, 0xb0, 0x1f, 0x21, 0x00, + 0x03, 0x40, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x02, 0x20, 0x07, 0x4d, + 0x04, 0x40, 0x20, 0x02, 0x20, 0x00, 0x28, 0x02, 0x04, 0x6a, 0x22, 0x03, + 0x20, 0x07, 0x4b, 0x0d, 0x03, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x08, 0x21, + 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x04, 0x20, 0x05, 0x6a, 0x36, + 0x02, 0x04, 0x20, 0x01, 0x41, 0x78, 0x20, 0x01, 0x6b, 0x41, 0x0f, 0x71, + 0x41, 0x00, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x41, 0x0f, 0x71, 0x1b, 0x6a, + 0x22, 0x08, 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, 0x02, + 0x41, 0x78, 0x20, 0x02, 0x6b, 0x41, 0x0f, 0x71, 0x41, 0x00, 0x20, 0x02, + 0x41, 0x08, 0x6a, 0x41, 0x0f, 0x71, 0x1b, 0x6a, 0x22, 0x01, 0x20, 0x08, + 0x6b, 0x20, 0x06, 0x6b, 0x21, 0x00, 0x20, 0x06, 0x20, 0x08, 0x6a, 0x21, + 0x04, 0x20, 0x01, 0x20, 0x07, 0x46, 0x04, 0x40, 0x41, 0x88, 0x1c, 0x20, + 0x04, 0x36, 0x02, 0x00, 0x41, 0xfc, 0x1b, 0x41, 0xfc, 0x1b, 0x28, 0x02, + 0x00, 0x20, 0x00, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x04, 0x20, + 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x0c, 0x03, 0x0b, 0x20, 0x01, + 0x41, 0x84, 0x1c, 0x28, 0x02, 0x00, 0x46, 0x04, 0x40, 0x41, 0x84, 0x1c, + 0x20, 0x04, 0x36, 0x02, 0x00, 0x41, 0xf8, 0x1b, 0x41, 0xf8, 0x1b, 0x28, + 0x02, 0x00, 0x20, 0x00, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x04, + 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x00, 0x20, 0x04, + 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x0c, 0x03, 0x0b, 0x20, 0x01, 0x28, + 0x02, 0x04, 0x22, 0x06, 0x41, 0x03, 0x71, 0x41, 0x01, 0x46, 0x04, 0x40, + 0x20, 0x06, 0x41, 0x78, 0x71, 0x21, 0x09, 0x02, 0x40, 0x20, 0x06, 0x41, + 0xff, 0x01, 0x4d, 0x04, 0x40, 0x20, 0x01, 0x28, 0x02, 0x08, 0x22, 0x03, + 0x20, 0x06, 0x41, 0x03, 0x76, 0x22, 0x06, 0x41, 0x03, 0x74, 0x41, 0x98, + 0x1c, 0x6a, 0x47, 0x1a, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x22, + 0x02, 0x46, 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x41, 0xf0, 0x1b, 0x28, 0x02, + 0x00, 0x41, 0x7e, 0x20, 0x06, 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, 0x02, + 0x0b, 0x20, 0x02, 0x20, 0x03, 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, 0x02, + 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x18, 0x21, + 0x07, 0x02, 0x40, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x22, 0x05, + 0x47, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x08, 0x22, 0x02, + 0x4d, 0x04, 0x40, 0x20, 0x02, 0x28, 0x02, 0x0c, 0x1a, 0x0b, 0x20, 0x05, + 0x20, 0x02, 0x36, 0x02, 0x08, 0x20, 0x02, 0x20, 0x05, 0x36, 0x02, 0x0c, + 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x01, 0x41, 0x14, 0x6a, 0x22, 0x02, + 0x28, 0x02, 0x00, 0x22, 0x06, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x10, 0x6a, + 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x06, 0x0d, 0x00, 0x41, 0x00, 0x21, + 0x05, 0x0c, 0x01, 0x0b, 0x03, 0x40, 0x20, 0x02, 0x21, 0x03, 0x20, 0x06, + 0x22, 0x05, 0x41, 0x14, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x06, + 0x0d, 0x00, 0x20, 0x05, 0x41, 0x10, 0x6a, 0x21, 0x02, 0x20, 0x05, 0x28, + 0x02, 0x10, 0x22, 0x06, 0x0d, 0x00, 0x0b, 0x20, 0x03, 0x41, 0x00, 0x36, + 0x02, 0x00, 0x0b, 0x20, 0x07, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x01, + 0x20, 0x01, 0x28, 0x02, 0x1c, 0x22, 0x02, 0x41, 0x02, 0x74, 0x41, 0xa0, + 0x1e, 0x6a, 0x22, 0x03, 0x28, 0x02, 0x00, 0x46, 0x04, 0x40, 0x20, 0x03, + 0x20, 0x05, 0x36, 0x02, 0x00, 0x20, 0x05, 0x0d, 0x01, 0x41, 0xf4, 0x1b, + 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, 0x41, 0x7e, 0x20, 0x02, 0x77, 0x71, + 0x36, 0x02, 0x00, 0x0c, 0x02, 0x0b, 0x20, 0x07, 0x41, 0x10, 0x41, 0x14, + 0x20, 0x07, 0x28, 0x02, 0x10, 0x20, 0x01, 0x46, 0x1b, 0x6a, 0x20, 0x05, + 0x36, 0x02, 0x00, 0x20, 0x05, 0x45, 0x0d, 0x01, 0x0b, 0x20, 0x05, 0x20, + 0x07, 0x36, 0x02, 0x18, 0x20, 0x01, 0x28, 0x02, 0x10, 0x22, 0x02, 0x04, + 0x40, 0x20, 0x05, 0x20, 0x02, 0x36, 0x02, 0x10, 0x20, 0x02, 0x20, 0x05, + 0x36, 0x02, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x14, 0x22, 0x02, 0x45, + 0x0d, 0x00, 0x20, 0x05, 0x41, 0x14, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, + 0x20, 0x02, 0x20, 0x05, 0x36, 0x02, 0x18, 0x0b, 0x20, 0x01, 0x20, 0x09, + 0x6a, 0x21, 0x01, 0x20, 0x00, 0x20, 0x09, 0x6a, 0x21, 0x00, 0x0b, 0x20, + 0x01, 0x20, 0x01, 0x28, 0x02, 0x04, 0x41, 0x7e, 0x71, 0x36, 0x02, 0x04, + 0x20, 0x00, 0x20, 0x04, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x04, + 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x00, 0x41, 0xff, + 0x01, 0x4d, 0x04, 0x40, 0x20, 0x00, 0x41, 0x03, 0x76, 0x22, 0x01, 0x41, + 0x03, 0x74, 0x41, 0x98, 0x1c, 0x6a, 0x21, 0x00, 0x02, 0x7f, 0x41, 0xf0, + 0x1b, 0x28, 0x02, 0x00, 0x22, 0x02, 0x41, 0x01, 0x20, 0x01, 0x74, 0x22, + 0x01, 0x71, 0x45, 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x01, 0x20, 0x02, + 0x72, 0x36, 0x02, 0x00, 0x20, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x28, + 0x02, 0x08, 0x0b, 0x22, 0x02, 0x20, 0x04, 0x36, 0x02, 0x0c, 0x20, 0x00, + 0x20, 0x04, 0x36, 0x02, 0x08, 0x20, 0x04, 0x20, 0x00, 0x36, 0x02, 0x0c, + 0x20, 0x04, 0x20, 0x02, 0x36, 0x02, 0x08, 0x0c, 0x03, 0x0b, 0x20, 0x04, + 0x02, 0x7f, 0x41, 0x00, 0x20, 0x00, 0x41, 0x08, 0x76, 0x22, 0x01, 0x45, + 0x0d, 0x00, 0x1a, 0x41, 0x1f, 0x20, 0x00, 0x41, 0xff, 0xff, 0xff, 0x07, + 0x4b, 0x0d, 0x00, 0x1a, 0x20, 0x01, 0x20, 0x01, 0x41, 0x80, 0xfe, 0x3f, + 0x6a, 0x41, 0x10, 0x76, 0x41, 0x08, 0x71, 0x22, 0x01, 0x74, 0x22, 0x02, + 0x20, 0x02, 0x41, 0x80, 0xe0, 0x1f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x04, + 0x71, 0x22, 0x02, 0x74, 0x22, 0x03, 0x20, 0x03, 0x41, 0x80, 0x80, 0x0f, + 0x6a, 0x41, 0x10, 0x76, 0x41, 0x02, 0x71, 0x22, 0x03, 0x74, 0x41, 0x0f, + 0x76, 0x20, 0x01, 0x20, 0x02, 0x72, 0x20, 0x03, 0x72, 0x6b, 0x22, 0x01, + 0x41, 0x01, 0x74, 0x20, 0x00, 0x20, 0x01, 0x41, 0x15, 0x6a, 0x76, 0x41, + 0x01, 0x71, 0x72, 0x41, 0x1c, 0x6a, 0x0b, 0x22, 0x02, 0x36, 0x02, 0x1c, + 0x20, 0x04, 0x42, 0x00, 0x37, 0x02, 0x10, 0x20, 0x02, 0x41, 0x02, 0x74, + 0x41, 0xa0, 0x1e, 0x6a, 0x21, 0x01, 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, + 0x22, 0x03, 0x41, 0x01, 0x20, 0x02, 0x74, 0x22, 0x06, 0x71, 0x45, 0x04, + 0x40, 0x20, 0x01, 0x20, 0x04, 0x36, 0x02, 0x00, 0x41, 0xf4, 0x1b, 0x20, + 0x03, 0x20, 0x06, 0x72, 0x36, 0x02, 0x00, 0x20, 0x04, 0x20, 0x01, 0x36, + 0x02, 0x18, 0x20, 0x04, 0x20, 0x04, 0x36, 0x02, 0x08, 0x20, 0x04, 0x20, + 0x04, 0x36, 0x02, 0x0c, 0x0c, 0x03, 0x0b, 0x20, 0x00, 0x41, 0x00, 0x41, + 0x19, 0x20, 0x02, 0x41, 0x01, 0x76, 0x6b, 0x20, 0x02, 0x41, 0x1f, 0x46, + 0x1b, 0x74, 0x21, 0x02, 0x20, 0x01, 0x28, 0x02, 0x00, 0x21, 0x01, 0x03, + 0x40, 0x20, 0x01, 0x22, 0x03, 0x28, 0x02, 0x04, 0x41, 0x78, 0x71, 0x20, + 0x00, 0x46, 0x0d, 0x02, 0x20, 0x02, 0x41, 0x1d, 0x76, 0x21, 0x01, 0x20, + 0x02, 0x41, 0x01, 0x74, 0x21, 0x02, 0x20, 0x03, 0x20, 0x01, 0x41, 0x04, + 0x71, 0x6a, 0x41, 0x10, 0x6a, 0x22, 0x06, 0x28, 0x02, 0x00, 0x22, 0x01, + 0x0d, 0x00, 0x0b, 0x20, 0x06, 0x20, 0x04, 0x36, 0x02, 0x00, 0x20, 0x04, + 0x20, 0x03, 0x36, 0x02, 0x18, 0x20, 0x04, 0x20, 0x04, 0x36, 0x02, 0x0c, + 0x20, 0x04, 0x20, 0x04, 0x36, 0x02, 0x08, 0x0c, 0x02, 0x0b, 0x20, 0x01, + 0x41, 0x78, 0x20, 0x01, 0x6b, 0x41, 0x0f, 0x71, 0x41, 0x00, 0x20, 0x01, + 0x41, 0x08, 0x6a, 0x41, 0x0f, 0x71, 0x1b, 0x22, 0x00, 0x6a, 0x22, 0x04, + 0x20, 0x05, 0x41, 0x48, 0x6a, 0x22, 0x02, 0x20, 0x00, 0x6b, 0x22, 0x00, + 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x01, 0x20, 0x02, 0x6a, 0x41, + 0x38, 0x36, 0x02, 0x04, 0x20, 0x07, 0x20, 0x03, 0x41, 0x37, 0x20, 0x03, + 0x6b, 0x41, 0x0f, 0x71, 0x41, 0x00, 0x20, 0x03, 0x41, 0x49, 0x6a, 0x41, + 0x0f, 0x71, 0x1b, 0x6a, 0x41, 0x41, 0x6a, 0x22, 0x02, 0x20, 0x02, 0x20, + 0x07, 0x41, 0x10, 0x6a, 0x49, 0x1b, 0x22, 0x02, 0x41, 0x23, 0x36, 0x02, + 0x04, 0x41, 0x8c, 0x1c, 0x41, 0xd8, 0x1f, 0x28, 0x02, 0x00, 0x36, 0x02, + 0x00, 0x41, 0xfc, 0x1b, 0x20, 0x00, 0x36, 0x02, 0x00, 0x41, 0x88, 0x1c, + 0x20, 0x04, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x41, 0xb8, + 0x1f, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x02, 0x41, 0xb0, 0x1f, + 0x29, 0x02, 0x00, 0x37, 0x02, 0x08, 0x41, 0xb8, 0x1f, 0x20, 0x02, 0x41, + 0x08, 0x6a, 0x36, 0x02, 0x00, 0x41, 0xb4, 0x1f, 0x20, 0x05, 0x36, 0x02, + 0x00, 0x41, 0xb0, 0x1f, 0x20, 0x01, 0x36, 0x02, 0x00, 0x41, 0xbc, 0x1f, + 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x24, 0x6a, 0x21, 0x00, + 0x03, 0x40, 0x20, 0x00, 0x41, 0x07, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, + 0x04, 0x6a, 0x22, 0x00, 0x20, 0x03, 0x49, 0x0d, 0x00, 0x0b, 0x20, 0x02, + 0x20, 0x07, 0x46, 0x0d, 0x03, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x04, + 0x41, 0x7e, 0x71, 0x36, 0x02, 0x04, 0x20, 0x02, 0x20, 0x02, 0x20, 0x07, + 0x6b, 0x22, 0x03, 0x36, 0x02, 0x00, 0x20, 0x07, 0x20, 0x03, 0x41, 0x01, + 0x72, 0x36, 0x02, 0x04, 0x20, 0x03, 0x41, 0xff, 0x01, 0x4d, 0x04, 0x40, + 0x20, 0x03, 0x41, 0x03, 0x76, 0x22, 0x01, 0x41, 0x03, 0x74, 0x41, 0x98, + 0x1c, 0x6a, 0x21, 0x00, 0x02, 0x7f, 0x41, 0xf0, 0x1b, 0x28, 0x02, 0x00, + 0x22, 0x02, 0x41, 0x01, 0x20, 0x01, 0x74, 0x22, 0x01, 0x71, 0x45, 0x04, + 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x01, 0x20, 0x02, 0x72, 0x36, 0x02, 0x00, + 0x20, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x08, 0x0b, 0x22, + 0x04, 0x20, 0x07, 0x36, 0x02, 0x0c, 0x20, 0x00, 0x20, 0x07, 0x36, 0x02, + 0x08, 0x20, 0x07, 0x20, 0x00, 0x36, 0x02, 0x0c, 0x20, 0x07, 0x20, 0x04, + 0x36, 0x02, 0x08, 0x0c, 0x04, 0x0b, 0x20, 0x07, 0x42, 0x00, 0x37, 0x02, + 0x10, 0x20, 0x07, 0x41, 0x1c, 0x6a, 0x02, 0x7f, 0x41, 0x00, 0x20, 0x03, + 0x41, 0x08, 0x76, 0x22, 0x01, 0x45, 0x0d, 0x00, 0x1a, 0x41, 0x1f, 0x20, + 0x03, 0x41, 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x00, 0x1a, 0x20, 0x01, + 0x20, 0x01, 0x41, 0x80, 0xfe, 0x3f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x08, + 0x71, 0x22, 0x00, 0x74, 0x22, 0x01, 0x20, 0x01, 0x41, 0x80, 0xe0, 0x1f, + 0x6a, 0x41, 0x10, 0x76, 0x41, 0x04, 0x71, 0x22, 0x01, 0x74, 0x22, 0x02, + 0x20, 0x02, 0x41, 0x80, 0x80, 0x0f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x02, + 0x71, 0x22, 0x02, 0x74, 0x41, 0x0f, 0x76, 0x20, 0x00, 0x20, 0x01, 0x72, + 0x20, 0x02, 0x72, 0x6b, 0x22, 0x00, 0x41, 0x01, 0x74, 0x20, 0x03, 0x20, + 0x00, 0x41, 0x15, 0x6a, 0x76, 0x41, 0x01, 0x71, 0x72, 0x41, 0x1c, 0x6a, + 0x0b, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, 0x02, 0x74, 0x41, + 0xa0, 0x1e, 0x6a, 0x21, 0x01, 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, 0x22, + 0x02, 0x41, 0x01, 0x20, 0x00, 0x74, 0x22, 0x04, 0x71, 0x45, 0x04, 0x40, + 0x20, 0x01, 0x20, 0x07, 0x36, 0x02, 0x00, 0x41, 0xf4, 0x1b, 0x20, 0x02, + 0x20, 0x04, 0x72, 0x36, 0x02, 0x00, 0x20, 0x07, 0x41, 0x18, 0x6a, 0x20, + 0x01, 0x36, 0x02, 0x00, 0x20, 0x07, 0x20, 0x07, 0x36, 0x02, 0x08, 0x20, + 0x07, 0x20, 0x07, 0x36, 0x02, 0x0c, 0x0c, 0x04, 0x0b, 0x20, 0x03, 0x41, + 0x00, 0x41, 0x19, 0x20, 0x00, 0x41, 0x01, 0x76, 0x6b, 0x20, 0x00, 0x41, + 0x1f, 0x46, 0x1b, 0x74, 0x21, 0x00, 0x20, 0x01, 0x28, 0x02, 0x00, 0x21, + 0x01, 0x03, 0x40, 0x20, 0x01, 0x22, 0x02, 0x28, 0x02, 0x04, 0x41, 0x78, + 0x71, 0x20, 0x03, 0x46, 0x0d, 0x03, 0x20, 0x00, 0x41, 0x1d, 0x76, 0x21, + 0x01, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x00, 0x20, 0x02, 0x20, 0x01, + 0x41, 0x04, 0x71, 0x6a, 0x41, 0x10, 0x6a, 0x22, 0x04, 0x28, 0x02, 0x00, + 0x22, 0x01, 0x0d, 0x00, 0x0b, 0x20, 0x04, 0x20, 0x07, 0x36, 0x02, 0x00, + 0x20, 0x07, 0x41, 0x18, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x07, + 0x20, 0x07, 0x36, 0x02, 0x0c, 0x20, 0x07, 0x20, 0x07, 0x36, 0x02, 0x08, + 0x0c, 0x03, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x08, 0x21, 0x00, 0x20, 0x03, + 0x20, 0x04, 0x36, 0x02, 0x08, 0x20, 0x00, 0x20, 0x04, 0x36, 0x02, 0x0c, + 0x20, 0x04, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x04, 0x20, 0x00, 0x36, + 0x02, 0x08, 0x20, 0x04, 0x20, 0x03, 0x36, 0x02, 0x0c, 0x0b, 0x20, 0x08, + 0x41, 0x08, 0x6a, 0x21, 0x00, 0x0c, 0x05, 0x0b, 0x20, 0x02, 0x28, 0x02, + 0x08, 0x21, 0x00, 0x20, 0x02, 0x20, 0x07, 0x36, 0x02, 0x08, 0x20, 0x00, + 0x20, 0x07, 0x36, 0x02, 0x0c, 0x20, 0x07, 0x41, 0x18, 0x6a, 0x41, 0x00, + 0x36, 0x02, 0x00, 0x20, 0x07, 0x20, 0x00, 0x36, 0x02, 0x08, 0x20, 0x07, + 0x20, 0x02, 0x36, 0x02, 0x0c, 0x0b, 0x41, 0xfc, 0x1b, 0x28, 0x02, 0x00, + 0x22, 0x01, 0x20, 0x06, 0x4d, 0x0d, 0x00, 0x41, 0x88, 0x1c, 0x28, 0x02, + 0x00, 0x22, 0x00, 0x20, 0x06, 0x6a, 0x22, 0x02, 0x20, 0x01, 0x20, 0x06, + 0x6b, 0x22, 0x01, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x41, 0xfc, 0x1b, + 0x20, 0x01, 0x36, 0x02, 0x00, 0x41, 0x88, 0x1c, 0x20, 0x02, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, + 0x00, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x0c, 0x03, 0x0b, 0x41, 0x00, 0x21, + 0x00, 0x41, 0xe0, 0x1f, 0x41, 0x30, 0x36, 0x02, 0x00, 0x0c, 0x02, 0x0b, + 0x02, 0x40, 0x20, 0x07, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x03, 0x28, + 0x02, 0x1c, 0x22, 0x00, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, 0x22, + 0x02, 0x28, 0x02, 0x00, 0x20, 0x03, 0x46, 0x04, 0x40, 0x20, 0x02, 0x20, + 0x01, 0x36, 0x02, 0x00, 0x20, 0x01, 0x0d, 0x01, 0x41, 0xf4, 0x1b, 0x20, + 0x08, 0x41, 0x7e, 0x20, 0x00, 0x77, 0x71, 0x22, 0x08, 0x36, 0x02, 0x00, + 0x0c, 0x02, 0x0b, 0x20, 0x07, 0x41, 0x10, 0x41, 0x14, 0x20, 0x07, 0x28, + 0x02, 0x10, 0x20, 0x03, 0x46, 0x1b, 0x6a, 0x20, 0x01, 0x36, 0x02, 0x00, + 0x20, 0x01, 0x45, 0x0d, 0x01, 0x0b, 0x20, 0x01, 0x20, 0x07, 0x36, 0x02, + 0x18, 0x20, 0x03, 0x28, 0x02, 0x10, 0x22, 0x00, 0x04, 0x40, 0x20, 0x01, + 0x20, 0x00, 0x36, 0x02, 0x10, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x18, + 0x0b, 0x20, 0x03, 0x41, 0x14, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, + 0x0d, 0x00, 0x20, 0x01, 0x41, 0x14, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, + 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x18, 0x0b, 0x02, 0x40, 0x20, 0x04, + 0x41, 0x0f, 0x4d, 0x04, 0x40, 0x20, 0x03, 0x20, 0x04, 0x20, 0x06, 0x6a, + 0x22, 0x00, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, 0x00, 0x20, 0x03, + 0x6a, 0x22, 0x00, 0x20, 0x00, 0x28, 0x02, 0x04, 0x41, 0x01, 0x72, 0x36, + 0x02, 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x20, 0x06, 0x6a, 0x22, 0x05, + 0x20, 0x04, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x03, 0x20, 0x06, + 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, 0x04, 0x20, 0x05, 0x6a, 0x20, + 0x04, 0x36, 0x02, 0x00, 0x20, 0x04, 0x41, 0xff, 0x01, 0x4d, 0x04, 0x40, + 0x20, 0x04, 0x41, 0x03, 0x76, 0x22, 0x01, 0x41, 0x03, 0x74, 0x41, 0x98, + 0x1c, 0x6a, 0x21, 0x00, 0x02, 0x7f, 0x41, 0xf0, 0x1b, 0x28, 0x02, 0x00, + 0x22, 0x02, 0x41, 0x01, 0x20, 0x01, 0x74, 0x22, 0x01, 0x71, 0x45, 0x04, + 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x01, 0x20, 0x02, 0x72, 0x36, 0x02, 0x00, + 0x20, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x08, 0x0b, 0x22, + 0x02, 0x20, 0x05, 0x36, 0x02, 0x0c, 0x20, 0x00, 0x20, 0x05, 0x36, 0x02, + 0x08, 0x20, 0x05, 0x20, 0x00, 0x36, 0x02, 0x0c, 0x20, 0x05, 0x20, 0x02, + 0x36, 0x02, 0x08, 0x0c, 0x01, 0x0b, 0x20, 0x05, 0x02, 0x7f, 0x41, 0x00, + 0x20, 0x04, 0x41, 0x08, 0x76, 0x22, 0x01, 0x45, 0x0d, 0x00, 0x1a, 0x41, + 0x1f, 0x20, 0x04, 0x41, 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x00, 0x1a, + 0x20, 0x01, 0x20, 0x01, 0x41, 0x80, 0xfe, 0x3f, 0x6a, 0x41, 0x10, 0x76, + 0x41, 0x08, 0x71, 0x22, 0x00, 0x74, 0x22, 0x01, 0x20, 0x01, 0x41, 0x80, + 0xe0, 0x1f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x04, 0x71, 0x22, 0x01, 0x74, + 0x22, 0x02, 0x20, 0x02, 0x41, 0x80, 0x80, 0x0f, 0x6a, 0x41, 0x10, 0x76, + 0x41, 0x02, 0x71, 0x22, 0x02, 0x74, 0x41, 0x0f, 0x76, 0x20, 0x00, 0x20, + 0x01, 0x72, 0x20, 0x02, 0x72, 0x6b, 0x22, 0x00, 0x41, 0x01, 0x74, 0x20, + 0x04, 0x20, 0x00, 0x41, 0x15, 0x6a, 0x76, 0x41, 0x01, 0x71, 0x72, 0x41, + 0x1c, 0x6a, 0x0b, 0x22, 0x00, 0x36, 0x02, 0x1c, 0x20, 0x05, 0x42, 0x00, + 0x37, 0x02, 0x10, 0x20, 0x00, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, + 0x21, 0x01, 0x20, 0x08, 0x41, 0x01, 0x20, 0x00, 0x74, 0x22, 0x02, 0x71, + 0x45, 0x04, 0x40, 0x20, 0x01, 0x20, 0x05, 0x36, 0x02, 0x00, 0x41, 0xf4, + 0x1b, 0x20, 0x02, 0x20, 0x08, 0x72, 0x36, 0x02, 0x00, 0x20, 0x05, 0x20, + 0x01, 0x36, 0x02, 0x18, 0x20, 0x05, 0x20, 0x05, 0x36, 0x02, 0x08, 0x20, + 0x05, 0x20, 0x05, 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x04, 0x41, + 0x00, 0x41, 0x19, 0x20, 0x00, 0x41, 0x01, 0x76, 0x6b, 0x20, 0x00, 0x41, + 0x1f, 0x46, 0x1b, 0x74, 0x21, 0x00, 0x20, 0x01, 0x28, 0x02, 0x00, 0x21, + 0x06, 0x02, 0x40, 0x03, 0x40, 0x20, 0x06, 0x22, 0x01, 0x28, 0x02, 0x04, + 0x41, 0x78, 0x71, 0x20, 0x04, 0x46, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x1d, + 0x76, 0x21, 0x02, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x00, 0x20, 0x01, + 0x20, 0x02, 0x41, 0x04, 0x71, 0x6a, 0x41, 0x10, 0x6a, 0x22, 0x02, 0x28, + 0x02, 0x00, 0x22, 0x06, 0x0d, 0x00, 0x0b, 0x20, 0x02, 0x20, 0x05, 0x36, + 0x02, 0x00, 0x20, 0x05, 0x20, 0x01, 0x36, 0x02, 0x18, 0x20, 0x05, 0x20, + 0x05, 0x36, 0x02, 0x0c, 0x20, 0x05, 0x20, 0x05, 0x36, 0x02, 0x08, 0x0c, + 0x01, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x08, 0x21, 0x00, 0x20, 0x01, 0x20, + 0x05, 0x36, 0x02, 0x08, 0x20, 0x00, 0x20, 0x05, 0x36, 0x02, 0x0c, 0x20, + 0x05, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x05, 0x20, 0x00, 0x36, 0x02, + 0x08, 0x20, 0x05, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x0b, 0x20, 0x03, 0x41, + 0x08, 0x6a, 0x21, 0x00, 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x09, 0x45, + 0x0d, 0x00, 0x02, 0x40, 0x20, 0x01, 0x28, 0x02, 0x1c, 0x22, 0x00, 0x41, + 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, 0x22, 0x04, 0x28, 0x02, 0x00, 0x20, + 0x01, 0x46, 0x04, 0x40, 0x20, 0x04, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, + 0x03, 0x0d, 0x01, 0x41, 0xf4, 0x1b, 0x20, 0x0a, 0x41, 0x7e, 0x20, 0x00, + 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, 0x02, 0x0b, 0x20, 0x09, 0x41, 0x10, + 0x41, 0x14, 0x20, 0x09, 0x28, 0x02, 0x10, 0x20, 0x01, 0x46, 0x1b, 0x6a, + 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, 0x03, 0x45, 0x0d, 0x01, 0x0b, 0x20, + 0x03, 0x20, 0x09, 0x36, 0x02, 0x18, 0x20, 0x01, 0x28, 0x02, 0x10, 0x22, + 0x00, 0x04, 0x40, 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x10, 0x20, 0x00, + 0x20, 0x03, 0x36, 0x02, 0x18, 0x0b, 0x20, 0x01, 0x41, 0x14, 0x6a, 0x28, + 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x20, 0x03, 0x41, 0x14, 0x6a, + 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x03, 0x36, 0x02, 0x18, + 0x0b, 0x02, 0x40, 0x20, 0x02, 0x41, 0x0f, 0x4d, 0x04, 0x40, 0x20, 0x01, + 0x20, 0x02, 0x20, 0x06, 0x6a, 0x22, 0x00, 0x41, 0x03, 0x72, 0x36, 0x02, + 0x04, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x22, 0x00, 0x20, 0x00, 0x28, 0x02, + 0x04, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x01, + 0x20, 0x06, 0x6a, 0x22, 0x07, 0x20, 0x02, 0x41, 0x01, 0x72, 0x36, 0x02, + 0x04, 0x20, 0x01, 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, + 0x02, 0x20, 0x07, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x08, 0x04, + 0x40, 0x20, 0x08, 0x41, 0x03, 0x76, 0x22, 0x03, 0x41, 0x03, 0x74, 0x41, + 0x98, 0x1c, 0x6a, 0x21, 0x00, 0x41, 0x84, 0x1c, 0x28, 0x02, 0x00, 0x21, + 0x04, 0x02, 0x7f, 0x41, 0x01, 0x20, 0x03, 0x74, 0x22, 0x03, 0x20, 0x05, + 0x71, 0x45, 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x03, 0x20, 0x05, 0x72, + 0x36, 0x02, 0x00, 0x20, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x28, 0x02, + 0x08, 0x0b, 0x22, 0x03, 0x20, 0x04, 0x36, 0x02, 0x0c, 0x20, 0x00, 0x20, + 0x04, 0x36, 0x02, 0x08, 0x20, 0x04, 0x20, 0x00, 0x36, 0x02, 0x0c, 0x20, + 0x04, 0x20, 0x03, 0x36, 0x02, 0x08, 0x0b, 0x41, 0x84, 0x1c, 0x20, 0x07, + 0x36, 0x02, 0x00, 0x41, 0xf8, 0x1b, 0x20, 0x02, 0x36, 0x02, 0x00, 0x0b, + 0x20, 0x01, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x0b, 0x20, 0x0b, 0x41, 0x10, + 0x6a, 0x24, 0x00, 0x20, 0x00, 0x0b, 0x9e, 0x0d, 0x01, 0x07, 0x7f, 0x02, + 0x40, 0x20, 0x00, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x78, 0x6a, 0x22, + 0x03, 0x20, 0x00, 0x41, 0x7c, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, + 0x78, 0x71, 0x22, 0x00, 0x6a, 0x21, 0x05, 0x02, 0x40, 0x20, 0x01, 0x41, + 0x01, 0x71, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x01, + 0x20, 0x03, 0x20, 0x03, 0x28, 0x02, 0x00, 0x22, 0x02, 0x6b, 0x22, 0x03, + 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, 0x22, 0x04, 0x49, 0x0d, 0x01, 0x20, + 0x00, 0x20, 0x02, 0x6a, 0x21, 0x00, 0x20, 0x03, 0x41, 0x84, 0x1c, 0x28, + 0x02, 0x00, 0x47, 0x04, 0x40, 0x20, 0x02, 0x41, 0xff, 0x01, 0x4d, 0x04, + 0x40, 0x20, 0x03, 0x28, 0x02, 0x08, 0x22, 0x04, 0x20, 0x02, 0x41, 0x03, + 0x76, 0x22, 0x02, 0x41, 0x03, 0x74, 0x41, 0x98, 0x1c, 0x6a, 0x47, 0x1a, + 0x20, 0x04, 0x20, 0x03, 0x28, 0x02, 0x0c, 0x22, 0x01, 0x46, 0x04, 0x40, + 0x41, 0xf0, 0x1b, 0x41, 0xf0, 0x1b, 0x28, 0x02, 0x00, 0x41, 0x7e, 0x20, + 0x02, 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, 0x03, 0x0b, 0x20, 0x01, 0x20, + 0x04, 0x36, 0x02, 0x08, 0x20, 0x04, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x0c, + 0x02, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x18, 0x21, 0x06, 0x02, 0x40, 0x20, + 0x03, 0x20, 0x03, 0x28, 0x02, 0x0c, 0x22, 0x01, 0x47, 0x04, 0x40, 0x20, + 0x04, 0x20, 0x03, 0x28, 0x02, 0x08, 0x22, 0x02, 0x4d, 0x04, 0x40, 0x20, + 0x02, 0x28, 0x02, 0x0c, 0x1a, 0x0b, 0x20, 0x01, 0x20, 0x02, 0x36, 0x02, + 0x08, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x02, + 0x40, 0x20, 0x03, 0x41, 0x14, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, + 0x04, 0x0d, 0x00, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x22, 0x02, 0x28, 0x02, + 0x00, 0x22, 0x04, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x01, 0x0c, 0x01, 0x0b, + 0x03, 0x40, 0x20, 0x02, 0x21, 0x07, 0x20, 0x04, 0x22, 0x01, 0x41, 0x14, + 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x04, 0x0d, 0x00, 0x20, 0x01, + 0x41, 0x10, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x28, 0x02, 0x10, 0x22, 0x04, + 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x41, 0x00, 0x36, 0x02, 0x00, 0x0b, 0x20, + 0x06, 0x45, 0x0d, 0x01, 0x02, 0x40, 0x20, 0x03, 0x20, 0x03, 0x28, 0x02, + 0x1c, 0x22, 0x02, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, 0x22, 0x04, + 0x28, 0x02, 0x00, 0x46, 0x04, 0x40, 0x20, 0x04, 0x20, 0x01, 0x36, 0x02, + 0x00, 0x20, 0x01, 0x0d, 0x01, 0x41, 0xf4, 0x1b, 0x41, 0xf4, 0x1b, 0x28, + 0x02, 0x00, 0x41, 0x7e, 0x20, 0x02, 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, + 0x03, 0x0b, 0x20, 0x06, 0x41, 0x10, 0x41, 0x14, 0x20, 0x06, 0x28, 0x02, + 0x10, 0x20, 0x03, 0x46, 0x1b, 0x6a, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, + 0x01, 0x45, 0x0d, 0x02, 0x0b, 0x20, 0x01, 0x20, 0x06, 0x36, 0x02, 0x18, + 0x20, 0x03, 0x28, 0x02, 0x10, 0x22, 0x02, 0x04, 0x40, 0x20, 0x01, 0x20, + 0x02, 0x36, 0x02, 0x10, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x18, 0x0b, + 0x20, 0x03, 0x28, 0x02, 0x14, 0x22, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x01, + 0x41, 0x14, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x02, 0x20, 0x01, + 0x36, 0x02, 0x18, 0x0c, 0x01, 0x0b, 0x20, 0x05, 0x28, 0x02, 0x04, 0x22, + 0x01, 0x41, 0x03, 0x71, 0x41, 0x03, 0x47, 0x0d, 0x00, 0x20, 0x05, 0x20, + 0x01, 0x41, 0x7e, 0x71, 0x36, 0x02, 0x04, 0x41, 0xf8, 0x1b, 0x20, 0x00, + 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x03, 0x6a, 0x20, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x03, 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x0f, + 0x0b, 0x20, 0x05, 0x20, 0x03, 0x4d, 0x0d, 0x00, 0x20, 0x05, 0x28, 0x02, + 0x04, 0x22, 0x01, 0x41, 0x01, 0x71, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, + 0x01, 0x41, 0x02, 0x71, 0x45, 0x04, 0x40, 0x20, 0x05, 0x41, 0x88, 0x1c, + 0x28, 0x02, 0x00, 0x46, 0x04, 0x40, 0x41, 0x88, 0x1c, 0x20, 0x03, 0x36, + 0x02, 0x00, 0x41, 0xfc, 0x1b, 0x41, 0xfc, 0x1b, 0x28, 0x02, 0x00, 0x20, + 0x00, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x00, 0x41, + 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x03, 0x41, 0x84, 0x1c, 0x28, 0x02, + 0x00, 0x47, 0x0d, 0x03, 0x41, 0xf8, 0x1b, 0x41, 0x00, 0x36, 0x02, 0x00, + 0x41, 0x84, 0x1c, 0x41, 0x00, 0x36, 0x02, 0x00, 0x0f, 0x0b, 0x20, 0x05, + 0x41, 0x84, 0x1c, 0x28, 0x02, 0x00, 0x46, 0x04, 0x40, 0x41, 0x84, 0x1c, + 0x20, 0x03, 0x36, 0x02, 0x00, 0x41, 0xf8, 0x1b, 0x41, 0xf8, 0x1b, 0x28, + 0x02, 0x00, 0x20, 0x00, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, + 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x00, 0x20, 0x03, + 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x0f, 0x0b, 0x20, 0x01, 0x41, 0x78, + 0x71, 0x20, 0x00, 0x6a, 0x21, 0x00, 0x02, 0x40, 0x20, 0x01, 0x41, 0xff, + 0x01, 0x4d, 0x04, 0x40, 0x20, 0x05, 0x28, 0x02, 0x0c, 0x21, 0x02, 0x20, + 0x05, 0x28, 0x02, 0x08, 0x22, 0x04, 0x20, 0x01, 0x41, 0x03, 0x76, 0x22, + 0x01, 0x41, 0x03, 0x74, 0x41, 0x98, 0x1c, 0x6a, 0x22, 0x07, 0x47, 0x04, + 0x40, 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, 0x1a, 0x0b, 0x20, 0x02, 0x20, + 0x04, 0x46, 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x41, 0xf0, 0x1b, 0x28, 0x02, + 0x00, 0x41, 0x7e, 0x20, 0x01, 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, 0x02, + 0x0b, 0x20, 0x02, 0x20, 0x07, 0x47, 0x04, 0x40, 0x41, 0x80, 0x1c, 0x28, + 0x02, 0x00, 0x1a, 0x0b, 0x20, 0x02, 0x20, 0x04, 0x36, 0x02, 0x08, 0x20, + 0x04, 0x20, 0x02, 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x05, 0x28, + 0x02, 0x18, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x20, 0x05, 0x28, 0x02, + 0x0c, 0x22, 0x01, 0x47, 0x04, 0x40, 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, + 0x20, 0x05, 0x28, 0x02, 0x08, 0x22, 0x02, 0x4d, 0x04, 0x40, 0x20, 0x02, + 0x28, 0x02, 0x0c, 0x1a, 0x0b, 0x20, 0x01, 0x20, 0x02, 0x36, 0x02, 0x08, + 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x02, 0x40, + 0x20, 0x05, 0x41, 0x14, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x04, + 0x0d, 0x00, 0x20, 0x05, 0x41, 0x10, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, + 0x22, 0x04, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x01, 0x0c, 0x01, 0x0b, 0x03, + 0x40, 0x20, 0x02, 0x21, 0x07, 0x20, 0x04, 0x22, 0x01, 0x41, 0x14, 0x6a, + 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x04, 0x0d, 0x00, 0x20, 0x01, 0x41, + 0x10, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x28, 0x02, 0x10, 0x22, 0x04, 0x0d, + 0x00, 0x0b, 0x20, 0x07, 0x41, 0x00, 0x36, 0x02, 0x00, 0x0b, 0x20, 0x06, + 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x05, 0x20, 0x05, 0x28, 0x02, 0x1c, + 0x22, 0x02, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, 0x22, 0x04, 0x28, + 0x02, 0x00, 0x46, 0x04, 0x40, 0x20, 0x04, 0x20, 0x01, 0x36, 0x02, 0x00, + 0x20, 0x01, 0x0d, 0x01, 0x41, 0xf4, 0x1b, 0x41, 0xf4, 0x1b, 0x28, 0x02, + 0x00, 0x41, 0x7e, 0x20, 0x02, 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, 0x02, + 0x0b, 0x20, 0x06, 0x41, 0x10, 0x41, 0x14, 0x20, 0x06, 0x28, 0x02, 0x10, + 0x20, 0x05, 0x46, 0x1b, 0x6a, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, 0x01, + 0x45, 0x0d, 0x01, 0x0b, 0x20, 0x01, 0x20, 0x06, 0x36, 0x02, 0x18, 0x20, + 0x05, 0x28, 0x02, 0x10, 0x22, 0x02, 0x04, 0x40, 0x20, 0x01, 0x20, 0x02, + 0x36, 0x02, 0x10, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x18, 0x0b, 0x20, + 0x05, 0x28, 0x02, 0x14, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x41, + 0x14, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x02, 0x20, 0x01, 0x36, + 0x02, 0x18, 0x0b, 0x20, 0x00, 0x20, 0x03, 0x6a, 0x20, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x03, 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, + 0x03, 0x41, 0x84, 0x1c, 0x28, 0x02, 0x00, 0x47, 0x0d, 0x01, 0x41, 0xf8, + 0x1b, 0x20, 0x00, 0x36, 0x02, 0x00, 0x0f, 0x0b, 0x20, 0x05, 0x20, 0x01, + 0x41, 0x7e, 0x71, 0x36, 0x02, 0x04, 0x20, 0x00, 0x20, 0x03, 0x6a, 0x20, + 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, + 0x02, 0x04, 0x0b, 0x20, 0x00, 0x41, 0xff, 0x01, 0x4d, 0x04, 0x40, 0x20, + 0x00, 0x41, 0x03, 0x76, 0x22, 0x01, 0x41, 0x03, 0x74, 0x41, 0x98, 0x1c, + 0x6a, 0x21, 0x00, 0x02, 0x7f, 0x41, 0xf0, 0x1b, 0x28, 0x02, 0x00, 0x22, + 0x02, 0x41, 0x01, 0x20, 0x01, 0x74, 0x22, 0x01, 0x71, 0x45, 0x04, 0x40, + 0x41, 0xf0, 0x1b, 0x20, 0x01, 0x20, 0x02, 0x72, 0x36, 0x02, 0x00, 0x20, + 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x08, 0x0b, 0x22, 0x02, + 0x20, 0x03, 0x36, 0x02, 0x0c, 0x20, 0x00, 0x20, 0x03, 0x36, 0x02, 0x08, + 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x0c, 0x20, 0x03, 0x20, 0x02, 0x36, + 0x02, 0x08, 0x0f, 0x0b, 0x20, 0x03, 0x42, 0x00, 0x37, 0x02, 0x10, 0x20, + 0x03, 0x41, 0x1c, 0x6a, 0x02, 0x7f, 0x41, 0x00, 0x20, 0x00, 0x41, 0x08, + 0x76, 0x22, 0x01, 0x45, 0x0d, 0x00, 0x1a, 0x41, 0x1f, 0x20, 0x00, 0x41, + 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x00, 0x1a, 0x20, 0x01, 0x20, 0x01, + 0x41, 0x80, 0xfe, 0x3f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x08, 0x71, 0x22, + 0x01, 0x74, 0x22, 0x02, 0x20, 0x02, 0x41, 0x80, 0xe0, 0x1f, 0x6a, 0x41, + 0x10, 0x76, 0x41, 0x04, 0x71, 0x22, 0x02, 0x74, 0x22, 0x04, 0x20, 0x04, + 0x41, 0x80, 0x80, 0x0f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x02, 0x71, 0x22, + 0x04, 0x74, 0x41, 0x0f, 0x76, 0x20, 0x01, 0x20, 0x02, 0x72, 0x20, 0x04, + 0x72, 0x6b, 0x22, 0x01, 0x41, 0x01, 0x74, 0x20, 0x00, 0x20, 0x01, 0x41, + 0x15, 0x6a, 0x76, 0x41, 0x01, 0x71, 0x72, 0x41, 0x1c, 0x6a, 0x0b, 0x22, + 0x02, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, + 0x6a, 0x21, 0x01, 0x02, 0x40, 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, 0x22, + 0x04, 0x41, 0x01, 0x20, 0x02, 0x74, 0x22, 0x07, 0x71, 0x45, 0x04, 0x40, + 0x20, 0x01, 0x20, 0x03, 0x36, 0x02, 0x00, 0x41, 0xf4, 0x1b, 0x20, 0x04, + 0x20, 0x07, 0x72, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x18, 0x6a, 0x20, + 0x01, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x03, 0x36, 0x02, 0x08, 0x20, + 0x03, 0x20, 0x03, 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x41, + 0x00, 0x41, 0x19, 0x20, 0x02, 0x41, 0x01, 0x76, 0x6b, 0x20, 0x02, 0x41, + 0x1f, 0x46, 0x1b, 0x74, 0x21, 0x02, 0x20, 0x01, 0x28, 0x02, 0x00, 0x21, + 0x01, 0x02, 0x40, 0x03, 0x40, 0x20, 0x01, 0x22, 0x04, 0x28, 0x02, 0x04, + 0x41, 0x78, 0x71, 0x20, 0x00, 0x46, 0x0d, 0x01, 0x20, 0x02, 0x41, 0x1d, + 0x76, 0x21, 0x01, 0x20, 0x02, 0x41, 0x01, 0x74, 0x21, 0x02, 0x20, 0x04, + 0x20, 0x01, 0x41, 0x04, 0x71, 0x6a, 0x41, 0x10, 0x6a, 0x22, 0x07, 0x28, + 0x02, 0x00, 0x22, 0x01, 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x20, 0x03, 0x36, + 0x02, 0x00, 0x20, 0x03, 0x20, 0x03, 0x36, 0x02, 0x0c, 0x20, 0x03, 0x41, + 0x18, 0x6a, 0x20, 0x04, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x03, 0x36, + 0x02, 0x08, 0x0c, 0x01, 0x0b, 0x20, 0x04, 0x28, 0x02, 0x08, 0x21, 0x00, + 0x20, 0x04, 0x20, 0x03, 0x36, 0x02, 0x08, 0x20, 0x00, 0x20, 0x03, 0x36, + 0x02, 0x0c, 0x20, 0x03, 0x41, 0x18, 0x6a, 0x41, 0x00, 0x36, 0x02, 0x00, + 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, 0x04, 0x36, + 0x02, 0x0c, 0x0b, 0x41, 0x90, 0x1c, 0x41, 0x90, 0x1c, 0x28, 0x02, 0x00, + 0x41, 0x7f, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x0d, 0x00, + 0x41, 0xb8, 0x1f, 0x21, 0x03, 0x03, 0x40, 0x20, 0x03, 0x28, 0x02, 0x00, + 0x22, 0x00, 0x41, 0x08, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x0d, 0x00, 0x0b, + 0x41, 0x90, 0x1c, 0x41, 0x7f, 0x36, 0x02, 0x00, 0x0b, 0x0b, 0x4c, 0x01, + 0x01, 0x7f, 0x02, 0x40, 0x02, 0x7f, 0x20, 0x00, 0x41, 0x18, 0x6c, 0x22, + 0x01, 0x20, 0x00, 0x41, 0x18, 0x72, 0x41, 0x80, 0x80, 0x04, 0x49, 0x0d, + 0x00, 0x1a, 0x20, 0x01, 0x41, 0x7f, 0x20, 0x01, 0x41, 0x18, 0x6e, 0x20, + 0x00, 0x46, 0x1b, 0x0b, 0x22, 0x01, 0x10, 0x14, 0x22, 0x00, 0x45, 0x0d, + 0x00, 0x20, 0x00, 0x41, 0x7c, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x03, 0x71, + 0x45, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x20, 0x01, 0x10, 0x3a, 0x0b, + 0x20, 0x00, 0x0b, 0x5d, 0x02, 0x02, 0x7f, 0x02, 0x7e, 0x23, 0x00, 0x41, + 0x10, 0x6b, 0x22, 0x01, 0x24, 0x00, 0x02, 0x40, 0x41, 0xa0, 0x09, 0x28, + 0x02, 0x00, 0x42, 0x01, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x10, 0x06, 0x22, + 0x02, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x20, 0x02, 0x36, 0x02, 0x00, 0x0c, + 0x01, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x29, 0x03, 0x08, 0x22, 0x03, 0x42, + 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x80, 0x22, 0x04, 0x37, 0x03, 0x00, 0x20, + 0x00, 0x20, 0x03, 0x20, 0x04, 0x42, 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x7e, + 0x7d, 0x3e, 0x02, 0x08, 0x0b, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x24, 0x00, + 0x0b, 0x07, 0x00, 0x20, 0x00, 0x10, 0x07, 0x00, 0x0b, 0x19, 0x00, 0x20, + 0x00, 0x10, 0x08, 0x22, 0x00, 0x45, 0x04, 0x40, 0x41, 0x00, 0x0f, 0x0b, + 0x41, 0xe0, 0x1f, 0x20, 0x00, 0x36, 0x02, 0x00, 0x41, 0x7f, 0x0b, 0x54, + 0x01, 0x01, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x02, 0x24, 0x00, + 0x20, 0x02, 0x41, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x02, 0x20, 0x01, 0x36, + 0x02, 0x08, 0x02, 0x7f, 0x20, 0x00, 0x20, 0x02, 0x41, 0x08, 0x6a, 0x41, + 0x01, 0x20, 0x02, 0x41, 0x04, 0x6a, 0x10, 0x09, 0x22, 0x00, 0x04, 0x40, + 0x41, 0xe0, 0x1f, 0x41, 0x08, 0x20, 0x00, 0x20, 0x00, 0x41, 0xcc, 0x00, + 0x46, 0x1b, 0x36, 0x02, 0x00, 0x41, 0x7f, 0x0c, 0x01, 0x0b, 0x20, 0x02, + 0x28, 0x02, 0x04, 0x0b, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x24, 0x00, 0x0b, + 0xaa, 0x01, 0x02, 0x02, 0x7f, 0x01, 0x7e, 0x23, 0x00, 0x41, 0x20, 0x6b, + 0x22, 0x03, 0x24, 0x00, 0x02, 0x40, 0x20, 0x00, 0x20, 0x03, 0x41, 0x08, + 0x6a, 0x10, 0x0a, 0x22, 0x02, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x20, 0x02, + 0x36, 0x02, 0x00, 0x41, 0x7f, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x20, 0x03, + 0x2d, 0x00, 0x08, 0x41, 0x03, 0x47, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, + 0x36, 0x36, 0x02, 0x00, 0x41, 0x7f, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x20, + 0x03, 0x29, 0x03, 0x18, 0x22, 0x04, 0x42, 0x02, 0x83, 0x42, 0x02, 0x52, + 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, 0xcc, 0x00, 0x36, 0x02, 0x00, 0x41, + 0x7f, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x41, 0x7f, 0x21, 0x02, 0x20, 0x00, + 0x41, 0x01, 0x20, 0x01, 0x20, 0x01, 0x10, 0x38, 0x41, 0x00, 0x20, 0x04, + 0x42, 0xbe, 0xfd, 0xff, 0x7d, 0x83, 0x20, 0x04, 0x41, 0x00, 0x20, 0x03, + 0x41, 0x04, 0x6a, 0x10, 0x0b, 0x22, 0x00, 0x04, 0x40, 0x41, 0xe0, 0x1f, + 0x20, 0x00, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x28, 0x02, + 0x04, 0x21, 0x02, 0x0c, 0x00, 0x0b, 0x20, 0x03, 0x41, 0x20, 0x6a, 0x24, + 0x00, 0x20, 0x02, 0x0b, 0x54, 0x01, 0x02, 0x7f, 0x23, 0x00, 0x41, 0x20, + 0x6b, 0x22, 0x01, 0x24, 0x00, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x20, 0x00, + 0x10, 0x1d, 0x41, 0x7f, 0x21, 0x00, 0x02, 0x40, 0x20, 0x01, 0x28, 0x02, + 0x10, 0x22, 0x02, 0x41, 0x7f, 0x46, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, + 0xcc, 0x00, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x28, 0x02, + 0x14, 0x21, 0x00, 0x20, 0x01, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x02, + 0x20, 0x00, 0x10, 0x1b, 0x21, 0x00, 0x0b, 0x20, 0x01, 0x41, 0x20, 0x6a, + 0x24, 0x00, 0x20, 0x00, 0x0b, 0x94, 0x04, 0x01, 0x0e, 0x7f, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x41, 0xe4, 0x1f, 0x28, 0x02, 0x00, 0x22, 0x03, + 0x45, 0x0d, 0x00, 0x20, 0x03, 0x10, 0x1e, 0x41, 0xe4, 0x1f, 0x28, 0x02, + 0x00, 0x22, 0x03, 0x10, 0x1e, 0x20, 0x01, 0x45, 0x04, 0x40, 0x41, 0x7f, + 0x21, 0x06, 0x0c, 0x03, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x0c, 0x22, 0x0b, + 0x45, 0x04, 0x40, 0x41, 0x7f, 0x21, 0x06, 0x0c, 0x02, 0x0b, 0x20, 0x03, + 0x28, 0x02, 0x04, 0x21, 0x0c, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x22, 0x09, + 0x41, 0x52, 0x6a, 0x22, 0x0d, 0x41, 0x01, 0x4b, 0x21, 0x0e, 0x41, 0x7f, + 0x21, 0x06, 0x03, 0x40, 0x20, 0x0c, 0x20, 0x0a, 0x41, 0x18, 0x6c, 0x6a, + 0x22, 0x07, 0x28, 0x02, 0x00, 0x22, 0x04, 0x10, 0x38, 0x21, 0x03, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, + 0x0e, 0x45, 0x04, 0x40, 0x20, 0x0d, 0x41, 0x01, 0x6b, 0x45, 0x0d, 0x01, + 0x20, 0x01, 0x2d, 0x00, 0x01, 0x22, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x02, + 0x41, 0x2f, 0x46, 0x0d, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x02, 0x4f, 0x04, + 0x40, 0x20, 0x04, 0x2d, 0x00, 0x00, 0x22, 0x02, 0x41, 0x2e, 0x47, 0x0d, + 0x03, 0x41, 0x2e, 0x21, 0x02, 0x20, 0x04, 0x2d, 0x00, 0x01, 0x41, 0x2f, + 0x47, 0x0d, 0x03, 0x20, 0x03, 0x41, 0x7e, 0x6a, 0x21, 0x03, 0x20, 0x04, + 0x41, 0x02, 0x6a, 0x21, 0x04, 0x0c, 0x02, 0x0b, 0x20, 0x03, 0x41, 0x01, + 0x47, 0x0d, 0x00, 0x20, 0x04, 0x41, 0x01, 0x6a, 0x20, 0x04, 0x20, 0x04, + 0x2d, 0x00, 0x00, 0x22, 0x03, 0x41, 0x2e, 0x46, 0x1b, 0x21, 0x04, 0x20, + 0x03, 0x41, 0x2e, 0x47, 0x21, 0x03, 0x0c, 0x01, 0x0b, 0x20, 0x04, 0x45, + 0x0d, 0x06, 0x0b, 0x20, 0x09, 0x41, 0x2f, 0x47, 0x04, 0x40, 0x41, 0x00, + 0x21, 0x02, 0x20, 0x03, 0x45, 0x0d, 0x03, 0x0b, 0x20, 0x03, 0x45, 0x04, + 0x40, 0x41, 0x00, 0x21, 0x02, 0x0c, 0x02, 0x0b, 0x20, 0x04, 0x2d, 0x00, + 0x00, 0x21, 0x02, 0x0b, 0x20, 0x09, 0x20, 0x02, 0x41, 0xff, 0x01, 0x71, + 0x47, 0x0d, 0x02, 0x41, 0x01, 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, 0x20, + 0x03, 0x46, 0x04, 0x40, 0x20, 0x03, 0x21, 0x02, 0x0c, 0x02, 0x0b, 0x20, + 0x02, 0x20, 0x04, 0x6a, 0x21, 0x08, 0x20, 0x01, 0x20, 0x02, 0x6a, 0x20, + 0x02, 0x41, 0x01, 0x6a, 0x21, 0x02, 0x2d, 0x00, 0x00, 0x20, 0x08, 0x2d, + 0x00, 0x00, 0x46, 0x0d, 0x00, 0x0b, 0x0c, 0x02, 0x0b, 0x20, 0x04, 0x41, + 0x7f, 0x6a, 0x21, 0x08, 0x20, 0x02, 0x21, 0x03, 0x03, 0x40, 0x20, 0x03, + 0x22, 0x05, 0x04, 0x40, 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x21, 0x03, 0x20, + 0x05, 0x20, 0x08, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x2f, 0x46, 0x0d, 0x01, + 0x0b, 0x0b, 0x20, 0x01, 0x20, 0x05, 0x6a, 0x2d, 0x00, 0x00, 0x22, 0x03, + 0x41, 0x2f, 0x46, 0x0d, 0x00, 0x20, 0x03, 0x0d, 0x01, 0x0b, 0x20, 0x07, + 0x29, 0x03, 0x08, 0x42, 0x7f, 0x85, 0x42, 0x80, 0xc0, 0x00, 0x83, 0x42, + 0x00, 0x52, 0x0d, 0x00, 0x20, 0x07, 0x29, 0x03, 0x10, 0x42, 0x7f, 0x85, + 0x42, 0x00, 0x83, 0x42, 0x00, 0x52, 0x0d, 0x00, 0x20, 0x07, 0x28, 0x02, + 0x04, 0x21, 0x06, 0x20, 0x02, 0x21, 0x0f, 0x0b, 0x20, 0x0b, 0x20, 0x0a, + 0x41, 0x01, 0x6a, 0x22, 0x0a, 0x47, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, + 0x00, 0x0b, 0x20, 0x01, 0x20, 0x0f, 0x6a, 0x21, 0x02, 0x03, 0x40, 0x20, + 0x02, 0x2d, 0x00, 0x00, 0x22, 0x01, 0x41, 0x2f, 0x46, 0x04, 0x40, 0x20, + 0x02, 0x41, 0x01, 0x6a, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x0b, 0x20, 0x01, + 0x0d, 0x00, 0x41, 0xa4, 0x09, 0x21, 0x02, 0x0b, 0x20, 0x00, 0x20, 0x02, + 0x36, 0x02, 0x04, 0x20, 0x00, 0x20, 0x06, 0x36, 0x02, 0x00, 0x0b, 0x63, + 0x01, 0x02, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x41, 0x00, 0x4c, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x0c, 0x22, 0x01, + 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x4b, 0x0d, 0x00, 0x41, 0x00, + 0x20, 0x02, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x00, 0x1b, 0x0d, 0x00, + 0x20, 0x01, 0x45, 0x0d, 0x01, 0x03, 0x40, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x41, + 0x7f, 0x4c, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x18, 0x6a, 0x21, 0x00, 0x20, + 0x01, 0x41, 0x7f, 0x6a, 0x22, 0x01, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, + 0x00, 0x0b, 0x0b, 0x4a, 0x01, 0x02, 0x7f, 0x02, 0x40, 0x41, 0x10, 0x10, + 0x14, 0x22, 0x00, 0x04, 0x40, 0x20, 0x00, 0x41, 0x04, 0x10, 0x16, 0x22, + 0x01, 0x36, 0x02, 0x04, 0x20, 0x01, 0x0d, 0x01, 0x20, 0x00, 0x10, 0x15, + 0x0b, 0x41, 0xe4, 0x1f, 0x41, 0x00, 0x36, 0x02, 0x00, 0x00, 0x0b, 0x20, + 0x00, 0x42, 0x04, 0x37, 0x02, 0x08, 0x20, 0x00, 0x41, 0x01, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x10, 0x1e, 0x41, 0xe4, 0x1f, 0x20, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x10, 0x1e, 0x0b, 0xfd, 0x01, 0x01, 0x05, 0x7f, 0x23, + 0x00, 0x41, 0x20, 0x6b, 0x22, 0x04, 0x24, 0x00, 0x41, 0xe4, 0x1f, 0x28, + 0x02, 0x00, 0x10, 0x1e, 0x41, 0x7f, 0x21, 0x06, 0x02, 0x40, 0x20, 0x01, + 0x45, 0x0d, 0x00, 0x41, 0xe4, 0x1f, 0x28, 0x02, 0x00, 0x22, 0x02, 0x10, + 0x1e, 0x20, 0x00, 0x41, 0x00, 0x48, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x02, + 0x28, 0x02, 0x0c, 0x22, 0x05, 0x20, 0x02, 0x28, 0x02, 0x08, 0x47, 0x04, + 0x40, 0x20, 0x02, 0x28, 0x02, 0x04, 0x21, 0x03, 0x0c, 0x01, 0x0b, 0x20, + 0x05, 0x41, 0x01, 0x74, 0x10, 0x16, 0x22, 0x03, 0x45, 0x0d, 0x01, 0x20, + 0x03, 0x20, 0x02, 0x28, 0x02, 0x04, 0x20, 0x02, 0x28, 0x02, 0x0c, 0x41, + 0x18, 0x6c, 0x10, 0x39, 0x1a, 0x20, 0x02, 0x28, 0x02, 0x04, 0x10, 0x15, + 0x20, 0x02, 0x20, 0x03, 0x36, 0x02, 0x04, 0x20, 0x02, 0x20, 0x02, 0x28, + 0x02, 0x08, 0x41, 0x01, 0x74, 0x36, 0x02, 0x08, 0x20, 0x02, 0x28, 0x02, + 0x0c, 0x21, 0x05, 0x0b, 0x20, 0x02, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x36, + 0x02, 0x0c, 0x20, 0x01, 0x10, 0x37, 0x21, 0x01, 0x20, 0x03, 0x20, 0x05, + 0x41, 0x18, 0x6c, 0x6a, 0x22, 0x03, 0x20, 0x00, 0x36, 0x02, 0x04, 0x20, + 0x03, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x04, 0x41, 0x08, + 0x6a, 0x10, 0x0a, 0x22, 0x00, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x20, 0x00, + 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x20, 0x04, 0x29, 0x03, + 0x10, 0x37, 0x03, 0x08, 0x20, 0x03, 0x20, 0x04, 0x29, 0x03, 0x18, 0x37, + 0x03, 0x10, 0x20, 0x02, 0x10, 0x1e, 0x20, 0x02, 0x10, 0x1e, 0x41, 0x00, + 0x21, 0x06, 0x41, 0xe4, 0x1f, 0x20, 0x02, 0x36, 0x02, 0x00, 0x0b, 0x20, + 0x04, 0x41, 0x20, 0x6a, 0x24, 0x00, 0x20, 0x06, 0x0b, 0x36, 0x00, 0x02, + 0x40, 0x20, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0d, 0x00, 0x20, 0x00, + 0x41, 0x7f, 0x4c, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x10, 0x76, 0x40, 0x00, + 0x22, 0x00, 0x41, 0x7f, 0x46, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, 0x30, + 0x36, 0x02, 0x00, 0x41, 0x7f, 0x0f, 0x0b, 0x20, 0x00, 0x41, 0x10, 0x74, + 0x0f, 0x0b, 0x00, 0x0b, 0x21, 0x01, 0x01, 0x7f, 0x23, 0x00, 0x41, 0x10, + 0x6b, 0x22, 0x02, 0x24, 0x00, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x0c, + 0x20, 0x00, 0x20, 0x01, 0x10, 0x25, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x24, + 0x00, 0x0b, 0x9e, 0x02, 0x01, 0x03, 0x7f, 0x20, 0x00, 0x45, 0x04, 0x40, + 0x41, 0xa0, 0x29, 0x28, 0x02, 0x00, 0x04, 0x40, 0x41, 0xa0, 0x29, 0x28, + 0x02, 0x00, 0x10, 0x23, 0x21, 0x01, 0x0b, 0x41, 0x98, 0x2a, 0x28, 0x02, + 0x00, 0x04, 0x40, 0x41, 0x98, 0x2a, 0x28, 0x02, 0x00, 0x10, 0x23, 0x20, + 0x01, 0x72, 0x21, 0x01, 0x0b, 0x41, 0xec, 0x1f, 0x28, 0x02, 0x00, 0x22, + 0x00, 0x04, 0x40, 0x03, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, + 0x28, 0x02, 0x18, 0x47, 0x04, 0x40, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, + 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x00, 0x00, 0x1a, 0x02, 0x7f, 0x41, + 0x7f, 0x20, 0x00, 0x28, 0x02, 0x14, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x00, + 0x28, 0x02, 0x04, 0x22, 0x02, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x03, + 0x47, 0x04, 0x40, 0x20, 0x00, 0x20, 0x02, 0x20, 0x03, 0x6b, 0xac, 0x41, + 0x00, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x03, 0x00, 0x1a, 0x0b, 0x20, + 0x00, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x00, 0x42, 0x00, 0x37, 0x03, + 0x10, 0x20, 0x00, 0x42, 0x00, 0x37, 0x02, 0x04, 0x41, 0x00, 0x0b, 0x20, + 0x01, 0x72, 0x21, 0x01, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x34, 0x22, 0x00, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x01, 0x0f, 0x0b, 0x02, 0x40, 0x20, 0x00, + 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, + 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x00, + 0x00, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x14, 0x0d, 0x00, 0x41, 0x7f, 0x0f, + 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, + 0x08, 0x22, 0x02, 0x47, 0x04, 0x40, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, + 0x6b, 0xac, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x03, 0x00, + 0x1a, 0x0b, 0x20, 0x00, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x00, 0x42, + 0x00, 0x37, 0x03, 0x10, 0x20, 0x00, 0x42, 0x00, 0x37, 0x02, 0x04, 0x41, + 0x00, 0x0b, 0x84, 0x01, 0x01, 0x04, 0x7f, 0x41, 0x88, 0x20, 0x28, 0x02, + 0x00, 0x22, 0x02, 0x45, 0x04, 0x40, 0x41, 0x88, 0x20, 0x41, 0xf0, 0x1f, + 0x36, 0x02, 0x00, 0x41, 0xf0, 0x1f, 0x21, 0x02, 0x0b, 0x02, 0x40, 0x02, + 0x40, 0x03, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0xb0, 0x09, 0x6a, 0x2d, + 0x00, 0x00, 0x47, 0x04, 0x40, 0x41, 0xcd, 0x00, 0x21, 0x03, 0x20, 0x01, + 0x41, 0x01, 0x6a, 0x22, 0x01, 0x41, 0xcd, 0x00, 0x47, 0x0d, 0x01, 0x0c, + 0x02, 0x0b, 0x0b, 0x20, 0x01, 0x22, 0x03, 0x0d, 0x00, 0x41, 0x80, 0x0a, + 0x21, 0x00, 0x0c, 0x01, 0x0b, 0x41, 0x80, 0x0a, 0x21, 0x01, 0x03, 0x40, + 0x20, 0x01, 0x2d, 0x00, 0x00, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x22, 0x00, + 0x21, 0x01, 0x0d, 0x00, 0x20, 0x00, 0x21, 0x01, 0x20, 0x03, 0x41, 0x7f, + 0x6a, 0x22, 0x03, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x02, 0x28, 0x02, 0x14, + 0x1a, 0x20, 0x00, 0x0b, 0xdd, 0x02, 0x01, 0x03, 0x7f, 0x23, 0x00, 0x41, + 0xd0, 0x01, 0x6b, 0x22, 0x02, 0x24, 0x00, 0x20, 0x02, 0x20, 0x01, 0x36, + 0x02, 0xcc, 0x01, 0x20, 0x02, 0x41, 0xc0, 0x01, 0x6a, 0x42, 0x00, 0x37, + 0x03, 0x00, 0x20, 0x02, 0x41, 0xb8, 0x01, 0x6a, 0x42, 0x00, 0x37, 0x03, + 0x00, 0x20, 0x02, 0x41, 0xb0, 0x01, 0x6a, 0x42, 0x00, 0x37, 0x03, 0x00, + 0x20, 0x02, 0x42, 0x00, 0x37, 0x03, 0xa8, 0x01, 0x20, 0x02, 0x42, 0x00, + 0x37, 0x03, 0xa0, 0x01, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0xc8, 0x01, + 0x41, 0x00, 0x20, 0x00, 0x20, 0x02, 0x41, 0xc8, 0x01, 0x6a, 0x20, 0x02, + 0x41, 0xd0, 0x00, 0x6a, 0x20, 0x02, 0x41, 0xa0, 0x01, 0x6a, 0x10, 0x26, + 0x41, 0x00, 0x4e, 0x04, 0x40, 0x41, 0xb0, 0x28, 0x28, 0x02, 0x00, 0x21, + 0x03, 0x41, 0xec, 0x28, 0x28, 0x02, 0x00, 0x41, 0x00, 0x4c, 0x04, 0x40, + 0x41, 0xb0, 0x28, 0x20, 0x03, 0x41, 0x5f, 0x71, 0x36, 0x02, 0x00, 0x0b, + 0x02, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x41, 0xdc, 0x28, 0x28, 0x02, 0x00, + 0x45, 0x04, 0x40, 0x41, 0xdc, 0x28, 0x41, 0xd0, 0x00, 0x36, 0x02, 0x00, + 0x41, 0xc8, 0x28, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, 0xc0, 0x28, 0x42, + 0x00, 0x37, 0x03, 0x00, 0x41, 0xd8, 0x28, 0x28, 0x02, 0x00, 0x21, 0x04, + 0x41, 0xd8, 0x28, 0x20, 0x02, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x41, + 0xc0, 0x28, 0x28, 0x02, 0x00, 0x0d, 0x01, 0x0b, 0x41, 0x7f, 0x41, 0xb0, + 0x28, 0x10, 0x31, 0x0d, 0x01, 0x1a, 0x0b, 0x41, 0xb0, 0x28, 0x20, 0x00, + 0x20, 0x02, 0x41, 0xc8, 0x01, 0x6a, 0x20, 0x02, 0x41, 0xd0, 0x00, 0x6a, + 0x20, 0x02, 0x41, 0xa0, 0x01, 0x6a, 0x10, 0x26, 0x0b, 0x21, 0x01, 0x20, + 0x04, 0x04, 0x7f, 0x41, 0xb0, 0x28, 0x41, 0x00, 0x41, 0x00, 0x41, 0xd0, + 0x28, 0x28, 0x02, 0x00, 0x11, 0x00, 0x00, 0x1a, 0x41, 0xdc, 0x28, 0x41, + 0x00, 0x36, 0x02, 0x00, 0x41, 0xd8, 0x28, 0x20, 0x04, 0x36, 0x02, 0x00, + 0x41, 0xc8, 0x28, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, 0xc0, 0x28, 0x41, + 0x00, 0x36, 0x02, 0x00, 0x41, 0xc4, 0x28, 0x28, 0x02, 0x00, 0x21, 0x00, + 0x41, 0xc4, 0x28, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, 0x00, 0x05, 0x20, + 0x01, 0x0b, 0x1a, 0x41, 0xb0, 0x28, 0x41, 0xb0, 0x28, 0x28, 0x02, 0x00, + 0x20, 0x03, 0x41, 0x20, 0x71, 0x72, 0x36, 0x02, 0x00, 0x0b, 0x20, 0x02, + 0x41, 0xd0, 0x01, 0x6a, 0x24, 0x00, 0x0b, 0xc7, 0x45, 0x03, 0x1d, 0x7f, + 0x02, 0x7e, 0x02, 0x7c, 0x23, 0x00, 0x41, 0xf0, 0x06, 0x6b, 0x22, 0x09, + 0x24, 0x00, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, 0x41, 0x08, 0x72, 0x21, + 0x1e, 0x20, 0x09, 0x41, 0x37, 0x6a, 0x21, 0x1f, 0x41, 0xae, 0x7d, 0x20, + 0x09, 0x6b, 0x21, 0x20, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, 0x41, 0x09, + 0x72, 0x21, 0x1b, 0x20, 0x09, 0x41, 0x90, 0x05, 0x6a, 0x21, 0x21, 0x20, + 0x09, 0x41, 0xd0, 0x02, 0x6a, 0x21, 0x19, 0x20, 0x09, 0x41, 0x38, 0x6a, + 0x21, 0x15, 0x02, 0x40, 0x02, 0x40, 0x03, 0x40, 0x02, 0x40, 0x20, 0x01, + 0x21, 0x08, 0x20, 0x05, 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x20, 0x13, + 0x6b, 0x4a, 0x0d, 0x00, 0x20, 0x05, 0x20, 0x13, 0x6a, 0x21, 0x13, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x08, 0x2d, 0x00, 0x00, 0x22, 0x05, + 0x04, 0x40, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x05, 0x41, 0xff, + 0x01, 0x71, 0x22, 0x06, 0x04, 0x40, 0x20, 0x06, 0x41, 0x25, 0x47, 0x0d, + 0x02, 0x20, 0x01, 0x22, 0x06, 0x21, 0x05, 0x03, 0x40, 0x20, 0x05, 0x41, + 0x01, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x25, 0x47, 0x04, 0x40, 0x20, 0x05, + 0x21, 0x01, 0x0c, 0x03, 0x0b, 0x20, 0x06, 0x41, 0x01, 0x6a, 0x21, 0x06, + 0x20, 0x05, 0x2d, 0x00, 0x02, 0x20, 0x05, 0x41, 0x02, 0x6a, 0x22, 0x01, + 0x21, 0x05, 0x41, 0x25, 0x46, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, + 0x01, 0x21, 0x06, 0x0b, 0x20, 0x06, 0x20, 0x08, 0x6b, 0x22, 0x05, 0x41, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x20, 0x13, 0x6b, 0x22, 0x18, 0x4a, 0x0d, + 0x06, 0x02, 0x40, 0x20, 0x00, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x2d, 0x00, + 0x00, 0x41, 0x20, 0x71, 0x0d, 0x00, 0x20, 0x08, 0x20, 0x05, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x05, 0x0d, 0x07, 0x20, 0x01, 0x41, 0x01, + 0x6a, 0x21, 0x05, 0x02, 0x7f, 0x41, 0x7f, 0x20, 0x01, 0x2c, 0x00, 0x01, + 0x22, 0x0b, 0x41, 0x50, 0x6a, 0x22, 0x07, 0x41, 0x09, 0x4b, 0x0d, 0x00, + 0x1a, 0x20, 0x01, 0x41, 0x03, 0x6a, 0x20, 0x05, 0x20, 0x01, 0x2d, 0x00, + 0x02, 0x41, 0x24, 0x46, 0x22, 0x06, 0x1b, 0x21, 0x05, 0x41, 0x01, 0x20, + 0x1a, 0x20, 0x06, 0x1b, 0x21, 0x1a, 0x20, 0x01, 0x41, 0x03, 0x41, 0x01, + 0x20, 0x06, 0x1b, 0x6a, 0x2c, 0x00, 0x00, 0x21, 0x0b, 0x20, 0x07, 0x41, + 0x7f, 0x20, 0x06, 0x1b, 0x0b, 0x21, 0x06, 0x41, 0x00, 0x21, 0x0c, 0x02, + 0x40, 0x20, 0x0b, 0x41, 0x60, 0x6a, 0x22, 0x01, 0x41, 0x1f, 0x4b, 0x0d, + 0x00, 0x41, 0x01, 0x20, 0x01, 0x74, 0x22, 0x01, 0x41, 0x89, 0xd1, 0x04, + 0x71, 0x45, 0x0d, 0x00, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x07, 0x03, + 0x40, 0x20, 0x01, 0x20, 0x0c, 0x72, 0x21, 0x0c, 0x20, 0x07, 0x22, 0x05, + 0x2c, 0x00, 0x00, 0x22, 0x0b, 0x41, 0x60, 0x6a, 0x22, 0x01, 0x41, 0x20, + 0x4f, 0x0d, 0x01, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x07, 0x41, 0x01, + 0x20, 0x01, 0x74, 0x22, 0x01, 0x41, 0x89, 0xd1, 0x04, 0x71, 0x0d, 0x00, + 0x0b, 0x0b, 0x02, 0x40, 0x20, 0x0b, 0x41, 0x2a, 0x46, 0x04, 0x40, 0x02, + 0x7f, 0x02, 0x40, 0x20, 0x05, 0x2c, 0x00, 0x01, 0x41, 0x50, 0x6a, 0x22, + 0x01, 0x41, 0x09, 0x4b, 0x0d, 0x00, 0x20, 0x05, 0x2d, 0x00, 0x02, 0x41, + 0x24, 0x47, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x01, 0x41, 0x02, 0x74, 0x6a, + 0x41, 0x0a, 0x36, 0x02, 0x00, 0x20, 0x05, 0x41, 0x03, 0x6a, 0x21, 0x0a, + 0x41, 0x01, 0x21, 0x1a, 0x20, 0x05, 0x2c, 0x00, 0x01, 0x41, 0x03, 0x74, + 0x20, 0x03, 0x6a, 0x41, 0x80, 0x7d, 0x6a, 0x28, 0x02, 0x00, 0x0c, 0x01, + 0x0b, 0x20, 0x1a, 0x0d, 0x06, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x0a, + 0x20, 0x00, 0x45, 0x04, 0x40, 0x41, 0x00, 0x21, 0x1a, 0x41, 0x00, 0x21, + 0x0e, 0x0c, 0x03, 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, + 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, 0x00, 0x41, 0x00, 0x21, 0x1a, 0x20, + 0x01, 0x28, 0x02, 0x00, 0x0b, 0x22, 0x0e, 0x41, 0x7f, 0x4a, 0x0d, 0x01, + 0x41, 0x00, 0x20, 0x0e, 0x6b, 0x21, 0x0e, 0x20, 0x0c, 0x41, 0x80, 0xc0, + 0x00, 0x72, 0x21, 0x0c, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x0e, 0x20, + 0x0b, 0x41, 0x50, 0x6a, 0x22, 0x07, 0x41, 0x09, 0x4b, 0x04, 0x40, 0x20, + 0x05, 0x21, 0x0a, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x01, 0x03, 0x40, + 0x41, 0x7f, 0x21, 0x0e, 0x20, 0x05, 0x2c, 0x00, 0x01, 0x20, 0x05, 0x41, + 0x01, 0x6a, 0x22, 0x0a, 0x21, 0x05, 0x20, 0x01, 0x41, 0xcc, 0x99, 0xb3, + 0xe6, 0x00, 0x4d, 0x04, 0x40, 0x41, 0x7f, 0x20, 0x01, 0x41, 0x0a, 0x6c, + 0x22, 0x01, 0x20, 0x07, 0x6a, 0x20, 0x07, 0x41, 0xff, 0xff, 0xff, 0xff, + 0x07, 0x20, 0x01, 0x6b, 0x4a, 0x1b, 0x21, 0x0e, 0x0b, 0x20, 0x0e, 0x21, + 0x01, 0x41, 0x50, 0x6a, 0x22, 0x07, 0x41, 0x0a, 0x49, 0x0d, 0x00, 0x0b, + 0x20, 0x0e, 0x41, 0x00, 0x48, 0x0d, 0x07, 0x0b, 0x41, 0x00, 0x21, 0x05, + 0x41, 0x7f, 0x21, 0x0b, 0x02, 0x40, 0x20, 0x0a, 0x2d, 0x00, 0x00, 0x41, + 0x2e, 0x47, 0x04, 0x40, 0x20, 0x0a, 0x21, 0x01, 0x41, 0x00, 0x21, 0x0d, + 0x0c, 0x01, 0x0b, 0x20, 0x0a, 0x2c, 0x00, 0x01, 0x22, 0x07, 0x41, 0x2a, + 0x46, 0x04, 0x40, 0x02, 0x7f, 0x02, 0x40, 0x20, 0x0a, 0x2c, 0x00, 0x02, + 0x41, 0x50, 0x6a, 0x22, 0x01, 0x41, 0x09, 0x4b, 0x0d, 0x00, 0x20, 0x0a, + 0x2d, 0x00, 0x03, 0x41, 0x24, 0x47, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x01, + 0x41, 0x02, 0x74, 0x6a, 0x41, 0x0a, 0x36, 0x02, 0x00, 0x20, 0x0a, 0x41, + 0x04, 0x6a, 0x21, 0x01, 0x20, 0x0a, 0x2c, 0x00, 0x02, 0x41, 0x03, 0x74, + 0x20, 0x03, 0x6a, 0x41, 0x80, 0x7d, 0x6a, 0x28, 0x02, 0x00, 0x0c, 0x01, + 0x0b, 0x20, 0x1a, 0x0d, 0x06, 0x20, 0x0a, 0x41, 0x02, 0x6a, 0x21, 0x01, + 0x41, 0x00, 0x20, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x02, 0x20, 0x02, + 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x04, 0x6a, 0x36, 0x02, 0x00, 0x20, + 0x07, 0x28, 0x02, 0x00, 0x0b, 0x22, 0x0b, 0x41, 0x7f, 0x73, 0x41, 0x1f, + 0x76, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x20, 0x0a, 0x41, 0x01, 0x6a, 0x21, + 0x01, 0x20, 0x07, 0x41, 0x50, 0x6a, 0x22, 0x10, 0x41, 0x09, 0x4b, 0x04, + 0x40, 0x41, 0x01, 0x21, 0x0d, 0x41, 0x00, 0x21, 0x0b, 0x0c, 0x01, 0x0b, + 0x41, 0x00, 0x21, 0x0a, 0x20, 0x01, 0x21, 0x07, 0x03, 0x40, 0x41, 0x7f, + 0x21, 0x0b, 0x20, 0x0a, 0x41, 0xcc, 0x99, 0xb3, 0xe6, 0x00, 0x4d, 0x04, + 0x40, 0x41, 0x7f, 0x20, 0x0a, 0x41, 0x0a, 0x6c, 0x22, 0x01, 0x20, 0x10, + 0x6a, 0x20, 0x10, 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x20, 0x01, 0x6b, + 0x4a, 0x1b, 0x21, 0x0b, 0x0b, 0x41, 0x01, 0x21, 0x0d, 0x20, 0x07, 0x2c, + 0x00, 0x01, 0x20, 0x07, 0x41, 0x01, 0x6a, 0x22, 0x01, 0x21, 0x07, 0x20, + 0x0b, 0x21, 0x0a, 0x41, 0x50, 0x6a, 0x22, 0x10, 0x41, 0x0a, 0x49, 0x0d, + 0x00, 0x0b, 0x0b, 0x03, 0x40, 0x20, 0x05, 0x21, 0x07, 0x20, 0x01, 0x2c, + 0x00, 0x00, 0x41, 0xbf, 0x7f, 0x6a, 0x22, 0x05, 0x41, 0x39, 0x4b, 0x0d, + 0x04, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x07, 0x41, 0x3a, + 0x6c, 0x20, 0x05, 0x6a, 0x41, 0xc0, 0x16, 0x6a, 0x2d, 0x00, 0x00, 0x22, + 0x05, 0x41, 0x7f, 0x6a, 0x41, 0x08, 0x49, 0x0d, 0x00, 0x0b, 0x20, 0x05, + 0x45, 0x0d, 0x03, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x05, 0x41, + 0x1b, 0x46, 0x04, 0x40, 0x20, 0x06, 0x41, 0x7f, 0x4c, 0x0d, 0x01, 0x0c, + 0x07, 0x0b, 0x20, 0x06, 0x41, 0x00, 0x48, 0x0d, 0x01, 0x20, 0x04, 0x20, + 0x06, 0x41, 0x02, 0x74, 0x6a, 0x20, 0x05, 0x36, 0x02, 0x00, 0x20, 0x09, + 0x20, 0x03, 0x20, 0x06, 0x41, 0x03, 0x74, 0x6a, 0x29, 0x03, 0x00, 0x37, + 0x03, 0x38, 0x0b, 0x41, 0x00, 0x21, 0x05, 0x20, 0x00, 0x45, 0x0d, 0x09, + 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x45, 0x04, 0x40, 0x41, 0x00, 0x21, 0x13, + 0x0c, 0x0b, 0x0b, 0x20, 0x09, 0x41, 0x38, 0x6a, 0x20, 0x05, 0x20, 0x02, + 0x10, 0x27, 0x0b, 0x20, 0x0c, 0x41, 0xff, 0xff, 0x7b, 0x71, 0x22, 0x06, + 0x20, 0x0c, 0x20, 0x0c, 0x41, 0x80, 0xc0, 0x00, 0x71, 0x1b, 0x21, 0x0f, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, 0x41, 0x7f, 0x6a, 0x2c, + 0x00, 0x00, 0x22, 0x05, 0x41, 0x5f, 0x71, 0x20, 0x05, 0x20, 0x05, 0x41, + 0x0f, 0x71, 0x41, 0x03, 0x46, 0x1b, 0x20, 0x05, 0x20, 0x07, 0x1b, 0x22, + 0x11, 0x41, 0xbf, 0x7f, 0x6a, 0x22, 0x05, 0x41, 0x37, 0x4b, 0x0d, 0x00, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x05, + 0x41, 0x01, 0x6b, 0x0e, 0x37, 0x11, 0x0d, 0x11, 0x10, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0c, 0x11, + 0x11, 0x11, 0x11, 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x10, 0x11, 0x08, 0x05, 0x10, 0x10, 0x10, 0x11, 0x05, 0x11, 0x11, 0x11, + 0x09, 0x01, 0x04, 0x02, 0x11, 0x11, 0x0a, 0x11, 0x00, 0x11, 0x11, 0x03, + 0x10, 0x0b, 0x41, 0x00, 0x21, 0x0a, 0x20, 0x09, 0x29, 0x03, 0x38, 0x21, + 0x22, 0x41, 0xa6, 0x16, 0x0c, 0x05, 0x0b, 0x41, 0x00, 0x21, 0x05, 0x20, + 0x07, 0x41, 0xff, 0x01, 0x71, 0x22, 0x06, 0x41, 0x07, 0x4b, 0x0d, 0x19, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x40, 0x20, 0x06, 0x41, 0x01, 0x6b, 0x0e, 0x07, 0x01, 0x02, 0x03, + 0x04, 0x20, 0x05, 0x06, 0x00, 0x0b, 0x20, 0x09, 0x28, 0x02, 0x38, 0x20, + 0x13, 0x36, 0x02, 0x00, 0x0c, 0x1f, 0x0b, 0x20, 0x09, 0x28, 0x02, 0x38, + 0x20, 0x13, 0x36, 0x02, 0x00, 0x0c, 0x1e, 0x0b, 0x20, 0x09, 0x28, 0x02, + 0x38, 0x20, 0x13, 0xac, 0x37, 0x03, 0x00, 0x0c, 0x1d, 0x0b, 0x20, 0x09, + 0x28, 0x02, 0x38, 0x20, 0x13, 0x3b, 0x01, 0x00, 0x0c, 0x1c, 0x0b, 0x20, + 0x09, 0x28, 0x02, 0x38, 0x20, 0x13, 0x3a, 0x00, 0x00, 0x0c, 0x1b, 0x0b, + 0x20, 0x09, 0x28, 0x02, 0x38, 0x20, 0x13, 0x36, 0x02, 0x00, 0x0c, 0x1a, + 0x0b, 0x20, 0x09, 0x28, 0x02, 0x38, 0x20, 0x13, 0xac, 0x37, 0x03, 0x00, + 0x0c, 0x19, 0x0b, 0x20, 0x0b, 0x41, 0x08, 0x20, 0x0b, 0x41, 0x08, 0x4b, + 0x1b, 0x21, 0x0b, 0x20, 0x0f, 0x41, 0x08, 0x72, 0x21, 0x0f, 0x41, 0xf8, + 0x00, 0x21, 0x11, 0x0b, 0x41, 0x00, 0x21, 0x0a, 0x41, 0xa6, 0x16, 0x21, + 0x10, 0x20, 0x09, 0x29, 0x03, 0x38, 0x22, 0x22, 0x50, 0x04, 0x40, 0x20, + 0x15, 0x21, 0x08, 0x0c, 0x04, 0x0b, 0x20, 0x11, 0x41, 0x20, 0x71, 0x21, + 0x06, 0x20, 0x15, 0x21, 0x08, 0x03, 0x40, 0x20, 0x08, 0x41, 0x7f, 0x6a, + 0x22, 0x08, 0x20, 0x22, 0xa7, 0x41, 0x0f, 0x71, 0x41, 0xa0, 0x1b, 0x6a, + 0x2d, 0x00, 0x00, 0x20, 0x06, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x22, 0x42, + 0x04, 0x88, 0x22, 0x22, 0x42, 0x00, 0x52, 0x0d, 0x00, 0x0b, 0x20, 0x0f, + 0x41, 0x08, 0x71, 0x45, 0x0d, 0x03, 0x20, 0x09, 0x29, 0x03, 0x38, 0x50, + 0x0d, 0x03, 0x20, 0x11, 0x41, 0x04, 0x75, 0x41, 0xa6, 0x16, 0x6a, 0x21, + 0x10, 0x41, 0x02, 0x21, 0x0a, 0x0c, 0x03, 0x0b, 0x20, 0x15, 0x21, 0x08, + 0x20, 0x09, 0x29, 0x03, 0x38, 0x22, 0x22, 0x50, 0x45, 0x04, 0x40, 0x03, + 0x40, 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x22, 0x08, 0x20, 0x22, 0xa7, 0x41, + 0x07, 0x71, 0x41, 0x30, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x22, 0x42, 0x03, + 0x88, 0x22, 0x22, 0x42, 0x00, 0x52, 0x0d, 0x00, 0x0b, 0x0b, 0x41, 0x00, + 0x21, 0x0a, 0x41, 0xa6, 0x16, 0x21, 0x10, 0x20, 0x0f, 0x41, 0x08, 0x71, + 0x45, 0x0d, 0x02, 0x20, 0x0b, 0x20, 0x15, 0x20, 0x08, 0x6b, 0x22, 0x06, + 0x41, 0x01, 0x6a, 0x20, 0x0b, 0x20, 0x06, 0x4a, 0x1b, 0x21, 0x0b, 0x0c, + 0x02, 0x0b, 0x20, 0x09, 0x29, 0x03, 0x38, 0x22, 0x22, 0x42, 0x7f, 0x57, + 0x04, 0x40, 0x20, 0x09, 0x42, 0x00, 0x20, 0x22, 0x7d, 0x22, 0x22, 0x37, + 0x03, 0x38, 0x41, 0x01, 0x21, 0x0a, 0x41, 0xa6, 0x16, 0x0c, 0x01, 0x0b, + 0x20, 0x0f, 0x41, 0x80, 0x10, 0x71, 0x04, 0x40, 0x41, 0x01, 0x21, 0x0a, + 0x41, 0xa7, 0x16, 0x0c, 0x01, 0x0b, 0x41, 0xa8, 0x16, 0x41, 0xa6, 0x16, + 0x20, 0x0f, 0x41, 0x01, 0x71, 0x22, 0x0a, 0x1b, 0x0b, 0x21, 0x10, 0x02, + 0x40, 0x20, 0x22, 0x42, 0x80, 0x80, 0x80, 0x80, 0x10, 0x54, 0x04, 0x40, + 0x20, 0x22, 0x21, 0x23, 0x20, 0x15, 0x21, 0x08, 0x0c, 0x01, 0x0b, 0x20, + 0x15, 0x21, 0x08, 0x03, 0x40, 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x22, 0x08, + 0x20, 0x22, 0x20, 0x22, 0x42, 0x0a, 0x80, 0x22, 0x23, 0x42, 0x0a, 0x7e, + 0x7d, 0xa7, 0x41, 0x30, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x22, 0x42, 0xff, + 0xff, 0xff, 0xff, 0x9f, 0x01, 0x56, 0x20, 0x23, 0x21, 0x22, 0x0d, 0x00, + 0x0b, 0x0b, 0x20, 0x23, 0xa7, 0x22, 0x05, 0x45, 0x0d, 0x00, 0x03, 0x40, + 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x22, 0x08, 0x20, 0x05, 0x20, 0x05, 0x41, + 0x0a, 0x6e, 0x22, 0x06, 0x41, 0x0a, 0x6c, 0x6b, 0x41, 0x30, 0x72, 0x3a, + 0x00, 0x00, 0x20, 0x05, 0x41, 0x09, 0x4b, 0x20, 0x06, 0x21, 0x05, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x0d, 0x41, 0x00, 0x20, 0x0b, 0x41, 0x00, 0x48, + 0x1b, 0x0d, 0x12, 0x20, 0x0f, 0x41, 0xff, 0xff, 0x7b, 0x71, 0x20, 0x0f, + 0x20, 0x0d, 0x1b, 0x21, 0x0f, 0x20, 0x09, 0x29, 0x03, 0x38, 0x21, 0x22, + 0x02, 0x40, 0x20, 0x0b, 0x0d, 0x00, 0x20, 0x22, 0x50, 0x45, 0x0d, 0x00, + 0x20, 0x15, 0x22, 0x08, 0x21, 0x05, 0x41, 0x00, 0x21, 0x0b, 0x0c, 0x12, + 0x0b, 0x20, 0x0b, 0x20, 0x22, 0x50, 0x20, 0x15, 0x20, 0x08, 0x6b, 0x6a, + 0x22, 0x06, 0x20, 0x0b, 0x20, 0x06, 0x4a, 0x1b, 0x21, 0x0b, 0x0c, 0x0a, + 0x0b, 0x20, 0x09, 0x20, 0x09, 0x29, 0x03, 0x38, 0x3c, 0x00, 0x37, 0x41, + 0x00, 0x21, 0x0a, 0x41, 0xa6, 0x16, 0x21, 0x10, 0x41, 0x01, 0x21, 0x0b, + 0x20, 0x1f, 0x21, 0x08, 0x20, 0x15, 0x21, 0x05, 0x20, 0x06, 0x21, 0x0f, + 0x0c, 0x10, 0x0b, 0x41, 0xe0, 0x1f, 0x28, 0x02, 0x00, 0x10, 0x24, 0x0c, + 0x01, 0x0b, 0x20, 0x09, 0x28, 0x02, 0x38, 0x22, 0x05, 0x41, 0xb0, 0x16, + 0x20, 0x05, 0x1b, 0x0b, 0x21, 0x08, 0x41, 0x00, 0x21, 0x0a, 0x20, 0x08, + 0x20, 0x08, 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x20, 0x0b, 0x20, 0x0b, + 0x41, 0x00, 0x48, 0x1b, 0x22, 0x05, 0x10, 0x3c, 0x22, 0x07, 0x20, 0x08, + 0x6b, 0x20, 0x05, 0x20, 0x07, 0x1b, 0x22, 0x07, 0x6a, 0x21, 0x05, 0x41, + 0xa6, 0x16, 0x21, 0x10, 0x20, 0x0b, 0x41, 0x7f, 0x4c, 0x0d, 0x07, 0x20, + 0x06, 0x21, 0x0f, 0x20, 0x07, 0x21, 0x0b, 0x0c, 0x0d, 0x0b, 0x20, 0x09, + 0x28, 0x02, 0x38, 0x22, 0x08, 0x20, 0x0b, 0x0d, 0x01, 0x1a, 0x41, 0x00, + 0x21, 0x05, 0x0c, 0x02, 0x0b, 0x20, 0x09, 0x41, 0x00, 0x36, 0x02, 0x0c, + 0x20, 0x09, 0x20, 0x09, 0x29, 0x03, 0x38, 0x3e, 0x02, 0x08, 0x20, 0x09, + 0x20, 0x09, 0x41, 0x08, 0x6a, 0x36, 0x02, 0x38, 0x41, 0x7f, 0x21, 0x0b, + 0x20, 0x09, 0x41, 0x08, 0x6a, 0x0b, 0x21, 0x08, 0x41, 0x00, 0x21, 0x05, + 0x20, 0x08, 0x21, 0x06, 0x02, 0x40, 0x03, 0x40, 0x20, 0x06, 0x28, 0x02, + 0x00, 0x22, 0x07, 0x45, 0x0d, 0x01, 0x02, 0x40, 0x20, 0x09, 0x41, 0x04, + 0x6a, 0x20, 0x07, 0x10, 0x3d, 0x22, 0x07, 0x41, 0x00, 0x48, 0x22, 0x0a, + 0x0d, 0x00, 0x20, 0x07, 0x20, 0x0b, 0x20, 0x05, 0x6b, 0x4b, 0x0d, 0x00, + 0x20, 0x06, 0x41, 0x04, 0x6a, 0x21, 0x06, 0x20, 0x0b, 0x20, 0x05, 0x20, + 0x07, 0x6a, 0x22, 0x05, 0x4b, 0x0d, 0x01, 0x0c, 0x02, 0x0b, 0x0b, 0x20, + 0x0a, 0x0d, 0x0e, 0x0b, 0x20, 0x05, 0x41, 0x00, 0x48, 0x0d, 0x0b, 0x0b, + 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, 0x04, 0x71, 0x22, 0x0a, 0x0d, + 0x00, 0x20, 0x0e, 0x20, 0x05, 0x4c, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, 0x05, 0x6b, 0x22, 0x10, 0x41, 0x80, + 0x02, 0x20, 0x10, 0x41, 0x80, 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, + 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x0b, 0x41, 0x20, 0x71, 0x21, 0x06, + 0x02, 0x40, 0x20, 0x07, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, + 0x20, 0x10, 0x21, 0x07, 0x03, 0x40, 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, + 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x0b, 0x0b, 0x20, 0x0b, + 0x41, 0x20, 0x71, 0x22, 0x0c, 0x45, 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, + 0x7e, 0x6a, 0x22, 0x07, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, + 0x0c, 0x0d, 0x02, 0x20, 0x10, 0x41, 0xff, 0x01, 0x71, 0x21, 0x10, 0x0c, + 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, + 0x20, 0x10, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x05, + 0x45, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x06, 0x03, 0x40, 0x20, 0x08, 0x28, + 0x02, 0x00, 0x22, 0x07, 0x45, 0x0d, 0x01, 0x20, 0x09, 0x41, 0x04, 0x6a, + 0x20, 0x07, 0x10, 0x3d, 0x22, 0x07, 0x20, 0x06, 0x6a, 0x22, 0x06, 0x20, + 0x05, 0x4b, 0x0d, 0x01, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, + 0x45, 0x04, 0x40, 0x20, 0x09, 0x41, 0x04, 0x6a, 0x20, 0x07, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x08, 0x41, 0x04, 0x6a, 0x21, 0x08, 0x20, + 0x06, 0x20, 0x05, 0x49, 0x0d, 0x00, 0x0b, 0x0b, 0x02, 0x40, 0x20, 0x0a, + 0x41, 0x80, 0xc0, 0x00, 0x47, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x05, 0x4c, + 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, + 0x05, 0x6b, 0x22, 0x0c, 0x41, 0x80, 0x02, 0x20, 0x0c, 0x41, 0x80, 0x02, + 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, + 0x08, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x07, 0x45, 0x04, + 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, 0x20, 0x0c, 0x21, 0x07, 0x03, 0x40, + 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, + 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, + 0x00, 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, 0x20, 0x71, 0x22, 0x0a, 0x45, + 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, 0x41, 0xff, + 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0a, 0x0d, 0x02, 0x20, 0x0c, 0x41, + 0xff, 0x01, 0x71, 0x21, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, + 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0c, 0x20, 0x00, 0x10, 0x33, + 0x1a, 0x0b, 0x20, 0x0e, 0x20, 0x05, 0x20, 0x0e, 0x20, 0x05, 0x4a, 0x1b, + 0x21, 0x05, 0x0c, 0x0b, 0x0b, 0x20, 0x0b, 0x41, 0x7f, 0x4c, 0x41, 0x00, + 0x20, 0x0d, 0x1b, 0x0d, 0x09, 0x20, 0x09, 0x2b, 0x03, 0x38, 0x21, 0x24, + 0x20, 0x09, 0x41, 0x00, 0x36, 0x02, 0xec, 0x02, 0x02, 0x7f, 0x20, 0x24, + 0xbd, 0x42, 0x7f, 0x57, 0x04, 0x40, 0x20, 0x24, 0x9a, 0x21, 0x24, 0x41, + 0x01, 0x21, 0x14, 0x41, 0xb0, 0x1b, 0x0c, 0x01, 0x0b, 0x20, 0x0f, 0x41, + 0x80, 0x10, 0x71, 0x04, 0x40, 0x41, 0x01, 0x21, 0x14, 0x41, 0xb3, 0x1b, + 0x0c, 0x01, 0x0b, 0x41, 0xb6, 0x1b, 0x41, 0xb1, 0x1b, 0x20, 0x0f, 0x41, + 0x01, 0x71, 0x22, 0x14, 0x1b, 0x0b, 0x21, 0x18, 0x02, 0x40, 0x20, 0x24, + 0x99, 0x22, 0x25, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, + 0x62, 0x20, 0x25, 0x20, 0x25, 0x61, 0x71, 0x45, 0x04, 0x40, 0x20, 0x14, + 0x41, 0x03, 0x6a, 0x21, 0x08, 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, + 0x00, 0x71, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x08, 0x4c, 0x0d, 0x00, 0x20, + 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, 0x08, 0x6b, 0x22, + 0x0c, 0x41, 0x80, 0x02, 0x20, 0x0c, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, + 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, + 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, + 0x45, 0x21, 0x05, 0x20, 0x0c, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, + 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, + 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, + 0x0b, 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, 0x0a, 0x45, 0x21, 0x05, 0x20, + 0x06, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, + 0x00, 0x0b, 0x20, 0x0a, 0x0d, 0x02, 0x20, 0x0c, 0x41, 0xff, 0x01, 0x71, + 0x21, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, + 0x41, 0x40, 0x6b, 0x20, 0x0c, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, + 0x00, 0x28, 0x02, 0x00, 0x22, 0x06, 0x41, 0x20, 0x71, 0x04, 0x7f, 0x20, + 0x06, 0x05, 0x20, 0x18, 0x20, 0x14, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, + 0x00, 0x28, 0x02, 0x00, 0x0b, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x41, + 0xcb, 0x1b, 0x41, 0xcf, 0x1b, 0x20, 0x11, 0x41, 0x20, 0x71, 0x41, 0x05, + 0x76, 0x22, 0x06, 0x1b, 0x41, 0xc3, 0x1b, 0x41, 0xc7, 0x1b, 0x20, 0x06, + 0x1b, 0x20, 0x24, 0x20, 0x24, 0x62, 0x1b, 0x41, 0x03, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, 0x04, 0x71, + 0x41, 0x80, 0xc0, 0x00, 0x47, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x08, 0x4c, + 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, + 0x08, 0x6b, 0x22, 0x0c, 0x41, 0x80, 0x02, 0x20, 0x0c, 0x41, 0x80, 0x02, + 0x49, 0x22, 0x05, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, + 0x07, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, + 0x40, 0x20, 0x06, 0x45, 0x21, 0x05, 0x20, 0x0c, 0x21, 0x06, 0x03, 0x40, + 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, + 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, + 0x00, 0x21, 0x07, 0x0b, 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, 0x0a, 0x45, + 0x21, 0x05, 0x20, 0x06, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, + 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0a, 0x0d, 0x02, 0x20, 0x0c, 0x41, + 0xff, 0x01, 0x71, 0x21, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, + 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0c, 0x20, 0x00, 0x10, 0x33, + 0x1a, 0x0b, 0x20, 0x0e, 0x20, 0x08, 0x20, 0x0e, 0x20, 0x08, 0x4a, 0x1b, + 0x21, 0x05, 0x0c, 0x01, 0x0b, 0x20, 0x24, 0x20, 0x09, 0x41, 0xec, 0x02, + 0x6a, 0x10, 0x3f, 0x22, 0x24, 0x20, 0x24, 0xa0, 0x22, 0x24, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x04, 0x40, 0x20, 0x09, + 0x20, 0x09, 0x28, 0x02, 0xec, 0x02, 0x41, 0x7f, 0x6a, 0x36, 0x02, 0xec, + 0x02, 0x0b, 0x20, 0x11, 0x41, 0x20, 0x72, 0x22, 0x0c, 0x41, 0xe1, 0x00, + 0x46, 0x04, 0x40, 0x20, 0x18, 0x41, 0x09, 0x6a, 0x20, 0x18, 0x20, 0x11, + 0x41, 0x20, 0x71, 0x22, 0x0a, 0x1b, 0x21, 0x0c, 0x02, 0x40, 0x20, 0x0b, + 0x41, 0x0b, 0x4b, 0x0d, 0x00, 0x41, 0x0c, 0x20, 0x0b, 0x6b, 0x45, 0x0d, + 0x00, 0x20, 0x0b, 0x41, 0x74, 0x6a, 0x21, 0x05, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x40, 0x21, 0x25, 0x03, 0x40, 0x20, 0x25, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 0xa2, 0x21, 0x25, 0x20, + 0x05, 0x41, 0x01, 0x6a, 0x22, 0x06, 0x20, 0x05, 0x4f, 0x20, 0x06, 0x21, + 0x05, 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x2d, 0x00, 0x00, 0x41, 0x2d, 0x46, + 0x04, 0x40, 0x20, 0x25, 0x20, 0x24, 0x9a, 0x20, 0x25, 0xa1, 0xa0, 0x9a, + 0x21, 0x24, 0x0c, 0x01, 0x0b, 0x20, 0x24, 0x20, 0x25, 0xa0, 0x20, 0x25, + 0xa1, 0x21, 0x24, 0x0b, 0x20, 0x19, 0x21, 0x07, 0x02, 0x40, 0x20, 0x09, + 0x28, 0x02, 0xec, 0x02, 0x22, 0x08, 0x20, 0x08, 0x41, 0x1f, 0x75, 0x22, + 0x06, 0x6a, 0x20, 0x06, 0x73, 0x22, 0x05, 0x04, 0x40, 0x41, 0x00, 0x21, + 0x06, 0x03, 0x40, 0x20, 0x06, 0x20, 0x09, 0x6a, 0x41, 0xcf, 0x02, 0x6a, + 0x20, 0x05, 0x20, 0x05, 0x41, 0x0a, 0x6e, 0x22, 0x07, 0x41, 0x0a, 0x6c, + 0x6b, 0x41, 0x30, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x06, 0x41, 0x7f, 0x6a, + 0x21, 0x06, 0x20, 0x05, 0x41, 0x09, 0x4b, 0x20, 0x07, 0x21, 0x05, 0x0d, + 0x00, 0x0b, 0x20, 0x06, 0x20, 0x09, 0x6a, 0x41, 0xd0, 0x02, 0x6a, 0x21, + 0x07, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x22, + 0x07, 0x41, 0x30, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x14, 0x41, 0x02, 0x72, + 0x21, 0x0d, 0x20, 0x07, 0x41, 0x7e, 0x6a, 0x22, 0x12, 0x20, 0x11, 0x41, + 0x0f, 0x6a, 0x3a, 0x00, 0x00, 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x41, 0x2d, + 0x41, 0x2b, 0x20, 0x08, 0x41, 0x00, 0x48, 0x1b, 0x3a, 0x00, 0x00, 0x20, + 0x0f, 0x41, 0x08, 0x71, 0x21, 0x07, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, + 0x21, 0x06, 0x03, 0x40, 0x20, 0x06, 0x22, 0x05, 0x02, 0x7f, 0x20, 0x24, + 0x99, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x41, 0x63, 0x04, + 0x40, 0x20, 0x24, 0xaa, 0x0c, 0x01, 0x0b, 0x41, 0x80, 0x80, 0x80, 0x80, + 0x78, 0x0b, 0x22, 0x06, 0x41, 0xa0, 0x1b, 0x6a, 0x2d, 0x00, 0x00, 0x20, + 0x0a, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x24, 0x20, 0x06, 0xb7, 0xa1, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 0xa2, 0x21, 0x24, 0x02, + 0x40, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x22, 0x06, 0x20, 0x09, 0x41, 0xd0, + 0x02, 0x6a, 0x6b, 0x41, 0x01, 0x47, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x07, + 0x0d, 0x00, 0x20, 0x0b, 0x41, 0x00, 0x4a, 0x0d, 0x00, 0x20, 0x24, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0d, 0x01, 0x0b, + 0x20, 0x05, 0x41, 0x2e, 0x3a, 0x00, 0x01, 0x20, 0x05, 0x41, 0x02, 0x6a, + 0x21, 0x06, 0x0b, 0x20, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x62, 0x0d, 0x00, 0x0b, 0x41, 0x7f, 0x21, 0x05, 0x41, 0xfd, + 0xff, 0xff, 0xff, 0x07, 0x20, 0x0d, 0x20, 0x19, 0x20, 0x12, 0x6b, 0x22, + 0x11, 0x6a, 0x22, 0x07, 0x6b, 0x20, 0x0b, 0x48, 0x0d, 0x01, 0x20, 0x07, + 0x20, 0x0b, 0x41, 0x02, 0x6a, 0x20, 0x06, 0x20, 0x09, 0x41, 0xd0, 0x02, + 0x6a, 0x6b, 0x22, 0x0a, 0x20, 0x06, 0x20, 0x20, 0x6a, 0x20, 0x0b, 0x48, + 0x1b, 0x20, 0x0a, 0x20, 0x0b, 0x1b, 0x22, 0x14, 0x6a, 0x21, 0x08, 0x02, + 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, 0x04, 0x71, 0x22, 0x0b, 0x0d, 0x00, + 0x20, 0x0e, 0x20, 0x08, 0x4c, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, + 0x41, 0x20, 0x20, 0x0e, 0x20, 0x08, 0x6b, 0x22, 0x0f, 0x41, 0x80, 0x02, + 0x20, 0x0f, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, 0x1b, 0x10, 0x3a, 0x20, + 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, + 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x05, 0x20, + 0x0f, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, + 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, + 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, 0x0b, 0x20, 0x07, 0x41, + 0x20, 0x71, 0x22, 0x10, 0x45, 0x21, 0x05, 0x20, 0x06, 0x41, 0x80, 0x7e, + 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x10, + 0x0d, 0x02, 0x20, 0x0f, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0f, 0x0c, 0x01, + 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, + 0x0f, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, + 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x0c, 0x20, 0x0d, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x0b, 0x41, 0x80, 0x80, 0x04, + 0x47, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x08, 0x4c, 0x0d, 0x00, 0x20, 0x09, + 0x41, 0x40, 0x6b, 0x41, 0x30, 0x20, 0x0e, 0x20, 0x08, 0x6b, 0x22, 0x10, + 0x41, 0x80, 0x02, 0x20, 0x10, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, 0x1b, + 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, 0x71, + 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, + 0x21, 0x05, 0x20, 0x10, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, + 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, + 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, 0x0b, + 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, 0x0c, 0x45, 0x21, 0x05, 0x20, 0x06, + 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, + 0x0b, 0x20, 0x0c, 0x0d, 0x02, 0x20, 0x10, 0x41, 0xff, 0x01, 0x71, 0x21, + 0x10, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x20, 0x10, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x00, + 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x09, 0x41, + 0xd0, 0x02, 0x6a, 0x20, 0x0a, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x02, + 0x40, 0x20, 0x14, 0x20, 0x0a, 0x6b, 0x22, 0x0c, 0x41, 0x01, 0x48, 0x0d, + 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x30, 0x20, 0x0c, 0x41, 0x80, + 0x02, 0x20, 0x0c, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, 0x1b, 0x10, 0x3a, + 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, 0x71, 0x21, 0x06, + 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x05, + 0x20, 0x0c, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, + 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, 0x0b, 0x20, 0x07, + 0x41, 0x20, 0x71, 0x22, 0x0a, 0x45, 0x21, 0x05, 0x20, 0x06, 0x41, 0x80, + 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, + 0x0a, 0x0d, 0x02, 0x20, 0x0c, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0c, 0x0c, + 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, + 0x20, 0x0c, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x00, 0x2d, 0x00, + 0x00, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x12, 0x20, 0x11, 0x20, + 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x0b, 0x41, 0x80, 0xc0, + 0x00, 0x47, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x08, 0x4c, 0x0d, 0x00, 0x20, + 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, 0x08, 0x6b, 0x22, + 0x0c, 0x41, 0x80, 0x02, 0x20, 0x0c, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, + 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, + 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, + 0x45, 0x21, 0x05, 0x20, 0x0c, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, + 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, + 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, + 0x0b, 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, 0x0a, 0x45, 0x21, 0x05, 0x20, + 0x06, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, + 0x00, 0x0b, 0x20, 0x0a, 0x0d, 0x02, 0x20, 0x0c, 0x41, 0xff, 0x01, 0x71, + 0x21, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, + 0x41, 0x40, 0x6b, 0x20, 0x0c, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, + 0x0e, 0x20, 0x08, 0x20, 0x0e, 0x20, 0x08, 0x4a, 0x1b, 0x21, 0x05, 0x0c, + 0x01, 0x0b, 0x20, 0x0b, 0x41, 0x00, 0x48, 0x21, 0x06, 0x02, 0x40, 0x20, + 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x04, + 0x40, 0x20, 0x09, 0x28, 0x02, 0xec, 0x02, 0x21, 0x08, 0x0c, 0x01, 0x0b, + 0x20, 0x09, 0x20, 0x09, 0x28, 0x02, 0xec, 0x02, 0x41, 0x64, 0x6a, 0x22, + 0x08, 0x36, 0x02, 0xec, 0x02, 0x20, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xb0, 0x41, 0xa2, 0x21, 0x24, 0x0b, 0x41, 0x06, 0x20, 0x0b, + 0x20, 0x06, 0x1b, 0x21, 0x0d, 0x20, 0x09, 0x41, 0xf0, 0x02, 0x6a, 0x20, + 0x21, 0x20, 0x08, 0x41, 0x00, 0x48, 0x1b, 0x22, 0x12, 0x21, 0x07, 0x03, + 0x40, 0x20, 0x07, 0x02, 0x7f, 0x20, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x41, 0x63, 0x20, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x71, 0x04, 0x40, 0x20, 0x24, 0xab, 0x0c, + 0x01, 0x0b, 0x41, 0x00, 0x0b, 0x22, 0x06, 0x36, 0x02, 0x00, 0x20, 0x07, + 0x41, 0x04, 0x6a, 0x21, 0x07, 0x20, 0x24, 0x20, 0x06, 0xb8, 0xa1, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x65, 0xcd, 0xcd, 0x41, 0xa2, 0x22, 0x24, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x0d, 0x00, 0x0b, + 0x02, 0x40, 0x20, 0x08, 0x41, 0x01, 0x48, 0x04, 0x40, 0x20, 0x07, 0x21, + 0x05, 0x20, 0x12, 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x20, 0x12, 0x21, 0x06, + 0x03, 0x40, 0x20, 0x08, 0x41, 0x1d, 0x20, 0x08, 0x41, 0x1d, 0x48, 0x1b, + 0x21, 0x08, 0x02, 0x40, 0x20, 0x07, 0x41, 0x7c, 0x6a, 0x22, 0x05, 0x20, + 0x06, 0x49, 0x0d, 0x00, 0x20, 0x08, 0xad, 0x21, 0x23, 0x42, 0x00, 0x21, + 0x22, 0x03, 0x40, 0x20, 0x05, 0x20, 0x22, 0x42, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x83, 0x20, 0x05, 0x35, 0x02, 0x00, 0x20, 0x23, 0x86, 0x7c, 0x22, + 0x22, 0x20, 0x22, 0x42, 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x80, 0x22, 0x22, + 0x42, 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x7e, 0x7d, 0x3e, 0x02, 0x00, 0x20, + 0x05, 0x41, 0x7c, 0x6a, 0x22, 0x05, 0x20, 0x06, 0x4f, 0x0d, 0x00, 0x0b, + 0x20, 0x22, 0xa7, 0x22, 0x05, 0x45, 0x0d, 0x00, 0x20, 0x06, 0x41, 0x7c, + 0x6a, 0x22, 0x06, 0x20, 0x05, 0x36, 0x02, 0x00, 0x0b, 0x03, 0x40, 0x20, + 0x07, 0x22, 0x05, 0x20, 0x06, 0x4b, 0x04, 0x40, 0x20, 0x05, 0x41, 0x7c, + 0x6a, 0x22, 0x07, 0x28, 0x02, 0x00, 0x45, 0x0d, 0x01, 0x0b, 0x0b, 0x20, + 0x09, 0x20, 0x09, 0x28, 0x02, 0xec, 0x02, 0x20, 0x08, 0x6b, 0x22, 0x08, + 0x36, 0x02, 0xec, 0x02, 0x20, 0x05, 0x21, 0x07, 0x20, 0x08, 0x41, 0x00, + 0x4a, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x08, 0x41, 0x7f, 0x4c, 0x04, 0x40, + 0x20, 0x0d, 0x41, 0x19, 0x6a, 0x41, 0x09, 0x6e, 0x41, 0x01, 0x6a, 0x21, + 0x0b, 0x03, 0x40, 0x41, 0x00, 0x20, 0x08, 0x6b, 0x22, 0x07, 0x41, 0x09, + 0x20, 0x07, 0x41, 0x09, 0x48, 0x1b, 0x21, 0x0a, 0x02, 0x40, 0x20, 0x06, + 0x20, 0x05, 0x4f, 0x04, 0x40, 0x20, 0x06, 0x20, 0x06, 0x41, 0x04, 0x6a, + 0x20, 0x06, 0x28, 0x02, 0x00, 0x1b, 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x41, + 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x20, 0x0a, 0x76, 0x21, 0x10, 0x41, 0x7f, + 0x20, 0x0a, 0x74, 0x41, 0x7f, 0x73, 0x21, 0x16, 0x41, 0x00, 0x21, 0x08, + 0x20, 0x06, 0x21, 0x07, 0x03, 0x40, 0x20, 0x07, 0x20, 0x08, 0x20, 0x07, + 0x28, 0x02, 0x00, 0x22, 0x17, 0x20, 0x0a, 0x76, 0x6a, 0x36, 0x02, 0x00, + 0x20, 0x16, 0x20, 0x17, 0x71, 0x20, 0x10, 0x6c, 0x21, 0x08, 0x20, 0x07, + 0x41, 0x04, 0x6a, 0x22, 0x07, 0x20, 0x05, 0x49, 0x0d, 0x00, 0x0b, 0x20, + 0x06, 0x20, 0x06, 0x41, 0x04, 0x6a, 0x20, 0x06, 0x28, 0x02, 0x00, 0x1b, + 0x21, 0x06, 0x20, 0x08, 0x45, 0x0d, 0x00, 0x20, 0x05, 0x20, 0x08, 0x36, + 0x02, 0x00, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x0b, 0x20, 0x09, + 0x20, 0x09, 0x28, 0x02, 0xec, 0x02, 0x20, 0x0a, 0x6a, 0x22, 0x08, 0x36, + 0x02, 0xec, 0x02, 0x20, 0x12, 0x20, 0x06, 0x20, 0x0c, 0x41, 0xe6, 0x00, + 0x46, 0x1b, 0x22, 0x07, 0x20, 0x0b, 0x41, 0x02, 0x74, 0x6a, 0x20, 0x05, + 0x20, 0x05, 0x20, 0x07, 0x6b, 0x41, 0x02, 0x75, 0x20, 0x0b, 0x4a, 0x1b, + 0x21, 0x05, 0x20, 0x08, 0x41, 0x00, 0x48, 0x0d, 0x00, 0x0b, 0x0b, 0x41, + 0x00, 0x21, 0x07, 0x02, 0x40, 0x20, 0x06, 0x20, 0x05, 0x4f, 0x0d, 0x00, + 0x20, 0x12, 0x20, 0x06, 0x6b, 0x41, 0x02, 0x75, 0x41, 0x09, 0x6c, 0x21, + 0x07, 0x20, 0x06, 0x28, 0x02, 0x00, 0x22, 0x0a, 0x41, 0x0a, 0x49, 0x0d, + 0x00, 0x41, 0x0a, 0x21, 0x08, 0x03, 0x40, 0x20, 0x07, 0x41, 0x01, 0x6a, + 0x21, 0x07, 0x20, 0x0a, 0x20, 0x08, 0x41, 0x0a, 0x6c, 0x22, 0x08, 0x4f, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x0d, 0x41, 0x00, 0x20, 0x07, 0x20, 0x0c, + 0x41, 0xe6, 0x00, 0x46, 0x1b, 0x22, 0x0a, 0x6b, 0x20, 0x0c, 0x41, 0xe7, + 0x00, 0x46, 0x22, 0x10, 0x20, 0x0d, 0x41, 0x00, 0x47, 0x71, 0x22, 0x0b, + 0x6b, 0x22, 0x08, 0x20, 0x05, 0x20, 0x12, 0x6b, 0x41, 0x02, 0x75, 0x41, + 0x09, 0x6c, 0x41, 0x77, 0x6a, 0x48, 0x04, 0x40, 0x20, 0x08, 0x41, 0x80, + 0xc8, 0x00, 0x6a, 0x22, 0x16, 0x41, 0x09, 0x6d, 0x22, 0x17, 0x41, 0x02, + 0x74, 0x20, 0x12, 0x6a, 0x22, 0x1d, 0x41, 0x84, 0x60, 0x6a, 0x21, 0x0c, + 0x41, 0x0a, 0x21, 0x08, 0x20, 0x16, 0x20, 0x17, 0x41, 0x09, 0x6c, 0x22, + 0x16, 0x6b, 0x41, 0x01, 0x6a, 0x41, 0x08, 0x4c, 0x04, 0x40, 0x20, 0x0a, + 0x20, 0x16, 0x6a, 0x20, 0x0b, 0x6a, 0x20, 0x0d, 0x6b, 0x41, 0x88, 0xb8, + 0x7f, 0x6a, 0x21, 0x0b, 0x03, 0x40, 0x20, 0x08, 0x41, 0x0a, 0x6c, 0x21, + 0x08, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, 0x0b, + 0x02, 0x40, 0x41, 0x00, 0x20, 0x05, 0x20, 0x0c, 0x41, 0x04, 0x6a, 0x22, + 0x16, 0x46, 0x20, 0x0c, 0x28, 0x02, 0x00, 0x22, 0x0b, 0x20, 0x0b, 0x20, + 0x08, 0x6e, 0x22, 0x17, 0x20, 0x08, 0x6c, 0x6b, 0x22, 0x0a, 0x1b, 0x0d, + 0x00, 0x02, 0x40, 0x20, 0x17, 0x41, 0x01, 0x71, 0x45, 0x04, 0x40, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x43, 0x21, 0x24, 0x20, 0x0c, + 0x20, 0x06, 0x4d, 0x0d, 0x01, 0x20, 0x08, 0x41, 0x80, 0x94, 0xeb, 0xdc, + 0x03, 0x47, 0x0d, 0x01, 0x20, 0x0c, 0x41, 0x7c, 0x6a, 0x2d, 0x00, 0x00, + 0x41, 0x01, 0x71, 0x45, 0x0d, 0x01, 0x0b, 0x44, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x43, 0x21, 0x24, 0x0b, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x3f, 0x21, 0x25, 0x20, 0x0a, 0x20, 0x08, 0x41, 0x01, + 0x76, 0x22, 0x17, 0x4f, 0x04, 0x40, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x3f, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, + 0x20, 0x0a, 0x20, 0x17, 0x46, 0x1b, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0x3f, 0x20, 0x05, 0x20, 0x16, 0x46, 0x1b, 0x21, 0x25, 0x0b, + 0x02, 0x40, 0x20, 0x14, 0x45, 0x0d, 0x00, 0x20, 0x18, 0x2d, 0x00, 0x00, + 0x41, 0x2d, 0x47, 0x0d, 0x00, 0x20, 0x25, 0x9a, 0x21, 0x25, 0x20, 0x24, + 0x9a, 0x21, 0x24, 0x0b, 0x20, 0x0c, 0x20, 0x0b, 0x20, 0x0a, 0x6b, 0x22, + 0x0a, 0x36, 0x02, 0x00, 0x20, 0x24, 0x20, 0x25, 0xa0, 0x20, 0x24, 0x61, + 0x0d, 0x00, 0x20, 0x0c, 0x20, 0x08, 0x20, 0x0a, 0x6a, 0x22, 0x07, 0x36, + 0x02, 0x00, 0x20, 0x07, 0x41, 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x4f, 0x04, + 0x40, 0x20, 0x1d, 0x41, 0x80, 0x60, 0x6a, 0x21, 0x07, 0x03, 0x40, 0x20, + 0x07, 0x41, 0x04, 0x6a, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x07, 0x20, + 0x06, 0x49, 0x04, 0x40, 0x20, 0x06, 0x41, 0x7c, 0x6a, 0x22, 0x06, 0x41, + 0x00, 0x36, 0x02, 0x00, 0x0b, 0x20, 0x07, 0x20, 0x07, 0x28, 0x02, 0x00, + 0x41, 0x01, 0x6a, 0x22, 0x08, 0x36, 0x02, 0x00, 0x20, 0x07, 0x41, 0x7c, + 0x6a, 0x21, 0x07, 0x20, 0x08, 0x41, 0xff, 0x93, 0xeb, 0xdc, 0x03, 0x4b, + 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x41, 0x04, 0x6a, 0x21, 0x0c, 0x0b, 0x20, + 0x12, 0x20, 0x06, 0x6b, 0x41, 0x02, 0x75, 0x41, 0x09, 0x6c, 0x21, 0x07, + 0x20, 0x06, 0x28, 0x02, 0x00, 0x22, 0x0a, 0x41, 0x0a, 0x49, 0x0d, 0x00, + 0x41, 0x0a, 0x21, 0x08, 0x03, 0x40, 0x20, 0x07, 0x41, 0x01, 0x6a, 0x21, + 0x07, 0x20, 0x0a, 0x20, 0x08, 0x41, 0x0a, 0x6c, 0x22, 0x08, 0x4f, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x0c, 0x41, 0x04, 0x6a, 0x22, 0x08, 0x20, 0x05, + 0x20, 0x05, 0x20, 0x08, 0x4b, 0x1b, 0x21, 0x05, 0x0b, 0x02, 0x7f, 0x03, + 0x40, 0x41, 0x00, 0x20, 0x05, 0x22, 0x0b, 0x20, 0x06, 0x4d, 0x0d, 0x01, + 0x1a, 0x20, 0x0b, 0x41, 0x7c, 0x6a, 0x22, 0x05, 0x28, 0x02, 0x00, 0x45, + 0x0d, 0x00, 0x0b, 0x41, 0x01, 0x0b, 0x21, 0x16, 0x02, 0x40, 0x20, 0x10, + 0x45, 0x04, 0x40, 0x20, 0x0f, 0x41, 0x08, 0x71, 0x21, 0x10, 0x0c, 0x01, + 0x0b, 0x20, 0x07, 0x41, 0x7f, 0x73, 0x41, 0x7f, 0x20, 0x0d, 0x41, 0x01, + 0x20, 0x0d, 0x1b, 0x22, 0x05, 0x20, 0x07, 0x4a, 0x20, 0x07, 0x41, 0x7b, + 0x4a, 0x71, 0x22, 0x08, 0x1b, 0x20, 0x05, 0x6a, 0x21, 0x0d, 0x41, 0x7f, + 0x41, 0x7e, 0x20, 0x08, 0x1b, 0x20, 0x11, 0x6a, 0x21, 0x11, 0x20, 0x0f, + 0x41, 0x08, 0x71, 0x22, 0x10, 0x0d, 0x00, 0x41, 0x09, 0x21, 0x05, 0x02, + 0x40, 0x20, 0x16, 0x45, 0x0d, 0x00, 0x20, 0x0b, 0x41, 0x7c, 0x6a, 0x28, + 0x02, 0x00, 0x22, 0x0a, 0x45, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x05, 0x20, + 0x0a, 0x41, 0x0a, 0x70, 0x0d, 0x00, 0x41, 0x0a, 0x21, 0x08, 0x03, 0x40, + 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x05, 0x20, 0x0a, 0x20, 0x08, 0x41, + 0x0a, 0x6c, 0x22, 0x08, 0x70, 0x45, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x0b, + 0x20, 0x12, 0x6b, 0x41, 0x02, 0x75, 0x41, 0x09, 0x6c, 0x41, 0x77, 0x6a, + 0x21, 0x08, 0x20, 0x11, 0x41, 0x20, 0x72, 0x41, 0xe6, 0x00, 0x46, 0x04, + 0x40, 0x41, 0x00, 0x21, 0x10, 0x20, 0x0d, 0x20, 0x08, 0x20, 0x05, 0x6b, + 0x22, 0x05, 0x41, 0x00, 0x20, 0x05, 0x41, 0x00, 0x4a, 0x1b, 0x22, 0x05, + 0x20, 0x0d, 0x20, 0x05, 0x48, 0x1b, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x41, + 0x00, 0x21, 0x10, 0x20, 0x0d, 0x20, 0x07, 0x20, 0x08, 0x6a, 0x20, 0x05, + 0x6b, 0x22, 0x05, 0x41, 0x00, 0x20, 0x05, 0x41, 0x00, 0x4a, 0x1b, 0x22, + 0x05, 0x20, 0x0d, 0x20, 0x05, 0x48, 0x1b, 0x21, 0x0d, 0x0b, 0x41, 0x7f, + 0x21, 0x05, 0x20, 0x0d, 0x41, 0xfd, 0xff, 0xff, 0xff, 0x07, 0x41, 0xfe, + 0xff, 0xff, 0xff, 0x07, 0x20, 0x0d, 0x20, 0x10, 0x72, 0x22, 0x17, 0x1b, + 0x4a, 0x0d, 0x00, 0x20, 0x0d, 0x20, 0x17, 0x41, 0x00, 0x47, 0x6a, 0x41, + 0x01, 0x6a, 0x21, 0x0c, 0x02, 0x40, 0x20, 0x11, 0x41, 0x20, 0x72, 0x41, + 0xe6, 0x00, 0x47, 0x22, 0x1d, 0x45, 0x04, 0x40, 0x20, 0x07, 0x41, 0xff, + 0xff, 0xff, 0xff, 0x07, 0x20, 0x0c, 0x6b, 0x4a, 0x0d, 0x02, 0x20, 0x07, + 0x41, 0x00, 0x20, 0x07, 0x41, 0x00, 0x4a, 0x1b, 0x21, 0x07, 0x0c, 0x01, + 0x0b, 0x20, 0x19, 0x21, 0x08, 0x20, 0x07, 0x20, 0x07, 0x41, 0x1f, 0x75, + 0x22, 0x05, 0x6a, 0x20, 0x05, 0x73, 0x22, 0x05, 0x04, 0x40, 0x03, 0x40, + 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x22, 0x08, 0x20, 0x05, 0x20, 0x05, 0x41, + 0x0a, 0x6e, 0x22, 0x0a, 0x41, 0x0a, 0x6c, 0x6b, 0x41, 0x30, 0x72, 0x3a, + 0x00, 0x00, 0x20, 0x05, 0x41, 0x09, 0x4b, 0x20, 0x0a, 0x21, 0x05, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x19, 0x20, 0x08, 0x6b, 0x41, 0x01, 0x4c, 0x04, + 0x40, 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x21, 0x05, 0x03, 0x40, 0x20, 0x05, + 0x41, 0x30, 0x3a, 0x00, 0x00, 0x20, 0x19, 0x20, 0x05, 0x6b, 0x20, 0x05, + 0x41, 0x7f, 0x6a, 0x22, 0x0a, 0x21, 0x05, 0x41, 0x02, 0x48, 0x0d, 0x00, + 0x0b, 0x20, 0x0a, 0x41, 0x01, 0x6a, 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, + 0x7e, 0x6a, 0x22, 0x1c, 0x20, 0x11, 0x3a, 0x00, 0x00, 0x41, 0x7f, 0x21, + 0x05, 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x41, 0x2d, 0x41, 0x2b, 0x20, 0x07, + 0x41, 0x00, 0x48, 0x1b, 0x3a, 0x00, 0x00, 0x20, 0x19, 0x20, 0x1c, 0x6b, + 0x22, 0x07, 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x20, 0x0c, 0x6b, 0x4a, + 0x0d, 0x01, 0x0b, 0x20, 0x07, 0x20, 0x0c, 0x6a, 0x22, 0x07, 0x20, 0x14, + 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x73, 0x4a, 0x0d, 0x00, 0x20, 0x07, + 0x20, 0x14, 0x6a, 0x21, 0x11, 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, + 0x04, 0x71, 0x22, 0x0f, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x11, 0x4c, 0x0d, + 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, 0x11, + 0x6b, 0x22, 0x0a, 0x41, 0x80, 0x02, 0x20, 0x0a, 0x41, 0x80, 0x02, 0x49, + 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x08, + 0x41, 0x20, 0x71, 0x21, 0x05, 0x02, 0x40, 0x20, 0x07, 0x45, 0x04, 0x40, + 0x20, 0x05, 0x45, 0x21, 0x05, 0x20, 0x0a, 0x21, 0x07, 0x03, 0x40, 0x20, + 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, + 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, 0x20, 0x71, 0x22, 0x0c, 0x45, 0x21, + 0x05, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, 0x41, 0xff, 0x01, + 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x0d, 0x02, 0x20, 0x0a, 0x41, 0xff, + 0x01, 0x71, 0x21, 0x0a, 0x0c, 0x01, 0x0b, 0x20, 0x05, 0x0d, 0x01, 0x0b, + 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0a, 0x20, 0x00, 0x10, 0x33, 0x1a, + 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, + 0x20, 0x18, 0x20, 0x14, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, + 0x20, 0x0f, 0x41, 0x80, 0x80, 0x04, 0x47, 0x0d, 0x00, 0x20, 0x0e, 0x20, + 0x11, 0x4c, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x30, 0x20, + 0x0e, 0x20, 0x11, 0x6b, 0x22, 0x0a, 0x41, 0x80, 0x02, 0x20, 0x0a, 0x41, + 0x80, 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, + 0x00, 0x22, 0x08, 0x41, 0x20, 0x71, 0x21, 0x05, 0x02, 0x40, 0x20, 0x07, + 0x45, 0x04, 0x40, 0x20, 0x05, 0x45, 0x21, 0x05, 0x20, 0x0a, 0x21, 0x07, + 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, + 0x28, 0x02, 0x00, 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, 0x20, 0x71, 0x22, + 0x0c, 0x45, 0x21, 0x05, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, + 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x0d, 0x02, 0x20, + 0x0a, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0a, 0x0c, 0x01, 0x0b, 0x20, 0x05, + 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0a, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x1d, 0x45, 0x04, 0x40, 0x20, + 0x12, 0x20, 0x06, 0x20, 0x06, 0x20, 0x12, 0x4b, 0x1b, 0x22, 0x08, 0x21, + 0x0c, 0x03, 0x40, 0x02, 0x40, 0x20, 0x0c, 0x28, 0x02, 0x00, 0x22, 0x05, + 0x45, 0x04, 0x40, 0x41, 0x00, 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x41, 0x00, + 0x21, 0x06, 0x03, 0x40, 0x20, 0x06, 0x20, 0x1e, 0x6a, 0x20, 0x05, 0x20, + 0x05, 0x41, 0x0a, 0x6e, 0x22, 0x07, 0x41, 0x0a, 0x6c, 0x6b, 0x41, 0x30, + 0x72, 0x3a, 0x00, 0x00, 0x20, 0x06, 0x41, 0x7f, 0x6a, 0x21, 0x06, 0x20, + 0x05, 0x41, 0x09, 0x4b, 0x20, 0x07, 0x21, 0x05, 0x0d, 0x00, 0x0b, 0x0b, + 0x20, 0x06, 0x20, 0x1b, 0x6a, 0x21, 0x05, 0x02, 0x40, 0x20, 0x08, 0x20, + 0x0c, 0x47, 0x04, 0x40, 0x20, 0x05, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, + 0x4d, 0x0d, 0x01, 0x03, 0x40, 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, + 0x41, 0x30, 0x3a, 0x00, 0x00, 0x20, 0x05, 0x20, 0x09, 0x41, 0xd0, 0x02, + 0x6a, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, 0x21, + 0x05, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x00, 0x20, 0x05, 0x41, 0x7f, + 0x6a, 0x22, 0x05, 0x41, 0x30, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x00, 0x2d, + 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x05, 0x20, 0x1b, + 0x20, 0x05, 0x6b, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x0c, 0x41, + 0x04, 0x6a, 0x22, 0x0c, 0x20, 0x12, 0x4d, 0x0d, 0x00, 0x0b, 0x02, 0x40, + 0x20, 0x17, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, + 0x71, 0x0d, 0x00, 0x41, 0xd3, 0x1b, 0x41, 0x01, 0x20, 0x00, 0x10, 0x33, + 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x0d, 0x41, 0x01, 0x48, 0x0d, 0x00, 0x20, + 0x0c, 0x20, 0x0b, 0x4f, 0x0d, 0x00, 0x03, 0x40, 0x20, 0x1b, 0x21, 0x05, + 0x02, 0x40, 0x20, 0x0c, 0x28, 0x02, 0x00, 0x22, 0x06, 0x04, 0x40, 0x03, + 0x40, 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x20, 0x06, 0x20, 0x06, + 0x41, 0x0a, 0x6e, 0x22, 0x07, 0x41, 0x0a, 0x6c, 0x6b, 0x41, 0x30, 0x72, + 0x3a, 0x00, 0x00, 0x20, 0x06, 0x41, 0x09, 0x4b, 0x20, 0x07, 0x21, 0x06, + 0x0d, 0x00, 0x0b, 0x20, 0x05, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, 0x4d, + 0x0d, 0x01, 0x0b, 0x03, 0x40, 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, + 0x41, 0x30, 0x3a, 0x00, 0x00, 0x20, 0x05, 0x20, 0x09, 0x41, 0xd0, 0x02, + 0x6a, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, + 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x05, 0x20, 0x0d, 0x41, 0x09, 0x20, + 0x0d, 0x41, 0x09, 0x48, 0x1b, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, + 0x0d, 0x41, 0x77, 0x6a, 0x22, 0x0d, 0x41, 0x01, 0x48, 0x0d, 0x01, 0x20, + 0x0c, 0x41, 0x04, 0x6a, 0x22, 0x0c, 0x20, 0x0b, 0x49, 0x0d, 0x00, 0x0b, + 0x0b, 0x20, 0x0d, 0x41, 0x01, 0x48, 0x0d, 0x01, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x41, 0x30, 0x20, 0x0d, 0x41, 0x80, 0x02, 0x20, 0x0d, 0x41, 0x80, + 0x02, 0x49, 0x22, 0x05, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x22, 0x07, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, + 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x05, 0x20, 0x0d, 0x21, 0x06, 0x03, + 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, + 0x02, 0x00, 0x21, 0x07, 0x0b, 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, 0x08, + 0x45, 0x21, 0x05, 0x20, 0x06, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, + 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x08, 0x0d, 0x03, 0x20, 0x0d, + 0x41, 0xff, 0x01, 0x71, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, + 0x02, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0d, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x0d, 0x41, 0x7f, 0x4c, + 0x0d, 0x00, 0x20, 0x0b, 0x20, 0x06, 0x41, 0x04, 0x6a, 0x20, 0x16, 0x1b, + 0x21, 0x0a, 0x20, 0x06, 0x21, 0x0c, 0x03, 0x40, 0x20, 0x1b, 0x21, 0x08, + 0x02, 0x40, 0x20, 0x0c, 0x28, 0x02, 0x00, 0x22, 0x05, 0x04, 0x40, 0x41, + 0x00, 0x21, 0x07, 0x03, 0x40, 0x20, 0x07, 0x20, 0x09, 0x6a, 0x41, 0xd8, + 0x02, 0x6a, 0x20, 0x05, 0x20, 0x05, 0x41, 0x0a, 0x6e, 0x22, 0x08, 0x41, + 0x0a, 0x6c, 0x6b, 0x41, 0x30, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x07, 0x41, + 0x7f, 0x6a, 0x21, 0x07, 0x20, 0x05, 0x41, 0x09, 0x4b, 0x20, 0x08, 0x21, + 0x05, 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x20, 0x09, 0x6a, 0x41, 0xd9, 0x02, + 0x6a, 0x21, 0x08, 0x20, 0x07, 0x0d, 0x01, 0x0b, 0x20, 0x08, 0x41, 0x7f, + 0x6a, 0x22, 0x08, 0x41, 0x30, 0x3a, 0x00, 0x00, 0x0b, 0x02, 0x40, 0x20, + 0x06, 0x20, 0x0c, 0x47, 0x04, 0x40, 0x20, 0x08, 0x20, 0x09, 0x41, 0xd0, + 0x02, 0x6a, 0x4d, 0x0d, 0x01, 0x03, 0x40, 0x20, 0x08, 0x41, 0x7f, 0x6a, + 0x22, 0x08, 0x41, 0x30, 0x3a, 0x00, 0x00, 0x20, 0x08, 0x20, 0x09, 0x41, + 0xd0, 0x02, 0x6a, 0x4b, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, 0x00, + 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x08, 0x41, + 0x01, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x08, 0x41, 0x01, 0x6a, + 0x21, 0x08, 0x20, 0x10, 0x45, 0x41, 0x00, 0x20, 0x0d, 0x41, 0x01, 0x48, + 0x1b, 0x0d, 0x00, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x0d, + 0x00, 0x41, 0xd3, 0x1b, 0x41, 0x01, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, + 0x20, 0x1b, 0x20, 0x08, 0x6b, 0x21, 0x05, 0x20, 0x00, 0x2d, 0x00, 0x00, + 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x08, 0x20, 0x05, 0x20, 0x0d, + 0x20, 0x0d, 0x20, 0x05, 0x4a, 0x1b, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, + 0x20, 0x0c, 0x41, 0x04, 0x6a, 0x22, 0x0c, 0x20, 0x0a, 0x49, 0x41, 0x00, + 0x20, 0x0d, 0x20, 0x05, 0x6b, 0x22, 0x0d, 0x41, 0x7f, 0x4a, 0x1b, 0x0d, + 0x00, 0x0b, 0x20, 0x0d, 0x41, 0x01, 0x48, 0x0d, 0x00, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x41, 0x30, 0x20, 0x0d, 0x41, 0x80, 0x02, 0x20, 0x0d, 0x41, + 0x80, 0x02, 0x49, 0x22, 0x05, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, + 0x00, 0x22, 0x07, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, + 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x05, 0x20, 0x0d, 0x21, 0x06, + 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, + 0x28, 0x02, 0x00, 0x21, 0x07, 0x0b, 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, + 0x08, 0x45, 0x21, 0x05, 0x20, 0x06, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, + 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x08, 0x0d, 0x02, 0x20, + 0x0d, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x20, 0x06, + 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0d, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, + 0x0d, 0x00, 0x20, 0x1c, 0x20, 0x19, 0x20, 0x1c, 0x6b, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, 0x00, 0x47, + 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x11, 0x4c, 0x0d, 0x00, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, 0x11, 0x6b, 0x22, 0x0b, 0x41, + 0x80, 0x02, 0x20, 0x0b, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, 0x1b, 0x10, + 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, 0x71, 0x21, + 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, + 0x05, 0x20, 0x0b, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, + 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, 0x0b, 0x20, + 0x07, 0x41, 0x20, 0x71, 0x22, 0x08, 0x45, 0x21, 0x05, 0x20, 0x06, 0x41, + 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, + 0x20, 0x08, 0x0d, 0x02, 0x20, 0x0b, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0b, + 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x20, 0x0b, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x0e, 0x20, + 0x11, 0x20, 0x0e, 0x20, 0x11, 0x4a, 0x1b, 0x21, 0x05, 0x0b, 0x20, 0x05, + 0x41, 0x00, 0x4e, 0x0d, 0x0a, 0x0c, 0x09, 0x0b, 0x41, 0x00, 0x21, 0x0a, + 0x41, 0xa6, 0x16, 0x21, 0x10, 0x0b, 0x20, 0x15, 0x21, 0x05, 0x0c, 0x06, + 0x0b, 0x20, 0x06, 0x21, 0x0f, 0x20, 0x07, 0x21, 0x0b, 0x20, 0x05, 0x2d, + 0x00, 0x00, 0x45, 0x0d, 0x05, 0x0c, 0x06, 0x0b, 0x20, 0x01, 0x2d, 0x00, + 0x01, 0x21, 0x05, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x0c, 0x00, + 0x0b, 0x00, 0x0b, 0x20, 0x00, 0x0d, 0x06, 0x20, 0x1a, 0x45, 0x04, 0x40, + 0x41, 0x00, 0x21, 0x13, 0x0c, 0x07, 0x0b, 0x02, 0x7f, 0x41, 0x01, 0x20, + 0x04, 0x28, 0x02, 0x04, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x08, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x02, 0x20, + 0x04, 0x28, 0x02, 0x08, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x10, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x03, 0x20, + 0x04, 0x28, 0x02, 0x0c, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x18, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x04, 0x20, + 0x04, 0x28, 0x02, 0x10, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x20, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x05, 0x20, + 0x04, 0x28, 0x02, 0x14, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x28, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x06, 0x20, + 0x04, 0x28, 0x02, 0x18, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x30, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x07, 0x20, + 0x04, 0x28, 0x02, 0x1c, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x38, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x08, 0x20, + 0x04, 0x28, 0x02, 0x20, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x40, 0x6b, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x20, 0x04, 0x28, + 0x02, 0x24, 0x22, 0x00, 0x0d, 0x02, 0x41, 0x09, 0x0b, 0x41, 0x02, 0x74, + 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, + 0x0d, 0x01, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x22, 0x01, 0x41, 0x28, 0x47, + 0x0d, 0x00, 0x0b, 0x41, 0x01, 0x21, 0x13, 0x0c, 0x06, 0x0b, 0x41, 0xe0, + 0x1f, 0x41, 0x1c, 0x36, 0x02, 0x00, 0x0c, 0x04, 0x0b, 0x20, 0x03, 0x41, + 0xc8, 0x00, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x01, 0x21, + 0x13, 0x0c, 0x04, 0x0b, 0x20, 0x05, 0x20, 0x08, 0x6b, 0x22, 0x11, 0x20, + 0x0b, 0x20, 0x0b, 0x20, 0x11, 0x48, 0x1b, 0x22, 0x14, 0x41, 0xff, 0xff, + 0xff, 0xff, 0x07, 0x20, 0x0a, 0x6b, 0x4a, 0x0d, 0x00, 0x20, 0x0a, 0x20, + 0x14, 0x6a, 0x22, 0x12, 0x20, 0x0e, 0x20, 0x0e, 0x20, 0x12, 0x48, 0x1b, + 0x22, 0x05, 0x20, 0x18, 0x4a, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x0f, 0x41, + 0x80, 0xc0, 0x04, 0x71, 0x22, 0x0f, 0x0d, 0x00, 0x20, 0x12, 0x20, 0x0e, + 0x4e, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x05, + 0x20, 0x12, 0x6b, 0x22, 0x0d, 0x41, 0x80, 0x02, 0x20, 0x0d, 0x41, 0x80, + 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x22, 0x0c, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x07, 0x45, + 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, 0x20, 0x0d, 0x21, 0x07, 0x03, + 0x40, 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, + 0x02, 0x00, 0x21, 0x0c, 0x0b, 0x20, 0x0c, 0x41, 0x20, 0x71, 0x22, 0x18, + 0x45, 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, 0x41, + 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x18, 0x0d, 0x02, 0x20, 0x0d, + 0x41, 0xff, 0x01, 0x71, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, + 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0d, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, + 0x04, 0x40, 0x20, 0x10, 0x20, 0x0a, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, + 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0x80, 0x04, 0x47, 0x0d, 0x00, 0x20, + 0x12, 0x20, 0x0e, 0x4e, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, + 0x30, 0x20, 0x05, 0x20, 0x12, 0x6b, 0x22, 0x0a, 0x41, 0x80, 0x02, 0x20, + 0x0a, 0x41, 0x80, 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, + 0x28, 0x02, 0x00, 0x22, 0x0c, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, + 0x20, 0x07, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, 0x20, 0x0a, + 0x21, 0x07, 0x03, 0x40, 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, + 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, + 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x0c, 0x0b, 0x20, 0x0c, 0x41, 0x20, + 0x71, 0x22, 0x0d, 0x45, 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, + 0x22, 0x07, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0d, 0x0d, + 0x02, 0x20, 0x0a, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0a, 0x0c, 0x01, 0x0b, + 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0a, + 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x11, 0x20, 0x0b, + 0x4e, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x30, 0x20, 0x14, + 0x20, 0x11, 0x6b, 0x22, 0x0a, 0x41, 0x80, 0x02, 0x20, 0x0a, 0x41, 0x80, + 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x22, 0x0b, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x07, 0x45, + 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, 0x20, 0x0a, 0x21, 0x07, 0x03, + 0x40, 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, + 0x02, 0x00, 0x21, 0x0b, 0x0b, 0x20, 0x0b, 0x41, 0x20, 0x71, 0x22, 0x0c, + 0x45, 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, 0x41, + 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x0d, 0x02, 0x20, 0x0a, + 0x41, 0xff, 0x01, 0x71, 0x21, 0x0a, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, + 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0a, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, + 0x04, 0x40, 0x20, 0x08, 0x20, 0x11, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, + 0x20, 0x0f, 0x41, 0x80, 0xc0, 0x00, 0x47, 0x0d, 0x01, 0x20, 0x12, 0x20, + 0x0e, 0x4e, 0x0d, 0x01, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, + 0x05, 0x20, 0x12, 0x6b, 0x22, 0x0b, 0x41, 0x80, 0x02, 0x20, 0x0b, 0x41, + 0x80, 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, + 0x00, 0x22, 0x08, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x07, + 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, 0x20, 0x0b, 0x21, 0x07, + 0x03, 0x40, 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, + 0x28, 0x02, 0x00, 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, 0x20, 0x71, 0x22, + 0x0a, 0x45, 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, + 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0a, 0x0d, 0x03, 0x20, + 0x0b, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0b, 0x0c, 0x01, 0x0b, 0x20, 0x06, + 0x0d, 0x02, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0b, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0c, 0x01, 0x0b, 0x0b, 0x41, 0xe0, 0x1f, 0x41, 0x3d, + 0x36, 0x02, 0x00, 0x0b, 0x41, 0x7f, 0x21, 0x13, 0x0b, 0x20, 0x09, 0x41, + 0xf0, 0x06, 0x6a, 0x24, 0x00, 0x20, 0x13, 0x0b, 0xa2, 0x02, 0x00, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, 0x41, 0x77, 0x6a, 0x22, 0x01, + 0x41, 0x11, 0x4d, 0x04, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, 0x41, 0x01, 0x6b, 0x0e, 0x11, + 0x07, 0x08, 0x09, 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x09, 0x08, 0x09, + 0x09, 0x07, 0x08, 0x09, 0x04, 0x05, 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, + 0x02, 0x00, 0x22, 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, + 0x20, 0x01, 0x32, 0x01, 0x00, 0x37, 0x03, 0x00, 0x0f, 0x0b, 0x20, 0x02, + 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x33, 0x01, 0x00, 0x37, 0x03, 0x00, 0x0f, + 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x04, + 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, 0x30, 0x00, 0x00, 0x37, + 0x03, 0x00, 0x0f, 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, + 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, 0x31, + 0x00, 0x00, 0x37, 0x03, 0x00, 0x0f, 0x0b, 0x41, 0x90, 0x1a, 0x41, 0xa8, + 0x29, 0x10, 0x29, 0x1a, 0x00, 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, + 0x00, 0x22, 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, + 0x01, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x0b, 0x0f, 0x0b, 0x20, 0x02, + 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x34, 0x02, 0x00, 0x37, 0x03, 0x00, 0x0f, + 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x04, + 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, 0x35, 0x02, 0x00, 0x37, + 0x03, 0x00, 0x0f, 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x41, + 0x07, 0x6a, 0x41, 0x78, 0x71, 0x22, 0x01, 0x41, 0x08, 0x6a, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x29, 0x03, 0x00, 0x37, 0x03, 0x00, 0x0b, + 0x38, 0x01, 0x01, 0x7f, 0x02, 0x40, 0x41, 0xf0, 0x28, 0x28, 0x02, 0x00, + 0x41, 0x0a, 0x46, 0x0d, 0x00, 0x41, 0xc4, 0x28, 0x28, 0x02, 0x00, 0x22, + 0x00, 0x41, 0xc0, 0x28, 0x28, 0x02, 0x00, 0x46, 0x0d, 0x00, 0x41, 0xc4, + 0x28, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, + 0x0a, 0x3a, 0x00, 0x00, 0x0f, 0x0b, 0x10, 0x2a, 0x0b, 0x18, 0x01, 0x01, + 0x7f, 0x41, 0x7f, 0x41, 0x00, 0x20, 0x00, 0x10, 0x38, 0x22, 0x02, 0x20, + 0x00, 0x20, 0x02, 0x20, 0x01, 0x10, 0x34, 0x47, 0x1b, 0x0b, 0x84, 0x01, + 0x01, 0x02, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x00, 0x24, 0x00, + 0x20, 0x00, 0x41, 0x0a, 0x3a, 0x00, 0x0f, 0x02, 0x40, 0x02, 0x40, 0x41, + 0xc0, 0x28, 0x28, 0x02, 0x00, 0x22, 0x01, 0x04, 0x7f, 0x20, 0x01, 0x05, + 0x41, 0xb0, 0x28, 0x10, 0x31, 0x0d, 0x02, 0x41, 0xc0, 0x28, 0x28, 0x02, + 0x00, 0x0b, 0x41, 0xc4, 0x28, 0x28, 0x02, 0x00, 0x22, 0x01, 0x46, 0x0d, + 0x00, 0x41, 0xf0, 0x28, 0x28, 0x02, 0x00, 0x41, 0x0a, 0x46, 0x0d, 0x00, + 0x41, 0xc4, 0x28, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x00, 0x20, + 0x01, 0x41, 0x0a, 0x3a, 0x00, 0x00, 0x0c, 0x01, 0x0b, 0x41, 0xb0, 0x28, + 0x20, 0x00, 0x41, 0x0f, 0x6a, 0x41, 0x01, 0x41, 0xd0, 0x28, 0x28, 0x02, + 0x00, 0x11, 0x00, 0x00, 0x41, 0x01, 0x47, 0x0d, 0x00, 0x20, 0x00, 0x2d, + 0x00, 0x0f, 0x1a, 0x0b, 0x20, 0x00, 0x41, 0x10, 0x6a, 0x24, 0x00, 0x0b, + 0x09, 0x00, 0x20, 0x00, 0x28, 0x02, 0x38, 0x10, 0x19, 0x0b, 0x48, 0x01, + 0x01, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, 0x00, 0x02, + 0x7e, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x41, 0xff, 0x01, 0x71, 0x20, + 0x03, 0x41, 0x08, 0x6a, 0x10, 0x0d, 0x22, 0x00, 0x04, 0x40, 0x41, 0xe0, + 0x1f, 0x41, 0xc6, 0x00, 0x20, 0x00, 0x20, 0x00, 0x41, 0xcc, 0x00, 0x46, + 0x1b, 0x36, 0x02, 0x00, 0x42, 0x7f, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x29, + 0x03, 0x08, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x00, 0x0b, 0x0d, + 0x00, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x01, 0x20, 0x02, 0x10, 0x2c, + 0x0b, 0x4d, 0x01, 0x01, 0x7f, 0x23, 0x00, 0x41, 0x20, 0x6b, 0x22, 0x01, + 0x24, 0x00, 0x02, 0x7f, 0x02, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0x08, + 0x6a, 0x10, 0x0a, 0x22, 0x00, 0x0d, 0x00, 0x41, 0x3b, 0x21, 0x00, 0x20, + 0x01, 0x2d, 0x00, 0x08, 0x41, 0x02, 0x47, 0x0d, 0x00, 0x20, 0x01, 0x2d, + 0x00, 0x10, 0x41, 0x24, 0x71, 0x0d, 0x00, 0x41, 0x01, 0x0c, 0x01, 0x0b, + 0x41, 0xe0, 0x1f, 0x20, 0x00, 0x36, 0x02, 0x00, 0x41, 0x00, 0x0b, 0x20, + 0x01, 0x41, 0x20, 0x6a, 0x24, 0x00, 0x0b, 0x2f, 0x00, 0x20, 0x00, 0x41, + 0x04, 0x36, 0x02, 0x20, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, + 0xc0, 0x00, 0x71, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x38, 0x10, 0x2e, + 0x0d, 0x00, 0x20, 0x00, 0x41, 0x7f, 0x36, 0x02, 0x40, 0x0b, 0x20, 0x00, + 0x20, 0x01, 0x20, 0x02, 0x10, 0x36, 0x0b, 0xca, 0x02, 0x01, 0x03, 0x7f, + 0x41, 0xec, 0x1f, 0x28, 0x02, 0x00, 0x22, 0x00, 0x04, 0x40, 0x03, 0x40, + 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x47, 0x04, + 0x40, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, + 0x11, 0x00, 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, + 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x47, 0x04, 0x40, 0x20, 0x00, + 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, + 0x24, 0x11, 0x03, 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x34, 0x22, + 0x00, 0x0d, 0x00, 0x0b, 0x0b, 0x02, 0x40, 0x41, 0x98, 0x28, 0x28, 0x02, + 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, + 0x00, 0x28, 0x02, 0x18, 0x47, 0x04, 0x40, 0x20, 0x00, 0x41, 0x00, 0x41, + 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x00, 0x00, 0x1a, 0x0b, 0x20, + 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, + 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, + 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x03, 0x00, 0x1a, 0x0b, + 0x02, 0x40, 0x41, 0xa0, 0x29, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, + 0x00, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x47, + 0x04, 0x40, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, + 0x20, 0x11, 0x00, 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, + 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, + 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x00, 0x20, 0x00, 0x28, + 0x02, 0x24, 0x11, 0x03, 0x00, 0x1a, 0x0b, 0x02, 0x40, 0x41, 0x98, 0x2a, + 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, + 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x47, 0x04, 0x40, 0x20, 0x00, 0x41, + 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x00, 0x00, 0x1a, + 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, + 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, + 0x6b, 0xac, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x03, 0x00, + 0x1a, 0x0b, 0x0b, 0x59, 0x01, 0x01, 0x7f, 0x20, 0x00, 0x20, 0x00, 0x28, + 0x02, 0x3c, 0x22, 0x01, 0x41, 0x7f, 0x6a, 0x20, 0x01, 0x72, 0x36, 0x02, + 0x3c, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x08, 0x71, 0x04, + 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0x20, 0x72, 0x36, 0x02, 0x00, 0x41, + 0x7f, 0x0f, 0x0b, 0x20, 0x00, 0x42, 0x00, 0x37, 0x02, 0x04, 0x20, 0x00, + 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, 0x01, 0x36, 0x02, 0x18, 0x20, 0x00, + 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, 0x00, 0x20, 0x01, 0x20, 0x00, 0x28, + 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, 0x41, 0x00, 0x0b, 0x47, 0x01, 0x01, + 0x7f, 0x41, 0x93, 0x09, 0x41, 0xb0, 0x28, 0x10, 0x29, 0x41, 0x00, 0x48, + 0x04, 0x40, 0x0f, 0x0b, 0x02, 0x40, 0x41, 0xf0, 0x28, 0x28, 0x02, 0x00, + 0x41, 0x0a, 0x46, 0x0d, 0x00, 0x41, 0xc4, 0x28, 0x28, 0x02, 0x00, 0x22, + 0x00, 0x41, 0xc0, 0x28, 0x28, 0x02, 0x00, 0x46, 0x0d, 0x00, 0x41, 0xc4, + 0x28, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, + 0x0a, 0x3a, 0x00, 0x00, 0x0f, 0x0b, 0x10, 0x2a, 0x0b, 0xcf, 0x01, 0x01, + 0x06, 0x7f, 0x02, 0x40, 0x20, 0x02, 0x28, 0x02, 0x10, 0x22, 0x03, 0x04, + 0x7f, 0x20, 0x03, 0x05, 0x20, 0x02, 0x10, 0x31, 0x0d, 0x01, 0x20, 0x02, + 0x28, 0x02, 0x10, 0x0b, 0x20, 0x02, 0x28, 0x02, 0x14, 0x22, 0x06, 0x6b, + 0x20, 0x01, 0x49, 0x04, 0x40, 0x20, 0x02, 0x20, 0x00, 0x20, 0x01, 0x20, + 0x02, 0x28, 0x02, 0x20, 0x11, 0x00, 0x00, 0x0f, 0x0b, 0x02, 0x40, 0x20, + 0x02, 0x28, 0x02, 0x40, 0x41, 0x00, 0x48, 0x0d, 0x00, 0x20, 0x00, 0x21, + 0x04, 0x41, 0x00, 0x21, 0x03, 0x03, 0x40, 0x20, 0x01, 0x20, 0x03, 0x46, + 0x0d, 0x01, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x20, + 0x04, 0x6a, 0x20, 0x04, 0x41, 0x7f, 0x6a, 0x22, 0x08, 0x21, 0x04, 0x41, + 0x7f, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x0a, 0x47, 0x0d, 0x00, 0x0b, 0x20, + 0x02, 0x20, 0x00, 0x20, 0x01, 0x20, 0x03, 0x6b, 0x41, 0x01, 0x6a, 0x22, + 0x05, 0x20, 0x02, 0x28, 0x02, 0x20, 0x11, 0x00, 0x00, 0x22, 0x04, 0x20, + 0x05, 0x49, 0x0d, 0x01, 0x20, 0x01, 0x20, 0x08, 0x6a, 0x41, 0x01, 0x6a, + 0x21, 0x00, 0x20, 0x02, 0x28, 0x02, 0x14, 0x21, 0x06, 0x20, 0x03, 0x41, + 0x7f, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x06, 0x20, 0x00, 0x20, 0x01, 0x10, + 0x39, 0x1a, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x14, 0x20, 0x01, 0x6a, + 0x36, 0x02, 0x14, 0x20, 0x01, 0x20, 0x05, 0x6a, 0x21, 0x04, 0x0b, 0x20, + 0x04, 0x0b, 0x17, 0x00, 0x20, 0x01, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, + 0x10, 0x33, 0x22, 0x00, 0x46, 0x04, 0x40, 0x20, 0x01, 0x0f, 0x0b, 0x20, + 0x00, 0x0b, 0x52, 0x01, 0x02, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, + 0x03, 0x24, 0x00, 0x41, 0x7f, 0x21, 0x04, 0x02, 0x40, 0x20, 0x02, 0x41, + 0x7f, 0x4c, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, 0x1c, 0x36, 0x02, 0x00, + 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x41, + 0x0c, 0x6a, 0x10, 0x0e, 0x22, 0x00, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x20, + 0x00, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x0c, + 0x21, 0x04, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x00, 0x20, 0x04, + 0x0b, 0x96, 0x02, 0x01, 0x06, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, + 0x03, 0x24, 0x00, 0x20, 0x03, 0x20, 0x02, 0x36, 0x02, 0x0c, 0x20, 0x03, + 0x20, 0x01, 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, 0x00, 0x28, 0x02, 0x18, + 0x22, 0x01, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x00, 0x28, 0x02, 0x14, + 0x20, 0x01, 0x6b, 0x22, 0x01, 0x36, 0x02, 0x04, 0x41, 0x02, 0x21, 0x06, + 0x02, 0x7f, 0x20, 0x01, 0x20, 0x02, 0x6a, 0x22, 0x07, 0x20, 0x00, 0x28, + 0x02, 0x38, 0x20, 0x03, 0x41, 0x02, 0x10, 0x35, 0x22, 0x04, 0x47, 0x04, + 0x40, 0x20, 0x03, 0x21, 0x01, 0x03, 0x40, 0x20, 0x04, 0x41, 0x7f, 0x4c, + 0x04, 0x40, 0x20, 0x00, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x00, 0x42, + 0x00, 0x37, 0x03, 0x10, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x00, 0x41, + 0x20, 0x72, 0x36, 0x02, 0x00, 0x41, 0x00, 0x20, 0x06, 0x41, 0x02, 0x46, + 0x0d, 0x03, 0x1a, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x04, 0x6b, 0x0c, + 0x03, 0x0b, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x20, 0x01, 0x20, 0x04, 0x20, + 0x01, 0x28, 0x02, 0x04, 0x22, 0x08, 0x4b, 0x22, 0x05, 0x1b, 0x22, 0x01, + 0x20, 0x04, 0x20, 0x08, 0x41, 0x00, 0x20, 0x05, 0x1b, 0x6b, 0x22, 0x08, + 0x20, 0x01, 0x28, 0x02, 0x00, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x01, 0x20, + 0x01, 0x28, 0x02, 0x04, 0x20, 0x08, 0x6b, 0x36, 0x02, 0x04, 0x20, 0x07, + 0x20, 0x04, 0x6b, 0x21, 0x07, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x01, + 0x20, 0x06, 0x20, 0x05, 0x6b, 0x22, 0x06, 0x10, 0x35, 0x22, 0x05, 0x21, + 0x04, 0x20, 0x05, 0x20, 0x07, 0x47, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, + 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, 0x01, 0x36, 0x02, 0x18, 0x20, 0x00, + 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, 0x00, 0x20, 0x01, 0x20, 0x00, 0x28, + 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, 0x20, 0x02, 0x0b, 0x20, 0x03, 0x41, + 0x10, 0x6a, 0x24, 0x00, 0x0b, 0x20, 0x01, 0x02, 0x7f, 0x20, 0x00, 0x10, + 0x38, 0x41, 0x01, 0x6a, 0x22, 0x01, 0x10, 0x14, 0x22, 0x02, 0x45, 0x04, + 0x40, 0x41, 0x00, 0x0f, 0x0b, 0x20, 0x02, 0x20, 0x00, 0x20, 0x01, 0x10, + 0x39, 0x0b, 0xa4, 0x01, 0x01, 0x03, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x02, + 0x40, 0x20, 0x00, 0x22, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, + 0x00, 0x2d, 0x00, 0x00, 0x45, 0x04, 0x40, 0x41, 0x00, 0x0f, 0x0b, 0x20, + 0x00, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0x03, + 0x71, 0x45, 0x0d, 0x01, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x20, 0x01, 0x41, + 0x01, 0x6a, 0x22, 0x03, 0x21, 0x01, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, + 0x20, 0x01, 0x41, 0x7c, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, + 0x04, 0x6a, 0x22, 0x01, 0x28, 0x02, 0x00, 0x22, 0x02, 0x41, 0x7f, 0x73, + 0x20, 0x02, 0x41, 0xff, 0xfd, 0xfb, 0x77, 0x6a, 0x71, 0x41, 0x80, 0x81, + 0x82, 0x84, 0x78, 0x71, 0x45, 0x0d, 0x00, 0x0b, 0x20, 0x02, 0x41, 0xff, + 0x01, 0x71, 0x45, 0x04, 0x40, 0x20, 0x01, 0x20, 0x00, 0x6b, 0x0f, 0x0b, + 0x03, 0x40, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x20, 0x01, 0x41, 0x01, 0x6a, + 0x22, 0x02, 0x21, 0x01, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, 0x03, + 0x41, 0x7f, 0x6a, 0x21, 0x02, 0x0b, 0x20, 0x02, 0x20, 0x00, 0x6b, 0x0b, + 0x92, 0x0b, 0x01, 0x08, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x45, + 0x0d, 0x00, 0x20, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x00, + 0x21, 0x03, 0x03, 0x40, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, + 0x00, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x21, 0x04, 0x20, 0x03, 0x41, + 0x01, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, + 0x02, 0x41, 0x01, 0x46, 0x0d, 0x02, 0x20, 0x04, 0x21, 0x02, 0x20, 0x01, + 0x41, 0x03, 0x71, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x21, + 0x04, 0x20, 0x00, 0x21, 0x03, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x03, + 0x71, 0x22, 0x02, 0x45, 0x04, 0x40, 0x02, 0x40, 0x20, 0x04, 0x41, 0x10, + 0x49, 0x04, 0x40, 0x20, 0x04, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x20, 0x04, + 0x41, 0x70, 0x6a, 0x21, 0x02, 0x03, 0x40, 0x20, 0x03, 0x20, 0x01, 0x28, + 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x04, 0x6a, 0x20, 0x01, + 0x41, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, + 0x08, 0x6a, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x20, 0x01, 0x41, 0x0c, 0x6a, 0x28, + 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x21, 0x03, + 0x20, 0x01, 0x41, 0x10, 0x6a, 0x21, 0x01, 0x20, 0x04, 0x41, 0x70, 0x6a, + 0x22, 0x04, 0x41, 0x0f, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x02, 0x41, + 0x08, 0x71, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, 0x29, 0x02, 0x00, 0x37, + 0x02, 0x00, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, + 0x08, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x02, 0x41, 0x04, 0x71, 0x04, 0x40, + 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, + 0x41, 0x04, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, + 0x0b, 0x20, 0x02, 0x41, 0x02, 0x71, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, + 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, + 0x01, 0x3a, 0x00, 0x01, 0x20, 0x03, 0x41, 0x02, 0x6a, 0x21, 0x03, 0x20, + 0x01, 0x41, 0x02, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x02, 0x41, 0x01, 0x71, + 0x45, 0x0d, 0x01, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, + 0x00, 0x20, 0x00, 0x0f, 0x0b, 0x02, 0x40, 0x20, 0x04, 0x41, 0x20, 0x49, + 0x0d, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x22, 0x02, 0x41, 0x02, 0x4b, + 0x0d, 0x00, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x41, 0x01, + 0x6b, 0x0e, 0x02, 0x01, 0x02, 0x00, 0x0b, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x01, 0x3a, 0x00, 0x01, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x00, + 0x22, 0x05, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x02, + 0x3a, 0x00, 0x02, 0x20, 0x04, 0x41, 0x7d, 0x6a, 0x21, 0x08, 0x20, 0x03, + 0x41, 0x03, 0x6a, 0x21, 0x09, 0x20, 0x04, 0x41, 0x6c, 0x6a, 0x41, 0x70, + 0x71, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, 0x20, + 0x09, 0x6a, 0x22, 0x03, 0x20, 0x01, 0x20, 0x02, 0x6a, 0x22, 0x06, 0x41, + 0x04, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x08, 0x74, 0x20, 0x05, + 0x41, 0x18, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x04, 0x6a, + 0x20, 0x06, 0x41, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x05, 0x41, 0x08, + 0x74, 0x20, 0x07, 0x41, 0x18, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x03, + 0x41, 0x08, 0x6a, 0x20, 0x06, 0x41, 0x0c, 0x6a, 0x28, 0x02, 0x00, 0x22, + 0x07, 0x41, 0x08, 0x74, 0x20, 0x05, 0x41, 0x18, 0x76, 0x72, 0x36, 0x02, + 0x00, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x20, 0x06, 0x41, 0x10, 0x6a, 0x28, + 0x02, 0x00, 0x22, 0x05, 0x41, 0x08, 0x74, 0x20, 0x07, 0x41, 0x18, 0x76, + 0x72, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x21, 0x02, 0x20, + 0x08, 0x41, 0x70, 0x6a, 0x22, 0x08, 0x41, 0x10, 0x4b, 0x0d, 0x00, 0x0b, + 0x20, 0x02, 0x20, 0x09, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x20, 0x02, 0x6a, + 0x41, 0x03, 0x6a, 0x21, 0x01, 0x20, 0x04, 0x20, 0x0a, 0x6b, 0x41, 0x6d, + 0x6a, 0x21, 0x04, 0x0c, 0x02, 0x0b, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, + 0x00, 0x22, 0x05, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, + 0x01, 0x3a, 0x00, 0x01, 0x20, 0x04, 0x41, 0x7e, 0x6a, 0x21, 0x08, 0x20, + 0x03, 0x41, 0x02, 0x6a, 0x21, 0x09, 0x20, 0x04, 0x41, 0x6c, 0x6a, 0x41, + 0x70, 0x71, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, + 0x20, 0x09, 0x6a, 0x22, 0x03, 0x20, 0x01, 0x20, 0x02, 0x6a, 0x22, 0x06, + 0x41, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x10, 0x74, 0x20, + 0x05, 0x41, 0x10, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x04, + 0x6a, 0x20, 0x06, 0x41, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x05, 0x41, + 0x10, 0x74, 0x20, 0x07, 0x41, 0x10, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, + 0x03, 0x41, 0x08, 0x6a, 0x20, 0x06, 0x41, 0x0c, 0x6a, 0x28, 0x02, 0x00, + 0x22, 0x07, 0x41, 0x10, 0x74, 0x20, 0x05, 0x41, 0x10, 0x76, 0x72, 0x36, + 0x02, 0x00, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x20, 0x06, 0x41, 0x10, 0x6a, + 0x28, 0x02, 0x00, 0x22, 0x05, 0x41, 0x10, 0x74, 0x20, 0x07, 0x41, 0x10, + 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x21, 0x02, + 0x20, 0x08, 0x41, 0x70, 0x6a, 0x22, 0x08, 0x41, 0x11, 0x4b, 0x0d, 0x00, + 0x0b, 0x20, 0x02, 0x20, 0x09, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x20, 0x02, + 0x6a, 0x41, 0x02, 0x6a, 0x21, 0x01, 0x20, 0x04, 0x20, 0x0a, 0x6b, 0x41, + 0x6e, 0x6a, 0x21, 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x20, 0x01, 0x28, + 0x02, 0x00, 0x22, 0x05, 0x3a, 0x00, 0x00, 0x20, 0x04, 0x41, 0x7f, 0x6a, + 0x21, 0x08, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x21, 0x09, 0x20, 0x04, 0x41, + 0x6c, 0x6a, 0x41, 0x70, 0x71, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x02, 0x03, + 0x40, 0x20, 0x02, 0x20, 0x09, 0x6a, 0x22, 0x03, 0x20, 0x01, 0x20, 0x02, + 0x6a, 0x22, 0x06, 0x41, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, + 0x18, 0x74, 0x20, 0x05, 0x41, 0x08, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, + 0x03, 0x41, 0x04, 0x6a, 0x20, 0x06, 0x41, 0x08, 0x6a, 0x28, 0x02, 0x00, + 0x22, 0x05, 0x41, 0x18, 0x74, 0x20, 0x07, 0x41, 0x08, 0x76, 0x72, 0x36, + 0x02, 0x00, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x20, 0x06, 0x41, 0x0c, 0x6a, + 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x18, 0x74, 0x20, 0x05, 0x41, 0x08, + 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x20, 0x06, + 0x41, 0x10, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x05, 0x41, 0x18, 0x74, 0x20, + 0x07, 0x41, 0x08, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x10, + 0x6a, 0x21, 0x02, 0x20, 0x08, 0x41, 0x70, 0x6a, 0x22, 0x08, 0x41, 0x12, + 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x02, 0x20, 0x09, 0x6a, 0x21, 0x03, 0x20, + 0x01, 0x20, 0x02, 0x6a, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x04, 0x20, + 0x0a, 0x6b, 0x41, 0x6f, 0x6a, 0x21, 0x04, 0x0b, 0x20, 0x04, 0x41, 0x10, + 0x71, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, 0x2f, 0x00, 0x00, 0x3b, 0x00, + 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x02, 0x3a, 0x00, 0x02, 0x20, + 0x03, 0x20, 0x01, 0x2d, 0x00, 0x03, 0x3a, 0x00, 0x03, 0x20, 0x03, 0x20, + 0x01, 0x2d, 0x00, 0x04, 0x3a, 0x00, 0x04, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x05, 0x3a, 0x00, 0x05, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x06, + 0x3a, 0x00, 0x06, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x07, 0x3a, 0x00, + 0x07, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x08, 0x3a, 0x00, 0x08, 0x20, + 0x03, 0x20, 0x01, 0x2d, 0x00, 0x09, 0x3a, 0x00, 0x09, 0x20, 0x03, 0x20, + 0x01, 0x2d, 0x00, 0x0a, 0x3a, 0x00, 0x0a, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x0b, 0x3a, 0x00, 0x0b, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x0c, + 0x3a, 0x00, 0x0c, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x0d, 0x3a, 0x00, + 0x0d, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x0e, 0x3a, 0x00, 0x0e, 0x20, + 0x03, 0x20, 0x01, 0x2d, 0x00, 0x0f, 0x3a, 0x00, 0x0f, 0x20, 0x03, 0x41, + 0x10, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x21, 0x01, 0x0b, + 0x20, 0x04, 0x41, 0x08, 0x71, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x01, + 0x3a, 0x00, 0x01, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x02, 0x3a, 0x00, + 0x02, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x03, 0x3a, 0x00, 0x03, 0x20, + 0x03, 0x20, 0x01, 0x2d, 0x00, 0x04, 0x3a, 0x00, 0x04, 0x20, 0x03, 0x20, + 0x01, 0x2d, 0x00, 0x05, 0x3a, 0x00, 0x05, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x06, 0x3a, 0x00, 0x06, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x07, + 0x3a, 0x00, 0x07, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x21, 0x03, 0x20, 0x01, + 0x41, 0x08, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x04, 0x41, 0x04, 0x71, 0x04, + 0x40, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, + 0x03, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, 0x20, 0x03, 0x20, + 0x01, 0x2d, 0x00, 0x02, 0x3a, 0x00, 0x02, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x03, 0x3a, 0x00, 0x03, 0x20, 0x03, 0x41, 0x04, 0x6a, 0x21, 0x03, + 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x04, 0x41, 0x02, + 0x71, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, + 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, 0x20, + 0x03, 0x41, 0x02, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, 0x02, 0x6a, 0x21, + 0x01, 0x0b, 0x20, 0x04, 0x41, 0x01, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x03, + 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x00, 0x0b, + 0xfa, 0x02, 0x02, 0x02, 0x7f, 0x01, 0x7e, 0x02, 0x40, 0x20, 0x02, 0x45, + 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x20, + 0x02, 0x6a, 0x22, 0x03, 0x41, 0x7f, 0x6a, 0x20, 0x01, 0x3a, 0x00, 0x00, + 0x20, 0x02, 0x41, 0x03, 0x49, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x3a, + 0x00, 0x02, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x01, 0x20, 0x03, 0x41, + 0x7d, 0x6a, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x41, 0x7e, 0x6a, + 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x07, 0x49, 0x0d, 0x00, + 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x03, 0x20, 0x03, 0x41, 0x7c, 0x6a, + 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x09, 0x49, 0x0d, 0x00, + 0x20, 0x00, 0x41, 0x00, 0x20, 0x00, 0x6b, 0x41, 0x03, 0x71, 0x22, 0x04, + 0x6a, 0x22, 0x03, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x41, 0x81, 0x82, + 0x84, 0x08, 0x6c, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x02, + 0x20, 0x04, 0x6b, 0x41, 0x7c, 0x71, 0x22, 0x02, 0x6a, 0x22, 0x01, 0x41, + 0x7c, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x09, 0x49, + 0x0d, 0x00, 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, + 0x00, 0x36, 0x02, 0x04, 0x20, 0x01, 0x41, 0x78, 0x6a, 0x20, 0x00, 0x36, + 0x02, 0x00, 0x20, 0x01, 0x41, 0x74, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, + 0x20, 0x02, 0x41, 0x19, 0x49, 0x0d, 0x00, 0x20, 0x03, 0x20, 0x00, 0x36, + 0x02, 0x18, 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x14, 0x20, 0x03, 0x20, + 0x00, 0x36, 0x02, 0x10, 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x0c, 0x20, + 0x01, 0x41, 0x70, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, + 0x6c, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, 0x68, 0x6a, + 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, 0x64, 0x6a, 0x20, 0x00, + 0x36, 0x02, 0x00, 0x20, 0x02, 0x20, 0x03, 0x41, 0x04, 0x71, 0x41, 0x18, + 0x72, 0x22, 0x01, 0x6b, 0x22, 0x02, 0x41, 0x20, 0x49, 0x0d, 0x00, 0x20, + 0x00, 0xad, 0x22, 0x05, 0x42, 0x20, 0x86, 0x20, 0x05, 0x84, 0x21, 0x05, + 0x20, 0x01, 0x20, 0x03, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x20, + 0x05, 0x37, 0x03, 0x00, 0x20, 0x01, 0x41, 0x18, 0x6a, 0x20, 0x05, 0x37, + 0x03, 0x00, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x20, 0x05, 0x37, 0x03, 0x00, + 0x20, 0x01, 0x41, 0x08, 0x6a, 0x20, 0x05, 0x37, 0x03, 0x00, 0x20, 0x01, + 0x41, 0x20, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x41, 0x60, 0x6a, 0x22, 0x02, + 0x41, 0x1f, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x0b, 0x5a, 0x01, 0x03, 0x7f, + 0x41, 0x8f, 0x09, 0x2d, 0x00, 0x00, 0x21, 0x01, 0x02, 0x40, 0x20, 0x00, + 0x2d, 0x00, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x20, 0x02, + 0x47, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x00, 0x41, 0x90, + 0x09, 0x21, 0x03, 0x03, 0x40, 0x20, 0x03, 0x2d, 0x00, 0x00, 0x21, 0x01, + 0x20, 0x00, 0x2d, 0x00, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x00, + 0x41, 0x01, 0x6a, 0x21, 0x00, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x21, 0x03, + 0x20, 0x01, 0x20, 0x02, 0x46, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x02, 0x20, + 0x01, 0x6b, 0x0b, 0xd7, 0x01, 0x01, 0x02, 0x7f, 0x20, 0x01, 0x41, 0x00, + 0x47, 0x21, 0x03, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, 0x45, + 0x04, 0x40, 0x20, 0x01, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x41, + 0x03, 0x71, 0x45, 0x04, 0x40, 0x20, 0x01, 0x21, 0x02, 0x0c, 0x01, 0x0b, + 0x03, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x45, 0x04, 0x40, 0x20, 0x01, + 0x21, 0x02, 0x0c, 0x03, 0x0b, 0x20, 0x01, 0x41, 0x01, 0x47, 0x21, 0x03, + 0x20, 0x01, 0x41, 0x7f, 0x6a, 0x21, 0x02, 0x20, 0x00, 0x41, 0x01, 0x6a, + 0x21, 0x00, 0x20, 0x01, 0x41, 0x01, 0x46, 0x0d, 0x01, 0x20, 0x02, 0x21, + 0x01, 0x20, 0x00, 0x41, 0x03, 0x71, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x03, + 0x45, 0x0d, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x45, + 0x0d, 0x00, 0x20, 0x02, 0x41, 0x04, 0x49, 0x0d, 0x00, 0x03, 0x40, 0x20, + 0x00, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x7f, 0x73, 0x20, 0x01, 0x41, + 0xff, 0xfd, 0xfb, 0x77, 0x6a, 0x71, 0x41, 0x80, 0x81, 0x82, 0x84, 0x78, + 0x71, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x21, 0x00, 0x20, 0x02, + 0x41, 0x7c, 0x6a, 0x22, 0x02, 0x41, 0x03, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, + 0x20, 0x02, 0x45, 0x0d, 0x00, 0x03, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, + 0x45, 0x04, 0x40, 0x20, 0x00, 0x0f, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x6a, + 0x21, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x22, 0x02, 0x0d, 0x00, 0x0b, + 0x0b, 0x41, 0x00, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x45, 0x04, 0x40, 0x41, + 0x00, 0x0f, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x10, 0x3e, 0x0b, 0x8c, 0x02, + 0x00, 0x20, 0x00, 0x04, 0x7f, 0x20, 0x01, 0x41, 0xff, 0x00, 0x4d, 0x04, + 0x40, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x41, 0x01, 0x0f, 0x0b, + 0x02, 0x40, 0x41, 0xf0, 0x1f, 0x28, 0x02, 0x00, 0x45, 0x04, 0x40, 0x20, + 0x01, 0x41, 0x80, 0x7f, 0x71, 0x41, 0x80, 0xbf, 0x03, 0x47, 0x0d, 0x01, + 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x41, 0x01, 0x0f, 0x0b, 0x20, + 0x01, 0x41, 0xff, 0x0f, 0x4d, 0x04, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, + 0x3f, 0x71, 0x41, 0x80, 0x01, 0x72, 0x3a, 0x00, 0x01, 0x20, 0x00, 0x20, + 0x01, 0x41, 0x06, 0x76, 0x41, 0xc0, 0x01, 0x72, 0x3a, 0x00, 0x00, 0x41, + 0x02, 0x0f, 0x0b, 0x20, 0x01, 0x41, 0x80, 0xb0, 0x03, 0x4f, 0x41, 0x00, + 0x20, 0x01, 0x41, 0x80, 0x40, 0x71, 0x41, 0x80, 0xc0, 0x03, 0x47, 0x1b, + 0x45, 0x04, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0x3f, 0x71, 0x41, 0x80, + 0x01, 0x72, 0x3a, 0x00, 0x02, 0x20, 0x00, 0x20, 0x01, 0x41, 0x0c, 0x76, + 0x41, 0xe0, 0x01, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x20, 0x01, 0x41, + 0x06, 0x76, 0x41, 0x3f, 0x71, 0x41, 0x80, 0x01, 0x72, 0x3a, 0x00, 0x01, + 0x41, 0x03, 0x0f, 0x0b, 0x20, 0x01, 0x41, 0x80, 0x80, 0x7c, 0x6a, 0x41, + 0xff, 0xff, 0x3f, 0x4d, 0x04, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0x3f, + 0x71, 0x41, 0x80, 0x01, 0x72, 0x3a, 0x00, 0x03, 0x20, 0x00, 0x20, 0x01, + 0x41, 0x12, 0x76, 0x41, 0xf0, 0x01, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x00, + 0x20, 0x01, 0x41, 0x06, 0x76, 0x41, 0x3f, 0x71, 0x41, 0x80, 0x01, 0x72, + 0x3a, 0x00, 0x02, 0x20, 0x00, 0x20, 0x01, 0x41, 0x0c, 0x76, 0x41, 0x3f, + 0x71, 0x41, 0x80, 0x01, 0x72, 0x3a, 0x00, 0x01, 0x41, 0x04, 0x0f, 0x0b, + 0x0b, 0x41, 0xe0, 0x1f, 0x41, 0x19, 0x36, 0x02, 0x00, 0x41, 0x7f, 0x05, + 0x41, 0x01, 0x0b, 0x0b, 0x81, 0x01, 0x02, 0x01, 0x7f, 0x01, 0x7e, 0x20, + 0x00, 0xbd, 0x22, 0x03, 0x42, 0x34, 0x88, 0xa7, 0x41, 0xff, 0x0f, 0x71, + 0x22, 0x02, 0x41, 0xff, 0x0f, 0x47, 0x04, 0x7c, 0x20, 0x02, 0x45, 0x04, + 0x40, 0x20, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x61, 0x04, 0x40, 0x20, 0x01, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, + 0x0f, 0x0b, 0x20, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x43, 0xa2, 0x20, 0x01, 0x10, 0x3f, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, + 0x00, 0x41, 0x40, 0x6a, 0x36, 0x02, 0x00, 0x0f, 0x0b, 0x20, 0x01, 0x20, + 0x02, 0x41, 0x82, 0x78, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x03, 0x42, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0x80, 0x7f, 0x83, 0x42, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf0, 0x3f, 0x84, 0xbf, 0x05, 0x20, + 0x00, 0x0b, 0x0b, 0x0b, 0xa0, 0x13, 0x1b, 0x00, 0x41, 0x80, 0x08, 0x0b, + 0xa5, 0x01, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, + 0x72, 0x20, 0x4f, 0x4b, 0x0a, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, + 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x20, 0x25, 0x73, 0x21, 0x0a, 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, + 0x00, 0x41, 0x72, 0x67, 0x73, 0x3a, 0x20, 0x00, 0x25, 0x73, 0x3b, 0x20, + 0x00, 0x25, 0x64, 0x20, 0x2b, 0x20, 0x25, 0x64, 0x20, 0x3d, 0x20, 0x25, + 0x64, 0x0a, 0x00, 0x4e, 0x6f, 0x77, 0x3a, 0x20, 0x25, 0x6c, 0x6c, 0x64, + 0x20, 0x73, 0x65, 0x63, 0x2c, 0x20, 0x25, 0x6c, 0x64, 0x20, 0x6e, 0x73, + 0x0a, 0x00, 0x66, 0x69, 0x62, 0x28, 0x25, 0x64, 0x29, 0x20, 0x3d, 0x20, + 0x00, 0x25, 0x64, 0x20, 0x5b, 0x25, 0x2e, 0x33, 0x66, 0x20, 0x6d, 0x73, + 0x5d, 0x0a, 0x00, 0x25, 0x30, 0x32, 0x78, 0x20, 0x00, 0x43, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x25, 0x73, 0x0a, + 0x00, 0x63, 0x61, 0x74, 0x00, 0x3d, 0x3d, 0x3d, 0x20, 0x64, 0x6f, 0x6e, + 0x65, 0x20, 0x3d, 0x3d, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, + 0x41, 0xb1, 0x09, 0x0b, 0x85, 0x0d, 0x19, 0x12, 0x44, 0x3b, 0x02, 0x3f, + 0x2c, 0x47, 0x14, 0x3d, 0x33, 0x30, 0x0a, 0x1b, 0x06, 0x46, 0x4b, 0x45, + 0x37, 0x0f, 0x49, 0x0e, 0x17, 0x03, 0x40, 0x1d, 0x3c, 0x2b, 0x36, 0x1f, + 0x4a, 0x2d, 0x1c, 0x01, 0x20, 0x25, 0x29, 0x21, 0x08, 0x0c, 0x15, 0x16, + 0x22, 0x2e, 0x10, 0x38, 0x3e, 0x0b, 0x34, 0x31, 0x18, 0x2f, 0x41, 0x09, + 0x39, 0x11, 0x23, 0x43, 0x32, 0x42, 0x3a, 0x05, 0x04, 0x26, 0x28, 0x27, + 0x0d, 0x2a, 0x1e, 0x35, 0x07, 0x1a, 0x48, 0x13, 0x24, 0x4c, 0xff, 0x00, + 0x00, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x00, 0x49, 0x6c, 0x6c, + 0x65, 0x67, 0x61, 0x6c, 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x73, 0x65, + 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x00, 0x44, 0x6f, 0x6d, 0x61, 0x69, + 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, + 0x73, 0x65, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x4e, 0x6f, 0x74, + 0x20, 0x61, 0x20, 0x74, 0x74, 0x79, 0x00, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, + 0x00, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, + 0x00, 0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x79, 0x00, 0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x00, 0x46, 0x69, 0x6c, 0x65, 0x20, + 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x00, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x00, 0x4e, 0x6f, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x6c, 0x65, + 0x66, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x00, 0x4f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x00, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, + 0x62, 0x75, 0x73, 0x79, 0x00, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, + 0x70, 0x74, 0x65, 0x64, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, + 0x63, 0x61, 0x6c, 0x6c, 0x00, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x69, 0x6c, + 0x79, 0x20, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x73, 0x65, + 0x65, 0x6b, 0x00, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x2d, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x00, 0x52, 0x65, 0x61, + 0x64, 0x2d, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, + 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x00, 0x44, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x6d, 0x70, + 0x74, 0x79, 0x00, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x62, 0x79, 0x20, 0x70, + 0x65, 0x65, 0x72, 0x00, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x00, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, + 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x00, 0x48, 0x6f, 0x73, 0x74, 0x20, + 0x69, 0x73, 0x20, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, + 0x6c, 0x65, 0x00, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x69, + 0x6e, 0x20, 0x75, 0x73, 0x65, 0x00, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, + 0x20, 0x70, 0x69, 0x70, 0x65, 0x00, 0x49, 0x2f, 0x4f, 0x20, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x00, 0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, + 0x68, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x4e, 0x6f, 0x74, + 0x20, 0x61, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, + 0x00, 0x49, 0x73, 0x20, 0x61, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x79, 0x00, 0x54, 0x65, 0x78, 0x74, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x62, 0x75, 0x73, 0x79, 0x00, 0x45, 0x78, 0x65, 0x63, 0x20, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x61, 0x72, 0x67, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, + 0x6e, 0x74, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x6f, 0x20, + 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, + 0x63, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x6c, 0x6f, 0x6f, 0x70, 0x00, + 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x6f, + 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, + 0x6e, 0x79, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x00, + 0x4e, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x42, 0x61, 0x64, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, + 0x72, 0x00, 0x4e, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x00, 0x42, 0x61, 0x64, 0x20, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x46, 0x69, 0x6c, 0x65, 0x20, + 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x00, 0x54, 0x6f, + 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x73, + 0x00, 0x4e, 0x6f, 0x20, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x61, 0x76, + 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x20, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x6f, 0x63, + 0x6b, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x63, 0x63, 0x75, + 0x72, 0x00, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x00, + 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x20, 0x64, 0x69, 0x65, 0x64, 0x00, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x65, 0x64, 0x00, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x65, 0x64, 0x00, 0x4e, 0x6f, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, + 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x00, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x64, 0x00, 0x4c, 0x69, 0x6e, 0x6b, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, + 0x65, 0x65, 0x6e, 0x20, 0x73, 0x65, 0x76, 0x65, 0x72, 0x65, 0x64, 0x00, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x00, 0x42, 0x61, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x00, 0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x00, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x00, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72, + 0x67, 0x65, 0x00, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, + 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x00, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, + 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x4e, 0x6f, 0x74, 0x20, + 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x00, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, + 0x00, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x73, 0x20, + 0x64, 0x6f, 0x77, 0x6e, 0x00, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x20, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, + 0x00, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x62, 0x79, 0x20, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x00, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, + 0x4e, 0x6f, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x00, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x53, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, + 0x20, 0x69, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x00, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, + 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x00, 0x53, + 0x74, 0x61, 0x6c, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x68, 0x61, + 0x6e, 0x64, 0x6c, 0x65, 0x00, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x20, 0x65, + 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x00, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x68, 0x6f, 0x70, 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, + 0x65, 0x64, 0x00, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x69, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, + 0x69, 0x65, 0x6e, 0x74, 0x00, 0x4e, 0x6f, 0x20, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x00, 0x00, 0x2d, 0x2b, 0x20, 0x20, 0x20, 0x30, 0x58, 0x30, 0x78, + 0x00, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x00, 0x41, 0xc0, 0x16, 0x0b, + 0x18, 0x19, 0x00, 0x0a, 0x00, 0x19, 0x19, 0x19, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x41, 0xe0, 0x16, 0x0b, 0x21, 0x19, 0x00, 0x11, 0x0a, 0x19, + 0x19, 0x19, 0x03, 0x0a, 0x07, 0x00, 0x01, 0x1b, 0x09, 0x0b, 0x18, 0x00, + 0x00, 0x09, 0x06, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x19, 0x00, 0x00, + 0x00, 0x19, 0x19, 0x19, 0x00, 0x41, 0x91, 0x17, 0x0b, 0x01, 0x0e, 0x00, + 0x41, 0x9a, 0x17, 0x0b, 0x18, 0x19, 0x00, 0x0a, 0x0d, 0x19, 0x19, 0x19, + 0x00, 0x0d, 0x00, 0x00, 0x02, 0x00, 0x09, 0x0e, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x41, 0xcb, 0x17, 0x0b, 0x01, 0x0c, + 0x00, 0x41, 0xd7, 0x17, 0x0b, 0x15, 0x13, 0x00, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x00, 0x09, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x0c, 0x00, 0x41, 0x85, 0x18, 0x0b, 0x01, 0x10, 0x00, 0x41, + 0x91, 0x18, 0x0b, 0x15, 0x0f, 0x00, 0x00, 0x00, 0x04, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x10, 0x00, 0x41, 0xbf, 0x18, 0x0b, 0x01, 0x12, 0x00, 0x41, 0xcb, 0x18, + 0x0b, 0x1e, 0x11, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, + 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x1a, 0x1a, 0x00, 0x41, 0x82, 0x19, + 0x0b, 0x0e, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x1a, 0x1a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x41, 0xb3, 0x19, 0x0b, 0x01, 0x14, 0x00, + 0x41, 0xbf, 0x19, 0x0b, 0x15, 0x17, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x00, 0x14, 0x00, 0x41, 0xed, 0x19, 0x0b, 0x01, 0x16, 0x00, 0x41, 0xf9, + 0x19, 0x0b, 0x99, 0x01, 0x15, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, + 0x00, 0x00, 0x09, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, + 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x20, 0x64, 0x69, + 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x0a, 0x54, 0x6f, 0x20, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x61, 0x64, + 0x64, 0x20, 0x2d, 0x6c, 0x63, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, + 0x63, 0x61, 0x6e, 0x2d, 0x6c, 0x6f, 0x6e, 0x67, 0x2d, 0x64, 0x6f, 0x75, + 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, + 0x69, 0x6e, 0x6b, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, + 0x0a, 0x00, 0x41, 0xa0, 0x1b, 0x0b, 0x3a, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x2d, + 0x30, 0x58, 0x2b, 0x30, 0x58, 0x20, 0x30, 0x58, 0x2d, 0x30, 0x78, 0x2b, + 0x30, 0x78, 0x20, 0x30, 0x78, 0x00, 0x69, 0x6e, 0x66, 0x00, 0x49, 0x4e, + 0x46, 0x00, 0x6e, 0x61, 0x6e, 0x00, 0x4e, 0x41, 0x4e, 0x00, 0x2e, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x14, 0x00, 0x41, 0xb0, 0x28, 0x0b, 0x01, 0x05, + 0x00, 0x41, 0xbc, 0x28, 0x0b, 0x01, 0x01, 0x00, 0x41, 0xd0, 0x28, 0x0b, + 0x0e, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x10, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x41, 0xe8, 0x28, 0x0b, 0x09, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x41, 0xa0, 0x29, 0x0b, 0x09, + 0x30, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x41, 0xb4, + 0x29, 0x0b, 0x01, 0x01, 0x00, 0x41, 0xc8, 0x29, 0x0b, 0x0a, 0x04, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x24, 0x14, 0x00, 0x41, 0xe0, 0x29, + 0x0b, 0x0c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x41, 0x98, 0x2a, 0x0b, 0x02, 0xa8, 0x14 +}; +unsigned int wasi_test_wasm_len = 27646; diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/sdkconfig.defaults b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/sdkconfig.defaults new file mode 100644 index 0000000..e5f6486 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf-wasi/sdkconfig.defaults @@ -0,0 +1,14 @@ +# Increased stack size +CONFIG_ESP_MAIN_TASK_STACK_SIZE=65536 + +# Disable task watchdog +CONFIG_ESP_TASK_WDT=n + +# Increase CPU frequency +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y + +# PSRAM support +CONFIG_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND=y +CONFIG_SPIRAM_USE_MALLOC=y + diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf/.gitignore b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/.gitignore new file mode 100644 index 0000000..d054d84 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/.gitignore @@ -0,0 +1,3 @@ +build +sdkconfig +sdkconfig.old diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf/.old/Makefile b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/.old/Makefile new file mode 100644 index 0000000..2f23716 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/.old/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := wasm3 + +include $(IDF_PATH)/make/project.mk + diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf/.old/component.mk b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/.old/component.mk new file mode 100644 index 0000000..0b9d758 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/.old/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf/CMakeLists.txt b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/CMakeLists.txt new file mode 100644 index 0000000..d88e541 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(wasm3) diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf/README.md b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/README.md new file mode 100644 index 0000000..d340fd6 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/README.md @@ -0,0 +1,24 @@ +## Build for ESP-IDF + +Download and install ESP-IDF v4.3-beta1 + +```sh +export IDF_PATH=/opt/esp32/esp-idf + +# Set tools path if needed: +#export IDF_TOOLS_PATH=/opt/esp32 + +source $IDF_PATH/export.sh + +idf.py menuconfig + +# Select target: +idf.py set-target esp32 +#idf.py set-target esp32s2 +#idf.py --preview set-target esp32c3 + +idf.py build + +idf.py -p /dev/ttyUSB0 flash monitor + +``` diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf/main/CMakeLists.txt b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/main/CMakeLists.txt new file mode 100644 index 0000000..eaa975a --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/main/CMakeLists.txt @@ -0,0 +1,26 @@ +set(idf_ver "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}") + +if (NOT CMAKE_BUILD_EARLY_EXPANSION) + idf_build_get_property(build_dir BUILD_DIR) + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../../../../source ${build_dir}/m3) +endif() + +set(APP_SOURCES "main.cpp") + +idf_component_register(SRCS ${APP_SOURCES} + INCLUDE_DIRS "" + LDFRAGMENTS linker.lf) + +if (idf_ver STREQUAL "4.0") + # IDF v4.0 links apps with -nostdlib, so need to explicitly list the dependencies. + + add_library(m3_deps INTERFACE) + target_link_libraries(m3_deps INTERFACE c m gcc) + target_link_libraries(${COMPONENT_TARGET} PRIVATE m3 m3_deps) +else() + # For IDF v4.1 and later, no tricks required. + + target_link_libraries(${COMPONENT_TARGET} PRIVATE m3) +endif() + +target_compile_options(m3 PUBLIC -DM3_IN_IRAM -DESP32 -O3 -freorder-blocks) diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf/main/linker.lf b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/main/linker.lf new file mode 100644 index 0000000..077c98a --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/main/linker.lf @@ -0,0 +1,6 @@ +[mapping:wasm3] +archive: libm3.a +entries: + m3_core (noflash_text) + m3_exec (noflash_text) + m3_compile (noflash_text) diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf/main/main.cpp b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/main/main.cpp new file mode 100644 index 0000000..43db66e --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/main/main.cpp @@ -0,0 +1,70 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "esp_system.h" + +#include +#include +#include + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +static void run_wasm(void) +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + uint32_t fsize = fib32_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + result = m3_CallV(f, 24); + if (result) FATAL("m3_Call: %s", result); + + unsigned value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %u\n", value); +} + +extern "C" void app_main(void) +{ + printf("\nWasm3 v" M3_VERSION " on " CONFIG_IDF_TARGET ", build " __DATE__ " " __TIME__ "\n"); + + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + printf("Elapsed: %ld ms\n", (end - start)*1000 / CLOCKS_PER_SEC); + + sleep(3); + printf("Restarting...\n\n\n"); + esp_restart(); +} diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-idf/sdkconfig.defaults b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/sdkconfig.defaults new file mode 100644 index 0000000..41dc237 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-idf/sdkconfig.defaults @@ -0,0 +1,8 @@ +# Increased stack size +CONFIG_ESP_MAIN_TASK_STACK_SIZE=32768 + +# Disable task watchdog +CONFIG_ESP_TASK_WDT=n + +# Increase CPU frequency +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-pio/.gitignore b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-pio/lib/wasm3/README.md b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/lib/wasm3/README.md new file mode 100644 index 0000000..6152d55 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/lib/wasm3/README.md @@ -0,0 +1,3 @@ +This is a placeholder for the wasm3 PIO library. + +At the moment it simply adds the source code as a symlink, and sets some build flags. diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-pio/lib/wasm3/library.json b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/lib/wasm3/library.json new file mode 100644 index 0000000..f1b6cbe --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/lib/wasm3/library.json @@ -0,0 +1,5 @@ +{ + "build" : { + "flags": "-DESP32 -O3 -Wfatal-errors -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers" + } +} diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-pio/lib/wasm3/src b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/lib/wasm3/src new file mode 120000 index 0000000..e3e41d7 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/lib/wasm3/src @@ -0,0 +1 @@ +../../../../../source \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-pio/platformio.ini b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/platformio.ini new file mode 100644 index 0000000..42e4107 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/platformio.ini @@ -0,0 +1,18 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32dev] +platform = espressif32 +board = esp32dev +framework = espidf + +monitor_speed = 115200 + +board_build.f_cpu = 240000000L diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-pio/src/main.cpp b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/src/main.cpp new file mode 100644 index 0000000..43db66e --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/src/main.cpp @@ -0,0 +1,70 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "esp_system.h" + +#include +#include +#include + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +static void run_wasm(void) +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + uint32_t fsize = fib32_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + result = m3_CallV(f, 24); + if (result) FATAL("m3_Call: %s", result); + + unsigned value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %u\n", value); +} + +extern "C" void app_main(void) +{ + printf("\nWasm3 v" M3_VERSION " on " CONFIG_IDF_TARGET ", build " __DATE__ " " __TIME__ "\n"); + + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + printf("Elapsed: %ld ms\n", (end - start)*1000 / CLOCKS_PER_SEC); + + sleep(3); + printf("Restarting...\n\n\n"); + esp_restart(); +} diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-pio/src/sdkconfig b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/src/sdkconfig new file mode 100644 index 0000000..20625d8 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/src/sdkconfig @@ -0,0 +1,962 @@ +# +# Automatically generated file; DO NOT EDIT. +# Espressif IoT Development Framework Configuration +# +CONFIG_IDF_TARGET="esp32" + +# +# SDK tool configuration +# +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +CONFIG_PYTHON="python" +CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +CONFIG_APP_EXCLUDE_PROJECT_VER_VAR= +CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR= + +# +# Bootloader config +# +CONFIG_LOG_BOOTLOADER_LEVEL_NONE= +CONFIG_LOG_BOOTLOADER_LEVEL_ERROR= +CONFIG_LOG_BOOTLOADER_LEVEL_WARN= +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= +CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= +CONFIG_LOG_BOOTLOADER_LEVEL=3 +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V= +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +CONFIG_BOOTLOADER_FACTORY_RESET= +CONFIG_BOOTLOADER_APP_TEST= +CONFIG_BOOTLOADER_WDT_ENABLE=y +CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE= +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +CONFIG_APP_ROLLBACK_ENABLE= + +# +# Security features +# +CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT= +CONFIG_SECURE_BOOT_ENABLED= +CONFIG_FLASH_ENCRYPTION_ENABLED= + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_PORT="COM19" +CONFIG_ESPTOOLPY_BAUD_115200B=y +CONFIG_ESPTOOLPY_BAUD_230400B= +CONFIG_ESPTOOLPY_BAUD_921600B= +CONFIG_ESPTOOLPY_BAUD_2MB= +CONFIG_ESPTOOLPY_BAUD_OTHER= +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_BAUD=115200 +CONFIG_ESPTOOLPY_COMPRESSED=y +CONFIG_FLASHMODE_QIO= +CONFIG_FLASHMODE_QOUT= +CONFIG_FLASHMODE_DIO=y +CONFIG_FLASHMODE_DOUT= +CONFIG_ESPTOOLPY_FLASHMODE="dio" +CONFIG_ESPTOOLPY_FLASHFREQ_80M= +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +CONFIG_ESPTOOLPY_FLASHFREQ_26M= +CONFIG_ESPTOOLPY_FLASHFREQ_20M= +CONFIG_ESPTOOLPY_FLASHFREQ="40m" +CONFIG_ESPTOOLPY_FLASHSIZE_1MB= +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB= +CONFIG_ESPTOOLPY_FLASHSIZE_8MB= +CONFIG_ESPTOOLPY_FLASHSIZE_16MB= +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +CONFIG_ESPTOOLPY_BEFORE_NORESET= +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +CONFIG_ESPTOOLPY_AFTER_NORESET= +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_MONITOR_BAUD_9600B= +CONFIG_MONITOR_BAUD_57600B= +CONFIG_MONITOR_BAUD_115200B=y +CONFIG_MONITOR_BAUD_230400B= +CONFIG_MONITOR_BAUD_921600B= +CONFIG_MONITOR_BAUD_2MB= +CONFIG_MONITOR_BAUD_OTHER= +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +CONFIG_PARTITION_TABLE_TWO_OTA= +CONFIG_PARTITION_TABLE_CUSTOM= +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y + +# +# Compiler options +# +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_OPTIMIZATION_LEVEL_RELEASE= +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +CONFIG_OPTIMIZATION_ASSERTIONS_SILENT= +CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED= +CONFIG_CXX_EXCEPTIONS=y +CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 +CONFIG_STACK_CHECK_NONE=y +CONFIG_STACK_CHECK_NORM= +CONFIG_STACK_CHECK_STRONG= +CONFIG_STACK_CHECK_ALL= +CONFIG_STACK_CHECK= +CONFIG_WARN_WRITE_STRINGS= +CONFIG_DISABLE_GCC8_WARNINGS= + +# +# Component config +# + +# +# Application Level Tracing +# +CONFIG_ESP32_APPTRACE_DEST_TRAX= +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_ENABLE= +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_AWS_IOT_SDK=y +CONFIG_AWS_IOT_MQTT_HOST="" +CONFIG_AWS_IOT_MQTT_PORT=8883 +CONFIG_AWS_IOT_MQTT_TX_BUF_LEN=512 +CONFIG_AWS_IOT_MQTT_RX_BUF_LEN=512 +CONFIG_AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS=5 +CONFIG_AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL=1000 +CONFIG_AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL=128000 + +# +# Thing Shadow +# +CONFIG_AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER= +CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES=80 +CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS=10 +CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES=10 +CONFIG_AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED=120 +CONFIG_AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME=60 +CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME=20 + +# +# Bluetooth +# +CONFIG_BT_ENABLED=y + +# +# Bluetooth controller +# +CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y +CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY= +CONFIG_BTDM_CONTROLLER_MODE_BTDM= +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=3 +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=3 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0=y +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1= +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y +CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4= + +# +# MODEM SLEEP Options +# +CONFIG_BTDM_CONTROLLER_MODEM_SLEEP= +CONFIG_BLE_SCAN_DUPLICATE=y +CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR=y +CONFIG_SCAN_DUPLICATE_BY_ADV_DATA= +CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR= +CONFIG_SCAN_DUPLICATE_TYPE=0 +CONFIG_DUPLICATE_SCAN_CACHE_SIZE=50 +CONFIG_BLE_MESH_SCAN_DUPLICATE_EN= +CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED= +CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED=y +CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM=100 +CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 +CONFIG_BLUEDROID_ENABLED=y +CONFIG_BLUEDROID_PINNED_TO_CORE_0=y +CONFIG_BLUEDROID_PINNED_TO_CORE_1= +CONFIG_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BTC_TASK_STACK_SIZE=32768 +CONFIG_BTU_TASK_STACK_SIZE=4096 +CONFIG_BLUEDROID_MEM_DEBUG= +CONFIG_CLASSIC_BT_ENABLED= +CONFIG_GATTS_ENABLE=y +CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL= +CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y +CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 +CONFIG_GATTC_ENABLE=y +CONFIG_GATTC_CACHE_NVS_FLASH= +CONFIG_BLE_SMP_ENABLE=y +CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE= +CONFIG_BT_STACK_NO_LOG= + +# +# BT DEBUG LOG LEVEL +# +CONFIG_HCI_TRACE_LEVEL_NONE= +CONFIG_HCI_TRACE_LEVEL_ERROR= +CONFIG_HCI_TRACE_LEVEL_WARNING=y +CONFIG_HCI_TRACE_LEVEL_API= +CONFIG_HCI_TRACE_LEVEL_EVENT= +CONFIG_HCI_TRACE_LEVEL_DEBUG= +CONFIG_HCI_TRACE_LEVEL_VERBOSE= +CONFIG_HCI_INITIAL_TRACE_LEVEL=2 +CONFIG_BTM_TRACE_LEVEL_NONE= +CONFIG_BTM_TRACE_LEVEL_ERROR= +CONFIG_BTM_TRACE_LEVEL_WARNING=y +CONFIG_BTM_TRACE_LEVEL_API= +CONFIG_BTM_TRACE_LEVEL_EVENT= +CONFIG_BTM_TRACE_LEVEL_DEBUG= +CONFIG_BTM_TRACE_LEVEL_VERBOSE= +CONFIG_BTM_INITIAL_TRACE_LEVEL=2 +CONFIG_L2CAP_TRACE_LEVEL_NONE= +CONFIG_L2CAP_TRACE_LEVEL_ERROR= +CONFIG_L2CAP_TRACE_LEVEL_WARNING=y +CONFIG_L2CAP_TRACE_LEVEL_API= +CONFIG_L2CAP_TRACE_LEVEL_EVENT= +CONFIG_L2CAP_TRACE_LEVEL_DEBUG= +CONFIG_L2CAP_TRACE_LEVEL_VERBOSE= +CONFIG_L2CAP_INITIAL_TRACE_LEVEL=2 +CONFIG_RFCOMM_TRACE_LEVEL_NONE= +CONFIG_RFCOMM_TRACE_LEVEL_ERROR= +CONFIG_RFCOMM_TRACE_LEVEL_WARNING=y +CONFIG_RFCOMM_TRACE_LEVEL_API= +CONFIG_RFCOMM_TRACE_LEVEL_EVENT= +CONFIG_RFCOMM_TRACE_LEVEL_DEBUG= +CONFIG_RFCOMM_TRACE_LEVEL_VERBOSE= +CONFIG_RFCOMM_INITIAL_TRACE_LEVEL=2 +CONFIG_SDP_TRACE_LEVEL_NONE= +CONFIG_SDP_TRACE_LEVEL_ERROR= +CONFIG_SDP_TRACE_LEVEL_WARNING=y +CONFIG_SDP_TRACE_LEVEL_API= +CONFIG_SDP_TRACE_LEVEL_EVENT= +CONFIG_SDP_TRACE_LEVEL_DEBUG= +CONFIG_SDP_TRACE_LEVEL_VERBOSE= +CONFIG_SDP_INITIAL_TRACE_LEVEL=2 +CONFIG_GAP_TRACE_LEVEL_NONE= +CONFIG_GAP_TRACE_LEVEL_ERROR= +CONFIG_GAP_TRACE_LEVEL_WARNING=y +CONFIG_GAP_TRACE_LEVEL_API= +CONFIG_GAP_TRACE_LEVEL_EVENT= +CONFIG_GAP_TRACE_LEVEL_DEBUG= +CONFIG_GAP_TRACE_LEVEL_VERBOSE= +CONFIG_GAP_INITIAL_TRACE_LEVEL=2 +CONFIG_BNEP_TRACE_LEVEL_NONE= +CONFIG_BNEP_TRACE_LEVEL_ERROR= +CONFIG_BNEP_TRACE_LEVEL_WARNING=y +CONFIG_BNEP_TRACE_LEVEL_API= +CONFIG_BNEP_TRACE_LEVEL_EVENT= +CONFIG_BNEP_TRACE_LEVEL_DEBUG= +CONFIG_BNEP_TRACE_LEVEL_VERBOSE= +CONFIG_BNEP_INITIAL_TRACE_LEVEL=2 +CONFIG_PAN_TRACE_LEVEL_NONE= +CONFIG_PAN_TRACE_LEVEL_ERROR= +CONFIG_PAN_TRACE_LEVEL_WARNING=y +CONFIG_PAN_TRACE_LEVEL_API= +CONFIG_PAN_TRACE_LEVEL_EVENT= +CONFIG_PAN_TRACE_LEVEL_DEBUG= +CONFIG_PAN_TRACE_LEVEL_VERBOSE= +CONFIG_PAN_INITIAL_TRACE_LEVEL=2 +CONFIG_A2D_TRACE_LEVEL_NONE= +CONFIG_A2D_TRACE_LEVEL_ERROR= +CONFIG_A2D_TRACE_LEVEL_WARNING=y +CONFIG_A2D_TRACE_LEVEL_API= +CONFIG_A2D_TRACE_LEVEL_EVENT= +CONFIG_A2D_TRACE_LEVEL_DEBUG= +CONFIG_A2D_TRACE_LEVEL_VERBOSE= +CONFIG_A2D_INITIAL_TRACE_LEVEL=2 +CONFIG_AVDT_TRACE_LEVEL_NONE= +CONFIG_AVDT_TRACE_LEVEL_ERROR= +CONFIG_AVDT_TRACE_LEVEL_WARNING=y +CONFIG_AVDT_TRACE_LEVEL_API= +CONFIG_AVDT_TRACE_LEVEL_EVENT= +CONFIG_AVDT_TRACE_LEVEL_DEBUG= +CONFIG_AVDT_TRACE_LEVEL_VERBOSE= +CONFIG_AVDT_INITIAL_TRACE_LEVEL=2 +CONFIG_AVCT_TRACE_LEVEL_NONE= +CONFIG_AVCT_TRACE_LEVEL_ERROR= +CONFIG_AVCT_TRACE_LEVEL_WARNING=y +CONFIG_AVCT_TRACE_LEVEL_API= +CONFIG_AVCT_TRACE_LEVEL_EVENT= +CONFIG_AVCT_TRACE_LEVEL_DEBUG= +CONFIG_AVCT_TRACE_LEVEL_VERBOSE= +CONFIG_AVCT_INITIAL_TRACE_LEVEL=2 +CONFIG_AVRC_TRACE_LEVEL_NONE= +CONFIG_AVRC_TRACE_LEVEL_ERROR= +CONFIG_AVRC_TRACE_LEVEL_WARNING=y +CONFIG_AVRC_TRACE_LEVEL_API= +CONFIG_AVRC_TRACE_LEVEL_EVENT= +CONFIG_AVRC_TRACE_LEVEL_DEBUG= +CONFIG_AVRC_TRACE_LEVEL_VERBOSE= +CONFIG_AVRC_INITIAL_TRACE_LEVEL=2 +CONFIG_MCA_TRACE_LEVEL_NONE= +CONFIG_MCA_TRACE_LEVEL_ERROR= +CONFIG_MCA_TRACE_LEVEL_WARNING=y +CONFIG_MCA_TRACE_LEVEL_API= +CONFIG_MCA_TRACE_LEVEL_EVENT= +CONFIG_MCA_TRACE_LEVEL_DEBUG= +CONFIG_MCA_TRACE_LEVEL_VERBOSE= +CONFIG_MCA_INITIAL_TRACE_LEVEL=2 +CONFIG_HID_TRACE_LEVEL_NONE= +CONFIG_HID_TRACE_LEVEL_ERROR= +CONFIG_HID_TRACE_LEVEL_WARNING=y +CONFIG_HID_TRACE_LEVEL_API= +CONFIG_HID_TRACE_LEVEL_EVENT= +CONFIG_HID_TRACE_LEVEL_DEBUG= +CONFIG_HID_TRACE_LEVEL_VERBOSE= +CONFIG_HID_INITIAL_TRACE_LEVEL=2 +CONFIG_APPL_TRACE_LEVEL_NONE= +CONFIG_APPL_TRACE_LEVEL_ERROR= +CONFIG_APPL_TRACE_LEVEL_WARNING=y +CONFIG_APPL_TRACE_LEVEL_API= +CONFIG_APPL_TRACE_LEVEL_EVENT= +CONFIG_APPL_TRACE_LEVEL_DEBUG= +CONFIG_APPL_TRACE_LEVEL_VERBOSE= +CONFIG_APPL_INITIAL_TRACE_LEVEL=2 +CONFIG_GATT_TRACE_LEVEL_NONE= +CONFIG_GATT_TRACE_LEVEL_ERROR= +CONFIG_GATT_TRACE_LEVEL_WARNING=y +CONFIG_GATT_TRACE_LEVEL_API= +CONFIG_GATT_TRACE_LEVEL_EVENT= +CONFIG_GATT_TRACE_LEVEL_DEBUG= +CONFIG_GATT_TRACE_LEVEL_VERBOSE= +CONFIG_GATT_INITIAL_TRACE_LEVEL=2 +CONFIG_SMP_TRACE_LEVEL_NONE= +CONFIG_SMP_TRACE_LEVEL_ERROR= +CONFIG_SMP_TRACE_LEVEL_WARNING=y +CONFIG_SMP_TRACE_LEVEL_API= +CONFIG_SMP_TRACE_LEVEL_EVENT= +CONFIG_SMP_TRACE_LEVEL_DEBUG= +CONFIG_SMP_TRACE_LEVEL_VERBOSE= +CONFIG_SMP_INITIAL_TRACE_LEVEL=2 +CONFIG_BTIF_TRACE_LEVEL_NONE= +CONFIG_BTIF_TRACE_LEVEL_ERROR= +CONFIG_BTIF_TRACE_LEVEL_WARNING=y +CONFIG_BTIF_TRACE_LEVEL_API= +CONFIG_BTIF_TRACE_LEVEL_EVENT= +CONFIG_BTIF_TRACE_LEVEL_DEBUG= +CONFIG_BTIF_TRACE_LEVEL_VERBOSE= +CONFIG_BTIF_INITIAL_TRACE_LEVEL=2 +CONFIG_BTC_TRACE_LEVEL_NONE= +CONFIG_BTC_TRACE_LEVEL_ERROR= +CONFIG_BTC_TRACE_LEVEL_WARNING=y +CONFIG_BTC_TRACE_LEVEL_API= +CONFIG_BTC_TRACE_LEVEL_EVENT= +CONFIG_BTC_TRACE_LEVEL_DEBUG= +CONFIG_BTC_TRACE_LEVEL_VERBOSE= +CONFIG_BTC_INITIAL_TRACE_LEVEL=2 +CONFIG_OSI_TRACE_LEVEL_NONE= +CONFIG_OSI_TRACE_LEVEL_ERROR= +CONFIG_OSI_TRACE_LEVEL_WARNING=y +CONFIG_OSI_TRACE_LEVEL_API= +CONFIG_OSI_TRACE_LEVEL_EVENT= +CONFIG_OSI_TRACE_LEVEL_DEBUG= +CONFIG_OSI_TRACE_LEVEL_VERBOSE= +CONFIG_OSI_INITIAL_TRACE_LEVEL=2 +CONFIG_BLUFI_TRACE_LEVEL_NONE= +CONFIG_BLUFI_TRACE_LEVEL_ERROR= +CONFIG_BLUFI_TRACE_LEVEL_WARNING=y +CONFIG_BLUFI_TRACE_LEVEL_API= +CONFIG_BLUFI_TRACE_LEVEL_EVENT= +CONFIG_BLUFI_TRACE_LEVEL_DEBUG= +CONFIG_BLUFI_TRACE_LEVEL_VERBOSE= +CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2 +CONFIG_BT_ACL_CONNECTIONS=4 +CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST= +CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY= +CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK= +CONFIG_SMP_ENABLE=y +CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY= +CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 +CONFIG_BT_RESERVE_DRAM=0xdb5c + +# +# Driver configurations +# + +# +# ADC configuration +# +CONFIG_ADC_FORCE_XPD_FSM= +CONFIG_ADC2_DISABLE_DAC=y + +# +# SPI configuration +# +CONFIG_SPI_MASTER_IN_IRAM= +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +CONFIG_SPI_SLAVE_IN_IRAM= +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y + +# +# eFuse Bit Manager +# +CONFIG_EFUSE_CUSTOM_TABLE= +CONFIG_EFUSE_VIRTUAL= +CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE= +CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y +CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT= +CONFIG_EFUSE_MAX_BLK_LEN=192 + +# +# ESP32-specific +# +CONFIG_IDF_TARGET_ESP32=y +CONFIG_ESP32_REV_MIN_0= +CONFIG_ESP32_REV_MIN_1=y +CONFIG_ESP32_REV_MIN_2= +CONFIG_ESP32_REV_MIN_3= +CONFIG_ESP32_REV_MIN=1 +CONFIG_ESP32_DPORT_WORKAROUND=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_80= +CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_240= +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160 +CONFIG_SPIRAM_SUPPORT= +CONFIG_MEMMAP_TRACEMEM= +CONFIG_MEMMAP_TRACEMEM_TWOBANKS= +CONFIG_ESP32_TRAX= +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +CONFIG_TWO_UNIVERSAL_MAC_ADDRESS= +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF= +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR= +CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF= +CONFIG_NEWLIB_STDIN_LINE_ENDING_LF= +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +CONFIG_NEWLIB_NANO_FORMAT= +CONFIG_CONSOLE_UART_DEFAULT=y +CONFIG_CONSOLE_UART_CUSTOM= +CONFIG_CONSOLE_UART_NONE= +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ULP_COPROC_ENABLED= +CONFIG_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32_PANIC_PRINT_HALT= +CONFIG_ESP32_PANIC_PRINT_REBOOT=y +CONFIG_ESP32_PANIC_SILENT_REBOOT= +CONFIG_ESP32_PANIC_GDBSTUB= +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_DEBUG_STUBS_ENABLE=y +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +CONFIG_TASK_WDT_PANIC= +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +CONFIG_BROWNOUT_DET_LVL_SEL_1= +CONFIG_BROWNOUT_DET_LVL_SEL_2= +CONFIG_BROWNOUT_DET_LVL_SEL_3= +CONFIG_BROWNOUT_DET_LVL_SEL_4= +CONFIG_BROWNOUT_DET_LVL_SEL_5= +CONFIG_BROWNOUT_DET_LVL_SEL_6= +CONFIG_BROWNOUT_DET_LVL_SEL_7= +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC= +CONFIG_ESP32_TIME_SYSCALL_USE_FRC1= +CONFIG_ESP32_TIME_SYSCALL_USE_NONE= +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL= +CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC= +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256= +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32_XTAL_FREQ_40=y +CONFIG_ESP32_XTAL_FREQ_26= +CONFIG_ESP32_XTAL_FREQ_AUTO= +CONFIG_ESP32_XTAL_FREQ=40 +CONFIG_DISABLE_BASIC_ROM_CONSOLE= +CONFIG_ESP_TIMER_PROFILING= +CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y + +# +# Wi-Fi +# +CONFIG_SW_COEXIST_ENABLE=y +CONFIG_SW_COEXIST_PREFERENCE_WIFI= +CONFIG_SW_COEXIST_PREFERENCE_BT= +CONFIG_SW_COEXIST_PREFERENCE_BALANCE=y +CONFIG_SW_COEXIST_PREFERENCE_VALUE=2 +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER= +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_CSI_ENABLED= +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1= +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE= +CONFIG_ESP32_WIFI_IRAM_OPT=y + +# +# PHY +# +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION= +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 + +# +# Power Management +# +CONFIG_PM_ENABLE= + +# +# ADC-Calibration +# +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y + +# +# Event Loop Library +# +CONFIG_EVENT_LOOP_PROFILING= + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +CONFIG_HTTPD_LOG_PURGE_DATA= + +# +# ESP HTTPS OTA +# +CONFIG_OTA_ALLOW_HTTP= + +# +# Core dump +# +CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH= +CONFIG_ESP32_ENABLE_COREDUMP_TO_UART= +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_ESP32_ENABLE_COREDUMP= + +# +# Ethernet +# +CONFIG_DMA_RX_BUF_NUM=10 +CONFIG_DMA_TX_BUF_NUM=10 +CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE= +CONFIG_EMAC_CHECK_LINK_PERIOD_MS=2000 +CONFIG_EMAC_TASK_PRIORITY=20 +CONFIG_EMAC_TASK_STACK_SIZE=3072 + +# +# FAT Filesystem support +# +CONFIG_FATFS_CODEPAGE_DYNAMIC= +CONFIG_FATFS_CODEPAGE_437=y +CONFIG_FATFS_CODEPAGE_720= +CONFIG_FATFS_CODEPAGE_737= +CONFIG_FATFS_CODEPAGE_771= +CONFIG_FATFS_CODEPAGE_775= +CONFIG_FATFS_CODEPAGE_850= +CONFIG_FATFS_CODEPAGE_852= +CONFIG_FATFS_CODEPAGE_855= +CONFIG_FATFS_CODEPAGE_857= +CONFIG_FATFS_CODEPAGE_860= +CONFIG_FATFS_CODEPAGE_861= +CONFIG_FATFS_CODEPAGE_862= +CONFIG_FATFS_CODEPAGE_863= +CONFIG_FATFS_CODEPAGE_864= +CONFIG_FATFS_CODEPAGE_865= +CONFIG_FATFS_CODEPAGE_866= +CONFIG_FATFS_CODEPAGE_869= +CONFIG_FATFS_CODEPAGE_932= +CONFIG_FATFS_CODEPAGE_936= +CONFIG_FATFS_CODEPAGE_949= +CONFIG_FATFS_CODEPAGE_950= +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +CONFIG_FATFS_LFN_HEAP= +CONFIG_FATFS_LFN_STACK= +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y + +# +# Modbus configuration +# +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT= +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_MB_TIMER_PORT_ENABLED=y +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 + +# +# FreeRTOS +# +CONFIG_FREERTOS_UNICORE= +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_CORETIMER_0=y +CONFIG_FREERTOS_CORETIMER_1= +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE= +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL= +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK= +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE= +CONFIG_FREERTOS_ASSERT_DISABLE= +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +CONFIG_FREERTOS_LEGACY_HOOKS= +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +CONFIG_SUPPORT_STATIC_ALLOCATION= +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_USE_TRACE_FACILITY= +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS= +CONFIG_FREERTOS_DEBUG_INTERNALS= +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE= + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +CONFIG_HEAP_POISONING_LIGHT= +CONFIG_HEAP_POISONING_COMPREHENSIVE= +CONFIG_HEAP_TRACING= + +# +# libsodium +# +CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y + +# +# Log output +# +CONFIG_LOG_DEFAULT_LEVEL_NONE= +CONFIG_LOG_DEFAULT_LEVEL_ERROR= +CONFIG_LOG_DEFAULT_LEVEL_WARN= +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +CONFIG_LOG_DEFAULT_LEVEL_DEBUG= +CONFIG_LOG_DEFAULT_LEVEL_VERBOSE= +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y + +# +# LWIP +# +CONFIG_L2_TO_L3_COPY= +CONFIG_LWIP_IRAM_OPTIMIZATION= +CONFIG_LWIP_MAX_SOCKETS=10 +CONFIG_USE_ONLY_LWIP_SELECT= +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +CONFIG_LWIP_SO_RCVBUF= +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +CONFIG_LWIP_IP_FRAG= +CONFIG_LWIP_IP_REASSEMBLY= +CONFIG_LWIP_STATS= +CONFIG_LWIP_ETHARP_TRUST_IP_MAC= +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +CONFIG_LWIP_DHCP_RESTORE_LAST_IP= + +# +# DHCP server +# +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_AUTOIP= +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1436 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= +CONFIG_TCP_OVERSIZE_MSS=y +CONFIG_TCP_OVERSIZE_QUARTER_MSS= +CONFIG_TCP_OVERSIZE_DISABLE= + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=2048 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +CONFIG_TCPIP_TASK_AFFINITY_CPU0= +CONFIG_TCPIP_TASK_AFFINITY_CPU1= +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +CONFIG_PPP_SUPPORT= + +# +# ICMP +# +CONFIG_LWIP_MULTICAST_PING= +CONFIG_LWIP_BROADCAST_PING= + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC= +CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC= +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN= +CONFIG_MBEDTLS_DEBUG= +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI= +CONFIG_MBEDTLS_HARDWARE_SHA= +CONFIG_MBEDTLS_HAVE_TIME=y +CONFIG_MBEDTLS_HAVE_TIME_DATE= +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +CONFIG_MBEDTLS_TLS_SERVER_ONLY= +CONFIG_MBEDTLS_TLS_CLIENT_ONLY= +CONFIG_MBEDTLS_TLS_DISABLED= +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +CONFIG_MBEDTLS_PSK_MODES= +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_SSL3= +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_SSL_PROTO_DTLS= +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +CONFIG_MBEDTLS_CAMELLIA_C= +CONFIG_MBEDTLS_DES_C= +CONFIG_MBEDTLS_RC4_DISABLED=y +CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT= +CONFIG_MBEDTLS_RC4_ENABLED= +CONFIG_MBEDTLS_BLOWFISH_C= +CONFIG_MBEDTLS_XTEA_C= +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +CONFIG_MBEDTLS_RIPEMD160_C= + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +CONFIG_MQTT_USE_CUSTOM_CONFIG= +CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED= +CONFIG_MQTT_CUSTOM_OUTBOX= + +# +# NVS +# + +# +# OpenSSL +# +CONFIG_OPENSSL_DEBUG= +CONFIG_OPENSSL_ASSERT_DO_NOTHING=y +CONFIG_OPENSSL_ASSERT_EXIT= + +# +# PThreads +# +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0= +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1= +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" + +# +# SPI Flash driver +# +CONFIG_SPI_FLASH_VERIFY_WRITE= +CONFIG_SPI_FLASH_ENABLE_COUNTERS= +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS= +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED= +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +CONFIG_SPIFFS_CACHE_STATS= +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +CONFIG_SPIFFS_GC_STATS= +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +CONFIG_SPIFFS_DBG= +CONFIG_SPIFFS_API_DBG= +CONFIG_SPIFFS_GC_DBG= +CONFIG_SPIFFS_CACHE_DBG= +CONFIG_SPIFFS_CHECK_DBG= +CONFIG_SPIFFS_TEST_VISUALISATION= + +# +# TCP/IP Adapter +# +CONFIG_IP_LOST_TIMER_INTERVAL=120 +CONFIG_TCPIP_LWIP=y + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +CONFIG_UNITY_ENABLE_COLOR= +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +CONFIG_UNITY_ENABLE_FIXTURE= + +# +# Virtual file system +# +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y + +# +# Wear Levelling +# +CONFIG_WL_SECTOR_SIZE_512= +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 diff --git a/wasm3-sys/wasm3/platforms/embedded/esp32-pio/src/sdkconfig.h b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/src/sdkconfig.h new file mode 100644 index 0000000..4423559 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp32-pio/src/sdkconfig.h @@ -0,0 +1,371 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * Espressif IoT Development Framework Configuration + * + */ + +#define CONFIG_ENABLE_ARDUINO_DEPENDS 1 +#define CONFIG_AUTOSTART_ARDUINO 1 +#define CONFIG_ARDUINO_RUNNING_CORE 1 +#define CONFIG_ARDUINO_UDP_RUN_CORE1 1 +#define CONFIG_ARDUINO_EVENT_RUN_CORE1 1 +#define CONFIG_ARDUINO_EVENT_RUNNING_CORE 1 +#define CONFIG_ARDUINO_UDP_RUNNING_CORE 1 + +#define CONFIG_GATTC_ENABLE 1 +#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 +#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_MQTT_TRANSPORT_SSL 1 +#define CONFIG_BLE_SMP_ENABLE 1 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_SDP_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MB_SERIAL_TASK_PRIO 10 +#define CONFIG_MQTT_PROTOCOL_311 1 +#define CONFIG_TCP_RECVMBOX_SIZE 6 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_BLE_SCAN_DUPLICATE 1 +#define CONFIG_AVDT_TRACE_LEVEL_WARNING 1 +#define CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS 10 +#define CONFIG_TCP_WND_DEFAULT 5744 +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_SW_COEXIST_ENABLE 1 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_AVCT_INITIAL_TRACE_LEVEL 2 +#define CONFIG_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" +#define CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME 20 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_UDP_RECVMBOX_SIZE 6 +#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB" +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_INT_WDT 1 +#define CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN 3 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 +#define CONFIG_ESP_GRATUITOUS_ARP 1 +#define CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1 +#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 +#define CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE 0 +#define CONFIG_AWS_IOT_MQTT_PORT 8883 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_BTM_TRACE_LEVEL_WARNING 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_RFCOMM_TRACE_LEVEL_WARNING 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_BT_RESERVE_DRAM 0xdb5c +#define CONFIG_APP_COMPILE_TIME_DATE 1 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_ESP32_PANIC_PRINT_REBOOT 1 +#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE 20 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_AWS_IOT_MQTT_RX_BUF_LEN 512 +#define CONFIG_MB_SERIAL_BUF_SIZE 256 +#define CONFIG_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_MCA_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT "pthread" +#define CONFIG_EMAC_TASK_PRIORITY 20 +#define CONFIG_TIMER_TASK_STACK_DEPTH 2048 +#define CONFIG_TCP_MSS 1436 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_BTIF_INITIAL_TRACE_LEVEL 2 +#define CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF 3 +#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_APPL_TRACE_LEVEL_WARNING 1 +#define CONFIG_BTC_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1 +#define CONFIG_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_ESPTOOLPY_BAUD 115200 +#define CONFIG_INT_WDT_CHECK_CPU1 1 +#define CONFIG_AVRC_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ADC_CAL_LUT_ENABLE 1 +#define CONFIG_AWS_IOT_MQTT_TX_BUF_LEN 512 +#define CONFIG_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED 1 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_TOOLPREFIX "xtensa-esp32-elf-" +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 +#define CONFIG_MBEDTLS_RC4_DISABLED 1 +#define CONFIG_GAP_TRACE_LEVEL_WARNING 1 +#define CONFIG_CONSOLE_UART_NUM 0 +#define CONFIG_AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED 120 +#define CONFIG_ESP32_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_PTHREAD_STACK_MIN 768 +#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC 1 +#define CONFIG_ESPTOOLPY_BAUD_115200B 1 +#define CONFIG_TCP_OVERSIZE_MSS 1 +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1 +#define CONFIG_CONSOLE_UART_DEFAULT 1 +#define CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN 16384 +#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4 +#define CONFIG_GATT_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 +#define CONFIG_TIMER_TASK_STACK_SIZE 3584 +#define CONFIG_BTIF_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 +#define CONFIG_HCI_INITIAL_TRACE_LEVEL 2 +#define CONFIG_AVDT_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 +#define CONFIG_HTTPD_PURGE_BUF_LEN 32 +#define CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR 1 +#define CONFIG_AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 +#define CONFIG_MB_SERIAL_TASK_STACK_SIZE 2048 +#define CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_EFUSE_MAX_BLK_LEN 192 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_TCPIP_TASK_STACK_SIZE 2048 +#define CONFIG_BLUFI_TRACE_LEVEL_WARNING 1 +#define CONFIG_BLUEDROID_PINNED_TO_CORE_0 1 +#define CONFIG_TASK_WDT 1 +#define CONFIG_RFCOMM_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MAIN_TASK_STACK_SIZE 32768 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_BTC_TASK_STACK_SIZE 3072 +#define CONFIG_BLUEDROID_ENABLED 1 +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ADC2_DISABLE_DAC 1 +#define CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM 100 +#define CONFIG_ESP32_REV_MIN_1 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 +#define CONFIG_TIMER_QUEUE_LENGTH 10 +#define CONFIG_ESP32_REV_MIN 1 +#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT 1 +#define CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE 0 +#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 +#define CONFIG_MAKE_WARN_UNDEFINED_VARIABLES 1 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 +#define CONFIG_PAN_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 +#define CONFIG_MCA_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_A2D_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 +#define CONFIG_MDNS_MAX_SERVICES 10 +#define CONFIG_IDF_TARGET_ESP32 1 +#define CONFIG_EMAC_CHECK_LINK_PERIOD_MS 2000 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 +#define CONFIG_LIBSODIUM_USE_MBEDTLS_SHA 1 +#define CONFIG_AWS_IOT_SDK 1 +#define CONFIG_DMA_RX_BUF_NUM 10 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_TCP_SYNMAXRTX 6 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF 0 +#define CONFIG_PYTHON "python" +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 +#define CONFIG_ESPTOOLPY_COMPRESSED 1 +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_MB_CONTROLLER_STACK_SIZE 4096 +#define CONFIG_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_GARP_TMR_INTERVAL 60 +#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 +#define CONFIG_BNEP_INITIAL_TRACE_LEVEL 2 +#define CONFIG_HCI_TRACE_LEVEL_WARNING 1 +#define CONFIG_TCP_MSL 60000 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT 20 +#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 +#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_UNITY_ENABLE_FLOAT 1 +#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_BTC_TRACE_LEVEL_WARNING 1 +#define CONFIG_EMAC_TASK_STACK_SIZE 3072 +#define CONFIG_SMP_TRACE_LEVEL_WARNING 1 +#define CONFIG_MB_QUEUE_LENGTH 20 +#define CONFIG_SW_COEXIST_PREFERENCE_VALUE 2 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 +#define CONFIG_A2D_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 +#define CONFIG_AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 +#define CONFIG_BROWNOUT_DET_LVL 0 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_ESP32_APPTRACE_DEST_NONE 1 +#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_HTTPD_MAX_URI_LEN 512 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_AVCT_TRACE_LEVEL_WARNING 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_LOG_COLORS 1 +#define CONFIG_OSI_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_STACK_CHECK_NONE 1 +#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 +#define CONFIG_BNEP_TRACE_LEVEL_WARNING 1 +#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 +#define CONFIG_BROWNOUT_DET 1 +#define CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES 10 +#define CONFIG_ESP32_XTAL_FREQ 40 +#define CONFIG_OSI_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MONITOR_BAUD_115200B 1 +#define CONFIG_LOG_BOOTLOADER_LEVEL 3 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_BTU_TASK_STACK_SIZE 4096 +#define CONFIG_SMP_ENABLE 1 +#define CONFIG_HID_TRACE_LEVEL_WARNING 1 +#define CONFIG_AVRC_TRACE_LEVEL_WARNING 1 +#define CONFIG_MBEDTLS_SSL_SESSION_TICKETS 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_HID_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_MB_EVENT_QUEUE_TIMEOUT 20 +#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF 0 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_TCP_MAXRTX 12 +#define CONFIG_BTM_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_TCPIP_TASK_AFFINITY 0x7FFFFFFF +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_ESP32_XTAL_FREQ_40 1 +#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY 1 +#define CONFIG_DMA_TX_BUF_NUM 10 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_ESP32_DEBUG_OCDAWARE 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 +#define CONFIG_TIMER_TASK_PRIORITY 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 +#define CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI 1 +#define CONFIG_BT_ENABLED 1 +#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY 1 +#define CONFIG_SDP_TRACE_LEVEL_WARNING 1 +#define CONFIG_SW_COEXIST_PREFERENCE_BALANCE 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MONITOR_BAUD 115200 +#define CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT -1 +#define CONFIG_ESP32_DEBUG_STUBS_ENABLE 1 +#define CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT 30 +#define CONFIG_TCPIP_LWIP 1 +#define CONFIG_REDUCE_PHY_TX_POWER 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#define CONFIG_PAN_TRACE_LEVEL_WARNING 1 +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_TCP_QUEUE_OOSEQ 1 +#define CONFIG_GATTS_ENABLE 1 +#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED 1 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_SUPPORT_TERMIOS 1 +#define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1 +#define CONFIG_IDF_TARGET "esp32" +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 +#define CONFIG_GATT_INITIAL_TRACE_LEVEL 2 +#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF +#define CONFIG_AWS_IOT_MQTT_HOST "" +#define CONFIG_L2CAP_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 +#define CONFIG_MB_TIMER_INDEX 0 +#define CONFIG_SCAN_DUPLICATE_TYPE 0 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_APPL_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 +#define CONFIG_SMP_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 +#define CONFIG_L2CAP_INITIAL_TRACE_LEVEL 2 +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_BT_ACL_CONNECTIONS 4 +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_BOOTLOADER_WDT_ENABLE 1 +#define CONFIG_GAP_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_MB_TIMER_GROUP 0 +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_ESP32_DPORT_WORKAROUND 1 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_MB_TIMER_PORT_ENABLED 1 +#define CONFIG_DUPLICATE_SCAN_CACHE_SIZE 50 +#define CONFIG_MONITOR_BAUD_OTHER_VAL 115200 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_ESPTOOLPY_PORT "COM19" +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 +#define CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD 20 +#define CONFIG_BLUEDROID_PINNED_TO_CORE 0 +#define CONFIG_ESP32_WIFI_IRAM_OPT 1 +#define CONFIG_BLUFI_INITIAL_TRACE_LEVEL 2 diff --git a/wasm3-sys/wasm3/platforms/embedded/esp8266/.gitignore b/wasm3-sys/wasm3/platforms/embedded/esp8266/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp8266/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/wasm3-sys/wasm3/platforms/embedded/esp8266/lib/wasm3 b/wasm3-sys/wasm3/platforms/embedded/esp8266/lib/wasm3 new file mode 120000 index 0000000..17056a9 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp8266/lib/wasm3 @@ -0,0 +1 @@ +../../../../source \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/esp8266/platformio.ini b/wasm3-sys/wasm3/platforms/embedded/esp8266/platformio.ini new file mode 100644 index 0000000..5e1b0d8 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp8266/platformio.ini @@ -0,0 +1,29 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp8266] +platform = espressif8266 +board = nodemcuv2 +framework = arduino +monitor_speed = 115200 +upload_speed = 460800 + +board_build.f_cpu = 160000000L + +src_filter = + +<*> + - + +src_build_flags = + -Dd_m3FixedHeap=8192 + -O3 -Wfatal-errors + -flto + #-fPIC -fverbose-asm -save-temps=obj + diff --git a/wasm3-sys/wasm3/platforms/embedded/esp8266/src/main.cpp b/wasm3-sys/wasm3/platforms/embedded/esp8266/src/main.cpp new file mode 100644 index 0000000..41d5417 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/esp8266/src/main.cpp @@ -0,0 +1,71 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "Arduino.h" + +#include +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + uint32_t fsize = fib32_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + result = m3_CallV(f, 24); + if (result) FATAL("m3_Call: %s", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %d\n", value); +} + +void setup() +{ + Serial.begin(115200); + delay(10); + + Serial.print("\nWasm3 v" M3_VERSION " on ESP8266, build " __DATE__ " " __TIME__ "\n"); + + u32 start = millis(); + run_wasm(); + u32 end = millis(); + + Serial.print(String("Elapsed: ") + (end - start) + " ms\n"); +} + +void loop() +{ + delay(100); +} diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/.env b/wasm3-sys/wasm3/platforms/embedded/fomu/.env new file mode 100644 index 0000000..c4f2f8b --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/.env @@ -0,0 +1,17 @@ +fomu-reset () { + wishbone-tool 0xe0006000 0xac +} + +fomu-reload () { + fomu-reset + dfu-util -e +} + +fomu-load-dbg () { + dfu-util -e + wishbone-tool -s gdb +} + +fomu-gdb () { + riscv64-unknown-elf-gdb $1 -ex 'target remote localhost:1234' +} diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/.gitignore b/wasm3-sys/wasm3/platforms/embedded/fomu/.gitignore new file mode 100644 index 0000000..ba969de --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/.gitignore @@ -0,0 +1,5 @@ +.obj +wasm3.bin +wasm3.dfu +wasm3.elf +wasm3.ihex diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/Makefile b/wasm3-sys/wasm3/platforms/embedded/fomu/Makefile new file mode 100644 index 0000000..4619d6b --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/Makefile @@ -0,0 +1,121 @@ +GIT_VERSION := $(shell git describe --tags) + +# There is no 64-bit gcc on Raspberry Pi, so use the 32-bit version +ifneq (,$(wildcard /etc/rpi-issue)) +TRGT ?= riscv32-unknown-elf- +else +TRGT ?= riscv64-unknown-elf- +endif + +CC := $(TRGT)gcc +CXX := $(TRGT)g++ +OBJCOPY := $(TRGT)objcopy + +RM := rm -rf +COPY := cp -a +PATH_SEP := / + +ifeq ($(OS),Windows_NT) +COPY := copy +RM := del +PATH_SEP := \\ +endif + +BASE_DIR := . +LD_DIR := $(BASE_DIR)/ld +LDSCRIPT := $(BASE_DIR)/ld/linker.ld +ADD_CFLAGS := -I$(BASE_DIR)/include -I$(BASE_DIR)/src/wasm3/ -D__vexriscv__ \ + -DFOMU -Dd_m3FixedHeap=8192 + +ADD_LFLAGS := -lm +PACKAGE := wasm3 + +LTO := -flto -Wl,--allow-multiple-definition + +LDSCRIPTS := $(LDSCRIPT) $(LD_DIR)/output_format.ld $(LD_DIR)/regions.ld +SRC_DIR := $(BASE_DIR)/src +DBG_CFLAGS := -ggdb -g -DDEBUG -Wall +DBG_LFLAGS := -ggdb -g -Wall +CFLAGS := $(ADD_CFLAGS) \ + -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable \ + -Wno-missing-field-initializers \ + -ffunction-sections -fdata-sections -fno-common \ + -fomit-frame-pointer -Os $(LTO) \ + -march=rv32i -mabi=ilp32 \ + -DGIT_VERSION=u\"$(GIT_VERSION)\" -std=gnu11 +CXXFLAGS := $(CFLAGS) -std=c++11 -fno-rtti -fno-exceptions +LFLAGS := $(CFLAGS) $(ADD_LFLAGS) -L$(LD_DIR) \ + -nostartfiles $(LTO) \ + -Wl,--gc-sections \ + -Wl,--script=$(LDSCRIPT) \ + -Wl,--build-id=none + +OBJ_DIR := .obj + +CSOURCES := $(shell find -L $(SRC_DIR) -type f -name '*.c') +CPPSOURCES := $(shell find -L $(SRC_DIR) -type f -name '*.cpp') +ASOURCES := $(shell find -L $(SRC_DIR) -type f -name '*.S') +COBJS := $(addprefix $(OBJ_DIR)/,$(CSOURCES:.c=.o)) +CXXOBJS := $(addprefix $(OBJ_DIR)/,$(CPPSOURCES:.cpp=.o)) +AOBJS := $(addprefix $(OBJ_DIR)/,$(ASOURCES:.S=.o)) +OBJECTS := $(COBJS) $(CXXOBJS) $(AOBJS) +VPATH := $(SRC_DIR) + +QUIET := @ + +ALL := all +TARGET := $(PACKAGE).elf +CLEAN := clean + +$(ALL): $(TARGET) $(PACKAGE).bin $(PACKAGE).ihex $(PACKAGE).dfu + +#$(OBJECTS): | $(OBJ_DIR) + +$(TARGET): $(OBJECTS) $(LDSCRIPTS) + $(QUIET) echo " LD $@" + $(QUIET) $(CC) $(OBJECTS) $(LFLAGS) -o $@ + +$(PACKAGE).bin: $(TARGET) + $(QUIET) echo " OBJCOPY $@" + $(QUIET) $(OBJCOPY) -O binary $(TARGET) $@ + +$(PACKAGE).dfu: $(PACKAGE).bin + $(QUIET) echo " DFU $@" + $(QUIET) $(COPY) $(PACKAGE).bin $@ + $(QUIET) dfu-suffix -v 1209 -p 70b1 -a $@ + +$(PACKAGE).ihex: $(TARGET) + $(QUIET) echo " IHEX $(PACKAGE).ihex" + $(QUIET) $(OBJCOPY) -O ihex $(TARGET) $@ + +$(DEBUG): CFLAGS += $(DBG_CFLAGS) +$(DEBUG): LFLAGS += $(DBG_LFLAGS) +CFLAGS += $(DBG_CFLAGS) +LFLAGS += $(DBG_LFLAGS) +$(DEBUG): $(TARGET) + +$(OBJ_DIR): + $(QUIET) mkdir $(OBJ_DIR) + +$(COBJS) : $(OBJ_DIR)/%.o : %.c $(BASE_DIR)/Makefile + $(QUIET) mkdir -p $(@D) + $(QUIET) echo " CC $< $@" + $(QUIET) $(CC) -c $< $(CFLAGS) -o $@ -MMD + +$(OBJ_DIR)/%.o: %.cpp + $(QUIET) mkdir -p $(@D) + $(QUIET) echo " CXX $< $@" + $(QUIET) $(CXX) -c $< $(CXXFLAGS) -o $@ -MMD + +$(OBJ_DIR)/%.o: %.S + $(QUIET) mkdir -p $(@D) + $(QUIET) echo " AS $< $@" + $(QUIET) $(CC) -x assembler-with-cpp -c $< $(CFLAGS) -o $@ -MMD + +.PHONY: clean + +clean: + - $(RM) -rf $(OBJ_DIR) + - $(RM) $(TARGET) $(PACKAGE).bin $(PACKAGE).symbol $(PACKAGE).ihex $(PACKAGE).dfu + +-include $(OBJECTS:.o=.d) diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/README.md b/wasm3-sys/wasm3/platforms/embedded/fomu/README.md new file mode 100644 index 0000000..e919a41 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/README.md @@ -0,0 +1,36 @@ +## Build for Fomu + +```sh +export PATH=/opt/fomu-toolchain-linux_x86_64-v1.5.6/bin:$PATH +make +``` + +### Upload: + +```sh +dfu-util -D wasm3.dfu +``` + +## Hints + +```sh +# To reboot fomu: +wishbone-tool 0xe0006000 0xac + +# To run previously flashed program on Fomu: +dfu-util -e +``` + +## Debugging + +```sh +wishbone-tool -s gdb +``` +On second tab: +```sh +riscv64-unknown-elf-gdb wasm3.elf -ex 'target remote localhost:1234' + +b m3_CallWithArgs +print *(uint64_t*)env->stack + +``` diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/gdb_init b/wasm3-sys/wasm3/platforms/embedded/fomu/gdb_init new file mode 100644 index 0000000..e2287c9 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/gdb_init @@ -0,0 +1,11 @@ +set history save on +set confirm off +set remotetimeout 240 +set print asm-demangle on + +target remote localhost:1234 + +# monitor reset halt +# load +# continue +# quit diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/console.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/console.h new file mode 100644 index 0000000..a1cf599 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/console.h @@ -0,0 +1,24 @@ +#ifndef __CONSOLE_H +#define __CONSOLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*console_write_hook)(char); +typedef char (*console_read_hook)(void); +typedef int (*console_read_nonblock_hook)(void); + +void console_set_write_hook(console_write_hook h); +void console_set_read_hook(console_read_hook r, console_read_nonblock_hook rn); + +char readchar(void); +int readchar_nonblock(void); + +void putsnonl(const char *s); + +#ifdef __cplusplus +} +#endif + +#endif /* __CONSOLE_H */ diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/crc.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/crc.h new file mode 100644 index 0000000..88c8d95 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/crc.h @@ -0,0 +1,15 @@ +#ifndef __CRC_H +#define __CRC_H + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned short crc16(const unsigned char *buffer, int len); +unsigned int crc32(const unsigned char *buffer, unsigned int len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/csr-defs.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/csr-defs.h new file mode 100644 index 0000000..d98e8df --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/csr-defs.h @@ -0,0 +1,11 @@ +#ifndef CSR_DEFS__H +#define CSR_DEFS__H + +#define CSR_MSTATUS_MIE 0x8 + +#define CSR_IRQ_MASK 0xBC0 +#define CSR_IRQ_PENDING 0xFC0 + +#define CSR_DCACHE_INFO 0xCC0 + +#endif /* CSR_DEFS__H */ diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/generated/csr.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/generated/csr.h new file mode 100644 index 0000000..c18b102 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/generated/csr.h @@ -0,0 +1,773 @@ +//-------------------------------------------------------------------------------- +// Auto-generated by Migen (ae42105) & LiteX (3a72688b) on 2019-08-23 13:21:26 +//-------------------------------------------------------------------------------- +#ifndef __GENERATED_CSR_H +#define __GENERATED_CSR_H +#include +#ifdef CSR_ACCESSORS_DEFINED +extern void csr_writeb(uint8_t value, unsigned long addr); +extern uint8_t csr_readb(unsigned long addr); +extern void csr_writew(uint16_t value, unsigned long addr); +extern uint16_t csr_readw(unsigned long addr); +extern void csr_writel(uint32_t value, unsigned long addr); +extern uint32_t csr_readl(unsigned long addr); +#else /* ! CSR_ACCESSORS_DEFINED */ +#include +#endif /* ! CSR_ACCESSORS_DEFINED */ + +/* ctrl */ +#define CSR_CTRL_BASE 0xe0000000L +#define CSR_CTRL_RESET_ADDR 0xe0000000L +#define CSR_CTRL_RESET_SIZE 1 +static inline unsigned char ctrl_reset_read(void) { + unsigned char r = csr_readl(0xe0000000L); + return r; +} +static inline void ctrl_reset_write(unsigned char value) { + csr_writel(value, 0xe0000000L); +} +#define CSR_CTRL_SCRATCH_ADDR 0xe0000004L +#define CSR_CTRL_SCRATCH_SIZE 4 +static inline unsigned int ctrl_scratch_read(void) { + unsigned int r = csr_readl(0xe0000004L); + r <<= 8; + r |= csr_readl(0xe0000008L); + r <<= 8; + r |= csr_readl(0xe000000cL); + r <<= 8; + r |= csr_readl(0xe0000010L); + return r; +} +static inline void ctrl_scratch_write(unsigned int value) { + csr_writel(value >> 24, 0xe0000004L); + csr_writel(value >> 16, 0xe0000008L); + csr_writel(value >> 8, 0xe000000cL); + csr_writel(value, 0xe0000010L); +} +#define CSR_CTRL_BUS_ERRORS_ADDR 0xe0000014L +#define CSR_CTRL_BUS_ERRORS_SIZE 4 +static inline unsigned int ctrl_bus_errors_read(void) { + unsigned int r = csr_readl(0xe0000014L); + r <<= 8; + r |= csr_readl(0xe0000018L); + r <<= 8; + r |= csr_readl(0xe000001cL); + r <<= 8; + r |= csr_readl(0xe0000020L); + return r; +} + +/* picorvspi */ +#define CSR_PICORVSPI_BASE 0xe0005000L +#define CSR_PICORVSPI_CFG1_ADDR 0xe0005000L +#define CSR_PICORVSPI_CFG1_SIZE 1 +static inline unsigned char picorvspi_cfg1_read(void) { + unsigned char r = csr_readl(0xe0005000L); + return r; +} +static inline void picorvspi_cfg1_write(unsigned char value) { + csr_writel(value, 0xe0005000L); +} +#define CSR_PICORVSPI_CFG2_ADDR 0xe0005004L +#define CSR_PICORVSPI_CFG2_SIZE 1 +static inline unsigned char picorvspi_cfg2_read(void) { + unsigned char r = csr_readl(0xe0005004L); + return r; +} +static inline void picorvspi_cfg2_write(unsigned char value) { + csr_writel(value, 0xe0005004L); +} +#define CSR_PICORVSPI_CFG3_ADDR 0xe0005008L +#define CSR_PICORVSPI_CFG3_SIZE 1 +static inline unsigned char picorvspi_cfg3_read(void) { + unsigned char r = csr_readl(0xe0005008L); + return r; +} +static inline void picorvspi_cfg3_write(unsigned char value) { + csr_writel(value, 0xe0005008L); +} +#define CSR_PICORVSPI_CFG4_ADDR 0xe000500cL +#define CSR_PICORVSPI_CFG4_SIZE 1 +static inline unsigned char picorvspi_cfg4_read(void) { + unsigned char r = csr_readl(0xe000500cL); + return r; +} +static inline void picorvspi_cfg4_write(unsigned char value) { + csr_writel(value, 0xe000500cL); +} +#define CSR_PICORVSPI_STAT1_ADDR 0xe0005010L +#define CSR_PICORVSPI_STAT1_SIZE 1 +static inline unsigned char picorvspi_stat1_read(void) { + unsigned char r = csr_readl(0xe0005010L); + return r; +} +#define CSR_PICORVSPI_STAT2_ADDR 0xe0005014L +#define CSR_PICORVSPI_STAT2_SIZE 1 +static inline unsigned char picorvspi_stat2_read(void) { + unsigned char r = csr_readl(0xe0005014L); + return r; +} +#define CSR_PICORVSPI_STAT3_ADDR 0xe0005018L +#define CSR_PICORVSPI_STAT3_SIZE 1 +static inline unsigned char picorvspi_stat3_read(void) { + unsigned char r = csr_readl(0xe0005018L); + return r; +} +#define CSR_PICORVSPI_STAT4_ADDR 0xe000501cL +#define CSR_PICORVSPI_STAT4_SIZE 1 +static inline unsigned char picorvspi_stat4_read(void) { + unsigned char r = csr_readl(0xe000501cL); + return r; +} + +/* reboot */ +#define CSR_REBOOT_BASE 0xe0006000L +#define CSR_REBOOT_CTRL_ADDR 0xe0006000L +#define CSR_REBOOT_CTRL_SIZE 1 +static inline unsigned char reboot_ctrl_read(void) { + unsigned char r = csr_readl(0xe0006000L); + return r; +} +static inline void reboot_ctrl_write(unsigned char value) { + csr_writel(value, 0xe0006000L); +} +#define CSR_REBOOT_ADDR_ADDR 0xe0006004L +#define CSR_REBOOT_ADDR_SIZE 4 +static inline unsigned int reboot_addr_read(void) { + unsigned int r = csr_readl(0xe0006004L); + r <<= 8; + r |= csr_readl(0xe0006008L); + r <<= 8; + r |= csr_readl(0xe000600cL); + r <<= 8; + r |= csr_readl(0xe0006010L); + return r; +} +static inline void reboot_addr_write(unsigned int value) { + csr_writel(value >> 24, 0xe0006004L); + csr_writel(value >> 16, 0xe0006008L); + csr_writel(value >> 8, 0xe000600cL); + csr_writel(value, 0xe0006010L); +} + +/* rgb */ +#define CSR_RGB_BASE 0xe0006800L +#define CSR_RGB_DAT_ADDR 0xe0006800L +#define CSR_RGB_DAT_SIZE 1 +static inline unsigned char rgb_dat_read(void) { + unsigned char r = csr_readl(0xe0006800L); + return r; +} +static inline void rgb_dat_write(unsigned char value) { + csr_writel(value, 0xe0006800L); +} +#define CSR_RGB_ADDR_ADDR 0xe0006804L +#define CSR_RGB_ADDR_SIZE 1 +static inline unsigned char rgb_addr_read(void) { + unsigned char r = csr_readl(0xe0006804L); + return r; +} +static inline void rgb_addr_write(unsigned char value) { + csr_writel(value, 0xe0006804L); +} +#define CSR_RGB_CTRL_ADDR 0xe0006808L +#define CSR_RGB_CTRL_SIZE 1 +static inline unsigned char rgb_ctrl_read(void) { + unsigned char r = csr_readl(0xe0006808L); + return r; +} +static inline void rgb_ctrl_write(unsigned char value) { + csr_writel(value, 0xe0006808L); +} +#define CSR_RGB_RAW_ADDR 0xe000680cL +#define CSR_RGB_RAW_SIZE 1 +static inline unsigned char rgb_raw_read(void) { + unsigned char r = csr_readl(0xe000680cL); + return r; +} +static inline void rgb_raw_write(unsigned char value) { + csr_writel(value, 0xe000680cL); +} + +/* timer0 */ +#define CSR_TIMER0_BASE 0xe0002800L +#define CSR_TIMER0_LOAD_ADDR 0xe0002800L +#define CSR_TIMER0_LOAD_SIZE 4 +static inline unsigned int timer0_load_read(void) { + unsigned int r = csr_readl(0xe0002800L); + r <<= 8; + r |= csr_readl(0xe0002804L); + r <<= 8; + r |= csr_readl(0xe0002808L); + r <<= 8; + r |= csr_readl(0xe000280cL); + return r; +} +static inline void timer0_load_write(unsigned int value) { + csr_writel(value >> 24, 0xe0002800L); + csr_writel(value >> 16, 0xe0002804L); + csr_writel(value >> 8, 0xe0002808L); + csr_writel(value, 0xe000280cL); +} +#define CSR_TIMER0_RELOAD_ADDR 0xe0002810L +#define CSR_TIMER0_RELOAD_SIZE 4 +static inline unsigned int timer0_reload_read(void) { + unsigned int r = csr_readl(0xe0002810L); + r <<= 8; + r |= csr_readl(0xe0002814L); + r <<= 8; + r |= csr_readl(0xe0002818L); + r <<= 8; + r |= csr_readl(0xe000281cL); + return r; +} +static inline void timer0_reload_write(unsigned int value) { + csr_writel(value >> 24, 0xe0002810L); + csr_writel(value >> 16, 0xe0002814L); + csr_writel(value >> 8, 0xe0002818L); + csr_writel(value, 0xe000281cL); +} +#define CSR_TIMER0_EN_ADDR 0xe0002820L +#define CSR_TIMER0_EN_SIZE 1 +static inline unsigned char timer0_en_read(void) { + unsigned char r = csr_readl(0xe0002820L); + return r; +} +static inline void timer0_en_write(unsigned char value) { + csr_writel(value, 0xe0002820L); +} +#define CSR_TIMER0_UPDATE_VALUE_ADDR 0xe0002824L +#define CSR_TIMER0_UPDATE_VALUE_SIZE 1 +static inline unsigned char timer0_update_value_read(void) { + unsigned char r = csr_readl(0xe0002824L); + return r; +} +static inline void timer0_update_value_write(unsigned char value) { + csr_writel(value, 0xe0002824L); +} +#define CSR_TIMER0_VALUE_ADDR 0xe0002828L +#define CSR_TIMER0_VALUE_SIZE 4 +static inline unsigned int timer0_value_read(void) { + unsigned int r = csr_readl(0xe0002828L); + r <<= 8; + r |= csr_readl(0xe000282cL); + r <<= 8; + r |= csr_readl(0xe0002830L); + r <<= 8; + r |= csr_readl(0xe0002834L); + return r; +} +#define CSR_TIMER0_EV_STATUS_ADDR 0xe0002838L +#define CSR_TIMER0_EV_STATUS_SIZE 1 +static inline unsigned char timer0_ev_status_read(void) { + unsigned char r = csr_readl(0xe0002838L); + return r; +} +static inline void timer0_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0002838L); +} +#define CSR_TIMER0_EV_PENDING_ADDR 0xe000283cL +#define CSR_TIMER0_EV_PENDING_SIZE 1 +static inline unsigned char timer0_ev_pending_read(void) { + unsigned char r = csr_readl(0xe000283cL); + return r; +} +static inline void timer0_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe000283cL); +} +#define CSR_TIMER0_EV_ENABLE_ADDR 0xe0002840L +#define CSR_TIMER0_EV_ENABLE_SIZE 1 +static inline unsigned char timer0_ev_enable_read(void) { + unsigned char r = csr_readl(0xe0002840L); + return r; +} +static inline void timer0_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe0002840L); +} + +/* touch */ +#define CSR_TOUCH_BASE 0xe0005800L +#define CSR_TOUCH_O_ADDR 0xe0005800L +#define CSR_TOUCH_O_SIZE 1 +static inline unsigned char touch_o_read(void) { + unsigned char r = csr_readl(0xe0005800L); + return r; +} +static inline void touch_o_write(unsigned char value) { + csr_writel(value, 0xe0005800L); +} +#define CSR_TOUCH_OE_ADDR 0xe0005804L +#define CSR_TOUCH_OE_SIZE 1 +static inline unsigned char touch_oe_read(void) { + unsigned char r = csr_readl(0xe0005804L); + return r; +} +static inline void touch_oe_write(unsigned char value) { + csr_writel(value, 0xe0005804L); +} +#define CSR_TOUCH_I_ADDR 0xe0005808L +#define CSR_TOUCH_I_SIZE 1 +static inline unsigned char touch_i_read(void) { + unsigned char r = csr_readl(0xe0005808L); + return r; +} + +/* usb */ +#define CSR_USB_BASE 0xe0004800L +#define CSR_USB_PULLUP_OUT_ADDR 0xe0004800L +#define CSR_USB_PULLUP_OUT_SIZE 1 +static inline unsigned char usb_pullup_out_read(void) { + unsigned char r = csr_readl(0xe0004800L); + return r; +} +static inline void usb_pullup_out_write(unsigned char value) { + csr_writel(value, 0xe0004800L); +} +#define CSR_USB_EP_0_OUT_EV_STATUS_ADDR 0xe0004804L +#define CSR_USB_EP_0_OUT_EV_STATUS_SIZE 1 +static inline unsigned char usb_ep_0_out_ev_status_read(void) { + unsigned char r = csr_readl(0xe0004804L); + return r; +} +static inline void usb_ep_0_out_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0004804L); +} +#define CSR_USB_EP_0_OUT_EV_PENDING_ADDR 0xe0004808L +#define CSR_USB_EP_0_OUT_EV_PENDING_SIZE 1 +static inline unsigned char usb_ep_0_out_ev_pending_read(void) { + unsigned char r = csr_readl(0xe0004808L); + return r; +} +static inline void usb_ep_0_out_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe0004808L); +} +#define CSR_USB_EP_0_OUT_EV_ENABLE_ADDR 0xe000480cL +#define CSR_USB_EP_0_OUT_EV_ENABLE_SIZE 1 +static inline unsigned char usb_ep_0_out_ev_enable_read(void) { + unsigned char r = csr_readl(0xe000480cL); + return r; +} +static inline void usb_ep_0_out_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe000480cL); +} +#define CSR_USB_EP_0_OUT_LAST_TOK_ADDR 0xe0004810L +#define CSR_USB_EP_0_OUT_LAST_TOK_SIZE 1 +static inline unsigned char usb_ep_0_out_last_tok_read(void) { + unsigned char r = csr_readl(0xe0004810L); + return r; +} +#define CSR_USB_EP_0_OUT_RESPOND_ADDR 0xe0004814L +#define CSR_USB_EP_0_OUT_RESPOND_SIZE 1 +static inline unsigned char usb_ep_0_out_respond_read(void) { + unsigned char r = csr_readl(0xe0004814L); + return r; +} +static inline void usb_ep_0_out_respond_write(unsigned char value) { + csr_writel(value, 0xe0004814L); +} +#define CSR_USB_EP_0_OUT_DTB_ADDR 0xe0004818L +#define CSR_USB_EP_0_OUT_DTB_SIZE 1 +static inline unsigned char usb_ep_0_out_dtb_read(void) { + unsigned char r = csr_readl(0xe0004818L); + return r; +} +static inline void usb_ep_0_out_dtb_write(unsigned char value) { + csr_writel(value, 0xe0004818L); +} +#define CSR_USB_EP_0_OUT_OBUF_HEAD_ADDR 0xe000481cL +#define CSR_USB_EP_0_OUT_OBUF_HEAD_SIZE 1 +static inline unsigned char usb_ep_0_out_obuf_head_read(void) { + unsigned char r = csr_readl(0xe000481cL); + return r; +} +static inline void usb_ep_0_out_obuf_head_write(unsigned char value) { + csr_writel(value, 0xe000481cL); +} +#define CSR_USB_EP_0_OUT_OBUF_EMPTY_ADDR 0xe0004820L +#define CSR_USB_EP_0_OUT_OBUF_EMPTY_SIZE 1 +static inline unsigned char usb_ep_0_out_obuf_empty_read(void) { + unsigned char r = csr_readl(0xe0004820L); + return r; +} +#define CSR_USB_EP_0_IN_EV_STATUS_ADDR 0xe0004824L +#define CSR_USB_EP_0_IN_EV_STATUS_SIZE 1 +static inline unsigned char usb_ep_0_in_ev_status_read(void) { + unsigned char r = csr_readl(0xe0004824L); + return r; +} +static inline void usb_ep_0_in_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0004824L); +} +#define CSR_USB_EP_0_IN_EV_PENDING_ADDR 0xe0004828L +#define CSR_USB_EP_0_IN_EV_PENDING_SIZE 1 +static inline unsigned char usb_ep_0_in_ev_pending_read(void) { + unsigned char r = csr_readl(0xe0004828L); + return r; +} +static inline void usb_ep_0_in_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe0004828L); +} +#define CSR_USB_EP_0_IN_EV_ENABLE_ADDR 0xe000482cL +#define CSR_USB_EP_0_IN_EV_ENABLE_SIZE 1 +static inline unsigned char usb_ep_0_in_ev_enable_read(void) { + unsigned char r = csr_readl(0xe000482cL); + return r; +} +static inline void usb_ep_0_in_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe000482cL); +} +#define CSR_USB_EP_0_IN_LAST_TOK_ADDR 0xe0004830L +#define CSR_USB_EP_0_IN_LAST_TOK_SIZE 1 +static inline unsigned char usb_ep_0_in_last_tok_read(void) { + unsigned char r = csr_readl(0xe0004830L); + return r; +} +#define CSR_USB_EP_0_IN_RESPOND_ADDR 0xe0004834L +#define CSR_USB_EP_0_IN_RESPOND_SIZE 1 +static inline unsigned char usb_ep_0_in_respond_read(void) { + unsigned char r = csr_readl(0xe0004834L); + return r; +} +static inline void usb_ep_0_in_respond_write(unsigned char value) { + csr_writel(value, 0xe0004834L); +} +#define CSR_USB_EP_0_IN_DTB_ADDR 0xe0004838L +#define CSR_USB_EP_0_IN_DTB_SIZE 1 +static inline unsigned char usb_ep_0_in_dtb_read(void) { + unsigned char r = csr_readl(0xe0004838L); + return r; +} +static inline void usb_ep_0_in_dtb_write(unsigned char value) { + csr_writel(value, 0xe0004838L); +} +#define CSR_USB_EP_0_IN_IBUF_HEAD_ADDR 0xe000483cL +#define CSR_USB_EP_0_IN_IBUF_HEAD_SIZE 1 +static inline unsigned char usb_ep_0_in_ibuf_head_read(void) { + unsigned char r = csr_readl(0xe000483cL); + return r; +} +static inline void usb_ep_0_in_ibuf_head_write(unsigned char value) { + csr_writel(value, 0xe000483cL); +} +#define CSR_USB_EP_0_IN_IBUF_EMPTY_ADDR 0xe0004840L +#define CSR_USB_EP_0_IN_IBUF_EMPTY_SIZE 1 +static inline unsigned char usb_ep_0_in_ibuf_empty_read(void) { + unsigned char r = csr_readl(0xe0004840L); + return r; +} +#define CSR_USB_EP_1_IN_EV_STATUS_ADDR 0xe0004844L +#define CSR_USB_EP_1_IN_EV_STATUS_SIZE 1 +static inline unsigned char usb_ep_1_in_ev_status_read(void) { + unsigned char r = csr_readl(0xe0004844L); + return r; +} +static inline void usb_ep_1_in_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0004844L); +} +#define CSR_USB_EP_1_IN_EV_PENDING_ADDR 0xe0004848L +#define CSR_USB_EP_1_IN_EV_PENDING_SIZE 1 +static inline unsigned char usb_ep_1_in_ev_pending_read(void) { + unsigned char r = csr_readl(0xe0004848L); + return r; +} +static inline void usb_ep_1_in_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe0004848L); +} +#define CSR_USB_EP_1_IN_EV_ENABLE_ADDR 0xe000484cL +#define CSR_USB_EP_1_IN_EV_ENABLE_SIZE 1 +static inline unsigned char usb_ep_1_in_ev_enable_read(void) { + unsigned char r = csr_readl(0xe000484cL); + return r; +} +static inline void usb_ep_1_in_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe000484cL); +} +#define CSR_USB_EP_1_IN_LAST_TOK_ADDR 0xe0004850L +#define CSR_USB_EP_1_IN_LAST_TOK_SIZE 1 +static inline unsigned char usb_ep_1_in_last_tok_read(void) { + unsigned char r = csr_readl(0xe0004850L); + return r; +} +#define CSR_USB_EP_1_IN_RESPOND_ADDR 0xe0004854L +#define CSR_USB_EP_1_IN_RESPOND_SIZE 1 +static inline unsigned char usb_ep_1_in_respond_read(void) { + unsigned char r = csr_readl(0xe0004854L); + return r; +} +static inline void usb_ep_1_in_respond_write(unsigned char value) { + csr_writel(value, 0xe0004854L); +} +#define CSR_USB_EP_1_IN_DTB_ADDR 0xe0004858L +#define CSR_USB_EP_1_IN_DTB_SIZE 1 +static inline unsigned char usb_ep_1_in_dtb_read(void) { + unsigned char r = csr_readl(0xe0004858L); + return r; +} +static inline void usb_ep_1_in_dtb_write(unsigned char value) { + csr_writel(value, 0xe0004858L); +} +#define CSR_USB_EP_1_IN_IBUF_HEAD_ADDR 0xe000485cL +#define CSR_USB_EP_1_IN_IBUF_HEAD_SIZE 1 +static inline unsigned char usb_ep_1_in_ibuf_head_read(void) { + unsigned char r = csr_readl(0xe000485cL); + return r; +} +static inline void usb_ep_1_in_ibuf_head_write(unsigned char value) { + csr_writel(value, 0xe000485cL); +} +#define CSR_USB_EP_1_IN_IBUF_EMPTY_ADDR 0xe0004860L +#define CSR_USB_EP_1_IN_IBUF_EMPTY_SIZE 1 +static inline unsigned char usb_ep_1_in_ibuf_empty_read(void) { + unsigned char r = csr_readl(0xe0004860L); + return r; +} +#define CSR_USB_EP_2_OUT_EV_STATUS_ADDR 0xe0004864L +#define CSR_USB_EP_2_OUT_EV_STATUS_SIZE 1 +static inline unsigned char usb_ep_2_out_ev_status_read(void) { + unsigned char r = csr_readl(0xe0004864L); + return r; +} +static inline void usb_ep_2_out_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0004864L); +} +#define CSR_USB_EP_2_OUT_EV_PENDING_ADDR 0xe0004868L +#define CSR_USB_EP_2_OUT_EV_PENDING_SIZE 1 +static inline unsigned char usb_ep_2_out_ev_pending_read(void) { + unsigned char r = csr_readl(0xe0004868L); + return r; +} +static inline void usb_ep_2_out_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe0004868L); +} +#define CSR_USB_EP_2_OUT_EV_ENABLE_ADDR 0xe000486cL +#define CSR_USB_EP_2_OUT_EV_ENABLE_SIZE 1 +static inline unsigned char usb_ep_2_out_ev_enable_read(void) { + unsigned char r = csr_readl(0xe000486cL); + return r; +} +static inline void usb_ep_2_out_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe000486cL); +} +#define CSR_USB_EP_2_OUT_LAST_TOK_ADDR 0xe0004870L +#define CSR_USB_EP_2_OUT_LAST_TOK_SIZE 1 +static inline unsigned char usb_ep_2_out_last_tok_read(void) { + unsigned char r = csr_readl(0xe0004870L); + return r; +} +#define CSR_USB_EP_2_OUT_RESPOND_ADDR 0xe0004874L +#define CSR_USB_EP_2_OUT_RESPOND_SIZE 1 +static inline unsigned char usb_ep_2_out_respond_read(void) { + unsigned char r = csr_readl(0xe0004874L); + return r; +} +static inline void usb_ep_2_out_respond_write(unsigned char value) { + csr_writel(value, 0xe0004874L); +} +#define CSR_USB_EP_2_OUT_DTB_ADDR 0xe0004878L +#define CSR_USB_EP_2_OUT_DTB_SIZE 1 +static inline unsigned char usb_ep_2_out_dtb_read(void) { + unsigned char r = csr_readl(0xe0004878L); + return r; +} +static inline void usb_ep_2_out_dtb_write(unsigned char value) { + csr_writel(value, 0xe0004878L); +} +#define CSR_USB_EP_2_OUT_OBUF_HEAD_ADDR 0xe000487cL +#define CSR_USB_EP_2_OUT_OBUF_HEAD_SIZE 1 +static inline unsigned char usb_ep_2_out_obuf_head_read(void) { + unsigned char r = csr_readl(0xe000487cL); + return r; +} +static inline void usb_ep_2_out_obuf_head_write(unsigned char value) { + csr_writel(value, 0xe000487cL); +} +#define CSR_USB_EP_2_OUT_OBUF_EMPTY_ADDR 0xe0004880L +#define CSR_USB_EP_2_OUT_OBUF_EMPTY_SIZE 1 +static inline unsigned char usb_ep_2_out_obuf_empty_read(void) { + unsigned char r = csr_readl(0xe0004880L); + return r; +} +#define CSR_USB_EP_2_IN_EV_STATUS_ADDR 0xe0004884L +#define CSR_USB_EP_2_IN_EV_STATUS_SIZE 1 +static inline unsigned char usb_ep_2_in_ev_status_read(void) { + unsigned char r = csr_readl(0xe0004884L); + return r; +} +static inline void usb_ep_2_in_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0004884L); +} +#define CSR_USB_EP_2_IN_EV_PENDING_ADDR 0xe0004888L +#define CSR_USB_EP_2_IN_EV_PENDING_SIZE 1 +static inline unsigned char usb_ep_2_in_ev_pending_read(void) { + unsigned char r = csr_readl(0xe0004888L); + return r; +} +static inline void usb_ep_2_in_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe0004888L); +} +#define CSR_USB_EP_2_IN_EV_ENABLE_ADDR 0xe000488cL +#define CSR_USB_EP_2_IN_EV_ENABLE_SIZE 1 +static inline unsigned char usb_ep_2_in_ev_enable_read(void) { + unsigned char r = csr_readl(0xe000488cL); + return r; +} +static inline void usb_ep_2_in_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe000488cL); +} +#define CSR_USB_EP_2_IN_LAST_TOK_ADDR 0xe0004890L +#define CSR_USB_EP_2_IN_LAST_TOK_SIZE 1 +static inline unsigned char usb_ep_2_in_last_tok_read(void) { + unsigned char r = csr_readl(0xe0004890L); + return r; +} +#define CSR_USB_EP_2_IN_RESPOND_ADDR 0xe0004894L +#define CSR_USB_EP_2_IN_RESPOND_SIZE 1 +static inline unsigned char usb_ep_2_in_respond_read(void) { + unsigned char r = csr_readl(0xe0004894L); + return r; +} +static inline void usb_ep_2_in_respond_write(unsigned char value) { + csr_writel(value, 0xe0004894L); +} +#define CSR_USB_EP_2_IN_DTB_ADDR 0xe0004898L +#define CSR_USB_EP_2_IN_DTB_SIZE 1 +static inline unsigned char usb_ep_2_in_dtb_read(void) { + unsigned char r = csr_readl(0xe0004898L); + return r; +} +static inline void usb_ep_2_in_dtb_write(unsigned char value) { + csr_writel(value, 0xe0004898L); +} +#define CSR_USB_EP_2_IN_IBUF_HEAD_ADDR 0xe000489cL +#define CSR_USB_EP_2_IN_IBUF_HEAD_SIZE 1 +static inline unsigned char usb_ep_2_in_ibuf_head_read(void) { + unsigned char r = csr_readl(0xe000489cL); + return r; +} +static inline void usb_ep_2_in_ibuf_head_write(unsigned char value) { + csr_writel(value, 0xe000489cL); +} +#define CSR_USB_EP_2_IN_IBUF_EMPTY_ADDR 0xe00048a0L +#define CSR_USB_EP_2_IN_IBUF_EMPTY_SIZE 1 +static inline unsigned char usb_ep_2_in_ibuf_empty_read(void) { + unsigned char r = csr_readl(0xe00048a0L); + return r; +} +#define CSR_USB_ADDRESS_ADDR 0xe00048a4L +#define CSR_USB_ADDRESS_SIZE 1 +static inline unsigned char usb_address_read(void) { + unsigned char r = csr_readl(0xe00048a4L); + return r; +} +static inline void usb_address_write(unsigned char value) { + csr_writel(value, 0xe00048a4L); +} + +/* version */ +#define CSR_VERSION_BASE 0xe0007000L +#define CSR_VERSION_MAJOR_ADDR 0xe0007000L +#define CSR_VERSION_MAJOR_SIZE 1 +static inline unsigned char version_major_read(void) { + unsigned char r = csr_readl(0xe0007000L); + return r; +} +#define CSR_VERSION_MINOR_ADDR 0xe0007004L +#define CSR_VERSION_MINOR_SIZE 1 +static inline unsigned char version_minor_read(void) { + unsigned char r = csr_readl(0xe0007004L); + return r; +} +#define CSR_VERSION_REVISION_ADDR 0xe0007008L +#define CSR_VERSION_REVISION_SIZE 1 +static inline unsigned char version_revision_read(void) { + unsigned char r = csr_readl(0xe0007008L); + return r; +} +#define CSR_VERSION_GITREV_ADDR 0xe000700cL +#define CSR_VERSION_GITREV_SIZE 4 +static inline unsigned int version_gitrev_read(void) { + unsigned int r = csr_readl(0xe000700cL); + r <<= 8; + r |= csr_readl(0xe0007010L); + r <<= 8; + r |= csr_readl(0xe0007014L); + r <<= 8; + r |= csr_readl(0xe0007018L); + return r; +} +#define CSR_VERSION_GITEXTRA_ADDR 0xe000701cL +#define CSR_VERSION_GITEXTRA_SIZE 2 +static inline unsigned short int version_gitextra_read(void) { + unsigned short int r = csr_readl(0xe000701cL); + r <<= 8; + r |= csr_readl(0xe0007020L); + return r; +} +#define CSR_VERSION_DIRTY_ADDR 0xe0007024L +#define CSR_VERSION_DIRTY_SIZE 1 +static inline unsigned char version_dirty_read(void) { + unsigned char r = csr_readl(0xe0007024L); + return r; +} +#define CSR_VERSION_MODEL_ADDR 0xe0007028L +#define CSR_VERSION_MODEL_SIZE 1 +static inline unsigned char version_model_read(void) { + unsigned char r = csr_readl(0xe0007028L); + return r; +} + +/* constants */ +#define TIMER0_INTERRUPT 0 +static inline int timer0_interrupt_read(void) { + return 0; +} +#define USB_INTERRUPT 3 +static inline int usb_interrupt_read(void) { + return 3; +} +#define CSR_DATA_WIDTH 8 +static inline int csr_data_width_read(void) { + return 8; +} +#define SYSTEM_CLOCK_FREQUENCY 12000000 +static inline int system_clock_frequency_read(void) { + return 12000000; +} +#define CONFIG_BITSTREAM_SYNC_HEADER1 2123999870 +static inline int config_bitstream_sync_header1_read(void) { + return 2123999870; +} +#define CONFIG_BITSTREAM_SYNC_HEADER2 2125109630 +static inline int config_bitstream_sync_header2_read(void) { + return 2125109630; +} +#define CONFIG_CLOCK_FREQUENCY 12000000 +static inline int config_clock_frequency_read(void) { + return 12000000; +} +#define CONFIG_CPU_RESET_ADDR 0 +static inline int config_cpu_reset_addr_read(void) { + return 0; +} +#define CONFIG_CPU_TYPE "VEXRISCV" +static inline const char * config_cpu_type_read(void) { + return "VEXRISCV"; +} +#define CONFIG_CPU_VARIANT "VEXRISCV" +static inline const char * config_cpu_variant_read(void) { + return "VEXRISCV"; +} +#define CONFIG_CSR_DATA_WIDTH 8 +static inline int config_csr_data_width_read(void) { + return 8; +} +#define CONFIG_FOMU_REV "HACKER" +static inline const char * config_fomu_rev_read(void) { + return "HACKER"; +} +#define CONFIG_FOMU_REV_HACKER 1 +static inline int config_fomu_rev_hacker_read(void) { + return 1; +} + +#endif diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/generated/mem.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/generated/mem.h new file mode 100644 index 0000000..6fe108e --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/generated/mem.h @@ -0,0 +1,16 @@ +#ifndef __GENERATED_MEM_H +#define __GENERATED_MEM_H + +#define VEXRISCV_DEBUG_BASE 0xf00f0000 +#define VEXRISCV_DEBUG_SIZE 0x00000010 + +#define SRAM_BASE 0x10000000 +#define SRAM_SIZE 0x00020000 + +#define ROM_BASE 0x00000000 +#define ROM_SIZE 0x00002000 + +#define SPIFLASH_BASE 0x20000000 +#define SPIFLASH_SIZE 0x00200000 + +#endif diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/hw/common.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/hw/common.h new file mode 100644 index 0000000..af668f7 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/hw/common.h @@ -0,0 +1,52 @@ +#ifndef __HW_COMMON_H +#define __HW_COMMON_H + +#include + +/* To overwrite CSR accessors, define extern, non-inlined versions + * of csr_read[bwl]() and csr_write[bwl](), and define + * CSR_ACCESSORS_DEFINED. + */ + +#ifndef CSR_ACCESSORS_DEFINED +#define CSR_ACCESSORS_DEFINED + +#ifdef __ASSEMBLER__ +#define MMPTR(x) x +#else /* ! __ASSEMBLER__ */ +#define MMPTR(x) (*((volatile unsigned int *)(x))) + +static inline void csr_writeb(uint8_t value, uint32_t addr) +{ + *((volatile uint8_t *)addr) = value; +} + +static inline uint8_t csr_readb(uint32_t addr) +{ + return *(volatile uint8_t *)addr; +} + +static inline void csr_writew(uint16_t value, uint32_t addr) +{ + *((volatile uint16_t *)addr) = value; +} + +static inline uint16_t csr_readw(uint32_t addr) +{ + return *(volatile uint16_t *)addr; +} + +static inline void csr_writel(uint32_t value, uint32_t addr) +{ + *((volatile uint32_t *)addr) = value; +} + +static inline uint32_t csr_readl(uint32_t addr) +{ + return *(volatile uint32_t *)addr; +} +#endif /* ! __ASSEMBLER__ */ + +#endif /* ! CSR_ACCESSORS_DEFINED */ + +#endif /* __HW_COMMON_H */ diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/hw/flags.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/hw/flags.h new file mode 100644 index 0000000..911a1b6 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/hw/flags.h @@ -0,0 +1,40 @@ +#ifndef __HW_FLAGS_H +#define __HW_FLAGS_H + +#define UART_EV_TX 0x1 +#define UART_EV_RX 0x2 + +#define DFII_CONTROL_SEL 0x01 +#define DFII_CONTROL_CKE 0x02 +#define DFII_CONTROL_ODT 0x04 +#define DFII_CONTROL_RESET_N 0x08 + +#define DFII_COMMAND_CS 0x01 +#define DFII_COMMAND_WE 0x02 +#define DFII_COMMAND_CAS 0x04 +#define DFII_COMMAND_RAS 0x08 +#define DFII_COMMAND_WRDATA 0x10 +#define DFII_COMMAND_RDDATA 0x20 + +#define ETHMAC_EV_SRAM_WRITER 0x1 +#define ETHMAC_EV_SRAM_READER 0x1 + +#define CLKGEN_STATUS_BUSY 0x1 +#define CLKGEN_STATUS_PROGDONE 0x2 +#define CLKGEN_STATUS_LOCKED 0x4 + +#define DVISAMPLER_TOO_LATE 0x1 +#define DVISAMPLER_TOO_EARLY 0x2 + +#define DVISAMPLER_DELAY_MASTER_CAL 0x01 +#define DVISAMPLER_DELAY_MASTER_RST 0x02 +#define DVISAMPLER_DELAY_SLAVE_CAL 0x04 +#define DVISAMPLER_DELAY_SLAVE_RST 0x08 +#define DVISAMPLER_DELAY_INC 0x10 +#define DVISAMPLER_DELAY_DEC 0x20 + +#define DVISAMPLER_SLOT_EMPTY 0 +#define DVISAMPLER_SLOT_LOADED 1 +#define DVISAMPLER_SLOT_PENDING 2 + +#endif /* __HW_FLAGS_H */ diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/irq.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/irq.h new file mode 100644 index 0000000..19f00b1 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/irq.h @@ -0,0 +1,144 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __picorv32__ +// PicoRV32 has a very limited interrupt support, implemented via custom +// instructions. It also doesn't have a global interrupt enable/disable, so +// we have to emulate it via saving and restoring a mask and using 0/~1 as a +// hardware mask. +// Due to all this somewhat low-level mess, all of the glue is implemented in +// the RiscV crt0, and this header is kept as a thin wrapper. Since interrupts +// managed by this layer, do not call interrupt instructions directly, as the +// state will go out of sync with the hardware. + +// Read only. +extern unsigned int _irq_pending; +// Read only. +extern unsigned int _irq_mask; +// Read only. +extern unsigned int _irq_enabled; +extern void _irq_enable(void); +extern void _irq_disable(void); +extern void _irq_setmask(unsigned int); +#endif + +static inline unsigned int irq_getie(void) +{ +#if defined (__lm32__) + unsigned int ie; + __asm__ __volatile__("rcsr %0, IE" : "=r" (ie)); + return ie; +#elif defined (__or1k__) + return !!(mfspr(SPR_SR) & SPR_SR_IEE); +#elif defined (__picorv32__) + return _irq_enabled != 0; +#elif defined (__vexriscv__) + return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; +#elif defined (__minerva__) + return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; +#else +#error Unsupported architecture +#endif +} + +static inline void irq_setie(unsigned int ie) +{ +#if defined (__lm32__) + __asm__ __volatile__("wcsr IE, %0" : : "r" (ie)); +#elif defined (__or1k__) + if (ie & 0x1) + mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE); + else + mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_IEE); +#elif defined (__picorv32__) + if (ie & 0x1) + _irq_enable(); + else + _irq_disable(); +#elif defined (__vexriscv__) + if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); +#elif defined (__minerva__) + if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); +#else +#error Unsupported architecture +#endif +} + +static inline unsigned int irq_getmask(void) +{ +#if defined (__lm32__) + unsigned int mask; + __asm__ __volatile__("rcsr %0, IM" : "=r" (mask)); + return mask; +#elif defined (__or1k__) + return mfspr(SPR_PICMR); +#elif defined (__picorv32__) + // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how + // LiteX sees things. + return ~_irq_mask; +#elif defined (__vexriscv__) + unsigned int mask; + asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK)); + return mask; +#elif defined (__minerva__) + unsigned int mask; + asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK)); + return mask; +#else +#error Unsupported architecture +#endif +} + +static inline void irq_setmask(unsigned int mask) +{ +#if defined (__lm32__) + __asm__ __volatile__("wcsr IM, %0" : : "r" (mask)); +#elif defined (__or1k__) + mtspr(SPR_PICMR, mask); +#elif defined (__picorv32__) + // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how + // LiteX sees things. + _irq_setmask(~mask); +#elif defined (__vexriscv__) + asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask)); +#elif defined (__minerva__) + asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask)); +#else +#error Unsupported architecture +#endif +} + +static inline unsigned int irq_pending(void) +{ +#if defined (__lm32__) + unsigned int pending; + __asm__ __volatile__("rcsr %0, IP" : "=r" (pending)); + return pending; +#elif defined (__or1k__) + return mfspr(SPR_PICSR); +#elif defined (__picorv32__) + return _irq_pending; +#elif defined (__vexriscv__) + unsigned int pending; + asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING)); + return pending; +#elif defined (__minerva__) + unsigned int pending; + asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING)); + return pending; +#else +#error Unsupported architecture +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif /* __IRQ_H */ diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/printf.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/printf.h new file mode 100644 index 0000000..73a80a7 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/printf.h @@ -0,0 +1,124 @@ +/* +File: printf.h + +Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or other +materials provided with the distribution. + +Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names of its +contributors may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +---------------------------------------------------------------------- + +This library is really just two files: 'printf.h' and 'printf.c'. + +They provide a simple and small (+200 loc) printf functionality to +be used in embedded systems. + +I've found them so useful in debugging that I do not bother with a +debugger at all. + +They are distributed in source form, so to use them, just compile them +into your project. + +Two printf variants are provided: printf and sprintf. + +The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'. + +Zero padding and field width are also supported. + +If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the +long specifier is also +supported. Note that this will pull in some long math routines (pun intended!) +and thus make your executable noticeably longer. + +The memory footprint of course depends on the target cpu, compiler and +compiler options, but a rough guestimate (based on a H8S target) is about +1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space. +Not too bad. Your mileage may vary. By hacking the source code you can +get rid of some hundred bytes, I'm sure, but personally I feel the balance of +functionality and flexibility versus code size is close to optimal for +many embedded systems. + +To use the printf you need to supply your own character output function, +something like : + +void putc ( void* p, char c) + { + while (!SERIAL_PORT_EMPTY) ; + SERIAL_PORT_TX_REGISTER = c; + } + +Before you can call printf you need to initialize it to use your +character output function with something like: + +init_printf(NULL,putc); + +Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc', +the NULL (or any pointer) you pass into the 'init_printf' will eventually be +passed to your 'putc' routine. This allows you to pass some storage space (or +anything really) to the character output function, if necessary. +This is not often needed but it was implemented like that because it made +implementing the sprintf function so neat (look at the source code). + +The code is re-entrant, except for the 'init_printf' function, so it +is safe to call it from interrupts too, although this may result in mixed output. +If you rely on re-entrancy, take care that your 'putc' function is re-entrant! + +The printf and sprintf functions are actually macros that translate to +'tfp_printf' and 'tfp_sprintf'. This makes it possible +to use them along with 'stdio.h' printf's in a single source file. +You just need to undef the names before you include the 'stdio.h'. +Note that these are not function like macros, so if you have variables +or struct members with these names, things will explode in your face. +Without variadic macros this is the best we can do to wrap these +fucnctions. If it is a problem just give up the macros and use the +functions directly or rename them. + +For further details see source code. + +regs Kusti, 23.10.2004 +*/ + + +#ifndef __TFP_PRINTF__ +#define __TFP_PRINTF__ + +#include + +void init_printf(void* putp,void (*putf) (void*,char)); + +void tfp_printf(char *fmt, ...); +void tfp_sprintf(char* s,char *fmt, ...); + +void tfp_format(void* putp,void (*putf) (void*,char),char *fmt, va_list va); + +#define printf tfp_printf +#define sprintf tfp_sprintf + +#endif + + + diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/rgb.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/rgb.h new file mode 100644 index 0000000..5455429 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/rgb.h @@ -0,0 +1,29 @@ +#ifndef _RGB_H_ +#define _RGB_H_ + +void rgb_init(void); +void rgb_set(uint8_t r, uint8_t g, uint8_t b); + +// The amount of time to stay off or on +void rgb_on_time(uint8_t ms); +void rgb_off_time(uint8_t ms); + +// The amount of time to breathe in/out +void rgb_in_time(uint8_t ms); +void rgb_out_time(uint8_t ms); + +enum led_registers { + LEDDCR0 = 8, + LEDDBR = 9, + LEDDONR = 10, + LEDDOFR = 11, + LEDDBCRR = 5, + LEDDBCFR = 6, + LEDDPWRR = 1, + LEDDPWRG = 2, + LEDDPWRB = 3, +}; + +void rgb_write(uint8_t value, uint8_t addr); + +#endif /* _RGB_H_ */ \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/spi.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/spi.h new file mode 100644 index 0000000..190cec8 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/spi.h @@ -0,0 +1,93 @@ +#ifndef BB_SPI_H_ +#define BB_SPI_H_ + +#include + +enum spi_state { + SS_UNCONFIGURED = 0, + SS_SINGLE, + SS_DUAL_RX, + SS_DUAL_TX, + SS_QUAD_RX, + SS_QUAD_TX, + SS_HARDWARE, +}; + +enum spi_type { + ST_UNCONFIGURED, + ST_SINGLE, + ST_DUAL, + ST_QUAD, + ST_QPI, +}; + +enum spi_pin { + SP_MOSI, + SP_MISO, + SP_HOLD, + SP_WP, + SP_CS, + SP_CLK, + SP_D0, + SP_D1, + SP_D2, + SP_D3, +}; + +struct spi_id { + uint8_t manufacturer_id; // Result from 0x90 + uint8_t device_id; // Result from 0x90 + uint8_t _manufacturer_id; // Result from 0x9f + uint8_t memory_type; // Result from 0x9f + uint8_t memory_size; // Result from 0x9f + uint8_t signature; // Result from 0xab + uint8_t serial[4]; // Result from 0x4b + int bytes; // -1 if unknown + const char *manufacturer; + const char *model; + const char *capacity; +}; + +struct ff_spi; + +void spiPause(struct ff_spi *spi); +void spiBegin(struct ff_spi *spi); +void spiEnd(struct ff_spi *spi); + +//void spiSingleTx(struct ff_spi *spi, uint8_t out); +//uint8_t spiSingleRx(struct ff_spi *spi); +//void spiDualTx(struct ff_spi *spi, uint8_t out); +//void spiQuadTx(struct ff_spi *spi, uint8_t out); +void spiCommand(struct ff_spi *spi, uint8_t cmd); +//uint8_t spiDualRx(struct ff_spi *spi); +//uint8_t spiQuadRx(struct ff_spi *spi); +int spiTx(struct ff_spi *spi, uint8_t word); +uint8_t spiRx(struct ff_spi *spi); +uint8_t spiReadStatus(struct ff_spi *spi, uint8_t sr); +void spiWriteStatus(struct ff_spi *spi, uint8_t sr, uint8_t val); +void spiReadSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]); +void spiWriteSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]); +int spiSetType(struct ff_spi *spi, enum spi_type type); +int spiRead(struct ff_spi *spi, uint32_t addr, uint8_t *data, unsigned int count); +int spiIsBusy(struct ff_spi *spi); +int spiBeginErase32(struct ff_spi *spi, uint32_t erase_addr); +int spiBeginErase64(struct ff_spi *spi, uint32_t erase_addr); +int spiBeginWrite(struct ff_spi *spi, uint32_t addr, const void *data, unsigned int count); + +struct spi_id spiId(struct ff_spi *spi); +void spiOverrideSize(struct ff_spi *spi, uint32_t new_size); + +//int spi_wait_for_not_busy(struct ff_spi *spi); +int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned int count); +uint8_t spiReset(struct ff_spi *spi); +int spiInit(struct ff_spi *spi); + +void spiHold(struct ff_spi *spi); +void spiUnhold(struct ff_spi *spi); +void spiSwapTxRx(struct ff_spi *spi); + +struct ff_spi *spiAlloc(void); +void spiSetPin(struct ff_spi *spi, enum spi_pin pin, int val); +void spiFree(void); + +#endif /* BB_SPI_H_ */ diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/spiflash.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/spiflash.h new file mode 100644 index 0000000..a4ff495 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/spiflash.h @@ -0,0 +1,8 @@ +#ifndef __SPIFLASH_H +#define __SPIFLASH_H + +void write_to_flash_page(unsigned int addr, const unsigned char *c, unsigned int len); +void erase_flash_sector(unsigned int addr); +void write_to_flash(unsigned int addr, const unsigned char *c, unsigned int len); + +#endif /* __SPIFLASH_H */ diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/system.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/system.h new file mode 100644 index 0000000..ea3da85 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/system.h @@ -0,0 +1,67 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +void flush_cpu_icache(void); +void flush_cpu_dcache(void); +void flush_l2_cache(void); + +#ifdef __or1k__ +#include +static inline unsigned long mfspr(unsigned long add) +{ + unsigned long ret; + + __asm__ __volatile__ ("l.mfspr %0,%1,0" : "=r" (ret) : "r" (add)); + + return ret; +} + +static inline void mtspr(unsigned long add, unsigned long val) +{ + __asm__ __volatile__ ("l.mtspr %0,%1,0" : : "r" (add), "r" (val)); +} +#endif + + +#if defined(__vexriscv__) || defined(__minerva__) +#include +#define csrr(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define csrw(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ + else \ + asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + +#define csrs(reg, bit) ({ \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrs x0, " #reg ", %0" :: "i"(bit)); \ + else \ + asm volatile ("csrrs x0, " #reg ", %0" :: "r"(bit)); }) + +#define csrc(reg, bit) ({ \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrc x0, " #reg ", %0" :: "i"(bit)); \ + else \ + asm volatile ("csrrc x0, " #reg ", %0" :: "r"(bit)); }) +#endif + +#ifdef __cplusplus +} +#endif + +#include + +__attribute__((noreturn)) void reboot(void); + +__attribute__((noreturn)) static inline void warmboot_to_image(uint8_t image_index) { + reboot_ctrl_write(0xac | (image_index & 3) << 0); + while (1); +} +#endif /* __SYSTEM_H */ diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/time.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/time.h new file mode 100644 index 0000000..cbbc688 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/time.h @@ -0,0 +1,16 @@ +#ifndef __TIME_H +#define __TIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +void time_init(void); +int elapsed(int *last_event, int period); +void msleep(int ms); + +#ifdef __cplusplus +} +#endif + +#endif /* __TIME_H */ diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/toboot-api.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/toboot-api.h new file mode 100644 index 0000000..a957f79 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/toboot-api.h @@ -0,0 +1,109 @@ +#ifndef TOBOOT_API_H_ +#define TOBOOT_API_H_ + +#include + +/// Store this configuration struct at offset 0x94 from the start +/// of your binary image. +/// You may set all RESERVED values to 0. as they will be calculated +/// when the program is written to flash. +struct toboot_configuration { + /// Set to 0x907070b2 to indicate a valid configuration header. + uint32_t magic; + + /// Reserved value. Used as a generational counter. Toboot will + /// overwrite this value with a monotonically-increasing counter + /// every time a new image is burned. This is used to determine + /// which image is the newest. + uint16_t reserved_gen; + + /// The starting page for your program in 1024-byte blocks. + /// Toboot itself sets this to 0. If this is nonzero, then it + /// must be located after the Toboot image. Toboot is currently + /// under 5 kilobytes, so make sure this value is at least 6. + uint8_t start; + + /// Configuration bitmask. See below for values. + uint8_t config; + + /// Set to 0x18349420 to prevent the user from entering Toboot manually. + /// Use this value with caution, as it can be used to lockout a Tomu. + uint32_t lock_entry; + + /// A bitmask of sectors to erase when updating the program. Each "1" + /// causes that sector to be erased, unless it's Toboot itself. Bit values + /// determine flash blocks 0-31. + uint32_t erase_mask_lo; + + /// A bitmask of sectors to erase when updating the program. Each "1" + /// causes that sector to e erased. Use these two values to e.g. force + /// private keys to be erased when updating. Bit values determine flash + /// blocks 32-63. + uint32_t erase_mask_hi; + + /// A hash of the entire header, minus this entry. Toboot calculates + /// this when it programs the first block. A Toboot configuration + /// header MUST have a valid hash in order to be considered valid. + uint32_t reserved_hash; +} __attribute__((packed)); + +/// Toboot V1.0 leaves IRQs enabled, mimicking the behavior of +/// AN0042. Toboot V2.0 makes this configurable by adding a +/// bit to the configuration area. +#define TOBOOT_CONFIG_FLAG_ENABLE_IRQ_MASK 0x01 +#define TOBOOT_CONFIG_FLAG_ENABLE_IRQ_SHIFT 0 +#define TOBOOT_CONFIG_FLAG_ENABLE_IRQ (1 << 0) +#define TOBOOT_CONFIG_FLAG_DISABLE_IRQ (0 << 0) + +/// When running a normal program, you won't want Toboot to run. +/// However, when developing new software it is handy to have +/// Toboot run at poweron, instead of jumping straight to your +/// program. Set this flag to enter your program whenever the +/// system has just powered on. +#define TOBOOT_CONFIG_FLAG_AUTORUN_MASK 0x02 +#define TOBOOT_CONFIG_FLAG_AUTORUN_SHIFT 1 +#define TOBOOT_CONFIG_FLAG_AUTORUN (1 << 1) +#define TOBOOT_CONFIG_FLAG_AUTORUN_DISABLED (0 << 1) + +/// When we create a fake header, this flag will be set. Otherwise, +/// leave the flag cleared. This field has no meaning in user +/// applications, and is only used internally. +#define TOBOOT_CONFIG_FAKE_MASK 0x04 +#define TOBOOT_CONFIG_FAKE_SHIFT 2 +#define TOBOOT_CONFIG_FAKE (1 << 2) + +/// Various magic values describing Toboot configuration headers. +#define TOBOOT_V1_MAGIC 0x6fb0 +#define TOBOOT_V1_MAGIC_MASK 0x0000ffff +#define TOBOOT_V2_MAGIC 0x907070b2 +#define TOBOOT_V2_MAGIC_MASK 0xffffffff + +/// This value is used to prevent manual entry into Toboot. +#define TOBOOT_LOCKOUT_MAGIC 0x18349420 + +/// The seed value for the hash of Toboot's configuration header +#define TOBOOT_HASH_SEED 0x037a5cf1 + +/// This is the runtime part that lives at the start of RAM. +/// Running programs can use this to force entry into Toboot +/// during the next reboot. +struct toboot_runtime { + /// Set this to 0x74624346 and reboot to enter bootloader, + /// even if LOCKOUT is enabled. + uint32_t magic; + + /// Set this to 0 when your program starts. + uint8_t boot_count; + + /// The bootloader should set this to 0x23 for Tomu. + uint8_t board_model; + + /// Unused. + uint16_t reserved; +}; + +/// Set runtime.magic to this value and reboot to force +/// entry into Toboot. +#define TOBOOT_FORCE_ENTRY_MAGIC 0x74624346 + +#endif /* TOBOOT_API_H_ */ \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/toboot-internal.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/toboot-internal.h new file mode 100644 index 0000000..9463766 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/toboot-internal.h @@ -0,0 +1,49 @@ +#ifndef TOBOOT_INTERNAL_H_ +#define TOBOOT_INTERNAL_H_ + +#include + +/// This describes the structure that allows the OS to communicate +/// with the bootloader. It keeps track of how many times we've +/// tried booting, as well as a magic value that tells us to enter +/// the bootloader instead of booting the app. +/// It also keeps track of the board model. +__attribute__((section(".boot_token"))) extern struct toboot_runtime boot_token; + +enum bootloader_reason +{ + NOT_ENTERING_BOOTLOADER = 0, + BOOT_TOKEN_PRESENT = 1, + BOOT_FAILED_TOO_MANY_TIMES = 2, + NO_PROGRAM_PRESENT = 3, + BUTTON_HELD_DOWN = 4, + COLD_BOOT_CONFIGURATION_FLAG = 5, +}; + +extern enum bootloader_reason bootloader_reason; + +/// Legacy Toboot V1 configuration values +#ifndef TOBOOT_V1_CFG_FLAGS +#define TOBOOT_V1_CFG_FLAGS 0 +#endif +#define TOBOOT_V1_CFG_MAGIC_MASK 0xffff +#define TOBOOT_V1_CFG_MAGIC 0x70b0 + +#ifndef TOBOOT_V1_APP_FLAGS +#define TOBOOT_V1_APP_FLAGS 0 +#endif + +#define TOBOOT_V1_APP_MAGIC_MASK 0xffff +#define TOBOOT_V1_APP_MAGIC 0x6fb0 +#define TOBOOT_V1_APP_PAGE_MASK 0x00ff0000 +#define TOBOOT_V1_APP_PAGE_SHIFT 16 + +uint32_t tb_first_free_address(void); +uint32_t tb_first_free_sector(void); +const struct toboot_configuration *tb_get_config(void); +uint32_t tb_config_hash(const struct toboot_configuration *cfg); +void tb_sign_config(struct toboot_configuration *cfg); +uint32_t tb_generation(const struct toboot_configuration *cfg); +int tb_valid_signature_at_page(uint32_t page); + +#endif /* TOBOOT_INTERNAL_H_ */ \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/usb-desc.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/usb-desc.h new file mode 100644 index 0000000..6ad6771 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/usb-desc.h @@ -0,0 +1,91 @@ +/* Teensyduino Core Library + * http://www.pjrc.com/teensy/ + * Copyright (c) 2013 PJRC.COM, LLC. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * 1. The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * 2. If the Software is incorporated into a build system that allows + * selection among a list of target devices, then similar target + * devices manufactured by PJRC.COM must be included in the list of + * target devices and selectable in the same manner. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _usb_desc_h_ +#define _usb_desc_h_ + +#include +#include +#include + +struct usb_setup_request { + union { + struct { + uint8_t bmRequestType; + uint8_t bRequest; + }; + uint16_t wRequestAndType; + }; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +}; + +struct usb_string_descriptor_struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wString[]; +}; + +#define NUM_USB_BUFFERS 8 +#define VENDOR_ID 0x1209 // pid.codes +#define PRODUCT_ID 0x5bf0 // Assigned to Fomu project +#define DEVICE_VER 0x0101 // Bootloader version +#define MANUFACTURER_NAME u"Foosn" +#define MANUFACTURER_NAME_LEN sizeof(MANUFACTURER_NAME) +#define PRODUCT_NAME u"Fomu App " GIT_VERSION +#define PRODUCT_NAME_LEN sizeof(PRODUCT_NAME) + +// Microsoft Compatible ID Feature Descriptor +#define MSFT_VENDOR_CODE '~' // Arbitrary, but should be printable ASCII +#define MSFT_WCID_LEN 40 +extern const uint8_t usb_microsoft_wcid[MSFT_WCID_LEN]; + +typedef struct { + uint16_t wValue; + uint16_t length; + const uint8_t *addr; +} usb_descriptor_list_t; + +extern const usb_descriptor_list_t usb_descriptor_list[]; + +// WebUSB Landing page URL descriptor +#define WEBUSB_VENDOR_CODE 2 + +#ifndef LANDING_PAGE_URL +#define LANDING_PAGE_URL "dfu.tomu.im" +#endif + +#define LANDING_PAGE_DESCRIPTOR_SIZE (WEBUSB_DT_URL_DESCRIPTOR_SIZE \ + + sizeof(LANDING_PAGE_URL) - 1) + +extern const struct webusb_url_descriptor landing_url_descriptor; + +#endif diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/usb.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/usb.h new file mode 100644 index 0000000..60d57e4 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/usb.h @@ -0,0 +1,40 @@ +#ifndef __USB_H +#define __USB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct usb_setup_request; + +void usb_isr(void); +void usb_init(void); +void usb_connect(void); +void usb_disconnect(void); + +int usb_irq_happened(void); +void usb_setup(const struct usb_setup_request *setup); +int usb_send(const void *data, int total_count); +void usb_ack_in(void); +void usb_ack_out(void); +void usb_err_in(void); +void usb_err_out(void); +int usb_recv(void *buffer, unsigned int buffer_len); +void usb_poll(void); +int usb_wait_for_send_done(void); +void usb_recv_done(void); +void usb_set_address(uint8_t new_address); + +void usb_putc(char c); +int usb_getc(void); +int usb_write(const char *buf, int count); +int usb_can_getc(void); +int usb_can_putc(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/usbcdc.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/usbcdc.h new file mode 100644 index 0000000..20b7836 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/usbcdc.h @@ -0,0 +1,162 @@ +/** @defgroup usb_cdc_defines USB CDC Type Definitions + +@brief Defined Constants and Types for the USB CDC Type Definitions + +@ingroup USB_defines + +@version 1.0.0 + +@author @htmlonly © @endhtmlonly 2010 +Gareth McMullin + +@date 10 March 2013 + +LGPL License Terms @ref lgpl_license +*/ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Gareth McMullin + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/**@{*/ + +#ifndef __CDC_H +#define __CDC_H + +/* Definitions of Communications Device Class from + * "Universal Serial Bus Class Definitions for Communications Devices + * Revision 1.2" + */ + +/* Table 2: Communications Device Class Code */ +#define USB_CLASS_CDC 0x02 + +/* Table 4: Class Subclass Code */ +#define USB_CDC_SUBCLASS_DLCM 0x01 +#define USB_CDC_SUBCLASS_ACM 0x02 +/* ... */ + +/* Table 5 Communications Interface Class Control Protocol Codes */ +#define USB_CDC_PROTOCOL_NONE 0x00 +#define USB_CDC_PROTOCOL_AT 0x01 +/* ... */ + +/* Table 6: Data Interface Class Code */ +#define USB_CLASS_DATA 0x0A + +/* Table 12: Type Values for the bDescriptorType Field */ +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +/* Table 13: bDescriptor SubType in Communications Class Functional + * Descriptors */ +#define USB_CDC_TYPE_HEADER 0x00 +#define USB_CDC_TYPE_CALL_MANAGEMENT 0x01 +#define USB_CDC_TYPE_ACM 0x02 +/* ... */ +#define USB_CDC_TYPE_UNION 0x06 +/* ... */ + +/* Table 15: Class-Specific Descriptor Header Format */ +struct usb_cdc_header_descriptor { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint16_t bcdCDC; +} __attribute__((packed)); + +/* Table 16: Union Interface Functional Descriptor */ +struct usb_cdc_union_descriptor { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bControlInterface; + uint8_t bSubordinateInterface0; + /* ... */ +} __attribute__((packed)); + + +/* Definitions for Abstract Control Model devices from: + * "Universal Serial Bus Communications Class Subclass Specification for + * PSTN Devices" + */ + +/* Table 3: Call Management Functional Descriptor */ +struct usb_cdc_call_management_descriptor { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; + uint8_t bDataInterface; +} __attribute__((packed)); + +/* Table 4: Abstract Control Management Functional Descriptor */ +struct usb_cdc_acm_descriptor { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; +} __attribute__((packed)); + +/* Table 13: Class-Specific Request Codes for PSTN subclasses */ +/* ... */ +#define USB_CDC_REQ_SET_LINE_CODING 0x20 +/* ... */ +#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 +/* ... */ + +/* Table 17: Line Coding Structure */ +struct usb_cdc_line_coding { + uint32_t dwDTERate; + uint8_t bCharFormat; + uint8_t bParityType; + uint8_t bDataBits; +} __attribute__((packed)); + +enum usb_cdc_line_coding_bCharFormat { + USB_CDC_1_STOP_BITS = 0, + USB_CDC_1_5_STOP_BITS = 1, + USB_CDC_2_STOP_BITS = 2, +}; + +enum usb_cdc_line_coding_bParityType { + USB_CDC_NO_PARITY = 0, + USB_CDC_ODD_PARITY = 1, + USB_CDC_EVEN_PARITY = 2, + USB_CDC_MARK_PARITY = 3, + USB_CDC_SPACE_PARITY = 4, +}; + +/* Table 30: Class-Specific Notification Codes for PSTN subclasses */ +/* ... */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20 +/* ... */ + +/* Notification Structure */ +struct usb_cdc_notification { + uint8_t bmRequestType; + uint8_t bNotification; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} __attribute__((packed)); + +#endif + +/**@}*/ + diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/usbstd.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/usbstd.h new file mode 100644 index 0000000..3c61700 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/usbstd.h @@ -0,0 +1,277 @@ +/** @defgroup usb_type_defines USB Standard Structure Definitions + +@brief Defined Constants and Types for the USB Standard Structure +Definitions + +@ingroup USB_defines + +@version 1.0.0 + +@author @htmlonly © @endhtmlonly 2010 +Gareth McMullin + +@date 10 March 2013 + +A set of structure definitions for the USB control structures +defined in chapter 9 of the "Universal Serial Bus Specification Revision 2.0" +Available from the USB Implementers Forum - http://www.usb.org/ + +LGPL License Terms @ref lgpl_license +*/ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Gareth McMullin + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/**@{*/ + +#ifndef __USBSTD_H +#define __USBSTD_H + +#include + +/* + * This file contains structure definitions for the USB control structures + * defined in chapter 9 of the "Universal Serial Bus Specification Revision 2.0" + * Available from the USB Implementers Forum - http://www.usb.org/ + */ + +/* USB Setup Data structure - Table 9-2 */ +struct usb_setup_data { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} __attribute__((packed)); + +/* Class Definition */ +#define USB_CLASS_VENDOR 0xFF + +/* bmRequestType bit definitions */ +/* bit 7 : direction */ +#define USB_REQ_TYPE_DIRECTION 0x80 +#define USB_REQ_TYPE_IN 0x80 +/* bits 6..5 : type */ +#define USB_REQ_TYPE_TYPE 0x60 +#define USB_REQ_TYPE_STANDARD 0x00 +#define USB_REQ_TYPE_CLASS 0x20 +#define USB_REQ_TYPE_VENDOR 0x40 +/* bits 4..0 : recipient */ +#define USB_REQ_TYPE_RECIPIENT 0x1F +#define USB_REQ_TYPE_DEVICE 0x00 +#define USB_REQ_TYPE_INTERFACE 0x01 +#define USB_REQ_TYPE_ENDPOINT 0x02 +#define USB_REQ_TYPE_OTHER 0x03 + +/* USB Standard Request Codes - Table 9-4 */ +#define USB_REQ_GET_STATUS 0 +#define USB_REQ_CLEAR_FEATURE 1 +/* Reserved for future use: 2 */ +#define USB_REQ_SET_FEATURE 3 +/* Reserved for future use: 3 */ +#define USB_REQ_SET_ADDRESS 5 +#define USB_REQ_GET_DESCRIPTOR 6 +#define USB_REQ_SET_DESCRIPTOR 7 +#define USB_REQ_GET_CONFIGURATION 8 +#define USB_REQ_SET_CONFIGURATION 9 +#define USB_REQ_GET_INTERFACE 10 +#define USB_REQ_SET_INTERFACE 11 +#define USB_REQ_SET_SYNCH_FRAME 12 + +/* USB Descriptor Types - Table 9-5 */ +#define USB_DT_DEVICE 1 +#define USB_DT_CONFIGURATION 2 +#define USB_DT_STRING 3 +#define USB_DT_INTERFACE 4 +#define USB_DT_ENDPOINT 5 +#define USB_DT_DEVICE_QUALIFIER 6 +#define USB_DT_OTHER_SPEED_CONFIGURATION 7 +#define USB_DT_INTERFACE_POWER 8 +/* From ECNs */ +#define USB_DT_OTG 9 +#define USB_DT_DEBUG 10 +#define USB_DT_INTERFACE_ASSOCIATION 11 + +/* USB Standard Feature Selectors - Table 9-6 */ +#define USB_FEAT_ENDPOINT_HALT 0 +#define USB_FEAT_DEVICE_REMOTE_WAKEUP 1 +#define USB_FEAT_TEST_MODE 2 + +/* Information Returned by a GetStatus() Request to a Device - Figure 9-4 */ +#define USB_DEV_STATUS_SELF_POWERED 0x01 +#define USB_DEV_STATUS_REMOTE_WAKEUP 0x02 + +/* USB Standard Device Descriptor - Table 9-8 */ +struct usb_device_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} __attribute__((packed)); + +#define USB_DT_DEVICE_SIZE sizeof(struct usb_device_descriptor) + +/* USB Device_Qualifier Descriptor - Table 9-9 + * Not used in this implementation. + */ +struct usb_device_qualifier_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint8_t bNumConfigurations; + uint8_t bReserved; +} __attribute__((packed)); + +/* This is only defined as a top level named struct to improve c++ + * compatibility. You should never need to instance this struct + * in user code! */ +struct usb_interface { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; +}; + +/* USB Standard Configuration Descriptor - Table 9-10 */ +struct usb_config_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; + + /* Descriptor ends here. The following are used internally: */ + const struct usb_interface interface[0]; +} __attribute__((packed)); +#define USB_DT_CONFIGURATION_SIZE 9 + +/* USB Configuration Descriptor bmAttributes bit definitions */ +#define USB_CONFIG_ATTR_DEFAULT 0x80 /** always required (USB2.0 table 9-10) */ +#define USB_CONFIG_ATTR_SELF_POWERED 0x40 +#define USB_CONFIG_ATTR_REMOTE_WAKEUP 0x20 + +/* Other Speed Configuration is the same as Configuration Descriptor. + * - Table 9-11 + */ + +/* USB Standard Interface Descriptor - Table 9-12 */ +struct usb_interface_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; + + /* Descriptor ends here. The following are used internally: */ + const struct usb_endpoint_descriptor *endpoint; + const void *extra; + int extralen; +} __attribute__((packed)); +#define USB_DT_INTERFACE_SIZE 9 + +/* USB Standard Endpoint Descriptor - Table 9-13 */ +struct usb_endpoint_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; + + /* Descriptor ends here. The following are used internally: */ + const void *extra; + int extralen; +} __attribute__((packed)); +#define USB_DT_ENDPOINT_SIZE 7 + +/* USB bEndpointAddress helper macros */ +#define USB_ENDPOINT_ADDR_OUT(x) (x) +#define USB_ENDPOINT_ADDR_IN(x) (0x80 | (x)) + +/* USB Endpoint Descriptor bmAttributes bit definitions - Table 9-13 */ +/* bits 1..0 : transfer type */ +#define USB_ENDPOINT_ATTR_CONTROL 0x00 +#define USB_ENDPOINT_ATTR_ISOCHRONOUS 0x01 +#define USB_ENDPOINT_ATTR_BULK 0x02 +#define USB_ENDPOINT_ATTR_INTERRUPT 0x03 +#define USB_ENDPOINT_ATTR_TYPE 0x03 +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_ENDPOINT_ATTR_NOSYNC 0x00 +#define USB_ENDPOINT_ATTR_ASYNC 0x04 +#define USB_ENDPOINT_ATTR_ADAPTIVE 0x08 +#define USB_ENDPOINT_ATTR_SYNC 0x0C +#define USB_ENDPOINT_ATTR_SYNCTYPE 0x0C +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_ENDPOINT_ATTR_DATA 0x00 +#define USB_ENDPOINT_ATTR_FEEDBACK 0x10 +#define USB_ENDPOINT_ATTR_IMPLICIT_FEEDBACK_DATA 0x20 +#define USB_ENDPOINT_ATTR_USAGETYPE 0x30 + +/* Table 9-15 specifies String Descriptor Zero. + * Table 9-16 specified UNICODE String Descriptor. + */ +struct usb_string_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wData[]; +} __attribute__((packed)); + +/* From ECN: Interface Association Descriptors, Table 9-Z */ +struct usb_iface_assoc_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bFirstInterface; + uint8_t bInterfaceCount; + uint8_t bFunctionClass; + uint8_t bFunctionSubClass; + uint8_t bFunctionProtocol; + uint8_t iFunction; +} __attribute__((packed)); +#define USB_DT_INTERFACE_ASSOCIATION_SIZE \ + sizeof(struct usb_iface_assoc_descriptor) + +enum usb_language_id { + USB_LANGID_ENGLISH_US = 0x409, +}; +#endif + +/**@}*/ + diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/webusb-defs.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/webusb-defs.h new file mode 100644 index 0000000..fd699e9 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/webusb-defs.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, Devan Lai + * + * Permission to use, copy, modify, and/or distribute this software + * for any purpose with or without fee is hereby granted, provided + * that the above copyright notice and this permission notice + * appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef WEBUSB_DEFS_H_INCLUDED +#define WEBUSB_DEFS_H_INCLUDED + +#include + +#define WEBUSB_REQ_GET_URL 0x02 + +#define WEBUSB_DT_URL 3 + +#define WEBUSB_URL_SCHEME_HTTP 0 +#define WEBUSB_URL_SCHEME_HTTPS 1 + +struct webusb_platform_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint8_t bReserved; + uint8_t platformCapabilityUUID[16]; + uint16_t bcdVersion; + uint8_t bVendorCode; + uint8_t iLandingPage; +} __attribute__((packed)); + +#define WEBUSB_PLATFORM_DESCRIPTOR_SIZE sizeof(struct webusb_platform_descriptor) + +#define WEBUSB_UUID {0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65} + +struct webusb_url_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bScheme; + char URL[]; +} __attribute__((packed)); + +#define WEBUSB_DT_URL_DESCRIPTOR_SIZE 3 + +#endif diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/xxhash.c b/wasm3-sys/wasm3/platforms/embedded/fomu/include/xxhash.c new file mode 100644 index 0000000..6f85fc4 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/xxhash.c @@ -0,0 +1,912 @@ +/* +* xxHash - Fast Hash algorithm +* Copyright (C) 2012-2016, Yann Collet +* +* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* You can contact the author at : +* - xxHash homepage: http://www.xxhash.com +* - xxHash source repository : https://github.com/Cyan4973/xxHash +*/ + + +/* ************************************* +* Tuning parameters +***************************************/ +/*!XXH_FORCE_MEMORY_ACCESS : + * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. + * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. + * The below switch allow to select different access method for improved performance. + * Method 0 (default) : use `memcpy()`. Safe and portable. + * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). + * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. + * Method 2 : direct access. This method doesn't depend on compiler but violate C standard. + * It can generate buggy code on targets which do not support unaligned memory accesses. + * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) + * See http://stackoverflow.com/a/32095106/646947 for details. + * Prefer these methods in priority order (0 > 1 > 2) + */ +#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ +# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) +# define XXH_FORCE_MEMORY_ACCESS 2 +# elif defined(__INTEL_COMPILER) || \ + (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7S__) )) +# define XXH_FORCE_MEMORY_ACCESS 1 +# endif +#endif + +/*!XXH_ACCEPT_NULL_INPUT_POINTER : + * If input pointer is NULL, xxHash default behavior is to dereference it, triggering a segfault. + * When this macro is enabled, xxHash actively checks input for null pointer. + * It it is, result for null input pointers is the same as a null-length input. + */ +#ifndef XXH_ACCEPT_NULL_INPUT_POINTER /* can be defined externally */ +# define XXH_ACCEPT_NULL_INPUT_POINTER 0 +#endif + +/*!XXH_FORCE_NATIVE_FORMAT : + * By default, xxHash library provides endian-independent Hash values, based on little-endian convention. + * Results are therefore identical for little-endian and big-endian CPU. + * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. + * Should endian-independence be of no importance for your application, you may set the #define below to 1, + * to improve speed for Big-endian CPU. + * This option has no impact on Little_Endian CPU. + */ +#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */ +# define XXH_FORCE_NATIVE_FORMAT 0 +#endif + +/*!XXH_FORCE_ALIGN_CHECK : + * This is a minor performance trick, only useful with lots of very small keys. + * It means : check for aligned/unaligned input. + * The check costs one initial branch per hash; + * set it to 0 when the input is guaranteed to be aligned, + * or when alignment doesn't matter for performance. + */ +#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ +# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) +# define XXH_FORCE_ALIGN_CHECK 0 +# else +# define XXH_FORCE_ALIGN_CHECK 1 +# endif +#endif + + +/* ************************************* +* Includes & Memory related functions +***************************************/ +/*! Modify the local functions below should you wish to use some other memory routines +* for malloc(), free() */ +#include +static void* XXH_malloc(size_t s) { return malloc(s); } +static void XXH_free (void* p) { free(p); } +/*! and for memcpy() */ +#include +static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } + +#define XXH_STATIC_LINKING_ONLY +#include "xxhash.h" + + +/* ************************************* +* Compiler Specific Options +***************************************/ +#ifdef _MSC_VER /* Visual Studio */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +# define FORCE_INLINE static __forceinline +#else +# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# ifdef __GNUC__ +# define FORCE_INLINE static inline __attribute__((always_inline)) +# else +# define FORCE_INLINE static inline +# endif +# else +# define FORCE_INLINE static +# endif /* __STDC_VERSION__ */ +#endif + + +/* ************************************* +* Basic Types +***************************************/ +#ifndef MEM_MODULE +# if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; +# else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; +# endif +#endif + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ +static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; } + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +typedef union { U32 u32; } __attribute__((packed)) unalign; +static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } + +#else + +/* portable and safe solution. Generally efficient. + * see : http://stackoverflow.com/a/32095106/646947 + */ +static U32 XXH_read32(const void* memPtr) +{ + U32 val; + memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + + +/* **************************************** +* Compiler-specific Functions and Macros +******************************************/ +#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ +#if defined(_MSC_VER) +# define XXH_rotl32(x,r) _rotl(x,r) +# define XXH_rotl64(x,r) _rotl64(x,r) +#else +# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) +# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r))) +#endif + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap32 _byteswap_ulong +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap32 __builtin_bswap32 +#else +static U32 XXH_swap32 (U32 x) +{ + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} +#endif + + +/* ************************************* +* Architecture Macros +***************************************/ +typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; + +/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */ +#ifndef XXH_CPU_LITTLE_ENDIAN + static const int g_one = 1; +# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&g_one)) +#endif + + +/* *************************** +* Memory reads +*****************************/ +typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; + +FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align) +{ + if (align==XXH_unaligned) + return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); + else + return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr); +} + +FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian) +{ + return XXH_readLE32_align(ptr, endian, XXH_unaligned); +} + +static U32 XXH_readBE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); +} + + +/* ************************************* +* Macros +***************************************/ +#define XXH_STATIC_ASSERT(c) { enum { XXH_sa = 1/(int)(!!(c)) }; } /* use after variable declarations */ +XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } + + +/* ******************************************************************* +* 32-bit hash functions +*********************************************************************/ +static const U32 PRIME32_1 = 2654435761U; +static const U32 PRIME32_2 = 2246822519U; +static const U32 PRIME32_3 = 3266489917U; +static const U32 PRIME32_4 = 668265263U; +static const U32 PRIME32_5 = 374761393U; + +static U32 XXH32_round(U32 seed, U32 input) +{ + seed += input * PRIME32_2; + seed = XXH_rotl32(seed, 13); + seed *= PRIME32_1; + return seed; +} + +FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* bEnd = p + len; + U32 h32; +#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align) + +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + if (p==NULL) { + len=0; + bEnd=p=(const BYTE*)(size_t)16; + } +#endif + + if (len>=16) { + const BYTE* const limit = bEnd - 16; + U32 v1 = seed + PRIME32_1 + PRIME32_2; + U32 v2 = seed + PRIME32_2; + U32 v3 = seed + 0; + U32 v4 = seed - PRIME32_1; + + do { + v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4; + v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4; + v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4; + v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4; + } while (p<=limit); + + h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); + } else { + h32 = seed + PRIME32_5; + } + + h32 += (U32) len; + + while (p+4<=bEnd) { + h32 += XXH_get32bits(p) * PRIME32_3; + h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; + p+=4; + } + + while (p> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} + + +XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed) +{ +#if 0 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH32_state_t state; + XXH32_reset(&state, seed); + XXH32_update(&state, input, len); + return XXH32_digest(&state); +#else + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); + } } + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); +#endif +} + + + +/*====== Hash streaming ======*/ + +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) +{ + return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); +} +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) +{ + memcpy(dstState, srcState, sizeof(*dstState)); +} + +XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed) +{ + XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ + memset(&state, 0, sizeof(state)); + state.v1 = seed + PRIME32_1 + PRIME32_2; + state.v2 = seed + PRIME32_2; + state.v3 = seed + 0; + state.v4 = seed - PRIME32_1; + /* do not write into reserved, planned to be removed in a future version */ + memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); + return XXH_OK; +} + + +FORCE_INLINE +XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + + if (input==NULL) +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + return XXH_OK; +#else + return XXH_ERROR; +#endif + + state->total_len_32 += (unsigned)len; + state->large_len |= (len>=16) | (state->total_len_32>=16); + + if (state->memsize + len < 16) { /* fill in tmp buffer */ + XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len); + state->memsize += (unsigned)len; + return XXH_OK; + } + + if (state->memsize) { /* some data left from previous update */ + XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize); + { const unsigned* p32 = state->mem32; + state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++; + state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++; + state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++; + state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); + } + p += 16-state->memsize; + state->memsize = 0; + } + + if (p <= bEnd-16) { + const BYTE* const limit = bEnd - 16; + U32 v1 = state->v1; + U32 v2 = state->v2; + U32 v3 = state->v3; + U32 v4 = state->v4; + + do { + v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4; + v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4; + v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4; + v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) { + XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + + return XXH_OK; +} + +XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_update_endian(state_in, input, len, XXH_littleEndian); + else + return XXH32_update_endian(state_in, input, len, XXH_bigEndian); +} + + + +FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian) +{ + const BYTE * p = (const BYTE*)state->mem32; + const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize; + U32 h32; + + if (state->large_len) { + h32 = XXH_rotl32(state->v1, 1) + + XXH_rotl32(state->v2, 7) + + XXH_rotl32(state->v3, 12) + + XXH_rotl32(state->v4, 18); + } else { + h32 = state->v3 /* == seed */ + PRIME32_5; + } + + h32 += state->total_len_32; + + while (p+4<=bEnd) { + h32 += XXH_readLE32(p, endian) * PRIME32_3; + h32 = XXH_rotl32(h32, 17) * PRIME32_4; + p+=4; + } + + while (p> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} + + +XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_digest_endian(state_in, XXH_littleEndian); + else + return XXH32_digest_endian(state_in, XXH_bigEndian); +} + + +/*====== Canonical representation ======*/ + +/*! Default XXH result types are basic unsigned 32 and 64 bits. +* The canonical representation follows human-readable write convention, aka big-endian (large digits first). +* These functions allow transformation of hash result into and from its canonical format. +* This way, hash values can be written into a file or buffer, remaining comparable across different systems. +*/ + +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); + memcpy(dst, &hash, sizeof(*dst)); +} + +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) +{ + return XXH_readBE32(src); +} + + +#ifndef XXH_NO_LONG_LONG + +/* ******************************************************************* +* 64-bit hash functions +*********************************************************************/ + +/*====== Memory access ======*/ + +#ifndef MEM_MODULE +# define MEM_MODULE +# if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include + typedef uint64_t U64; +# else + /* if compiler doesn't support unsigned long long, replace by another 64-bit type */ + typedef unsigned long long U64; +# endif +#endif + + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ +static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; } + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign64; +static U64 XXH_read64(const void* ptr) { return ((const unalign64*)ptr)->u64; } + +#else + +/* portable and safe solution. Generally efficient. + * see : http://stackoverflow.com/a/32095106/646947 + */ + +static U64 XXH_read64(const void* memPtr) +{ + U64 val; + memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap64 _byteswap_uint64 +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap64 __builtin_bswap64 +#else +static U64 XXH_swap64 (U64 x) +{ + return ((x << 56) & 0xff00000000000000ULL) | + ((x << 40) & 0x00ff000000000000ULL) | + ((x << 24) & 0x0000ff0000000000ULL) | + ((x << 8) & 0x000000ff00000000ULL) | + ((x >> 8) & 0x00000000ff000000ULL) | + ((x >> 24) & 0x0000000000ff0000ULL) | + ((x >> 40) & 0x000000000000ff00ULL) | + ((x >> 56) & 0x00000000000000ffULL); +} +#endif + +FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align) +{ + if (align==XXH_unaligned) + return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); + else + return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr); +} + +FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian) +{ + return XXH_readLE64_align(ptr, endian, XXH_unaligned); +} + +static U64 XXH_readBE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); +} + + +/*====== xxh64 ======*/ + +static const U64 PRIME64_1 = 11400714785074694791ULL; +static const U64 PRIME64_2 = 14029467366897019727ULL; +static const U64 PRIME64_3 = 1609587929392839161ULL; +static const U64 PRIME64_4 = 9650029242287828579ULL; +static const U64 PRIME64_5 = 2870177450012600261ULL; + +static U64 XXH64_round(U64 acc, U64 input) +{ + acc += input * PRIME64_2; + acc = XXH_rotl64(acc, 31); + acc *= PRIME64_1; + return acc; +} + +static U64 XXH64_mergeRound(U64 acc, U64 val) +{ + val = XXH64_round(0, val); + acc ^= val; + acc = acc * PRIME64_1 + PRIME64_4; + return acc; +} + +FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* bEnd = p + len; + U64 h64; +#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align) + +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + if (p==NULL) { + len=0; + bEnd=p=(const BYTE*)(size_t)32; + } +#endif + + if (len>=32) { + const BYTE* const limit = bEnd - 32; + U64 v1 = seed + PRIME64_1 + PRIME64_2; + U64 v2 = seed + PRIME64_2; + U64 v3 = seed + 0; + U64 v4 = seed - PRIME64_1; + + do { + v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8; + v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8; + v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8; + v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8; + } while (p<=limit); + + h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); + h64 = XXH64_mergeRound(h64, v1); + h64 = XXH64_mergeRound(h64, v2); + h64 = XXH64_mergeRound(h64, v3); + h64 = XXH64_mergeRound(h64, v4); + + } else { + h64 = seed + PRIME64_5; + } + + h64 += (U64) len; + + while (p+8<=bEnd) { + U64 const k1 = XXH64_round(0, XXH_get64bits(p)); + h64 ^= k1; + h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; + p+=8; + } + + if (p+4<=bEnd) { + h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; + h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; + p+=4; + } + + while (p> 33; + h64 *= PRIME64_2; + h64 ^= h64 >> 29; + h64 *= PRIME64_3; + h64 ^= h64 >> 32; + + return h64; +} + + +XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed) +{ +#if 0 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH64_state_t state; + XXH64_reset(&state, seed); + XXH64_update(&state, input, len); + return XXH64_digest(&state); +#else + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); + else + return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); + } } + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); + else + return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); +#endif +} + +/*====== Hash Streaming ======*/ + +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) +{ + return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); +} +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState) +{ + memcpy(dstState, srcState, sizeof(*dstState)); +} + +XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed) +{ + XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ + memset(&state, 0, sizeof(state)); + state.v1 = seed + PRIME64_1 + PRIME64_2; + state.v2 = seed + PRIME64_2; + state.v3 = seed + 0; + state.v4 = seed - PRIME64_1; + /* do not write into reserved, planned to be removed in a future version */ + memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); + return XXH_OK; +} + +FORCE_INLINE +XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + + if (input==NULL) +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + return XXH_OK; +#else + return XXH_ERROR; +#endif + + state->total_len += len; + + if (state->memsize + len < 32) { /* fill in tmp buffer */ + XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len); + state->memsize += (U32)len; + return XXH_OK; + } + + if (state->memsize) { /* tmp buffer is full */ + XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize); + state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian)); + state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian)); + state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian)); + state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian)); + p += 32-state->memsize; + state->memsize = 0; + } + + if (p+32 <= bEnd) { + const BYTE* const limit = bEnd - 32; + U64 v1 = state->v1; + U64 v2 = state->v2; + U64 v3 = state->v3; + U64 v4 = state->v4; + + do { + v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8; + v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8; + v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8; + v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) { + XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + + return XXH_OK; +} + +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_update_endian(state_in, input, len, XXH_littleEndian); + else + return XXH64_update_endian(state_in, input, len, XXH_bigEndian); +} + +FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian) +{ + const BYTE * p = (const BYTE*)state->mem64; + const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize; + U64 h64; + + if (state->total_len >= 32) { + U64 const v1 = state->v1; + U64 const v2 = state->v2; + U64 const v3 = state->v3; + U64 const v4 = state->v4; + + h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); + h64 = XXH64_mergeRound(h64, v1); + h64 = XXH64_mergeRound(h64, v2); + h64 = XXH64_mergeRound(h64, v3); + h64 = XXH64_mergeRound(h64, v4); + } else { + h64 = state->v3 + PRIME64_5; + } + + h64 += (U64) state->total_len; + + while (p+8<=bEnd) { + U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian)); + h64 ^= k1; + h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; + p+=8; + } + + if (p+4<=bEnd) { + h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1; + h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; + p+=4; + } + + while (p> 33; + h64 *= PRIME64_2; + h64 ^= h64 >> 29; + h64 *= PRIME64_3; + h64 ^= h64 >> 32; + + return h64; +} + +XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_digest_endian(state_in, XXH_littleEndian); + else + return XXH64_digest_endian(state_in, XXH_bigEndian); +} + + +/*====== Canonical representation ======*/ + +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); + memcpy(dst, &hash, sizeof(*dst)); +} + +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src) +{ + return XXH_readBE64(src); +} + +#endif /* XXH_NO_LONG_LONG */ diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/include/xxhash.h b/wasm3-sys/wasm3/platforms/embedded/fomu/include/xxhash.h new file mode 100644 index 0000000..4099da0 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/include/xxhash.h @@ -0,0 +1,294 @@ +/* + xxHash - Extremely Fast Hash algorithm + Header File + Copyright (C) 2012-2016, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - xxHash source repository : https://github.com/Cyan4973/xxHash +*/ + +/* Notice extracted from xxHash homepage : + +xxHash is an extremely fast Hash algorithm, running at RAM speed limits. +It also successfully passes all tests from the SMHasher suite. + +Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) + +Name Speed Q.Score Author +xxHash 5.4 GB/s 10 +CrapWow 3.2 GB/s 2 Andrew +MumurHash 3a 2.7 GB/s 10 Austin Appleby +SpookyHash 2.0 GB/s 10 Bob Jenkins +SBox 1.4 GB/s 9 Bret Mulvey +Lookup3 1.2 GB/s 9 Bob Jenkins +SuperFastHash 1.2 GB/s 1 Paul Hsieh +CityHash64 1.05 GB/s 10 Pike & Alakuijala +FNV 0.55 GB/s 5 Fowler, Noll, Vo +CRC32 0.43 GB/s 9 +MD5-32 0.33 GB/s 10 Ronald L. Rivest +SHA1-32 0.28 GB/s 10 + +Q.Score is a measure of quality of the hash function. +It depends on successfully passing SMHasher test set. +10 is a perfect score. + +A 64-bit version, named XXH64, is available since r35. +It offers much better speed, but for 64-bit applications only. +Name Speed on 64 bits Speed on 32 bits +XXH64 13.8 GB/s 1.9 GB/s +XXH32 6.8 GB/s 6.0 GB/s +*/ + +#ifndef XXHASH_H_5627135585666179 +#define XXHASH_H_5627135585666179 1 + +#if defined (__cplusplus) +extern "C" { +#endif + + +/* **************************** +* Definitions +******************************/ +#include /* size_t */ +typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; + + +/* **************************** +* API modifier +******************************/ +/** XXH_PRIVATE_API +* This is useful to include xxhash functions in `static` mode +* in order to inline them, and remove their symbol from the public list. +* Methodology : +* #define XXH_PRIVATE_API +* #include "xxhash.h" +* `xxhash.c` is automatically included. +* It's not useful to compile and link it as a separate module. +*/ +#ifdef XXH_PRIVATE_API +# ifndef XXH_STATIC_LINKING_ONLY +# define XXH_STATIC_LINKING_ONLY +# endif +# if defined(__GNUC__) +# define XXH_PUBLIC_API static __inline __attribute__((unused)) +# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define XXH_PUBLIC_API static inline +# elif defined(_MSC_VER) +# define XXH_PUBLIC_API static __inline +# else + /* this version may generate warnings for unused static functions */ +# define XXH_PUBLIC_API static +# endif +#else +# define XXH_PUBLIC_API /* do nothing */ +#endif /* XXH_PRIVATE_API */ + +/*!XXH_NAMESPACE, aka Namespace Emulation : + +If you want to include _and expose_ xxHash functions from within your own library, +but also want to avoid symbol collisions with other libraries which may also include xxHash, + +you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library +with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values). + +Note that no change is required within the calling program as long as it includes `xxhash.h` : +regular symbol name will be automatically translated by this header. +*/ +#ifdef XXH_NAMESPACE +# define XXH_CAT(A,B) A##B +# define XXH_NAME2(A,B) XXH_CAT(A,B) +# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) +# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) +# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) +# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) +# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) +# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) +# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) +# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) +# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) +# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) +# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) +# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) +# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) +# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) +# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) +# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) +# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) +# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) +# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) +#endif + + +/* ************************************* +* Version +***************************************/ +#define XXH_VERSION_MAJOR 0 +#define XXH_VERSION_MINOR 6 +#define XXH_VERSION_RELEASE 4 +#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) +XXH_PUBLIC_API unsigned XXH_versionNumber (void); + + +/*-********************************************************************** +* 32-bit hash +************************************************************************/ +typedef unsigned int XXH32_hash_t; + +/*! XXH32() : + Calculate the 32-bit hash of sequence "length" bytes stored at memory address "input". + The memory between input & input+length must be valid (allocated and read-accessible). + "seed" can be used to alter the result predictably. + Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */ +XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed); + +/*====== Streaming ======*/ +typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */ +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); + +XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed); +XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); +XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); + +/* +These functions generate the xxHash of an input provided in multiple segments. +Note that, for small input, they are slower than single-call functions, due to state management. +For small input, prefer `XXH32()` and `XXH64()` . + +XXH state must first be allocated, using XXH*_createState() . + +Start a new hash by initializing state with a seed, using XXH*_reset(). + +Then, feed the hash state by calling XXH*_update() as many times as necessary. +Obviously, input must be allocated and read accessible. +The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. + +Finally, a hash value can be produced anytime, by using XXH*_digest(). +This function returns the nn-bits hash as an int or long long. + +It's still possible to continue inserting input into the hash state after a digest, +and generate some new hashes later on, by calling again XXH*_digest(). + +When done, free XXH state space if it was allocated dynamically. +*/ + +/*====== Canonical representation ======*/ + +typedef struct { unsigned char digest[4]; } XXH32_canonical_t; +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); + +/* Default result type for XXH functions are primitive unsigned 32 and 64 bits. +* The canonical representation uses human-readable write convention, aka big-endian (large digits first). +* These functions allow transformation of hash result into and from its canonical format. +* This way, hash values can be written into a file / memory, and remain comparable on different systems and programs. +*/ + + +#ifndef XXH_NO_LONG_LONG +/*-********************************************************************** +* 64-bit hash +************************************************************************/ +typedef unsigned long long XXH64_hash_t; + +/*! XXH64() : + Calculate the 64-bit hash of sequence of length "len" stored at memory address "input". + "seed" can be used to alter the result predictably. + This function runs faster on 64-bit systems, but slower on 32-bit systems (see benchmark). +*/ +XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed); + +/*====== Streaming ======*/ +typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); +XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state); + +XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed); +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); +XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); + +/*====== Canonical representation ======*/ +typedef struct { unsigned char digest[8]; } XXH64_canonical_t; +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); +#endif /* XXH_NO_LONG_LONG */ + + +#ifdef XXH_STATIC_LINKING_ONLY + +/* ================================================================================================ + This section contains declarations which are not guaranteed to remain stable. + They may change in future versions, becoming incompatible with a different version of the library. + These declarations should only be used with static linking. + Never use them in association with dynamic linking ! +=================================================================================================== */ + +/* These definitions are only meant to make possible + static allocation of XXH state, on stack or in a struct for example. + Never use members directly. */ + +struct XXH32_state_s { + unsigned total_len_32; + unsigned large_len; + unsigned v1; + unsigned v2; + unsigned v3; + unsigned v4; + unsigned mem32[4]; /* buffer defined as U32 for alignment */ + unsigned memsize; + unsigned reserved; /* never read nor write, will be removed in a future version */ +}; /* typedef'd to XXH32_state_t */ + +#ifndef XXH_NO_LONG_LONG /* remove 64-bit support */ +struct XXH64_state_s { + unsigned long long total_len; + unsigned long long v1; + unsigned long long v2; + unsigned long long v3; + unsigned long long v4; + unsigned long long mem64[4]; /* buffer defined as U64 for alignment */ + unsigned memsize; + unsigned reserved[2]; /* never read nor write, will be removed in a future version */ +}; /* typedef'd to XXH64_state_t */ +#endif + +#ifdef XXH_PRIVATE_API +# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */ +#endif + +#endif /* XXH_STATIC_LINKING_ONLY */ + + +#if defined (__cplusplus) +} +#endif + +#endif /* XXHASH_H_5627135585666179 */ diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/ld/linker.ld b/wasm3-sys/wasm3/platforms/embedded/fomu/ld/linker.ld new file mode 100644 index 0000000..a0fa473 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/ld/linker.ld @@ -0,0 +1,56 @@ +INCLUDE output_format.ld +ENTRY(_start) + +__DYNAMIC = 0; + +INCLUDE regions.ld + +SECTIONS +{ + .text : + { + _ftext = .; + *(.text.start) + *(.text .stub .text.* .gnu.linkonce.t.*) + _etext = .; + } > rom + + .rodata : + { + . = ALIGN(4); + _frodata = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.srodata .srodata.*) + _erodata = .; + } > rom + + .data : AT (ADDR(.rodata) + SIZEOF (.rodata)) + { + . = ALIGN(4); + _fdata = .; + *(.data .data.* .gnu.linkonce.d.*) + *(.data1) + _gp = ALIGN(16); + *(.sdata .sdata.* .gnu.linkonce.s.* .sdata2 .sdata2.*) + *(.ramtext .ramtext.*) + _edata = ALIGN(16); /* Make sure _edata is >= _gp. */ + } > sram + + .bss : + { + . = ALIGN(4); + _fbss = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + _end = .; + } > sram +} + +PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram) - 4); diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/ld/output_format.ld b/wasm3-sys/wasm3/platforms/embedded/fomu/ld/output_format.ld new file mode 100644 index 0000000..5e76f5f --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/ld/output_format.ld @@ -0,0 +1 @@ +OUTPUT_FORMAT("elf32-littleriscv") diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/ld/regions.ld b/wasm3-sys/wasm3/platforms/embedded/fomu/ld/regions.ld new file mode 100644 index 0000000..72cb118 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/ld/regions.ld @@ -0,0 +1,4 @@ +MEMORY { + sram : ORIGIN = 0x10000000, LENGTH = 0x00020000 + rom : ORIGIN = 0x20040000, LENGTH = 0x100000 /* 1 MBit */ +} diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/src/crt0-vexriscv.S b/wasm3-sys/wasm3/platforms/embedded/fomu/src/crt0-vexriscv.S new file mode 100644 index 0000000..a02c3aa --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/src/crt0-vexriscv.S @@ -0,0 +1,83 @@ +.global main +.global isr + +.section .text.start +.global _start + +_start: + j crt_init + +.global trap_entry +.section .ramtext +trap_entry: + sw x1, - 1*4(sp) + sw x5, - 2*4(sp) + sw x6, - 3*4(sp) + sw x7, - 4*4(sp) + sw x10, - 5*4(sp) + sw x11, - 6*4(sp) + sw x12, - 7*4(sp) + sw x13, - 8*4(sp) + sw x14, - 9*4(sp) + sw x15, -10*4(sp) + sw x16, -11*4(sp) + sw x17, -12*4(sp) + sw x28, -13*4(sp) + sw x29, -14*4(sp) + sw x30, -15*4(sp) + sw x31, -16*4(sp) + addi sp,sp,-16*4 + call isr + lw x1 , 15*4(sp) + lw x5, 14*4(sp) + lw x6, 13*4(sp) + lw x7, 12*4(sp) + lw x10, 11*4(sp) + lw x11, 10*4(sp) + lw x12, 9*4(sp) + lw x13, 8*4(sp) + lw x14, 7*4(sp) + lw x15, 6*4(sp) + lw x16, 5*4(sp) + lw x17, 4*4(sp) + lw x28, 3*4(sp) + lw x29, 2*4(sp) + lw x30, 1*4(sp) + lw x31, 0*4(sp) + addi sp,sp,16*4 + mret + +.text +crt_init: + la sp, _fstack + 4 + la a0, trap_entry + csrw mtvec, a0 + +bss_init: + la a0, _fbss + la a1, _ebss +bss_loop: + beq a0,a1,bss_done + sw zero,0(a0) + add a0,a0,4 + j bss_loop +bss_done: + + /* Load DATA */ + la t0, _erodata + la t1, _fdata + la t2, _edata +3: + lw t3, 0(t0) + sw t3, 0(t1) + /* _edata is aligned to 16 bytes. Use word-xfers. */ + addi t0, t0, 4 + addi t1, t1, 4 + bltu t1, t2, 3b + + li a0, 0x880 //880 enable timer + external interrupt sources (until mstatus.MIE is set, they will never trigger an interrupt) + csrw mie,a0 + + call main +infinite_loop: + j infinite_loop diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/src/ltoa.c b/wasm3-sys/wasm3/platforms/embedded/fomu/src/ltoa.c new file mode 100644 index 0000000..f0bdcd6 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/src/ltoa.c @@ -0,0 +1,58 @@ +/* +** LTOA.C +** +** Converts a long integer to a string. +** +** Copyright 1988-90 by Robert B. Stout dba MicroFirm +** +** Released to public domain, 1991 +** +** Parameters: 1 - number to be converted +** 2 - buffer in which to build the converted string +** 3 - number base to use for conversion +** +** Returns: A character pointer to the converted string if +** successful, a NULL pointer if the number base specified +** is out of range. +*/ + +#include +#include + +#define BUFSIZE (sizeof(long) * 8 + 1) + +char *ltoa(long N, char *str, int base) +{ + register int i = 2; + long uarg; + char *tail, *head = str, buf[BUFSIZE]; + + if (36 < base || 2 > base) + base = 10; /* can only use 0-9, A-Z */ + tail = &buf[BUFSIZE - 1]; /* last character position */ + *tail-- = '\0'; + + if (10 == base && N < 0L) + { + *head++ = '-'; + uarg = -N; + } + else uarg = N; + + if (uarg) + { + for (i = 1; uarg; ++i) + { + register ldiv_t r; + + r = ldiv(uarg, base); + *tail-- = (char)(r.rem + ((9L < r.rem) ? + ('A' - 10L) : '0')); + uarg = r.quot; + } + } + else *tail-- = '0'; + + memcpy(head, ++tail, i); + return str; +} diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/src/main.c b/wasm3-sys/wasm3/platforms/embedded/fomu/src/main.c new file mode 100644 index 0000000..77cea3e --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/src/main.c @@ -0,0 +1,148 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ff_spi *spi; + +char *ltoa(long N, char *str, int base); + +void uart_write(const char *str, unsigned len) { + if (!usb_can_putc()) return; + + while (len) { + while (!usb_can_putc()) + usb_poll(); + int bytes_written = usb_write(str, len); + str += bytes_written; + len -= bytes_written; + } +} + +void uart_print(const char *str) { + uart_write(str, strlen(str)); +} + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(func, msg) { \ + uart_print("Fatal: " func ": "); \ + uart_print(msg); uart_print("\n"); \ + return false; } + +bool run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + size_t fsize = fib32_wasm_len; + + uart_print("Loading WebAssembly...\n"); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment", "failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime", "failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction", result); + + uart_print("Running...\n"); + + result = m3_CallV (f, 24); + if (result) FATAL("m3_Call", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults", result); + + char buff[32]; + ltoa(value, buff, 10); + + uart_print("Result: "); + uart_print(buff); + uart_print("\n"); + + return true; +} + + +__attribute__((section(".ramtext"))) +void isr(void) +{ + unsigned int irqs; + + irqs = irq_pending() & irq_getmask(); + + if (irqs & (1 << USB_INTERRUPT)) + usb_isr(); +} + +__attribute__((section(".ramtext"))) +static void init(void) +{ + irq_setmask(0); + irq_setie(1); + usb_init(); + time_init(); + rgb_init(); +} + +void m3Yield () +{ + usb_poll(); +} + +__attribute__((section(".ramtext"))) +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + + usb_connect(); + + for (int i = 0; i< 10000; i++) { + usb_poll(); + msleep(1); + } + + uart_print("\nWasm3 v" M3_VERSION " on Fomu (" M3_ARCH "), build " __DATE__ " " __TIME__ "\n"); + + rgb_set(0, 0, 255); + if (run_wasm()) { + rgb_set(0, 255, 0); + } else { + rgb_set(255, 0, 0); + } + + while (1) + { + usb_poll(); + } + return 0; +} diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/src/rgb.c b/wasm3-sys/wasm3/platforms/embedded/fomu/src/rgb.c new file mode 100644 index 0000000..7cc3d21 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/src/rgb.c @@ -0,0 +1,73 @@ +#include +#include +#include + +#define BREATHE_ENABLE (1 << 7) +#define BREATHE_EDGE_ON (0 << 6) +#define BREATHE_EDGE_BOTH (1 << 6) +#define BREATHE_MODE_MODULATE (1 << 5) +#define BREATHE_MODE_FIXED (0 << 5) + +// Breathe rate is in 128 ms increments +#define BREATHE_RATE_MS(x) ((((x)+1) / 128 & 7) << 0) + +// Blink on/off time is in 32 ms increments +#define BLINK_TIME_MS(x) (((x)) / 32) + +#define LEDDEN (1 << 7) +#define FR250 (1 << 6) +#define OUTPUL (1 << 5) +#define OUTSKEW (1 << 4) +#define QUICK_STOP (1 << 3) +#define PWM_MODE_LFSR (1 << 2) +#define PWM_MODE_LINEAR (0 << 2) + +void rgb_write(uint8_t value, uint8_t addr) { + rgb_addr_write(addr); + rgb_dat_write(value); +} + +void rgb_init(void) { + // Turn on the RGB block and current enable, as well as enabling led control + rgb_ctrl_write((1 << 0) | (1 << 1) | (1 << 2)); + + // Enable the LED driver, and set 250 Hz mode. + // Also set quick stop, which we'll use to switch patterns quickly. + rgb_write(LEDDEN | FR250 | QUICK_STOP, LEDDCR0); + + // Set clock register to 12 MHz / 64 kHz - 1 + rgb_write((12000000/64000)-1, LEDDBR); + + rgb_write(BLINK_TIME_MS(32), LEDDONR); // Amount of time to stay "on" + rgb_write(BLINK_TIME_MS(0), LEDDOFR); // Amount of time to stay "off" + + rgb_write(BREATHE_ENABLE | BREATHE_MODE_FIXED | BREATHE_RATE_MS(128), LEDDBCRR); + rgb_write(BREATHE_ENABLE | BREATHE_MODE_FIXED | BREATHE_RATE_MS(128), LEDDBCFR); +} + +void rgb_set(uint8_t r, uint8_t g, uint8_t b) { + // Note: the LEDD control registers have arbitrary names that + // do not match up with the LEDD pin outputs. Hence this strange + // mapping. + rgb_write(r, LEDDPWRR); // Blue + rgb_write(g, LEDDPWRG); // Red + rgb_write(b, LEDDPWRB); // Green +} + +// The amount of time to stay off or on +void rgb_on_time(uint8_t ms) { + rgb_write(BLINK_TIME_MS(ms), LEDDONR); // Amount of time to stay "on" +} + +void rgb_off_time(uint8_t ms) { + rgb_write(BLINK_TIME_MS(ms), LEDDOFR); // Amount of time to stay "off" +} + +// The amount of time to breathe in/out +void rgb_in_time(uint8_t ms) { + rgb_write(BREATHE_ENABLE| BREATHE_MODE_FIXED | BREATHE_RATE_MS(ms), LEDDBCRR); +} + +void rgb_out_time(uint8_t ms) { + rgb_write(BREATHE_ENABLE | BREATHE_MODE_FIXED | BREATHE_RATE_MS(ms), LEDDBCFR); +} diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/src/time.c b/wasm3-sys/wasm3/platforms/embedded/fomu/src/time.c new file mode 100644 index 0000000..c7ab3f7 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/src/time.c @@ -0,0 +1,43 @@ +#include +#include + +void time_init(void) +{ + int t; + + timer0_en_write(0); + t = 2*SYSTEM_CLOCK_FREQUENCY; + timer0_reload_write(t); + timer0_load_write(t); + timer0_en_write(1); +} + +int elapsed(int *last_event, int period) +{ + int t, dt; + + timer0_update_value_write(1); + t = timer0_reload_read() - timer0_value_read(); + if(period < 0) { + *last_event = t; + return 1; + } + dt = t - *last_event; + if(dt < 0) + dt += timer0_reload_read(); + if((dt > period) || (dt < 0)) { + *last_event = t; + return 1; + } else + return 0; +} + +void msleep(int ms) +{ + timer0_en_write(0); + timer0_reload_write(0); + timer0_load_write(SYSTEM_CLOCK_FREQUENCY/1000*ms); + timer0_en_write(1); + timer0_update_value_write(1); + while(timer0_value_read()) timer0_update_value_write(1); +} diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/src/usb-desc.c b/wasm3-sys/wasm3/platforms/embedded/fomu/src/usb-desc.c new file mode 100644 index 0000000..105cc29 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/src/usb-desc.c @@ -0,0 +1,284 @@ +/* Teensyduino Core Library + * http://www.pjrc.com/teensy/ + * Copyright (c) 2013 PJRC.COM, LLC. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * 1. The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * 2. If the Software is incorporated into a build system that allows + * selection among a list of target devices, then similar target + * devices manufactured by PJRC.COM must be included in the list of + * target devices and selectable in the same manner. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +// USB Descriptors are binary data which the USB host reads to +// automatically detect a USB device's capabilities. The format +// and meaning of every field is documented in numerous USB +// standards. When working with USB descriptors, despite the +// complexity of the standards and poor writing quality in many +// of those documents, remember descriptors are nothing more +// than constant binary data that tells the USB host what the +// device can do. Computers will load drivers based on this data. +// Those drivers then communicate on the endpoints specified by +// the descriptors. + +// To configure a new combination of interfaces or make minor +// changes to existing configuration (eg, change the name or ID +// numbers), usually you would edit "usb_desc.h". This file +// is meant to be configured by the header, so generally it is +// only edited to add completely new USB interfaces or features. + +// ************************************************************** +// USB Device +// ************************************************************** + +#define LSB(n) ((n) & 255) +#define MSB(n) (((n) >> 8) & 255) + +#define USB_DT_BOS_SIZE 5 +#define USB_DT_BOS 0xf +#define USB_DT_DEVICE_CAPABILITY 0x10 +#define USB_DC_PLATFORM 5 + +struct usb_bos_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumDeviceCaps; +} __attribute__((packed)); + +// USB Device Descriptor. The USB host reads this first, to learn +// what type of device is connected. +static const uint8_t device_descriptor[] = { + 18, // bLength + 1, // bDescriptorType + 0x10, 0x02, // bcdUSB + USB_CLASS_CDC, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + 64, // bMaxPacketSize0 + LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor + LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct + LSB(DEVICE_VER), MSB(DEVICE_VER), // bcdDevice + 1, // iManufacturer + 2, // iProduct + 0, // iSerialNumber + 1 // bNumConfigurations +}; + + +// ************************************************************** +// USB Configuration +// ************************************************************** + +// USB Configuration Descriptor. This huge descriptor tells all +// of the devices capbilities. +#define CONFIG_DESC_SIZE 67 +static const uint8_t config_descriptor[CONFIG_DESC_SIZE] = { + // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 + 9, // bLength; + 2, // bDescriptorType; + LSB(CONFIG_DESC_SIZE), // wTotalLength + MSB(CONFIG_DESC_SIZE), + 2, // bNumInterfaces + 1, // bConfigurationValue + 0, // iConfiguration + 0x80, // bmAttributes + 50, // bMaxPower + + // interface descriptor, CDC + USB_DT_INTERFACE_SIZE, // bLength + USB_DT_INTERFACE, // bDescriptorType + 0, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + USB_CLASS_CDC, // bInterfaceClass + USB_CDC_SUBCLASS_ACM, // bInterfaceSubClass + USB_CDC_PROTOCOL_AT, // bInterfaceProtocol + 0, // iInterface + + // Header Functional Descriptor + 0x05, // bLength: Endpoint Descriptor size + CS_INTERFACE, // bDescriptorType: CS_INTERFACE + USB_CDC_TYPE_HEADER, // bDescriptorSubtype: Header Func Desc + 0x10, // bcdCDC: spec release number + 0x01, + + // Call Management Functional Descriptor + 0x05, // bFunctionLength + CS_INTERFACE, // bDescriptorType: CS_INTERFACE + USB_CDC_TYPE_CALL_MANAGEMENT, // bDescriptorSubtype: Call Management Func Desc + 0, // bmCapabilities: D0+D1 + 1, // bDataInterface: 1 + + // ACM Functional Descriptor + 0x04, // bFunctionLength + CS_INTERFACE, // bDescriptorType: CS_INTERFACE + USB_CDC_TYPE_ACM, // bDescriptorSubtype: Abstract Control Management desc + 6, // bmCapabilities + + // Union Functional Descriptor + 0x05, // bFunctionLength + CS_INTERFACE, // bDescriptorType: CS_INTERFACE + USB_CDC_TYPE_UNION, // bDescriptorSubtype: Union func desc + 0, // bMasterInterface: Communication class interface + 1, // bSlaveInterface0: Data Class Interface + + // Endpoint descriptor + USB_DT_ENDPOINT_SIZE, // bLength + USB_DT_ENDPOINT, // bDescriptorType + 0x81, // bEndpointAddress + USB_ENDPOINT_ATTR_INTERRUPT, // bmAttributes + LSB(16), // wMaxPacketSize + MSB(16), // wMaxPacketSize + 255, // bInterval + + // interface descriptor, CDC + USB_DT_INTERFACE_SIZE, // bLength + USB_DT_INTERFACE, // bDescriptorType + 1, // bInterfaceNumber + 0, // bAlternateSetting + 2, // bNumEndpoints + USB_CLASS_DATA, // bInterfaceClass + 0, // bInterfaceSubClass + 0, // bInterfaceProtocol + 0, // iInterface + + // Endpoint descriptor + USB_DT_ENDPOINT_SIZE, // bLength + USB_DT_ENDPOINT, // bDescriptorType + 0x82, // bEndpointAddress + USB_ENDPOINT_ATTR_BULK, // bmAttributes + LSB(64), // wMaxPacketSize + MSB(64), // wMaxPacketSize + 1, // bInterval + + // Endpoint descriptor + USB_DT_ENDPOINT_SIZE, // bLength + USB_DT_ENDPOINT, // bDescriptorType + 0x02, // bEndpointAddress + USB_ENDPOINT_ATTR_BULK, // bmAttributes + LSB(64), // wMaxPacketSize + MSB(64), // wMaxPacketSize + 1, // bInterval +}; + + +// ************************************************************** +// String Descriptors +// ************************************************************** + +// The descriptors above can provide human readable strings, +// referenced by index numbers. These descriptors are the +// actual string data + +static const struct usb_string_descriptor_struct string0 = { + 4, + 3, + {0x0409} +}; + +// Microsoft OS String Descriptor. See: https://github.com/pbatard/libwdi/wiki/WCID-Devices +static const struct usb_string_descriptor_struct usb_string_microsoft = { + 18, 3, + {'M','S','F','T','1','0','0', MSFT_VENDOR_CODE} +}; + +// Microsoft WCID +const uint8_t usb_microsoft_wcid[MSFT_WCID_LEN] = { + MSFT_WCID_LEN, 0, 0, 0, // Length + 0x00, 0x01, // Version + 0x04, 0x00, // Compatibility ID descriptor index + 0x01, // Number of sections + 0, 0, 0, 0, 0, 0, 0, // Reserved (7 bytes) + + 0, // Interface number + 0x01, // Reserved + 'W','I','N','U','S','B',0,0, // Compatible ID + 0,0,0,0,0,0,0,0, // Sub-compatible ID (unused) + 0,0,0,0,0,0, // Reserved +}; + +const struct webusb_url_descriptor landing_url_descriptor = { + .bLength = LANDING_PAGE_DESCRIPTOR_SIZE, + .bDescriptorType = WEBUSB_DT_URL, + .bScheme = WEBUSB_URL_SCHEME_HTTPS, + .URL = LANDING_PAGE_URL +}; + +struct full_bos { + struct usb_bos_descriptor bos; + struct webusb_platform_descriptor webusb; +}; + +static const struct full_bos full_bos = { + .bos = { + .bLength = USB_DT_BOS_SIZE, + .bDescriptorType = USB_DT_BOS, + .wTotalLength = USB_DT_BOS_SIZE + WEBUSB_PLATFORM_DESCRIPTOR_SIZE, + .bNumDeviceCaps = 1, + }, + .webusb = { + .bLength = WEBUSB_PLATFORM_DESCRIPTOR_SIZE, + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_DC_PLATFORM, + .bReserved = 0, + .platformCapabilityUUID = WEBUSB_UUID, + .bcdVersion = 0x0100, + .bVendorCode = WEBUSB_VENDOR_CODE, + .iLandingPage = 1, + }, +}; + +__attribute__((aligned(4))) +static const struct usb_string_descriptor_struct usb_string_manufacturer_name = { + 2 + MANUFACTURER_NAME_LEN, + 3, + MANUFACTURER_NAME +}; + +__attribute__((aligned(4))) +struct usb_string_descriptor_struct usb_string_product_name = { + 2 + PRODUCT_NAME_LEN, + 3, + PRODUCT_NAME +}; + +// ************************************************************** +// Descriptors List +// ************************************************************** + +// This table provides access to all the descriptor data above. + +__attribute__((section(".data"))) +const usb_descriptor_list_t usb_descriptor_list[] = { + {0x0100, sizeof(device_descriptor), device_descriptor}, + {0x0200, sizeof(config_descriptor), config_descriptor}, + {0x0300, 0, (const uint8_t *)&string0}, + {0x0301, 0, (const uint8_t *)&usb_string_manufacturer_name}, + {0x0302, 0, (const uint8_t *)&usb_string_product_name}, + {0x03EE, 0, (const uint8_t *)&usb_string_microsoft}, + {0x0F00, sizeof(full_bos), (const uint8_t *)&full_bos}, + {0, 0, NULL} +}; diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/src/usb-dev.c b/wasm3-sys/wasm3/platforms/embedded/fomu/src/usb-dev.c new file mode 100644 index 0000000..bf0739e --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/src/usb-dev.c @@ -0,0 +1,285 @@ +#include +#include +#include +#include +#include + +static uint8_t reply_buffer[8]; +static uint8_t usb_configuration = 0; +// #define USB_MAX_PACKET_SIZE 64 +// static uint32_t rx_buffer[USB_MAX_PACKET_SIZE/4]; + +volatile uint8_t terminal_is_connected; + +__attribute__((section(".ramtext"))) +void usb_setup(const struct usb_setup_request *setup) { + const uint8_t *data = NULL; + uint32_t datalen = 0; + const usb_descriptor_list_t *list; + + switch (setup->wRequestAndType) + { + case 0x2021: // Set Line Coding + break; + case 0x2221: // Set control line state + terminal_is_connected = setup->wValue & 1; + break; + + case 0x0500: // SET_ADDRESS + usb_set_address(((uint8_t *)setup)[2]); + break; + + case 0x0b01: // SET_INTERFACE + //dfu_clrstatus(); + break; + + case 0x0900: // SET_CONFIGURATION + usb_configuration = setup->wValue; + break; + + case 0x0880: // GET_CONFIGURATION + reply_buffer[0] = usb_configuration; + datalen = 1; + data = reply_buffer; + break; + + case 0x0080: // GET_STATUS (device) + reply_buffer[0] = 0; + reply_buffer[1] = 0; + datalen = 2; + data = reply_buffer; + break; + + case 0x0082: // GET_STATUS (endpoint) + if (setup->wIndex > 0) + { + usb_err_in(); + return; + } + reply_buffer[0] = 0; + reply_buffer[1] = 0; + + // XXX handle endpoint stall here +// if (USB->DIEP0CTL & USB_DIEP_CTL_STALL) +// reply_buffer[0] = 1; + data = reply_buffer; + datalen = 2; + break; + + case 0x0102: // CLEAR_FEATURE (endpoint) + // if (setup->wIndex > 0 || setup->wValue != 0) + // { + // // TODO: do we need to handle IN vs OUT here? + // usb_err_in(); + // return; + // } + // XXX: Should we clear the stall bit? + // USB->DIEP0CTL &= ~USB_DIEP_CTL_STALL; + // TODO: do we need to clear the data toggle here? + break; + + case 0x0302: // SET_FEATURE (endpoint) + // if (setup->wIndex > 0 || setup->wValue != 0) + // { + // // TODO: do we need to handle IN vs OUT here? + // usb_err_in(); + // return; + // } + // XXX: Should we set the stall bit? + // USB->DIEP0CTL |= USB_DIEP_CTL_STALL; + // TODO: do we need to clear the data toggle here? + break; + + case 0x0680: // GET_DESCRIPTOR + case 0x0681: + for (list = usb_descriptor_list; 1; list++) + { + if (list->addr == NULL) + break; + if (setup->wValue == list->wValue) + { + data = list->addr; + if ((setup->wValue >> 8) == 3) + { + // for string descriptors, use the descriptor's + // length field, allowing runtime configured + // length. + datalen = *(list->addr); + } + else + { + datalen = list->length; + } + goto send; + } + } + usb_err_in(); + return; +#if 0 + case (MSFT_VENDOR_CODE << 8) | 0xC0: // Get Microsoft descriptor + case (MSFT_VENDOR_CODE << 8) | 0xC1: + if (setup->wIndex == 0x0004) + { + // Return WCID descriptor + data = usb_microsoft_wcid; + datalen = MSFT_WCID_LEN; + break; + } + usb_err(); + return; + + case (WEBUSB_VENDOR_CODE << 8) | 0xC0: // Get WebUSB descriptor + if (setup->wIndex == 0x0002) + { + if (setup->wValue == 0x0001) + { + // Return landing page URL descriptor + data = (uint8_t*)&landing_url_descriptor; + datalen = LANDING_PAGE_DESCRIPTOR_SIZE; + break; + } + } + // printf("%s:%d couldn't find webusb descriptor (%d / %d)\n", __FILE__, __LINE__, setup->wIndex, setup->wValue); + usb_err(); + return; +#endif + +#if 0 + case 0x0121: // DFU_DNLOAD + if (setup->wIndex > 0) + { + usb_err(); + return; + } + // Data comes in the OUT phase. But if it's a zero-length request, handle it now. + if (setup->wLength == 0) + { + if (!dfu_download(setup->wValue, 0, 0, 0, NULL)) + { + usb_err(); + return; + } + usb_ack_in(); + return; + } + + // ACK the setup packet + // usb_ack_out(); + + int bytes_remaining = setup->wLength; + int ep0_rx_offset = 0; + // Fill the buffer, or if there is enough space transfer the whole packet. + unsigned int blockLength = setup->wLength; + unsigned int blockNum = setup->wValue; + + while (bytes_remaining > 0) { + unsigned int i; + unsigned int len = blockLength; + if (len > sizeof(rx_buffer)) + len = sizeof(rx_buffer); + for (i = 0; i < sizeof(rx_buffer)/4; i++) + rx_buffer[i] = 0xffffffff; + + // Receive DATA packets (which are automatically ACKed) + len = usb_recv((void *)rx_buffer, len); + + // Append the data to the download buffer. + dfu_download(blockNum, blockLength, ep0_rx_offset, len, (void *)rx_buffer); + + bytes_remaining -= len; + ep0_rx_offset += len; + } + + // ACK the final IN packet. + usb_ack_in(); + + return; + + case 0x0021: // DFU_DETACH + // Send the "ACK" packet and wait for it + // to be received. + usb_ack_in(); + usb_wait_for_send_done(); + reboot(); + while (1) + ; + return; + + case 0x03a1: // DFU_GETSTATUS + if (setup->wIndex > 0) + { + usb_err(); + return; + } + if (dfu_getstatus(reply_buffer)) + { + data = reply_buffer; + datalen = 6; + break; + } + else + { + usb_err(); + return; + } + break; + + case 0x0421: // DFU_CLRSTATUS + if (setup->wIndex > 0) + { + usb_err(); + return; + } + if (dfu_clrstatus()) + { + break; + } + else + { + usb_err(); + return; + } + + case 0x05a1: // DFU_GETSTATE + if (setup->wIndex > 0) + { + usb_err(); + return; + } + reply_buffer[0] = dfu_getstate(); + data = reply_buffer; + datalen = 1; + break; + + case 0x0621: // DFU_ABORT + if (setup->wIndex > 0) + { + usb_err(); + return; + } + if (dfu_abort()) + { + break; + } + else + { + usb_err(); + return; + } +#endif + + default: + usb_err_in(); + return; + } + +send: + if (data && datalen) { + if (datalen > setup->wLength) + datalen = setup->wLength; + usb_send(data, datalen); + } + else + usb_ack_in(); + return; +} diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/src/usb-epfifo.c b/wasm3-sys/wasm3/platforms/embedded/fomu/src/usb-epfifo.c new file mode 100644 index 0000000..35dd83c --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/src/usb-epfifo.c @@ -0,0 +1,369 @@ +#include +#include +#include +#include +#include + +#ifdef CSR_USB_EP_0_OUT_EV_PENDING_ADDR + +static volatile uint8_t usb_rx_fifo[64]; +static volatile uint8_t usb_rx_fifo_rd; +static volatile uint8_t usb_rx_fifo_wr; + +static volatile int have_new_address; +static volatile uint8_t new_address; + +// Firmware versions < 1.9 didn't have usb_address_write() +static inline void usb_set_address_wrapper(uint8_t address) { + if (version_major_read() < 1) + return; + if (version_minor_read() < 9) + return; + usb_address_write(address); +} + +// Note that our PIDs are only bits 2 and 3 of the token, +// since all other bits are effectively redundant at this point. +enum USB_PID { + USB_PID_OUT = 0, + USB_PID_SOF = 1, + USB_PID_IN = 2, + USB_PID_SETUP = 3, +}; + +enum epfifo_response { + EPF_ACK = 0, + EPF_NAK = 1, + EPF_NONE = 2, + EPF_STALL = 3, +}; + +#define USB_EV_ERROR 1 +#define USB_EV_PACKET 2 + +void usb_disconnect(void) { + usb_ep_0_out_ev_enable_write(0); + usb_ep_0_in_ev_enable_write(0); + irq_setmask(irq_getmask() & ~(1 << USB_INTERRUPT)); + usb_pullup_out_write(0); + usb_set_address_wrapper(0); +} + +void usb_connect(void) { + + usb_set_address_wrapper(0); + usb_ep_0_out_ev_pending_write(usb_ep_0_out_ev_enable_read()); + usb_ep_0_in_ev_pending_write(usb_ep_0_in_ev_pending_read()); + usb_ep_0_out_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + usb_ep_0_in_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + + usb_ep_1_in_ev_pending_write(usb_ep_1_in_ev_enable_read()); + usb_ep_1_in_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + + usb_ep_2_out_ev_pending_write(usb_ep_2_out_ev_enable_read()); + usb_ep_2_in_ev_pending_write(usb_ep_2_in_ev_pending_read()); + usb_ep_2_out_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + usb_ep_2_in_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + + // Accept incoming data by default. + usb_ep_0_out_respond_write(EPF_ACK); + usb_ep_2_out_respond_write(EPF_ACK); + + // Reject outgoing data, since we have none to give yet. + usb_ep_0_in_respond_write(EPF_NAK); + usb_ep_1_in_respond_write(EPF_NAK); + usb_ep_2_in_respond_write(EPF_NAK); + + usb_pullup_out_write(1); + + irq_setmask(irq_getmask() | (1 << USB_INTERRUPT)); +} + +void usb_init(void) { + usb_pullup_out_write(0); + return; +} + +#define EP0OUT_BUFFERS 4 +__attribute__((aligned(4))) +static uint8_t volatile usb_ep0out_buffer[EP0OUT_BUFFERS][256]; +static uint8_t volatile usb_ep0out_buffer_len[EP0OUT_BUFFERS]; +static uint8_t volatile usb_ep0out_last_tok[EP0OUT_BUFFERS]; +static volatile uint8_t usb_ep0out_wr_ptr; +static volatile uint8_t usb_ep0out_rd_ptr; +static const int max_byte_length = 64; + +static const uint8_t * volatile current_data; +static volatile int current_length; +static volatile int data_offset; +static volatile int data_to_send; +static int next_packet_is_empty; +static volatile uint8_t ep2_fifo_bytes; + +__attribute__((section(".ramtext"))) +static void process_tx(void) { + + // Don't allow requeueing -- only queue more data if we're + // currently set up to respond NAK. + if (usb_ep_0_in_respond_read() != EPF_NAK) { + return; + } + + // Prevent us from double-filling the buffer. + if (!usb_ep_0_in_ibuf_empty_read()) { + return; + } + + if (!current_data || !current_length) { + return; + } + + data_offset += data_to_send; + + data_to_send = current_length - data_offset; + + // Clamp the data to the maximum packet length + if (data_to_send > max_byte_length) { + data_to_send = max_byte_length; + next_packet_is_empty = 0; + } + else if (data_to_send == max_byte_length) { + next_packet_is_empty = 1; + } + else if (next_packet_is_empty) { + next_packet_is_empty = 0; + data_to_send = 0; + } + else if (current_data == NULL || data_to_send <= 0) { + next_packet_is_empty = 0; + current_data = NULL; + current_length = 0; + data_offset = 0; + data_to_send = 0; + return; + } + + int this_offset; + for (this_offset = data_offset; this_offset < (data_offset + data_to_send); this_offset++) { + usb_ep_0_in_ibuf_head_write(current_data[this_offset]); + } + usb_ep_0_in_respond_write(EPF_ACK); + return; +} + +int usb_send(const void *data, int total_count) { + + while ((current_length || current_data))// && usb_ep_0_in_respond_read() != EPF_NAK) + ; + current_data = (uint8_t *)data; + current_length = total_count; + data_offset = 0; + data_to_send = 0; + process_tx(); + + return 0; +} + +int usb_wait_for_send_done(void) { + while (current_data && current_length) + usb_poll(); + while ((usb_ep_0_in_dtb_read() & 1) == 1) + usb_poll(); + return 0; +} + +__attribute__((section(".ramtext"))) +void usb_isr(void) { + uint8_t ep_pending; + + ep_pending = usb_ep_0_out_ev_pending_read(); + + // We got an OUT or a SETUP packet. Copy it to usb_ep0out_buffer + // and clear the "pending" bit. + if (ep_pending) { + uint8_t last_tok = usb_ep_0_out_last_tok_read(); + + int byte_count = 0; + usb_ep0out_last_tok[usb_ep0out_wr_ptr] = last_tok; + volatile uint8_t * obuf = usb_ep0out_buffer[usb_ep0out_wr_ptr]; + while (!usb_ep_0_out_obuf_empty_read()) { + obuf[byte_count++] = usb_ep_0_out_obuf_head_read(); + usb_ep_0_out_obuf_head_write(0); + } + + if (last_tok == USB_PID_SETUP) { + usb_ep_0_in_dtb_write(1); + data_offset = 0; + current_length = 0; + current_data = NULL; + const struct usb_setup_request *request = (const struct usb_setup_request *)obuf; + usb_setup(request); + } + else { + usb_ep0out_buffer_len[usb_ep0out_wr_ptr] = byte_count - 2 /* Strip off CRC16 */; + usb_ep0out_wr_ptr = (usb_ep0out_wr_ptr + 1) & (EP0OUT_BUFFERS-1); + } + usb_ep_0_out_ev_pending_write(ep_pending); + usb_ep_0_out_respond_write(EPF_ACK); + } + + ep_pending = usb_ep_0_in_ev_pending_read(); + // We just got an "IN" token. Send data if we have it. + if (ep_pending) { + usb_ep_0_in_respond_write(EPF_NAK); + usb_ep_0_in_ev_pending_write(ep_pending); + if (have_new_address) { + have_new_address = 0; + usb_set_address_wrapper(new_address); + } + process_tx(); + } + + ep_pending = usb_ep_1_in_ev_pending_read(); + if (ep_pending) { + usb_ep_1_in_respond_write(EPF_NAK); + usb_ep_1_in_ev_pending_write(ep_pending); + } + + ep_pending = usb_ep_2_in_ev_pending_read(); + if (ep_pending) { + usb_ep_2_in_respond_write(EPF_NAK); + usb_ep_2_in_ev_pending_write(ep_pending); + ep2_fifo_bytes = 0; + } + + ep_pending = usb_ep_2_out_ev_pending_read(); + if (ep_pending) { + while (!usb_ep_2_out_obuf_empty_read()) { + usb_rx_fifo[(usb_rx_fifo_wr++) & 0x3f] = usb_ep_2_out_obuf_head_read(); + usb_ep_2_out_obuf_head_write(0); + } + // Strip off the CRC16. + usb_rx_fifo_wr -= 2; + + usb_ep_2_out_ev_pending_write(ep_pending); + usb_ep_2_out_respond_write(EPF_NAK); + } + + return; +} + +__attribute__((section(".ramtext"))) +int usb_getc(void) { + if (usb_rx_fifo_rd == usb_rx_fifo_wr) { + usb_ep_2_out_respond_write(EPF_ACK); + return -1; + } + return usb_rx_fifo[(usb_rx_fifo_rd++) & 0x3f]; +} + +__attribute__((section(".ramtext"))) +void usb_putc(char c) { + usb_ep_2_in_ibuf_head_write(c); + ep2_fifo_bytes++; + usb_ep_2_in_respond_write(EPF_ACK); +} + +__attribute__((section(".ramtext"))) +int usb_write(const char *buf, int count) { + int to_write = 64; + int i; + if (to_write > count) + to_write = count; + for (i = 0; i < to_write; i++) + usb_ep_2_in_ibuf_head_write(buf[i]); + ep2_fifo_bytes += to_write; + usb_ep_2_in_respond_write(EPF_ACK); + + return to_write; +} + +extern volatile uint8_t terminal_is_connected; + +__attribute__((section(".ramtext"))) +int usb_can_getc(void) { + if (usb_rx_fifo_rd == usb_rx_fifo_wr) { + usb_ep_2_out_respond_write(EPF_ACK); + return 0; + } + return terminal_is_connected; +} + +__attribute__((section(".ramtext"))) +int usb_can_putc(void) { + return terminal_is_connected && usb_ep_2_in_ibuf_empty_read() && (usb_ep_2_in_respond_read() == EPF_NAK);// (ep2_fifo_bytes <= 60); +} + +__attribute__((section(".ramtext"))) +void usb_ack_in(void) { + // usb_ep_0_in_dtb_write(1); + while (usb_ep_0_in_respond_read() == EPF_ACK) + ; + usb_ep_0_in_respond_write(EPF_ACK); +} + +__attribute__((section(".ramtext"))) +void usb_ack_out(void) { + // usb_ep_0_out_dtb_write(1); + while (usb_ep_0_out_respond_read() == EPF_ACK) + ; + usb_ep_0_out_respond_write(EPF_ACK); +} + +__attribute__((section(".ramtext"))) +void usb_err_in(void) { + usb_ep_0_in_respond_write(EPF_STALL); +} + +__attribute__((section(".ramtext"))) +void usb_err_out(void) { + usb_ep_0_out_respond_write(EPF_STALL); +} + +__attribute__((section(".ramtext"))) +int usb_recv(void *buffer, unsigned int buffer_len) { + + // Set the OUT response to ACK, since we are in a position to receive data now. + usb_ep_0_out_respond_write(EPF_ACK); + while (1) { + if (usb_ep0out_rd_ptr != usb_ep0out_wr_ptr) { + if (usb_ep0out_last_tok[usb_ep0out_rd_ptr] == USB_PID_OUT) { + unsigned int ep0_buffer_len = usb_ep0out_buffer_len[usb_ep0out_rd_ptr]; + if (ep0_buffer_len < buffer_len) + buffer_len = ep0_buffer_len; + usb_ep0out_buffer_len[usb_ep0out_rd_ptr] = 0; + memcpy(buffer, (void *)&usb_ep0out_buffer[usb_ep0out_rd_ptr], buffer_len); + usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1); + return buffer_len; + } + usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1); + } + } + return 0; +} + +void usb_set_address(uint8_t new_address_) { + new_address = new_address_; + have_new_address = 1; +} + +__attribute__((section(".ramtext"))) +void usb_poll(void) { + // If some data was received, then process it. + while (usb_ep0out_rd_ptr != usb_ep0out_wr_ptr) { + const struct usb_setup_request *request = (const struct usb_setup_request *)(usb_ep0out_buffer[usb_ep0out_rd_ptr]); + // unsigned int len = usb_ep0out_buffer_len[usb_ep0out_rd_ptr]; + uint8_t last_tok = usb_ep0out_last_tok[usb_ep0out_rd_ptr]; + + usb_ep0out_buffer_len[usb_ep0out_rd_ptr] = 0; + usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1); + + if (last_tok == USB_PID_SETUP) { + usb_setup(request); + } + } + + process_tx(); +} + +#endif /* CSR_USB_EP_0_OUT_EV_PENDING_ADDR */ \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/fomu/src/wasm3 b/wasm3-sys/wasm3/platforms/embedded/fomu/src/wasm3 new file mode 120000 index 0000000..17056a9 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/fomu/src/wasm3 @@ -0,0 +1 @@ +../../../../source \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/hifive1/.gitignore b/wasm3-sys/wasm3/platforms/embedded/hifive1/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/hifive1/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/wasm3-sys/wasm3/platforms/embedded/hifive1/README.md b/wasm3-sys/wasm3/platforms/embedded/hifive1/README.md new file mode 100644 index 0000000..f49dfbc --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/hifive1/README.md @@ -0,0 +1,19 @@ +## Build for HiFive1 + +### Debugging: + +On first console, run +```sh +JLinkGDBServer -singlerun -if JTAG -select USB -speed 1000 -jtagconf -1,-1 -device FE310 --port 2331 +``` + +On second console, run `riscv64-unknown-elf-gdb`: +```gdb +file ".pio/build/hifive1-revb/firmware.elf" +target extended-remote :2331 +b main +monitor halt +monitor reset +load +c +``` diff --git a/wasm3-sys/wasm3/platforms/embedded/hifive1/lib/wasm3 b/wasm3-sys/wasm3/platforms/embedded/hifive1/lib/wasm3 new file mode 120000 index 0000000..17056a9 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/hifive1/lib/wasm3 @@ -0,0 +1 @@ +../../../../source \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/hifive1/platformio.ini b/wasm3-sys/wasm3/platforms/embedded/hifive1/platformio.ini new file mode 100644 index 0000000..50b1d46 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/hifive1/platformio.ini @@ -0,0 +1,36 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +default_envs = hifive1-revb + +[env] +platform = sifive +framework = freedom-e-sdk +monitor_speed = 115200 + +board_build.f_cpu = 320000000L + +src_filter = + +<*> + - + +src_build_flags = + -Dd_m3FixedHeap=8192 + -Os -Wfatal-errors + -flto + +build_flags = -lm + +[env:hifive1] +board = hifive1 + +[env:hifive1-revb] +board = hifive1-revb diff --git a/wasm3-sys/wasm3/platforms/embedded/hifive1/src/main.c b/wasm3-sys/wasm3/platforms/embedded/hifive1/src/main.c new file mode 100644 index 0000000..3e489c3 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/hifive1/src/main.c @@ -0,0 +1,62 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + uint32_t fsize = fib32_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + result = m3_CallV (f, 24); + if (result) FATAL("m3_Call: %s", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %d\n", value); +} + +int main() { + printf("\n"); + printf("Wasm3 v" M3_VERSION " on HiFive1 (" M3_ARCH "), build " __DATE__ " " __TIME__ "\n"); + // TODO: fix clock (shows wrong time) + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + printf("Elapsed: %ld ms\n", (end - start)*1000 / CLOCKS_PER_SEC); +} diff --git a/wasm3-sys/wasm3/platforms/embedded/particle/.gitignore b/wasm3-sys/wasm3/platforms/embedded/particle/.gitignore new file mode 100644 index 0000000..a8a0dce --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/particle/.gitignore @@ -0,0 +1 @@ +*.bin diff --git a/wasm3-sys/wasm3/platforms/embedded/particle/README.md b/wasm3-sys/wasm3/platforms/embedded/particle/README.md new file mode 100644 index 0000000..bbb0420 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/particle/README.md @@ -0,0 +1,18 @@ +## Build for Particle + +You need to install Particle CLI. + +Build for `photon`, `electron`, `pi`, `duo`, `p1`, `argon`, `boron`, `xenon`: +```sh +particle compile --followSymlinks photon +``` + +Upload to device: +``` +particle list +particle flash MyDevice1 ./firmware_*.bin + +# Or using USB: +particle flash --usb ./firmware_*.bin +``` + diff --git a/wasm3-sys/wasm3/platforms/embedded/particle/lib/wasm3/library.properties b/wasm3-sys/wasm3/platforms/embedded/particle/lib/wasm3/library.properties new file mode 100644 index 0000000..a257fd2 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/particle/lib/wasm3/library.properties @@ -0,0 +1,6 @@ +name=wasm3 +version=0.1.0 +license=MIT +author=Volodymyr Shymanskyy +sentence=WebAssembly interpreter for Particle devices +url=https://github.com/vshymanskyy/wasm3 diff --git a/wasm3-sys/wasm3/platforms/embedded/particle/lib/wasm3/src b/wasm3-sys/wasm3/platforms/embedded/particle/lib/wasm3/src new file mode 120000 index 0000000..e3e41d7 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/particle/lib/wasm3/src @@ -0,0 +1 @@ +../../../../../source \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/embedded/particle/project.properties b/wasm3-sys/wasm3/platforms/embedded/particle/project.properties new file mode 100644 index 0000000..e09fa29 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/particle/project.properties @@ -0,0 +1 @@ +name=wasm3 diff --git a/wasm3-sys/wasm3/platforms/embedded/particle/src/main.ino b/wasm3-sys/wasm3/platforms/embedded/particle/src/main.ino new file mode 100644 index 0000000..227557c --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/particle/src/main.ino @@ -0,0 +1,80 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(func, msg) { \ + Serial.print("Fatal: " func ": "); \ + Serial.println(msg); return; } + +// Redefine puts +int puts(const char* s) { + Serial.println(s); +} + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + size_t fsize = fib32_wasm_len; + + Serial.println("Loading WebAssembly..."); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment", "failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime", "failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction", result); + + Serial.println("Running..."); + + result = m3_CallV (f, 24); + if (result) FATAL("m3_Call: %s", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + Serial.print("Result: "); + Serial.println(value); +} + +void setup() +{ + Serial.begin(115200); + delay(10); + + Serial.println(); + Serial.println("Wasm3 v" M3_VERSION " on Particle, build " __DATE__ " " __TIME__); + + uint32_t start = millis(); + run_wasm(); + uint32_t end = millis(); + + Serial.print("Elapsed: "); + Serial.print(end - start); + Serial.println(" ms"); +} + +void loop() +{ + delay(100); +} diff --git a/wasm3-sys/wasm3/platforms/embedded/wm_w600/.gitignore b/wasm3-sys/wasm3/platforms/embedded/wm_w600/.gitignore new file mode 100644 index 0000000..16ff3c7 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/wm_w600/.gitignore @@ -0,0 +1 @@ +.output diff --git a/wasm3-sys/wasm3/platforms/embedded/wm_w600/Makefile b/wasm3-sys/wasm3/platforms/embedded/wm_w600/Makefile new file mode 100644 index 0000000..645616f --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/wm_w600/Makefile @@ -0,0 +1,120 @@ +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of object file images to be generated () +# GEN_BINS - list of binaries to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# + +TOP_DIR:= $(WM_SDK) + +sinclude $(TOP_DIR)/tools/tool_chain.def + +USE_LIB=1 + +CSRCS = $(wildcard *.c) $(wildcard wasm3/*.c) + +#EXTRA_CCFLAGS += -u +ifndef PDIR +GEN_IMAGES= $(TARGET).out +GEN_BINS = $(TARGET).bin +SUBDIRS = \ + $(TOP_DIR)/platform/boot/$(COMPILE) + +ifeq ($(USE_LIB), 0) +SUBDIRS += \ + $(TOP_DIR)/platform/common \ + $(TOP_DIR)/platform/drivers \ + $(TOP_DIR)/platform/sys \ + $(TOP_DIR)/src/os \ + $(TOP_DIR)/src/app \ + $(TOP_DIR)/src/network +endif +endif + +COMPONENTS_$(TARGET) = \ + $(TOP_DIR)/platform/boot/$(COMPILE)/startup.o \ + $(TOP_DIR)/platform/boot/$(COMPILE)/misc.o \ + $(TOP_DIR)/platform/boot/$(COMPILE)/retarget.o + +ifeq ($(USE_LIB), 0) +COMPONENTS_$(TARGET) += \ + $(TOP_DIR)/platform/common/libcommon$(LIB_EXT) \ + $(TOP_DIR)/platform/drivers/libdrivers$(LIB_EXT) \ + $(TOP_DIR)/platform/sys/libsys$(LIB_EXT) \ + $(TOP_DIR)/src/os/libos$(LIB_EXT) \ + $(TOP_DIR)/src/network/libnetwork$(LIB_EXT) \ + $(TOP_DIR)/src/app/libapp$(LIB_EXT) +endif + +ifeq ($(USE_LIB), 1) +LINKLIB = \ + $(TOP_DIR)/lib/libcommon$(LIB_EXT) \ + $(TOP_DIR)/lib/libdrivers$(LIB_EXT) \ + $(TOP_DIR)/lib/libsys$(LIB_EXT) \ + $(TOP_DIR)/lib/libos$(LIB_EXT) \ + $(TOP_DIR)/lib/libnetwork$(LIB_EXT) \ + $(TOP_DIR)/lib/libapp$(LIB_EXT) +endif + +LINKLIB += \ + $(TOP_DIR)/lib/libairkiss_log$(LIB_EXT) \ + $(TOP_DIR)/lib/libwlan$(LIB_EXT) + +ifeq ($(COMPILE), gcc) +LINKFLAGS_$(TARGET) = \ + $(LINKLIB) \ + -T$(LD_FILE) \ + -Wl,-warn-common +else +LINKFLAGS_$(TARGET) = \ + --library_type=microlib \ + $(LINKLIB) \ + --strict --scatter $(LD_FILE) +endif + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# + +CONFIGURATION_DEFINES += -DWM_W600 + +DEFINES += $(CONFIGURATION_DEFINES) -Os -flto -Wfatal-errors \ + -fomit-frame-pointer -fno-stack-check -fno-stack-protector \ + -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers +# -Dd_m3FixedHeap=8192 +# -fno-optimize-sibling-calls + +LINKFLAGS_$(TARGET) += -Os -flto + +LINKLIB += -lm + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I$(PDIR)include +INCLUDES += -I ./ -I ./wasm3/ + +sinclude $(TOP_DIR)/tools/rules.mk + +.PHONY: FORCE +FORCE: diff --git a/wasm3-sys/wasm3/platforms/embedded/wm_w600/README.md b/wasm3-sys/wasm3/platforms/embedded/wm_w600/README.md new file mode 100644 index 0000000..7e7983d --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/wm_w600/README.md @@ -0,0 +1,28 @@ +## Build for Winner Micro W600 + +You will need: + +- [W600 SDK from ThingsTurn](https://github.com/w600/sdk) + `git clone --depth=1 --branch=sdk_v3.2.0 https://github.com/w600/sdk.git /opt/w600-sdk` +- [gcc-arm-none-eabi-4_9-2015q3](https://launchpad.net/gcc-arm-embedded/4.9/4.9-2015-q3-update) +- [w600tool](https://github.com/vshymanskyy/w600tool) + +```sh +export PATH=/opt/gcc-arm-none-eabi-4_9-2015q3/bin:$PATH + +export PATH=/opt/w600tool:$PATH + +export WM_SDK=/opt/w600-sdk + +./build.sh +``` + +To upload: + +```sh +w600tool.py --upload .output/wasm3_gz.img +``` +or +```sh +w600tool.py --upload .output/wasm3.fls +``` diff --git a/wasm3-sys/wasm3/platforms/embedded/wm_w600/build.sh b/wasm3-sys/wasm3/platforms/embedded/wm_w600/build.sh new file mode 100755 index 0000000..dc28b5f --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/wm_w600/build.sh @@ -0,0 +1,10 @@ +#!/bin/sh +rm -rf .output + +mkdir -p .output/wasm3/obj/wasm3/ + +make COMPILE=gcc TARGET=wasm3 FLASH_SIZE=1M VERBOSE=YES + +cp $WM_SDK/bin/wasm3/* ./.output/ + +rm test.bin diff --git a/wasm3-sys/wasm3/platforms/embedded/wm_w600/main.c b/wasm3-sys/wasm3/platforms/embedded/wm_w600/main.c new file mode 100644 index 0000000..8777eb0 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/wm_w600/main.c @@ -0,0 +1,91 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "wm_include.h" + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +unsigned int millis(void) +{ + return tls_os_get_time()*2; +} + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + uint32_t fsize = fib32_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + result = m3_CallV (f, 24); + if (result) FATAL("m3_Call: %s", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %ld\n", value); +} + + +#define USER_TASK_STK_SIZE 32768 +#define USER_TASK_PRIO 32 + +static u8 user_task_stk[USER_TASK_STK_SIZE]; + +void wasm3_task(void *data) +{ + printf("\nWasm3 v" M3_VERSION " on W600, build " __DATE__ " " __TIME__ "\n"); + + uint32_t start = millis(); + run_wasm(); + uint32_t end = millis(); + + printf("Elapsed: %ld ms\n", (end - start)); +} + +void pre_gpio_config(void) +{ + +} + +void UserMain(void) +{ + /* create task */ + tls_os_task_create(NULL, + "wasm3", + wasm3_task, + (void*) 0, + (void*) &user_task_stk, + USER_TASK_STK_SIZE, + USER_TASK_PRIO, + 0); +} diff --git a/wasm3-sys/wasm3/platforms/embedded/wm_w600/wasm3 b/wasm3-sys/wasm3/platforms/embedded/wm_w600/wasm3 new file mode 120000 index 0000000..03cc5a6 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/embedded/wm_w600/wasm3 @@ -0,0 +1 @@ +../../../source \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/emscripten/README.md b/wasm3-sys/wasm3/platforms/emscripten/README.md new file mode 100644 index 0000000..d16d5bd --- /dev/null +++ b/wasm3-sys/wasm3/platforms/emscripten/README.md @@ -0,0 +1,35 @@ +## Build using Emscripten + +In root: + +```sh +source /opt/emsdk/emsdk_env.sh --build=Release +mkdir -p build +cd build +cmake -GNinja -DEMSCRIPTEN=1 .. +ninja +``` + +**Note:** + +To enable WebAssembly extensions: +```sh +cmake -GNinja -DEMSCRIPTEN=1 -DWASM_EXT=1 .. +``` + +You can convert the generated wasm to wat to see the effect: +```sh +wasm2wat --enable-tail-call --enable-bulk-memory wasm3.wasm > wasm3.wat +``` + +Running `tail-call` version will require Chrome with experimental flags: +```sh +emrun --no_browser --no_emrun_detect --port 8080 . +chrome --js-flags="--experimental-wasm-return-call --wasm-opt" --no-sandbox http://localhost:8080/wasm3.html +``` + +Or use Node.js: +```sh +node --experimental-wasm-return-call --wasm-opt ./wasm3.js +``` + diff --git a/wasm3-sys/wasm3/platforms/emscripten/main.c b/wasm3-sys/wasm3/platforms/emscripten/main.c new file mode 100644 index 0000000..da7633f --- /dev/null +++ b/wasm3-sys/wasm3/platforms/emscripten/main.c @@ -0,0 +1,65 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + size_t fsize = fib32_wasm_len; + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 64*1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + result = m3_CallV (f, 40); + + if (result) FATAL("Call: %s", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %d\n", value); +} + +int main (int i_argc, const char * i_argv []) +{ + printf("Wasm3 v" M3_VERSION " on WASM, build " __DATE__ " " __TIME__ "\n"); + + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + uint32_t elapsed_time = (end - start)*1000 / CLOCKS_PER_SEC ; + printf("Elapsed: %d ms\n", elapsed_time); + + return 0; +} diff --git a/wasm3-sys/wasm3/platforms/emscripten_lib/main.c b/wasm3-sys/wasm3/platforms/emscripten_lib/main.c new file mode 100644 index 0000000..81a909a --- /dev/null +++ b/wasm3-sys/wasm3/platforms/emscripten_lib/main.c @@ -0,0 +1,57 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include + +#include "wasm3.h" +#include "m3_env.h" + +IM3Environment env; + +EMSCRIPTEN_KEEPALIVE +void init() { + env = m3_NewEnvironment (); + if (!env) return; +} + +EMSCRIPTEN_KEEPALIVE +IM3Runtime new_runtime() { + return m3_NewRuntime (env, 64*1024, NULL); +} + +EMSCRIPTEN_KEEPALIVE +void free_runtime(IM3Runtime runtime) { + m3_FreeRuntime (runtime); +} + +EMSCRIPTEN_KEEPALIVE +void load(IM3Runtime runtime, uint8_t* wasm, size_t fsize) { + M3Result result = m3Err_none; + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) return; + + result = m3_LoadModule (runtime, module); + if (result) return; +} + +EMSCRIPTEN_KEEPALIVE +uint32_t call(IM3Runtime runtime, int argc, const char* argv[]) { + M3Result result = m3Err_none; + + IM3Function f; + result = m3_FindFunction (&f, runtime, argv[0]); + if (result) return -1; + + result = m3_CallArgv (f, argc-1, argv+1); + if (result) return -2; + + return *(uint64_t*)(runtime->stack); +} diff --git a/wasm3-sys/wasm3/platforms/emscripten_lib/run_native.js b/wasm3-sys/wasm3/platforms/emscripten_lib/run_native.js new file mode 100644 index 0000000..13c93d1 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/emscripten_lib/run_native.js @@ -0,0 +1,28 @@ +'use strict'; + +if (typeof(process) != 'undefined') { // Node.js environment? + var scriptArgs = process.argv.slice(2); + const fs = require('fs'); + var readFile = (fn) => new Uint8Array(fs.readFileSync(fn)); +} else { + var readFile = (fn) => read(fn, 'binary'); +} + +let instances = []; + +(async() => { + const wasm = scriptArgs[0]; + const func = scriptArgs[1]; + const args = scriptArgs.slice(2); + + const binary = readFile(wasm); + + for (let i=0; i<1000; i++) { // V8: 1028 max, SpiderMonkey: 32650 max + let instance = (await WebAssembly.instantiate(binary)).instance; + + instances[i] = instance; + + let result = instance.exports[func](...args); + //console.log(i, result); + } +})(); diff --git a/wasm3-sys/wasm3/platforms/emscripten_lib/run_wasm3.js b/wasm3-sys/wasm3/platforms/emscripten_lib/run_wasm3.js new file mode 100644 index 0000000..56a80b9 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/emscripten_lib/run_wasm3.js @@ -0,0 +1,129 @@ +'use strict'; + +/* + Node.js + ------- + node --v8-options | grep -A1 wasm + --print_wasm_code --code-comments + --wasm_interpret_all --trace_wasm_interpreter + + SpiderMonkey + ------------ + export PATH=/opt/jsshell/:$PATH + js --help | grep wasm + --wasm-compiler=baseline/ion/cranelift/baseline+ion/baseline+cranelift + --wasm-verbose + --ion-full-warmup-threshold=1 +*/ + +if (typeof(process) != 'undefined') { // Node.js environment? + var scriptArgs = process.argv.slice(2); + const fs = require('fs'); + var readFile = (fn) => new Uint8Array(fs.readFileSync(fn)); +} else { + var readFile = (fn) => read(fn, 'binary'); +} + + +// Encode string into Uint8Array (with '\0' terminator) +// Could use TextEncoder instead +function encode(str) { + const len = str.length; + const res = new Uint8Array(len + 1); + let pos = 0; + for (let i = 0; i < len; i++) { + const point = str.charCodeAt(i); + if (point <= 0x007f) { + res[pos++] = point; + } + } + return res.subarray(0, pos + 1); +} + +let instance; +let runtimes = {}; + +const imports = { + "env": { + "emscripten_notify_memory_growth": function() {}, + "emscripten_get_sbrk_ptr": function() {}, + }, + "wasi_snapshot_preview1": { + "fd_close": function() { return -1; }, + "fd_seek": function() { return -1; }, + "fd_write": function() { return -1; }, + "proc_exit": function() { } + } +} + +function load(buff) { + const runtime = instance.exports.new_runtime(); + const ptr = instance.exports.malloc(buff.length); + const mem = new Uint8Array(instance.exports.memory.buffer); + mem.set(buff, ptr); + instance.exports.load(runtime, ptr, buff.length); + runtimes[runtime] = { binary_ptr: ptr } + return runtime; +} + +function unload(runtime) { + if (!runtimes[runtime]) return; + instance.exports.free_runtime(runtime); + instance.exports.free(runtimes[runtime].binary_ptr); + runtimes[runtime] = undefined; +} + +function call(runtime, fname, args) { + // Convert names to buffers + args = [fname].concat(args).map(arg => encode(arg.toString())); + + const arglen = args.length; + let argbytes = arglen*4; + for (let arg of args) { + argbytes += arg.length; + } + + // Allocate the required memory + const buff = instance.exports.malloc(argbytes); + const mem = new Uint8Array(instance.exports.memory.buffer); + const ptrs = new Uint32Array(mem.buffer, buff, arglen); + + // Fill-in memory + let ptr = buff + ptrs.byteLength; + for (let i=0; i { + instance = (await WebAssembly.instantiate(readFile('wasm3.wasm'), imports)).instance; + instance.exports.init(); + + const wasm = scriptArgs[0]; + const func = scriptArgs[1]; + const args = scriptArgs.slice(2); + + const binary = readFile(wasm); + + for (let i=0; i<100000; i++) { + let module = load(binary); + + let result = call(module, func, args); + //console.log(i, result); + + unload(module); + } + + console.log(`Memory size: ${instance.exports.memory.buffer.byteLength/(1024*1024)} MB`); +})(); diff --git a/wasm3-sys/wasm3/platforms/ios/.gitignore b/wasm3-sys/wasm3/platforms/ios/.gitignore new file mode 100644 index 0000000..5073505 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/.gitignore @@ -0,0 +1,2 @@ +## User settings +xcuserdata/ diff --git a/wasm3-sys/wasm3/platforms/ios/README.md b/wasm3-sys/wasm3/platforms/ios/README.md new file mode 100644 index 0000000..4fd1a31 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/README.md @@ -0,0 +1,17 @@ +## Build for iOS + +


+ Wasm3 running on iPhone 8 +

+ + +Install Xcode, then open and build the project as usual. + +**Note:** Xcode runs apps in `Debug` mode by default. Select `Release` mode for significantly better performance. + +You can also build the project from command line: + +```sh +xcodebuild build -scheme wasm3 -project wasm3.xcodeproj -configuration Release -destination 'platform=iOS Simulator,name=iPhone 11,OS=13.3' +``` + diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.pbxproj b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.pbxproj new file mode 100644 index 0000000..8306fd2 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.pbxproj @@ -0,0 +1,465 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 3D1B3B1123C8E20D00142C16 /* m3_api_libc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AF423C8E20C00142C16 /* m3_api_libc.c */; }; + 3D1B3B1223C8E20D00142C16 /* m3_api_meta_wasi.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AF623C8E20C00142C16 /* m3_api_meta_wasi.c */; }; + 3D1B3B1323C8E20D00142C16 /* m3_api_wasi.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AF723C8E20C00142C16 /* m3_api_wasi.c */; }; + 3D1B3B1423C8E20D00142C16 /* m3_bind.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AF923C8E20C00142C16 /* m3_bind.c */; }; + 3D1B3B1523C8E20D00142C16 /* m3_code.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AFA23C8E20C00142C16 /* m3_code.c */; }; + 3D1B3B1623C8E20D00142C16 /* m3_compile.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AFC23C8E20C00142C16 /* m3_compile.c */; }; + 3D1B3B1723C8E20D00142C16 /* m3_core.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0023C8E20C00142C16 /* m3_core.c */; }; + 3D1B3B1823C8E20D00142C16 /* m3_emit.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0223C8E20C00142C16 /* m3_emit.c */; }; + 3D1B3B1923C8E20D00142C16 /* m3_env.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0423C8E20C00142C16 /* m3_env.c */; }; + 3D1B3B1A23C8E20D00142C16 /* m3_exec.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0723C8E20C00142C16 /* m3_exec.c */; }; + 3D1B3B1B23C8E20D00142C16 /* m3_info.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0A23C8E20C00142C16 /* m3_info.c */; }; + 3D1B3B1C23C8E20D00142C16 /* m3_module.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0D23C8E20C00142C16 /* m3_module.c */; }; + 3D1B3B1E23C8E20D00142C16 /* m3_parse.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0F23C8E20C00142C16 /* m3_parse.c */; }; + 3D1ED51023C8C8E70072E395 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1ED50F23C8C8E70072E395 /* AppDelegate.swift */; }; + 3D1ED51223C8C8E70072E395 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1ED51123C8C8E70072E395 /* ViewController.swift */; }; + 3D1ED51523C8C8E70072E395 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3D1ED51323C8C8E70072E395 /* Main.storyboard */; }; + 3D1ED51723C8C8E70072E395 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3D1ED51623C8C8E70072E395 /* Assets.xcassets */; }; + 3D1ED51A23C8C8E70072E395 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3D1ED51823C8C8E70072E395 /* LaunchScreen.storyboard */; }; + 3D1ED52423C8CB560072E395 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1ED52223C8CB560072E395 /* main.c */; }; + 3D3C322E23C9319A00DB9F7E /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D3C322D23C9319A00DB9F7E /* icon.png */; }; + B5E985C8262018B700FBE0FC /* m3_function.c in Sources */ = {isa = PBXBuildFile; fileRef = B5E985C7262018B700FBE0FC /* m3_function.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 3D1B3AEE23C8E20C00142C16 /* fib32.wasm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fib32.wasm.h; sourceTree = ""; }; + 3D1B3AEF23C8E20C00142C16 /* fib32_tail.wasm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fib32_tail.wasm.h; sourceTree = ""; }; + 3D1B3AF023C8E20C00142C16 /* fib64.wasm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fib64.wasm.h; sourceTree = ""; }; + 3D1B3AF123C8E20C00142C16 /* wasi_core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wasi_core.h; sourceTree = ""; }; + 3D1B3AF423C8E20C00142C16 /* m3_api_libc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_api_libc.c; sourceTree = ""; }; + 3D1B3AF523C8E20C00142C16 /* m3_api_libc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_api_libc.h; sourceTree = ""; }; + 3D1B3AF623C8E20C00142C16 /* m3_api_meta_wasi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_api_meta_wasi.c; sourceTree = ""; }; + 3D1B3AF723C8E20C00142C16 /* m3_api_wasi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_api_wasi.c; sourceTree = ""; }; + 3D1B3AF823C8E20C00142C16 /* m3_api_wasi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_api_wasi.h; sourceTree = ""; }; + 3D1B3AF923C8E20C00142C16 /* m3_bind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_bind.c; sourceTree = ""; }; + 3D1B3AFA23C8E20C00142C16 /* m3_code.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_code.c; sourceTree = ""; }; + 3D1B3AFB23C8E20C00142C16 /* m3_code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_code.h; sourceTree = ""; }; + 3D1B3AFC23C8E20C00142C16 /* m3_compile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_compile.c; sourceTree = ""; }; + 3D1B3AFD23C8E20C00142C16 /* m3_compile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_compile.h; sourceTree = ""; }; + 3D1B3AFE23C8E20C00142C16 /* m3_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_config.h; sourceTree = ""; }; + 3D1B3AFF23C8E20C00142C16 /* m3_config_platforms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_config_platforms.h; sourceTree = ""; }; + 3D1B3B0023C8E20C00142C16 /* m3_core.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_core.c; sourceTree = ""; }; + 3D1B3B0123C8E20C00142C16 /* m3_core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_core.h; sourceTree = ""; }; + 3D1B3B0223C8E20C00142C16 /* m3_emit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_emit.c; sourceTree = ""; }; + 3D1B3B0323C8E20C00142C16 /* m3_emit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_emit.h; sourceTree = ""; }; + 3D1B3B0423C8E20C00142C16 /* m3_env.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_env.c; sourceTree = ""; }; + 3D1B3B0523C8E20C00142C16 /* m3_env.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_env.h; sourceTree = ""; }; + 3D1B3B0623C8E20C00142C16 /* m3_exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_exception.h; sourceTree = ""; }; + 3D1B3B0723C8E20C00142C16 /* m3_exec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_exec.c; sourceTree = ""; }; + 3D1B3B0823C8E20C00142C16 /* m3_exec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_exec.h; sourceTree = ""; }; + 3D1B3B0923C8E20C00142C16 /* m3_exec_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_exec_defs.h; sourceTree = ""; }; + 3D1B3B0A23C8E20C00142C16 /* m3_info.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_info.c; sourceTree = ""; }; + 3D1B3B0B23C8E20C00142C16 /* m3_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_info.h; sourceTree = ""; }; + 3D1B3B0C23C8E20C00142C16 /* m3_math_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_math_utils.h; sourceTree = ""; }; + 3D1B3B0D23C8E20C00142C16 /* m3_module.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_module.c; sourceTree = ""; }; + 3D1B3B0F23C8E20C00142C16 /* m3_parse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_parse.c; sourceTree = ""; }; + 3D1ED50C23C8C8E70072E395 /* wasm3.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = wasm3.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3D1ED50F23C8C8E70072E395 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 3D1ED51123C8C8E70072E395 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 3D1ED51423C8C8E70072E395 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 3D1ED51623C8C8E70072E395 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 3D1ED51923C8C8E70072E395 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 3D1ED51B23C8C8E70072E395 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 3D1ED52123C8CB550072E395 /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; + 3D1ED52223C8CB560072E395 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 3D3C322D23C9319A00DB9F7E /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = ""; }; + 3D3EC19D23D558D5008FD665 /* wasm3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wasm3.h; sourceTree = ""; }; + B5E985C6262018B700FBE0FC /* m3_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_function.h; sourceTree = ""; }; + B5E985C7262018B700FBE0FC /* m3_function.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_function.c; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3D1ED50923C8C8E70072E395 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3D1B3AEC23C8E20C00142C16 /* source */ = { + isa = PBXGroup; + children = ( + B5E985C7262018B700FBE0FC /* m3_function.c */, + B5E985C6262018B700FBE0FC /* m3_function.h */, + 3D1B3AED23C8E20C00142C16 /* extra */, + 3D3EC19D23D558D5008FD665 /* wasm3.h */, + 3D1B3AF423C8E20C00142C16 /* m3_api_libc.c */, + 3D1B3AF523C8E20C00142C16 /* m3_api_libc.h */, + 3D1B3AF623C8E20C00142C16 /* m3_api_meta_wasi.c */, + 3D1B3AF723C8E20C00142C16 /* m3_api_wasi.c */, + 3D1B3AF823C8E20C00142C16 /* m3_api_wasi.h */, + 3D1B3AF923C8E20C00142C16 /* m3_bind.c */, + 3D1B3AFA23C8E20C00142C16 /* m3_code.c */, + 3D1B3AFB23C8E20C00142C16 /* m3_code.h */, + 3D1B3AFC23C8E20C00142C16 /* m3_compile.c */, + 3D1B3AFD23C8E20C00142C16 /* m3_compile.h */, + 3D1B3AFE23C8E20C00142C16 /* m3_config.h */, + 3D1B3AFF23C8E20C00142C16 /* m3_config_platforms.h */, + 3D1B3B0023C8E20C00142C16 /* m3_core.c */, + 3D1B3B0123C8E20C00142C16 /* m3_core.h */, + 3D1B3B0223C8E20C00142C16 /* m3_emit.c */, + 3D1B3B0323C8E20C00142C16 /* m3_emit.h */, + 3D1B3B0423C8E20C00142C16 /* m3_env.c */, + 3D1B3B0523C8E20C00142C16 /* m3_env.h */, + 3D1B3B0623C8E20C00142C16 /* m3_exception.h */, + 3D1B3B0723C8E20C00142C16 /* m3_exec.c */, + 3D1B3B0823C8E20C00142C16 /* m3_exec.h */, + 3D1B3B0923C8E20C00142C16 /* m3_exec_defs.h */, + 3D1B3B0A23C8E20C00142C16 /* m3_info.c */, + 3D1B3B0B23C8E20C00142C16 /* m3_info.h */, + 3D1B3B0C23C8E20C00142C16 /* m3_math_utils.h */, + 3D1B3B0D23C8E20C00142C16 /* m3_module.c */, + 3D1B3B0F23C8E20C00142C16 /* m3_parse.c */, + ); + name = source; + path = ../../source; + sourceTree = SOURCE_ROOT; + }; + 3D1B3AED23C8E20C00142C16 /* extra */ = { + isa = PBXGroup; + children = ( + 3D1B3AEE23C8E20C00142C16 /* fib32.wasm.h */, + 3D1B3AEF23C8E20C00142C16 /* fib32_tail.wasm.h */, + 3D1B3AF023C8E20C00142C16 /* fib64.wasm.h */, + 3D1B3AF123C8E20C00142C16 /* wasi_core.h */, + ); + path = extra; + sourceTree = ""; + }; + 3D1ED50323C8C8E70072E395 = { + isa = PBXGroup; + children = ( + 3D1ED50E23C8C8E70072E395 /* wasm3 */, + 3D1ED50D23C8C8E70072E395 /* Products */, + ); + sourceTree = ""; + }; + 3D1ED50D23C8C8E70072E395 /* Products */ = { + isa = PBXGroup; + children = ( + 3D1ED50C23C8C8E70072E395 /* wasm3.app */, + ); + name = Products; + sourceTree = ""; + }; + 3D1ED50E23C8C8E70072E395 /* wasm3 */ = { + isa = PBXGroup; + children = ( + 3D1B3AEC23C8E20C00142C16 /* source */, + 3D1ED50F23C8C8E70072E395 /* AppDelegate.swift */, + 3D1ED51123C8C8E70072E395 /* ViewController.swift */, + 3D1ED51323C8C8E70072E395 /* Main.storyboard */, + 3D1ED51623C8C8E70072E395 /* Assets.xcassets */, + 3D1ED51823C8C8E70072E395 /* LaunchScreen.storyboard */, + 3D1ED51B23C8C8E70072E395 /* Info.plist */, + 3D1ED52223C8CB560072E395 /* main.c */, + 3D3C322D23C9319A00DB9F7E /* icon.png */, + 3D1ED52123C8CB550072E395 /* Bridging-Header.h */, + ); + path = wasm3; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 3D1ED50B23C8C8E70072E395 /* wasm3 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3D1ED51E23C8C8E70072E395 /* Build configuration list for PBXNativeTarget "wasm3" */; + buildPhases = ( + 3D1ED50823C8C8E70072E395 /* Sources */, + 3D1ED50923C8C8E70072E395 /* Frameworks */, + 3D1ED50A23C8C8E70072E395 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = wasm3; + productName = wasm3; + productReference = 3D1ED50C23C8C8E70072E395 /* wasm3.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3D1ED50423C8C8E70072E395 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0900; + LastUpgradeCheck = 1130; + ORGANIZATIONNAME = wasm3; + TargetAttributes = { + 3D1ED50B23C8C8E70072E395 = { + CreatedOnToolsVersion = 9.0.1; + LastSwiftMigration = 0900; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 3D1ED50723C8C8E70072E395 /* Build configuration list for PBXProject "wasm3" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 3D1ED50323C8C8E70072E395; + productRefGroup = 3D1ED50D23C8C8E70072E395 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3D1ED50B23C8C8E70072E395 /* wasm3 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3D1ED50A23C8C8E70072E395 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D1ED51A23C8C8E70072E395 /* LaunchScreen.storyboard in Resources */, + 3D3C322E23C9319A00DB9F7E /* icon.png in Resources */, + 3D1ED51723C8C8E70072E395 /* Assets.xcassets in Resources */, + 3D1ED51523C8C8E70072E395 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3D1ED50823C8C8E70072E395 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D1B3B1323C8E20D00142C16 /* m3_api_wasi.c in Sources */, + 3D1B3B1123C8E20D00142C16 /* m3_api_libc.c in Sources */, + 3D1B3B1723C8E20D00142C16 /* m3_core.c in Sources */, + B5E985C8262018B700FBE0FC /* m3_function.c in Sources */, + 3D1ED51223C8C8E70072E395 /* ViewController.swift in Sources */, + 3D1B3B1A23C8E20D00142C16 /* m3_exec.c in Sources */, + 3D1B3B1223C8E20D00142C16 /* m3_api_meta_wasi.c in Sources */, + 3D1B3B1823C8E20D00142C16 /* m3_emit.c in Sources */, + 3D1B3B1523C8E20D00142C16 /* m3_code.c in Sources */, + 3D1B3B1423C8E20D00142C16 /* m3_bind.c in Sources */, + 3D1B3B1C23C8E20D00142C16 /* m3_module.c in Sources */, + 3D1B3B1B23C8E20D00142C16 /* m3_info.c in Sources */, + 3D1ED51023C8C8E70072E395 /* AppDelegate.swift in Sources */, + 3D1B3B1923C8E20D00142C16 /* m3_env.c in Sources */, + 3D1B3B1623C8E20D00142C16 /* m3_compile.c in Sources */, + 3D1ED52423C8CB560072E395 /* main.c in Sources */, + 3D1B3B1E23C8E20D00142C16 /* m3_parse.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 3D1ED51323C8C8E70072E395 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3D1ED51423C8C8E70072E395 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 3D1ED51823C8C8E70072E395 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3D1ED51923C8C8E70072E395 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 3D1ED51C23C8C8E70072E395 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ""; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 3D1ED51D23C8C8E70072E395 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = "-fomit-frame-pointer"; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 3D1ED51F23C8C8E70072E395 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = wasm3/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.wasm3; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "wasm3/Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3D1ED52023C8C8E70072E395 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = wasm3/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.wasm3; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "wasm3/Bridging-Header.h"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3D1ED50723C8C8E70072E395 /* Build configuration list for PBXProject "wasm3" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3D1ED51C23C8C8E70072E395 /* Debug */, + 3D1ED51D23C8C8E70072E395 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3D1ED51E23C8C8E70072E395 /* Build configuration list for PBXNativeTarget "wasm3" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3D1ED51F23C8C8E70072E395 /* Debug */, + 3D1ED52023C8C8E70072E395 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3D1ED50423C8C8E70072E395 /* Project object */; +} diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..b90c664 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + + diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3 Release.xcscheme b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3 Release.xcscheme new file mode 100644 index 0000000..f65f4f6 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3 Release.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3.xcscheme b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3.xcscheme new file mode 100644 index 0000000..d925f22 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3/AppDelegate.swift b/wasm3-sys/wasm3/platforms/ios/wasm3/AppDelegate.swift new file mode 100644 index 0000000..99e5823 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// wasm3 +// +// Created by Volodymyr Shymanskyy on 1/10/20. +// Copyright © 2020 wasm3. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3/Assets.xcassets/AppIcon.appiconset/Contents.json b/wasm3-sys/wasm3/platforms/ios/wasm3/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d8db8d6 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3/Base.lproj/LaunchScreen.storyboard b/wasm3-sys/wasm3/platforms/ios/wasm3/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..438943d --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3/Base.lproj/Main.storyboard b/wasm3-sys/wasm3/platforms/ios/wasm3/Base.lproj/Main.storyboard new file mode 100644 index 0000000..280c7f8 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3/Base.lproj/Main.storyboard @@ -0,0 +1,55 @@ + + + + + + + + + + + + + Menlo-Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3/Bridging-Header.h b/wasm3-sys/wasm3/platforms/ios/wasm3/Bridging-Header.h new file mode 100644 index 0000000..efa8f80 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3/Bridging-Header.h @@ -0,0 +1,8 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +typedef void (*print_cbk_t)(const char* buff, int len); + +void redirect_output (print_cbk_t f); +int run_app (void); diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3/Info.plist b/wasm3-sys/wasm3/platforms/ios/wasm3/Info.plist new file mode 100644 index 0000000..d67a26c --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleIconFiles + + logo.png + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3/ViewController.swift b/wasm3-sys/wasm3/platforms/ios/wasm3/ViewController.swift new file mode 100644 index 0000000..77b1b43 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3/ViewController.swift @@ -0,0 +1,41 @@ +// +// ViewController.swift +// wasm3 +// +// Created by Volodymyr Shymanskyy on 1/10/20. +// Copyright © 2020 wasm3. All rights reserved. +// + +import UIKit + +var gLog: UITextView! + +class ViewController: UIViewController { + + // MARK: Properties + @IBOutlet var log: UITextView! + + override func viewDidLoad() { + super.viewDidLoad() + + gLog = log + + redirect_output({ + if let ptr = $0 { + let data = Data(bytes: ptr, count: Int($1)) + if let str = String(data: data, encoding: String.Encoding.utf8) { + DispatchQueue.main.async { + gLog.text += str + } + } + } + }) + + run_app() + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + } +} + diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3/icon.png b/wasm3-sys/wasm3/platforms/ios/wasm3/icon.png new file mode 100644 index 0000000..85c1d06 Binary files /dev/null and b/wasm3-sys/wasm3/platforms/ios/wasm3/icon.png differ diff --git a/wasm3-sys/wasm3/platforms/ios/wasm3/main.c b/wasm3-sys/wasm3/platforms/ios/wasm3/main.c new file mode 100644 index 0000000..7380fd8 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/ios/wasm3/main.c @@ -0,0 +1,148 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wasm3.h" +#include "m3_config.h" + +#include "fib32.wasm.h" + +#define FIB_ARG_VALUE "40" +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +uint32_t fib_native(uint32_t n) { + if (n < 2) return n; + return fib_native(n - 1) + fib_native(n - 2); +} + +// same function uses on fib.wasm so we preserve is as is. +// Note: for prevent precalculation FIB_ARG_VALUE on compile time we need disable inlining +__attribute__((noinline)) +int parseInt(char* str) { + int res = 0; + for (int i = 0; str[i] != '\0'; ++i) { + res = res * 10 + str[i] - '0'; + } + return res; +} + +void run_native() { + printf("Running fib(" FIB_ARG_VALUE ") on Native C...\n"); + + clock_t start = clock(); + uint32_t result = fib_native(parseInt(FIB_ARG_VALUE)); + clock_t end = clock(); + + printf("Result: %u\n", result); + printf("Elapsed: %ld ms\n", (end - start) * 1000 / CLOCKS_PER_SEC); +} + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + uint32_t fsize = fib32_wasm_len; + + printf("Loading WebAssembly...\n"); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 8192, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running fib(" FIB_ARG_VALUE ") on WebAssembly...\n"); + + const char* i_argv[2] = { FIB_ARG_VALUE, NULL }; + + clock_t start = clock(); + result = m3_CallArgv (f, 1, i_argv); + clock_t end = clock(); + + if (result) FATAL("m3_Call: %s", result); + printf("Elapsed: %ld ms\n\n", (end - start) * 1000 / CLOCKS_PER_SEC); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %d\n", value); +} + +static void* runMain(void* ctx) +{ + struct utsname systemInfo; + uname(&systemInfo); + + printf("Wasm3 v" M3_VERSION " on iOS (" M3_ARCH ")\n"); + printf("Build " __DATE__ " " __TIME__ "\n"); + printf("Device: %s\n\n", systemInfo.machine); + + run_wasm(); + run_native(); + + return 0; +} + +// +// Swift Bridging +// + +#include "Bridging-Header.h" + +static print_cbk_t gPrintFunc; + +static int stdout_redirect(void* prefix, const char* buffer, int size) +{ + if (gPrintFunc) + gPrintFunc(buffer, size); + return size; +} + +void redirect_output(print_cbk_t f) +{ + gPrintFunc = f; + + setvbuf(stdout, 0, _IOLBF, 0); // stdout: line-buffered + setvbuf(stderr, 0, _IONBF, 0); // stderr: unbuffered + + stdout->_write = stdout_redirect; + stderr->_write = stdout_redirect; +} + +int run_app() +{ + mlockall(MCL_CURRENT | MCL_FUTURE); + static pthread_t mainThread; + pthread_attr_t threadAttr; + pthread_attr_init(&threadAttr); + pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED); + pthread_create(&mainThread, &threadAttr, runMain, NULL); + pthread_attr_destroy(&threadAttr); + return 0; +} + diff --git a/wasm3-sys/wasm3/platforms/openwrt/README.md b/wasm3-sys/wasm3/platforms/openwrt/README.md new file mode 100644 index 0000000..70dd8c3 --- /dev/null +++ b/wasm3-sys/wasm3/platforms/openwrt/README.md @@ -0,0 +1,6 @@ +# wasm3 for OpenWrt + +You can find `wasm3` package and build instructions here: + +https://github.com/wasm3/wasm3-openwrt-packages + diff --git a/wasm3-sys/wasm3/platforms/openwrt/build/Makefile b/wasm3-sys/wasm3/platforms/openwrt/build/Makefile new file mode 100644 index 0000000..59bd8cd --- /dev/null +++ b/wasm3-sys/wasm3/platforms/openwrt/build/Makefile @@ -0,0 +1,15 @@ + +M3_SRC_DIR := ../../../source + +SOURCES := ../../app/main.c \ + $(shell find $(M3_SRC_DIR) -type f -name '*.c') + +override CFLAGS += -std=c99 -O3 -flto -Wno-error=format-security -Wfatal-errors -I$(M3_SRC_DIR) + +all: wasm3 + +wasm3: $(SOURCES) + $(CC) $(CFLAGS) $(SOURCES) -o wasm3 -lm + +clean: + $(RM) wasm3 diff --git a/wasm3-sys/wasm3/platforms/python/README.md b/wasm3-sys/wasm3/platforms/python/README.md new file mode 100644 index 0000000..38b89df --- /dev/null +++ b/wasm3-sys/wasm3/platforms/python/README.md @@ -0,0 +1,5 @@ +# pywasm3 + +Python binding for Wasm3, the fastest WebAssembly interpreter. + +## Moved to https://github.com/wasm3/pywasm3 diff --git a/wasm3-sys/wasm3/source/CMakeLists.txt b/wasm3-sys/wasm3/source/CMakeLists.txt new file mode 100644 index 0000000..070c7fa --- /dev/null +++ b/wasm3-sys/wasm3/source/CMakeLists.txt @@ -0,0 +1,58 @@ +set(sources + "m3_api_libc.c" + "m3_api_wasi.c" + "m3_api_uvwasi.c" + "m3_api_meta_wasi.c" + "m3_api_tracer.c" + "m3_bind.c" + "m3_code.c" + "m3_compile.c" + "m3_core.c" + "m3_emit.c" + "m3_env.c" + "m3_exec.c" + "m3_function.c" + "m3_info.c" + "m3_module.c" + "m3_parse.c" +) + +add_library(m3 STATIC ${sources}) + +target_include_directories(m3 PUBLIC .) + +target_compile_features(m3 PRIVATE c_std_99) + +if (CMAKE_C_COMPILER_ID MATCHES "MSVC") + # add MSVC specific flags here +else() + # Flags common for GCC and Clang + + # FIXME: cast to 'void *' from smaller integer type 'i32' + set_source_files_properties(m3_emit.c PROPERTIES COMPILE_FLAGS -Wno-int-to-pointer-cast) + + # FIXME: comparison of integers of different signs: 'u32' and 'i32' + set_source_files_properties(m3_env.c PROPERTIES COMPILE_FLAGS -Wno-sign-compare) + + if (WASIENV) + # FIXME: declaration of 'struct sigaction' will not be visible outside of this function + target_compile_options(m3 PUBLIC -Wno-visibility) + # FIXME incompatible pointer types passing 'u32 *' to parameter of type 'char **' + set_source_files_properties(m3_api_meta_wasi.c PROPERTIES COMPILE_FLAGS -Wno-incompatible-pointer-types) + endif() + + if (CMAKE_C_COMPILER_ID MATCHES "Clang") + # Clang specific flags here + else() + # GCC specific flags here + endif() +endif() + +if(BUILD_WASI MATCHES "simple") + target_compile_definitions(m3 PUBLIC d_m3HasWASI) +elseif(BUILD_WASI MATCHES "metawasi") + target_compile_definitions(m3 PUBLIC d_m3HasMetaWASI) +elseif(BUILD_WASI MATCHES "uvwasi") + target_compile_definitions(m3 PUBLIC d_m3HasUVWASI) + include_directories("${libuv_SOURCE_DIR}/include") +endif() diff --git a/wasm3-sys/wasm3/source/extensions/m3_extensions.c b/wasm3-sys/wasm3/source/extensions/m3_extensions.c new file mode 100644 index 0000000..17ba6ee --- /dev/null +++ b/wasm3-sys/wasm3/source/extensions/m3_extensions.c @@ -0,0 +1,112 @@ +// +// m3_extensions.c +// +// Created by Steven Massey on 3/30/21. +// Copyright © 2021 Steven Massey. All rights reserved. +// + +#include "wasm3_ext.h" + +#include "m3_env.h" +#include "m3_bind.h" +#include "m3_exception.h" + + +IM3Module m3_NewModule (IM3Environment i_environment) +{ + IM3Module module = m3_AllocStruct (M3Module); + + if (module) + { + module->name = ".unnamed"; + module->startFunction = -1; + module->environment = i_environment; + + module->wasmStart = NULL; + module->wasmEnd = NULL; + } + + return module; +} + + + +M3Result m3_InjectFunction (IM3Module i_module, + int32_t * io_functionIndex, + const char * const i_signature, + const uint8_t * const i_wasmBytes, + bool i_doCompilation) +{ + M3Result result = m3Err_none; d_m3Assert (io_functionIndex); + + IM3Function function = NULL; + IM3FuncType ftype = NULL; +_ (SignatureToFuncType (& ftype, i_signature)); + + i32 index = * io_functionIndex; + + bytes_t bytes = i_wasmBytes; + bytes_t end = i_wasmBytes + 5; + + u32 size; +_ (ReadLEB_u32 (& size, & bytes, end)); + end = bytes + size; + + if (index >= 0) + { + _throwif ("function index out of bounds", index >= i_module->numFunctions); + + function = & i_module->functions [index]; + + if (not AreFuncTypesEqual (ftype, function->funcType)) + _throw ("function type mismatch"); + } + else + { + // add slot to function type table in the module + u32 funcTypeIndex = i_module->numFuncTypes++; + i_module->funcTypes = m3_ReallocArray (IM3FuncType, i_module->funcTypes, i_module->numFuncTypes, funcTypeIndex); + _throwifnull (i_module->funcTypes); + + // add functype object to the environment + Environment_AddFuncType (i_module->environment, & ftype); + i_module->funcTypes [funcTypeIndex] = ftype; + ftype = NULL; // prevent freeing below + + index = (i32) i_module->numFunctions; +_ (Module_AddFunction (i_module, funcTypeIndex, NULL)); + function = Module_GetFunction (i_module, index); + + * io_functionIndex = index; + } + + function->compiled = NULL; + + if (function->ownsWasmCode) + m3_Free (function->wasm); + + size_t numBytes = end - i_wasmBytes; + function->wasm = m3_CopyMem (i_wasmBytes, numBytes); + _throwifnull (function->wasm); + + function->wasmEnd = function->wasm + numBytes; + function->ownsWasmCode = true; + + function->module = i_module; + + if (i_doCompilation and not i_module->runtime) + _throw ("module must be loaded into runtime to compile function"); + +_ (CompileFunction (function)); + + _catch: + m3_Free (ftype); + + return result; +} + + +IM3Function m3_GetFunctionByIndex (IM3Module i_module, uint32_t i_index) +{ + return Module_GetFunction (i_module, i_index); +} diff --git a/wasm3-sys/wasm3/source/extensions/wasm3_ext.h b/wasm3-sys/wasm3/source/extensions/wasm3_ext.h new file mode 100644 index 0000000..2de1fc3 --- /dev/null +++ b/wasm3-sys/wasm3/source/extensions/wasm3_ext.h @@ -0,0 +1,51 @@ +// +// Wasm3, high performance WebAssembly interpreter +// +// Extensions +// +// Copyright © 2019-2021 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#ifndef wasm3_ext_h +#define wasm3_ext_h + +#include "wasm3.h" +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +//------------------------------------------------------------------------------------------------------------------------------- +// API extensions +//------------------------------------------------------------------------------------------------------------------------------- +/* + These extensions allow for unconventional uses of Wasm3 -- mainly dynamic modification of modules to inject new Wasm + functions during runtime. +*/ +//------------------------------------------------------------------------------------------------------------------------------- + + // Creates an empty module. + IM3Module m3_NewModule (IM3Environment i_environment); + + + // To append a new function, set io_functionIndex to negative. On return, the new function index will be set. + // To overwrite an existing function, set io_functionIndex to the desired element. i_signature must match the existing + // function signature. + // ** InjectFunction invalidates any existing IM3Function pointers + M3Result m3_InjectFunction (IM3Module i_module, + int32_t * io_functionIndex, + const char * const i_signature, + const uint8_t * const i_wasmBytes, // i_wasmBytes is copied + bool i_doCompilation); + + + IM3Function m3_GetFunctionByIndex (IM3Module i_module, + uint32_t i_index); + +#if defined(__cplusplus) +} +#endif + +#endif // wasm3_h diff --git a/wasm3-sys/wasm3/source/extra/coremark_minimal.wasm.h b/wasm3-sys/wasm3/source/extra/coremark_minimal.wasm.h new file mode 100644 index 0000000..cf5aba8 --- /dev/null +++ b/wasm3-sys/wasm3/source/extra/coremark_minimal.wasm.h @@ -0,0 +1,651 @@ +unsigned char coremark_minimal_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x3e, 0x0a, 0x60, + 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x00, 0x60, 0x02, 0x7f, 0x7f, + 0x00, 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x00, 0x60, 0x04, 0x7f, 0x7f, 0x7f, + 0x7f, 0x00, 0x60, 0x00, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x01, + 0x7f, 0x60, 0x05, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x06, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x7d, + 0x02, 0x10, 0x01, 0x03, 0x65, 0x6e, 0x76, 0x08, 0x63, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x6d, 0x73, 0x00, 0x05, 0x03, 0x10, 0x0f, 0x00, 0x00, 0x06, + 0x09, 0x07, 0x04, 0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, + 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x07, 0x01, 0x7f, 0x01, 0x41, 0x80, + 0x04, 0x0b, 0x07, 0x10, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, + 0x02, 0x00, 0x03, 0x72, 0x75, 0x6e, 0x00, 0x04, 0x0a, 0x82, 0x39, 0x0f, + 0xdb, 0x01, 0x01, 0x04, 0x7f, 0x20, 0x00, 0x2f, 0x01, 0x00, 0x22, 0x03, + 0x41, 0x80, 0x01, 0x71, 0x04, 0x40, 0x20, 0x03, 0x41, 0xff, 0x00, 0x71, + 0x0f, 0x0b, 0x20, 0x03, 0x41, 0x03, 0x76, 0x41, 0x0f, 0x71, 0x22, 0x02, + 0x41, 0x04, 0x74, 0x20, 0x02, 0x72, 0x21, 0x04, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x40, 0x20, 0x03, 0x22, 0x02, 0x41, 0x07, 0x71, 0x0e, 0x02, 0x00, + 0x01, 0x02, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x18, 0x20, 0x01, 0x41, 0x14, + 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x2e, 0x01, 0x00, 0x20, 0x01, 0x2e, + 0x01, 0x02, 0x20, 0x04, 0x41, 0x22, 0x20, 0x04, 0x41, 0x22, 0x4b, 0x1b, + 0x20, 0x01, 0x2f, 0x01, 0x38, 0x10, 0x07, 0x21, 0x02, 0x20, 0x01, 0x2f, + 0x01, 0x3e, 0x0d, 0x01, 0x20, 0x01, 0x20, 0x02, 0x3b, 0x01, 0x3e, 0x0c, + 0x01, 0x0b, 0x20, 0x01, 0x2f, 0x01, 0x38, 0x21, 0x02, 0x20, 0x01, 0x41, + 0x28, 0x6a, 0x22, 0x05, 0x28, 0x02, 0x00, 0x20, 0x05, 0x28, 0x02, 0x0c, + 0x20, 0x05, 0x28, 0x02, 0x04, 0x20, 0x05, 0x28, 0x02, 0x08, 0x20, 0x04, + 0x10, 0x05, 0x20, 0x02, 0x10, 0x0c, 0x21, 0x02, 0x20, 0x01, 0x2f, 0x01, + 0x3c, 0x0d, 0x00, 0x20, 0x01, 0x20, 0x02, 0x3b, 0x01, 0x3c, 0x0b, 0x20, + 0x01, 0x20, 0x02, 0x20, 0x01, 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x3b, 0x01, + 0x38, 0x20, 0x00, 0x20, 0x02, 0x41, 0xff, 0x00, 0x71, 0x22, 0x00, 0x20, + 0x03, 0x41, 0x80, 0xfe, 0x03, 0x71, 0x72, 0x41, 0x80, 0x01, 0x72, 0x3b, + 0x01, 0x00, 0x20, 0x00, 0x0b, 0x97, 0x0a, 0x01, 0x10, 0x7f, 0x20, 0x00, + 0x28, 0x02, 0x24, 0x21, 0x04, 0x02, 0x7f, 0x20, 0x00, 0x2e, 0x01, 0x04, + 0x22, 0x0b, 0x41, 0x01, 0x48, 0x04, 0x40, 0x20, 0x01, 0x21, 0x09, 0x41, + 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x21, 0x09, 0x03, 0x40, 0x20, 0x04, + 0x21, 0x03, 0x02, 0x40, 0x02, 0x40, 0x20, 0x09, 0x41, 0x10, 0x74, 0x41, + 0x10, 0x75, 0x41, 0x7f, 0x4a, 0x04, 0x40, 0x03, 0x40, 0x20, 0x03, 0x28, + 0x02, 0x04, 0x2f, 0x01, 0x02, 0x20, 0x09, 0x41, 0xff, 0xff, 0x03, 0x71, + 0x46, 0x0d, 0x03, 0x20, 0x03, 0x28, 0x02, 0x00, 0x22, 0x03, 0x0d, 0x00, + 0x0b, 0x0c, 0x01, 0x0b, 0x03, 0x40, 0x20, 0x03, 0x28, 0x02, 0x04, 0x2d, + 0x00, 0x00, 0x20, 0x06, 0x41, 0xff, 0x01, 0x71, 0x73, 0x45, 0x0d, 0x02, + 0x20, 0x03, 0x28, 0x02, 0x00, 0x22, 0x03, 0x0d, 0x00, 0x0b, 0x0b, 0x41, + 0x00, 0x21, 0x03, 0x0b, 0x02, 0x40, 0x20, 0x04, 0x45, 0x04, 0x40, 0x41, + 0x00, 0x21, 0x04, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x05, 0x20, 0x04, + 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, 0x22, 0x04, 0x28, 0x02, 0x00, 0x21, + 0x02, 0x20, 0x04, 0x20, 0x05, 0x36, 0x02, 0x00, 0x20, 0x04, 0x21, 0x05, + 0x20, 0x02, 0x0d, 0x00, 0x0b, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x45, 0x04, + 0x40, 0x20, 0x0e, 0x41, 0x01, 0x6a, 0x21, 0x0e, 0x20, 0x04, 0x28, 0x02, + 0x00, 0x28, 0x02, 0x04, 0x2d, 0x00, 0x01, 0x41, 0x01, 0x71, 0x20, 0x0d, + 0x6a, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x20, 0x0f, 0x41, 0x01, 0x6a, 0x21, + 0x0f, 0x20, 0x03, 0x28, 0x02, 0x04, 0x2f, 0x01, 0x00, 0x22, 0x02, 0x41, + 0x09, 0x76, 0x20, 0x02, 0x71, 0x41, 0x01, 0x71, 0x20, 0x0d, 0x6a, 0x21, + 0x0d, 0x20, 0x03, 0x28, 0x02, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x20, + 0x03, 0x20, 0x02, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x02, 0x20, + 0x04, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x04, 0x20, 0x02, 0x36, + 0x02, 0x00, 0x0b, 0x20, 0x09, 0x41, 0x7f, 0x73, 0x41, 0x80, 0x80, 0x02, + 0x71, 0x41, 0x0f, 0x76, 0x20, 0x09, 0x6a, 0x21, 0x09, 0x20, 0x06, 0x41, + 0x10, 0x74, 0x41, 0x80, 0x80, 0x04, 0x6a, 0x41, 0x10, 0x75, 0x22, 0x06, + 0x20, 0x0b, 0x48, 0x0d, 0x00, 0x0b, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x41, + 0xff, 0x01, 0x71, 0x0b, 0x21, 0x10, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, + 0x41, 0x01, 0x48, 0x0d, 0x00, 0x41, 0x01, 0x21, 0x0a, 0x03, 0x40, 0x20, + 0x0a, 0x41, 0x01, 0x48, 0x0d, 0x02, 0x41, 0x00, 0x21, 0x0c, 0x41, 0x00, + 0x21, 0x06, 0x20, 0x04, 0x21, 0x02, 0x41, 0x00, 0x21, 0x04, 0x03, 0x40, + 0x20, 0x0c, 0x22, 0x11, 0x41, 0x01, 0x6a, 0x21, 0x0c, 0x41, 0x00, 0x21, + 0x03, 0x20, 0x02, 0x21, 0x05, 0x02, 0x7f, 0x02, 0x40, 0x03, 0x40, 0x20, + 0x05, 0x28, 0x02, 0x00, 0x22, 0x05, 0x45, 0x0d, 0x01, 0x20, 0x0a, 0x20, + 0x03, 0x41, 0x01, 0x6a, 0x22, 0x03, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x0a, + 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x0b, 0x21, 0x08, 0x20, + 0x02, 0x21, 0x03, 0x20, 0x05, 0x21, 0x02, 0x20, 0x0a, 0x21, 0x07, 0x03, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, 0x02, 0x40, 0x02, 0x7f, 0x02, + 0x40, 0x20, 0x08, 0x41, 0x00, 0x4a, 0x0d, 0x00, 0x20, 0x02, 0x45, 0x0d, + 0x04, 0x20, 0x07, 0x41, 0x01, 0x48, 0x0d, 0x04, 0x20, 0x08, 0x0d, 0x00, + 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x21, 0x07, 0x41, 0x00, 0x21, 0x08, 0x20, + 0x02, 0x28, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x45, 0x0d, 0x01, + 0x20, 0x07, 0x45, 0x0d, 0x01, 0x20, 0x02, 0x28, 0x02, 0x04, 0x21, 0x01, + 0x20, 0x03, 0x28, 0x02, 0x04, 0x20, 0x00, 0x10, 0x01, 0x41, 0xff, 0xff, + 0x03, 0x71, 0x20, 0x01, 0x20, 0x00, 0x10, 0x01, 0x41, 0xff, 0xff, 0x03, + 0x71, 0x4d, 0x0d, 0x01, 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x21, 0x07, 0x20, + 0x02, 0x28, 0x02, 0x00, 0x0b, 0x21, 0x01, 0x20, 0x03, 0x21, 0x0b, 0x20, + 0x02, 0x0c, 0x01, 0x0b, 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x21, 0x08, 0x20, + 0x03, 0x28, 0x02, 0x00, 0x21, 0x0b, 0x20, 0x02, 0x21, 0x01, 0x20, 0x03, + 0x0b, 0x21, 0x05, 0x20, 0x06, 0x45, 0x04, 0x40, 0x20, 0x05, 0x21, 0x04, + 0x0c, 0x02, 0x0b, 0x20, 0x06, 0x20, 0x05, 0x36, 0x02, 0x00, 0x0c, 0x01, + 0x0b, 0x20, 0x02, 0x0d, 0x02, 0x20, 0x06, 0x41, 0x00, 0x36, 0x02, 0x00, + 0x20, 0x0a, 0x41, 0x01, 0x74, 0x21, 0x0a, 0x20, 0x11, 0x0d, 0x03, 0x0c, + 0x04, 0x0b, 0x20, 0x0b, 0x21, 0x03, 0x20, 0x01, 0x21, 0x02, 0x20, 0x05, + 0x21, 0x06, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x20, + 0x0f, 0x41, 0x02, 0x74, 0x20, 0x0e, 0x6b, 0x20, 0x0d, 0x6a, 0x21, 0x0c, + 0x20, 0x04, 0x28, 0x02, 0x00, 0x22, 0x01, 0x28, 0x02, 0x04, 0x21, 0x06, + 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x00, 0x22, 0x00, 0x28, 0x02, 0x04, + 0x36, 0x02, 0x04, 0x20, 0x01, 0x20, 0x00, 0x28, 0x02, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x06, 0x36, 0x02, 0x04, 0x20, 0x00, 0x41, 0x00, + 0x36, 0x02, 0x00, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x09, 0x41, + 0x10, 0x74, 0x41, 0x10, 0x75, 0x41, 0x7f, 0x4c, 0x04, 0x40, 0x20, 0x04, + 0x45, 0x0d, 0x01, 0x20, 0x04, 0x21, 0x02, 0x03, 0x40, 0x20, 0x10, 0x20, + 0x02, 0x28, 0x02, 0x04, 0x2d, 0x00, 0x00, 0x46, 0x0d, 0x03, 0x20, 0x02, + 0x28, 0x02, 0x00, 0x22, 0x02, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, + 0x04, 0x45, 0x0d, 0x00, 0x20, 0x09, 0x41, 0xff, 0xff, 0x03, 0x71, 0x21, + 0x01, 0x20, 0x04, 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, 0x28, 0x02, 0x04, + 0x2f, 0x01, 0x02, 0x20, 0x01, 0x46, 0x0d, 0x02, 0x20, 0x02, 0x28, 0x02, + 0x00, 0x22, 0x02, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x04, 0x28, 0x02, 0x00, + 0x22, 0x02, 0x45, 0x0d, 0x01, 0x0b, 0x03, 0x40, 0x20, 0x04, 0x28, 0x02, + 0x04, 0x2e, 0x01, 0x00, 0x20, 0x0c, 0x41, 0xff, 0xff, 0x03, 0x71, 0x10, + 0x0c, 0x21, 0x0c, 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, 0x02, 0x0d, 0x00, + 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x21, 0x06, 0x0b, 0x20, 0x00, 0x20, + 0x04, 0x28, 0x02, 0x00, 0x22, 0x01, 0x28, 0x02, 0x04, 0x36, 0x02, 0x04, + 0x20, 0x00, 0x20, 0x01, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x01, + 0x20, 0x06, 0x36, 0x02, 0x04, 0x20, 0x01, 0x20, 0x00, 0x36, 0x02, 0x00, + 0x41, 0x01, 0x21, 0x00, 0x03, 0x40, 0x20, 0x00, 0x41, 0x01, 0x4e, 0x04, + 0x40, 0x41, 0x00, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x06, 0x20, 0x04, 0x21, + 0x02, 0x41, 0x00, 0x21, 0x04, 0x03, 0x40, 0x20, 0x0a, 0x22, 0x09, 0x41, + 0x01, 0x6a, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x03, 0x20, 0x02, 0x21, 0x05, + 0x02, 0x7f, 0x02, 0x40, 0x03, 0x40, 0x20, 0x05, 0x28, 0x02, 0x00, 0x22, + 0x05, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x22, + 0x03, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x03, + 0x41, 0x01, 0x6a, 0x0b, 0x21, 0x08, 0x20, 0x02, 0x21, 0x03, 0x20, 0x05, + 0x21, 0x02, 0x20, 0x00, 0x21, 0x07, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x7f, 0x02, 0x40, 0x02, 0x7f, 0x02, 0x40, 0x20, 0x08, 0x41, 0x00, + 0x4a, 0x0d, 0x00, 0x20, 0x02, 0x45, 0x0d, 0x04, 0x20, 0x07, 0x41, 0x01, + 0x48, 0x0d, 0x04, 0x20, 0x08, 0x0d, 0x00, 0x20, 0x07, 0x41, 0x7f, 0x6a, + 0x21, 0x07, 0x41, 0x00, 0x21, 0x08, 0x20, 0x02, 0x28, 0x02, 0x00, 0x0c, + 0x01, 0x0b, 0x20, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x07, 0x45, 0x0d, 0x01, + 0x20, 0x03, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x01, 0x2d, 0x00, 0x01, + 0x3a, 0x00, 0x00, 0x20, 0x02, 0x28, 0x02, 0x04, 0x22, 0x05, 0x20, 0x05, + 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x01, 0x2e, 0x01, 0x02, 0x20, + 0x05, 0x2e, 0x01, 0x02, 0x4c, 0x0d, 0x01, 0x20, 0x07, 0x41, 0x7f, 0x6a, + 0x21, 0x07, 0x20, 0x02, 0x28, 0x02, 0x00, 0x0b, 0x21, 0x0b, 0x20, 0x02, + 0x21, 0x05, 0x20, 0x03, 0x0c, 0x01, 0x0b, 0x20, 0x08, 0x41, 0x7f, 0x6a, + 0x21, 0x08, 0x20, 0x02, 0x21, 0x0b, 0x20, 0x03, 0x21, 0x05, 0x20, 0x03, + 0x28, 0x02, 0x00, 0x0b, 0x21, 0x01, 0x20, 0x06, 0x45, 0x04, 0x40, 0x20, + 0x05, 0x21, 0x04, 0x0c, 0x02, 0x0b, 0x20, 0x06, 0x20, 0x05, 0x36, 0x02, + 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x0d, 0x02, 0x20, 0x06, 0x41, 0x00, + 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x00, 0x20, 0x09, + 0x0d, 0x04, 0x20, 0x04, 0x28, 0x02, 0x00, 0x22, 0x02, 0x04, 0x40, 0x03, + 0x40, 0x20, 0x04, 0x28, 0x02, 0x04, 0x2e, 0x01, 0x00, 0x20, 0x0c, 0x41, + 0xff, 0xff, 0x03, 0x71, 0x10, 0x0c, 0x21, 0x0c, 0x20, 0x02, 0x28, 0x02, + 0x00, 0x22, 0x02, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x0c, 0x41, 0xff, 0xff, + 0x03, 0x71, 0x0f, 0x0b, 0x20, 0x01, 0x21, 0x03, 0x20, 0x0b, 0x21, 0x02, + 0x20, 0x05, 0x21, 0x06, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x0b, + 0x03, 0x40, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x03, 0x40, 0x0c, 0x00, 0x0b, + 0x00, 0x0b, 0xac, 0x05, 0x01, 0x09, 0x7f, 0x20, 0x01, 0x41, 0x00, 0x36, + 0x02, 0x00, 0x20, 0x01, 0x20, 0x01, 0x20, 0x00, 0x41, 0x14, 0x6e, 0x41, + 0x7e, 0x6a, 0x22, 0x06, 0x41, 0x03, 0x74, 0x6a, 0x22, 0x07, 0x36, 0x02, + 0x04, 0x20, 0x07, 0x41, 0x80, 0x81, 0x02, 0x36, 0x01, 0x00, 0x20, 0x07, + 0x20, 0x06, 0x41, 0x02, 0x74, 0x6a, 0x21, 0x09, 0x20, 0x01, 0x41, 0x08, + 0x6a, 0x21, 0x03, 0x20, 0x07, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x02, 0x40, + 0x20, 0x00, 0x41, 0xe4, 0x00, 0x49, 0x0d, 0x00, 0x20, 0x09, 0x20, 0x05, + 0x41, 0x04, 0x6a, 0x22, 0x00, 0x4d, 0x04, 0x40, 0x0c, 0x01, 0x0b, 0x20, + 0x01, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, 0x00, 0x36, 0x02, + 0x08, 0x20, 0x05, 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x36, 0x01, 0x00, + 0x20, 0x01, 0x41, 0x0c, 0x6a, 0x20, 0x05, 0x36, 0x02, 0x00, 0x20, 0x03, + 0x21, 0x04, 0x20, 0x00, 0x21, 0x05, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x21, + 0x03, 0x0b, 0x20, 0x06, 0x04, 0x40, 0x41, 0x00, 0x21, 0x00, 0x03, 0x40, + 0x02, 0x40, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x22, 0x08, 0x20, 0x07, 0x4f, + 0x0d, 0x00, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x22, 0x0a, 0x20, 0x09, 0x4f, + 0x0d, 0x00, 0x20, 0x03, 0x20, 0x04, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, + 0x05, 0x36, 0x02, 0x04, 0x20, 0x05, 0x41, 0xff, 0xff, 0x01, 0x3b, 0x01, + 0x02, 0x20, 0x05, 0x20, 0x00, 0x20, 0x02, 0x73, 0x41, 0x03, 0x74, 0x41, + 0xf8, 0x00, 0x71, 0x20, 0x00, 0x41, 0x07, 0x71, 0x72, 0x22, 0x04, 0x41, + 0x08, 0x74, 0x20, 0x04, 0x72, 0x3b, 0x01, 0x00, 0x20, 0x01, 0x20, 0x03, + 0x36, 0x02, 0x00, 0x20, 0x03, 0x21, 0x04, 0x20, 0x0a, 0x21, 0x05, 0x20, + 0x08, 0x21, 0x03, 0x0b, 0x20, 0x06, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x22, + 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x04, 0x28, 0x02, 0x00, 0x22, + 0x03, 0x04, 0x40, 0x20, 0x06, 0x41, 0x05, 0x6e, 0x21, 0x08, 0x41, 0x01, + 0x21, 0x00, 0x03, 0x40, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x05, 0x20, + 0x04, 0x28, 0x02, 0x04, 0x20, 0x00, 0x20, 0x08, 0x4f, 0x04, 0x7f, 0x20, + 0x05, 0x41, 0x08, 0x74, 0x41, 0x80, 0x0e, 0x71, 0x20, 0x00, 0x20, 0x02, + 0x73, 0x41, 0xff, 0xff, 0x00, 0x71, 0x72, 0x05, 0x20, 0x00, 0x0b, 0x3b, + 0x01, 0x02, 0x20, 0x05, 0x21, 0x00, 0x20, 0x03, 0x22, 0x04, 0x28, 0x02, + 0x00, 0x22, 0x03, 0x0d, 0x00, 0x0b, 0x0b, 0x41, 0x01, 0x21, 0x06, 0x03, + 0x40, 0x20, 0x06, 0x41, 0x01, 0x4e, 0x04, 0x40, 0x41, 0x00, 0x21, 0x09, + 0x41, 0x00, 0x21, 0x05, 0x20, 0x01, 0x21, 0x00, 0x41, 0x00, 0x21, 0x01, + 0x03, 0x40, 0x20, 0x09, 0x22, 0x0b, 0x41, 0x01, 0x6a, 0x21, 0x09, 0x41, + 0x00, 0x21, 0x03, 0x20, 0x00, 0x21, 0x04, 0x02, 0x7f, 0x02, 0x40, 0x03, + 0x40, 0x20, 0x04, 0x28, 0x02, 0x00, 0x22, 0x04, 0x45, 0x0d, 0x01, 0x20, + 0x06, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x22, 0x03, 0x47, 0x0d, 0x00, 0x0b, + 0x20, 0x06, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x0b, 0x21, + 0x07, 0x20, 0x00, 0x21, 0x03, 0x20, 0x04, 0x21, 0x00, 0x20, 0x06, 0x21, + 0x02, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, 0x02, 0x40, 0x02, + 0x7f, 0x02, 0x40, 0x20, 0x07, 0x41, 0x00, 0x4a, 0x0d, 0x00, 0x20, 0x00, + 0x45, 0x0d, 0x04, 0x20, 0x02, 0x41, 0x01, 0x48, 0x0d, 0x04, 0x20, 0x07, + 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x08, 0x41, 0x00, 0x21, + 0x07, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x45, + 0x0d, 0x01, 0x20, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x03, 0x28, 0x02, 0x04, + 0x22, 0x04, 0x20, 0x04, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x00, + 0x28, 0x02, 0x04, 0x22, 0x08, 0x20, 0x08, 0x2d, 0x00, 0x01, 0x3a, 0x00, + 0x00, 0x20, 0x04, 0x2e, 0x01, 0x02, 0x20, 0x08, 0x2e, 0x01, 0x02, 0x4c, + 0x0d, 0x01, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x08, 0x20, 0x02, 0x41, + 0x7f, 0x6a, 0x0b, 0x21, 0x02, 0x20, 0x03, 0x21, 0x0a, 0x20, 0x00, 0x0c, + 0x01, 0x0b, 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x21, 0x07, 0x20, 0x03, 0x28, + 0x02, 0x00, 0x21, 0x0a, 0x20, 0x00, 0x21, 0x08, 0x20, 0x03, 0x0b, 0x21, + 0x04, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x04, 0x21, 0x01, 0x0c, 0x02, + 0x0b, 0x20, 0x05, 0x20, 0x04, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, + 0x00, 0x0d, 0x02, 0x20, 0x05, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x06, + 0x41, 0x01, 0x74, 0x21, 0x06, 0x20, 0x0b, 0x0d, 0x04, 0x20, 0x01, 0x0f, + 0x0b, 0x20, 0x0a, 0x21, 0x03, 0x20, 0x08, 0x21, 0x00, 0x20, 0x04, 0x21, + 0x05, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x0b, 0x03, 0x40, 0x0c, + 0x00, 0x0b, 0x00, 0x0b, 0xa7, 0x0c, 0x03, 0x0f, 0x7f, 0x01, 0x7d, 0x01, + 0x7c, 0x23, 0x00, 0x41, 0xd0, 0x00, 0x6b, 0x22, 0x00, 0x24, 0x00, 0x20, + 0x00, 0x41, 0x00, 0x36, 0x02, 0x4c, 0x20, 0x00, 0x41, 0xc2, 0x00, 0x6a, + 0x22, 0x0e, 0x41, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 0xa0, 0x06, + 0x28, 0x02, 0x00, 0x28, 0x02, 0x00, 0x3b, 0x01, 0x00, 0x20, 0x00, 0x41, + 0xa4, 0x06, 0x28, 0x02, 0x00, 0x28, 0x02, 0x00, 0x3b, 0x01, 0x02, 0x20, + 0x00, 0x41, 0xa8, 0x06, 0x28, 0x02, 0x00, 0x28, 0x02, 0x00, 0x3b, 0x01, + 0x04, 0x20, 0x00, 0x41, 0xac, 0x06, 0x28, 0x02, 0x00, 0x28, 0x02, 0x00, + 0x36, 0x02, 0x1c, 0x20, 0x00, 0x41, 0xb0, 0x06, 0x28, 0x02, 0x00, 0x28, + 0x02, 0x00, 0x22, 0x01, 0x41, 0x07, 0x20, 0x01, 0x1b, 0x22, 0x01, 0x36, + 0x02, 0x20, 0x02, 0x40, 0x20, 0x00, 0x2f, 0x01, 0x04, 0x22, 0x05, 0x20, + 0x00, 0x2f, 0x01, 0x02, 0x22, 0x04, 0x20, 0x00, 0x2f, 0x01, 0x00, 0x22, + 0x02, 0x72, 0x72, 0x04, 0x40, 0x20, 0x02, 0x41, 0xff, 0xff, 0x03, 0x71, + 0x41, 0x01, 0x47, 0x0d, 0x01, 0x41, 0x95, 0xe8, 0x00, 0x21, 0x03, 0x20, + 0x04, 0x20, 0x05, 0x72, 0x0d, 0x01, 0x0b, 0x20, 0x00, 0x41, 0xe6, 0x00, + 0x3b, 0x01, 0x04, 0x20, 0x00, 0x20, 0x03, 0x3b, 0x01, 0x02, 0x20, 0x00, + 0x20, 0x03, 0x3b, 0x01, 0x00, 0x20, 0x03, 0x21, 0x02, 0x0b, 0x20, 0x00, + 0x41, 0x00, 0x3b, 0x01, 0x40, 0x20, 0x00, 0x41, 0xc0, 0x06, 0x36, 0x02, + 0x08, 0x20, 0x00, 0x41, 0xd0, 0x0f, 0x20, 0x01, 0x41, 0x01, 0x71, 0x22, + 0x05, 0x20, 0x01, 0x41, 0x02, 0x71, 0x22, 0x04, 0x41, 0x01, 0x76, 0x6a, + 0x20, 0x01, 0x41, 0x04, 0x71, 0x22, 0x03, 0x41, 0x02, 0x76, 0x6a, 0x6e, + 0x22, 0x06, 0x36, 0x02, 0x18, 0x20, 0x05, 0x04, 0x40, 0x20, 0x00, 0x41, + 0xc0, 0x06, 0x36, 0x02, 0x0c, 0x41, 0x01, 0x21, 0x07, 0x0b, 0x20, 0x04, + 0x04, 0x40, 0x20, 0x00, 0x41, 0x10, 0x6a, 0x20, 0x06, 0x20, 0x07, 0x6c, + 0x41, 0xc0, 0x06, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x07, 0x41, 0x01, 0x6a, + 0x21, 0x07, 0x0b, 0x20, 0x03, 0x04, 0x40, 0x20, 0x00, 0x41, 0x14, 0x6a, + 0x20, 0x06, 0x20, 0x07, 0x6c, 0x41, 0xc0, 0x06, 0x6a, 0x36, 0x02, 0x00, + 0x0b, 0x20, 0x05, 0x04, 0x7f, 0x20, 0x00, 0x20, 0x06, 0x20, 0x00, 0x28, + 0x02, 0x0c, 0x20, 0x02, 0x41, 0x10, 0x74, 0x41, 0x10, 0x75, 0x10, 0x03, + 0x36, 0x02, 0x24, 0x20, 0x00, 0x28, 0x02, 0x20, 0x22, 0x01, 0x41, 0x02, + 0x71, 0x05, 0x20, 0x04, 0x0b, 0x04, 0x7f, 0x20, 0x00, 0x28, 0x02, 0x18, + 0x20, 0x00, 0x28, 0x02, 0x10, 0x20, 0x00, 0x2e, 0x01, 0x00, 0x20, 0x00, + 0x2f, 0x01, 0x02, 0x41, 0x10, 0x74, 0x72, 0x20, 0x00, 0x41, 0x28, 0x6a, + 0x10, 0x06, 0x20, 0x00, 0x28, 0x02, 0x20, 0x05, 0x20, 0x01, 0x0b, 0x41, + 0x04, 0x71, 0x04, 0x40, 0x20, 0x00, 0x28, 0x02, 0x18, 0x20, 0x00, 0x2e, + 0x01, 0x00, 0x20, 0x00, 0x28, 0x02, 0x14, 0x10, 0x09, 0x0b, 0x20, 0x00, + 0x28, 0x02, 0x1c, 0x45, 0x04, 0x40, 0x20, 0x00, 0x41, 0x01, 0x36, 0x02, + 0x1c, 0x41, 0x01, 0x21, 0x01, 0x03, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, + 0x0a, 0x6c, 0x36, 0x02, 0x1c, 0x10, 0x0e, 0x20, 0x00, 0x42, 0x00, 0x37, + 0x03, 0x38, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x1c, 0x22, 0x01, 0x45, + 0x0d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x41, 0x01, 0x10, 0x02, 0x20, 0x00, + 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x3b, 0x01, 0x38, 0x20, 0x00, 0x20, 0x00, + 0x41, 0x7f, 0x10, 0x02, 0x20, 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x22, + 0x03, 0x3b, 0x01, 0x3a, 0x20, 0x00, 0x20, 0x03, 0x3b, 0x01, 0x38, 0x20, + 0x01, 0x41, 0x01, 0x46, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x7f, 0x6a, 0x21, + 0x01, 0x03, 0x40, 0x20, 0x00, 0x20, 0x00, 0x41, 0x01, 0x10, 0x02, 0x20, + 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x3b, 0x01, 0x38, 0x20, 0x00, 0x20, + 0x00, 0x41, 0x7f, 0x10, 0x02, 0x20, 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, + 0x3b, 0x01, 0x38, 0x20, 0x01, 0x41, 0x7f, 0x6a, 0x22, 0x01, 0x0d, 0x00, + 0x0b, 0x0b, 0x10, 0x0f, 0x41, 0xa4, 0x16, 0x28, 0x02, 0x00, 0x41, 0xa0, + 0x16, 0x28, 0x02, 0x00, 0x6b, 0xb8, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x8f, 0x40, 0xa3, 0x22, 0x10, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x3f, 0x63, 0x41, 0x01, 0x73, 0x45, 0x04, 0x40, 0x20, 0x00, + 0x28, 0x02, 0x1c, 0x21, 0x01, 0x0c, 0x01, 0x0b, 0x0b, 0x20, 0x00, 0x20, + 0x00, 0x28, 0x02, 0x1c, 0x41, 0x0a, 0x02, 0x7f, 0x20, 0x10, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x41, 0x63, 0x20, 0x10, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x71, 0x04, 0x40, 0x20, + 0x10, 0xab, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x0b, 0x22, 0x03, 0x41, 0x01, + 0x20, 0x03, 0x1b, 0x6e, 0x41, 0x01, 0x6a, 0x6c, 0x36, 0x02, 0x1c, 0x0b, + 0x10, 0x0e, 0x20, 0x00, 0x42, 0x00, 0x37, 0x03, 0x38, 0x02, 0x40, 0x20, + 0x00, 0x28, 0x02, 0x1c, 0x22, 0x01, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x41, 0x01, 0x10, 0x02, 0x20, 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, + 0x3b, 0x01, 0x38, 0x20, 0x00, 0x20, 0x00, 0x41, 0x7f, 0x10, 0x02, 0x20, + 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x22, 0x03, 0x3b, 0x01, 0x3a, 0x20, + 0x00, 0x20, 0x03, 0x3b, 0x01, 0x38, 0x20, 0x01, 0x41, 0x01, 0x46, 0x0d, + 0x00, 0x20, 0x01, 0x41, 0x7f, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x00, + 0x20, 0x00, 0x41, 0x01, 0x10, 0x02, 0x20, 0x00, 0x2f, 0x01, 0x38, 0x10, + 0x0a, 0x3b, 0x01, 0x38, 0x20, 0x00, 0x20, 0x00, 0x41, 0x7f, 0x10, 0x02, + 0x20, 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x3b, 0x01, 0x38, 0x20, 0x01, + 0x41, 0x7f, 0x6a, 0x22, 0x01, 0x0d, 0x00, 0x0b, 0x0b, 0x10, 0x0f, 0x41, + 0x00, 0x21, 0x02, 0x41, 0xa4, 0x16, 0x28, 0x02, 0x00, 0x41, 0xa0, 0x16, + 0x28, 0x02, 0x00, 0x6b, 0x21, 0x0c, 0x20, 0x00, 0x2e, 0x01, 0x00, 0x41, + 0x00, 0x10, 0x0c, 0x21, 0x03, 0x20, 0x00, 0x2e, 0x01, 0x02, 0x20, 0x03, + 0x10, 0x0c, 0x21, 0x03, 0x20, 0x00, 0x2e, 0x01, 0x04, 0x20, 0x03, 0x10, + 0x0c, 0x21, 0x01, 0x41, 0xff, 0xff, 0x03, 0x21, 0x03, 0x02, 0x40, 0x02, + 0x40, 0x02, 0x40, 0x20, 0x00, 0x2e, 0x01, 0x18, 0x20, 0x01, 0x10, 0x0c, + 0x22, 0x01, 0x41, 0x84, 0xf6, 0x01, 0x4c, 0x04, 0x40, 0x20, 0x01, 0x41, + 0xf2, 0x31, 0x46, 0x0d, 0x01, 0x20, 0x01, 0x41, 0xaf, 0x9d, 0x01, 0x47, + 0x0d, 0x03, 0x41, 0x02, 0x21, 0x02, 0x0c, 0x02, 0x0b, 0x20, 0x01, 0x41, + 0xf5, 0xd3, 0x03, 0x47, 0x04, 0x40, 0x20, 0x01, 0x41, 0x82, 0x94, 0x02, + 0x46, 0x0d, 0x02, 0x20, 0x01, 0x41, 0x85, 0xf6, 0x01, 0x47, 0x0d, 0x03, + 0x41, 0x01, 0x21, 0x02, 0x0c, 0x02, 0x0b, 0x41, 0x03, 0x21, 0x02, 0x0c, + 0x01, 0x0b, 0x41, 0x04, 0x21, 0x02, 0x0b, 0x41, 0x00, 0x21, 0x03, 0x41, + 0xb8, 0x06, 0x28, 0x02, 0x00, 0x22, 0x08, 0x45, 0x0d, 0x00, 0x20, 0x00, + 0x28, 0x02, 0x20, 0x22, 0x04, 0x41, 0x04, 0x71, 0x21, 0x09, 0x20, 0x04, + 0x41, 0x02, 0x71, 0x21, 0x0d, 0x20, 0x02, 0x41, 0x01, 0x74, 0x22, 0x01, + 0x41, 0x94, 0x04, 0x6a, 0x21, 0x0a, 0x20, 0x01, 0x41, 0x8a, 0x04, 0x6a, + 0x21, 0x07, 0x20, 0x00, 0x2f, 0x01, 0x3e, 0x21, 0x0b, 0x20, 0x00, 0x2f, + 0x01, 0x3c, 0x21, 0x06, 0x02, 0x40, 0x20, 0x04, 0x41, 0x01, 0x71, 0x04, + 0x40, 0x41, 0x02, 0x41, 0x01, 0x20, 0x00, 0x2f, 0x01, 0x3a, 0x20, 0x01, + 0x41, 0x80, 0x04, 0x6a, 0x2f, 0x01, 0x00, 0x47, 0x22, 0x04, 0x1b, 0x21, + 0x05, 0x41, 0x00, 0x21, 0x02, 0x03, 0x40, 0x20, 0x04, 0x21, 0x01, 0x20, + 0x0d, 0x04, 0x40, 0x20, 0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x2f, + 0x01, 0x00, 0x46, 0x1b, 0x21, 0x01, 0x0b, 0x20, 0x09, 0x04, 0x40, 0x20, + 0x01, 0x20, 0x0b, 0x20, 0x0a, 0x2f, 0x01, 0x00, 0x47, 0x6a, 0x21, 0x01, + 0x0b, 0x20, 0x01, 0x20, 0x03, 0x6a, 0x21, 0x03, 0x20, 0x08, 0x20, 0x02, + 0x41, 0x01, 0x6a, 0x22, 0x02, 0x41, 0xff, 0xff, 0x03, 0x71, 0x4b, 0x0d, + 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, 0x0d, 0x45, 0x04, 0x40, 0x41, 0x00, + 0x21, 0x02, 0x03, 0x40, 0x41, 0x00, 0x21, 0x01, 0x20, 0x09, 0x04, 0x40, + 0x20, 0x0b, 0x20, 0x0a, 0x2f, 0x01, 0x00, 0x47, 0x21, 0x01, 0x0b, 0x20, + 0x01, 0x20, 0x03, 0x6a, 0x21, 0x03, 0x20, 0x08, 0x20, 0x02, 0x41, 0x01, + 0x6a, 0x22, 0x02, 0x41, 0xff, 0xff, 0x03, 0x71, 0x4b, 0x0d, 0x00, 0x0b, + 0x0c, 0x01, 0x0b, 0x41, 0x02, 0x41, 0x01, 0x20, 0x06, 0x20, 0x07, 0x2f, + 0x01, 0x00, 0x47, 0x22, 0x04, 0x1b, 0x21, 0x05, 0x41, 0x00, 0x21, 0x02, + 0x03, 0x40, 0x20, 0x04, 0x21, 0x01, 0x20, 0x09, 0x04, 0x40, 0x20, 0x04, + 0x20, 0x05, 0x20, 0x0b, 0x20, 0x0a, 0x2f, 0x01, 0x00, 0x46, 0x1b, 0x21, + 0x01, 0x0b, 0x20, 0x01, 0x20, 0x03, 0x6a, 0x21, 0x03, 0x20, 0x08, 0x20, + 0x02, 0x41, 0x01, 0x6a, 0x22, 0x02, 0x41, 0xff, 0xff, 0x03, 0x71, 0x4b, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x3b, 0x01, 0x40, 0x0b, + 0x20, 0x0c, 0xb8, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8f, 0x40, + 0xa3, 0x21, 0x10, 0x20, 0x00, 0x28, 0x02, 0x20, 0x22, 0x06, 0x41, 0x01, + 0x71, 0x04, 0x40, 0x41, 0xb8, 0x06, 0x28, 0x02, 0x00, 0x21, 0x02, 0x41, + 0x00, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0xff, 0xff, 0x03, 0x71, + 0x21, 0x04, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x20, + 0x04, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x06, 0x41, 0x02, 0x71, 0x04, + 0x40, 0x41, 0x00, 0x21, 0x01, 0x41, 0xb8, 0x06, 0x28, 0x02, 0x00, 0x21, + 0x02, 0x03, 0x40, 0x20, 0x01, 0x41, 0xff, 0xff, 0x03, 0x71, 0x21, 0x04, + 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x20, 0x04, 0x4b, + 0x0d, 0x00, 0x0b, 0x0b, 0x41, 0x00, 0x21, 0x01, 0x41, 0xb8, 0x06, 0x28, + 0x02, 0x00, 0x21, 0x05, 0x20, 0x06, 0x41, 0x04, 0x71, 0x04, 0x40, 0x03, + 0x40, 0x20, 0x01, 0x41, 0xff, 0xff, 0x03, 0x71, 0x21, 0x04, 0x20, 0x01, + 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x05, 0x20, 0x04, 0x4b, 0x0d, 0x00, + 0x0b, 0x0b, 0x41, 0x7f, 0x41, 0x00, 0x20, 0x10, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x40, 0x63, 0x1b, 0x21, 0x02, 0x41, 0x00, 0x21, + 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0xff, 0xff, 0x03, 0x71, 0x21, 0x04, + 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x05, 0x20, 0x04, 0x4b, + 0x0d, 0x00, 0x0b, 0x20, 0x0e, 0x41, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x03, + 0x41, 0xff, 0xff, 0x03, 0x71, 0x20, 0x02, 0x41, 0xff, 0xff, 0x03, 0x71, + 0x46, 0x04, 0x40, 0x20, 0x00, 0x28, 0x02, 0x1c, 0x41, 0xb8, 0x06, 0x28, + 0x02, 0x00, 0x6c, 0xb8, 0x20, 0x0c, 0xb8, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x8f, 0x40, 0xa3, 0xa3, 0xb6, 0x21, 0x0f, 0x0b, 0x20, 0x00, + 0x41, 0xd0, 0x00, 0x6a, 0x24, 0x00, 0x20, 0x0f, 0x0b, 0xfb, 0x09, 0x01, + 0x0d, 0x7f, 0x02, 0x40, 0x20, 0x00, 0x04, 0x40, 0x20, 0x04, 0x41, 0x80, + 0x60, 0x72, 0x21, 0x10, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x0a, 0x20, + 0x02, 0x21, 0x07, 0x03, 0x40, 0x20, 0x00, 0x21, 0x05, 0x20, 0x07, 0x21, + 0x06, 0x03, 0x40, 0x20, 0x06, 0x20, 0x06, 0x2f, 0x01, 0x00, 0x20, 0x04, + 0x6a, 0x3b, 0x01, 0x00, 0x20, 0x06, 0x41, 0x02, 0x6a, 0x21, 0x06, 0x20, + 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x20, + 0x0a, 0x6a, 0x21, 0x07, 0x20, 0x0b, 0x41, 0x01, 0x6a, 0x22, 0x0b, 0x20, + 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x0a, + 0x20, 0x00, 0x41, 0x02, 0x74, 0x21, 0x0c, 0x20, 0x02, 0x21, 0x0b, 0x20, + 0x01, 0x21, 0x08, 0x03, 0x40, 0x20, 0x00, 0x21, 0x07, 0x20, 0x0b, 0x21, + 0x06, 0x20, 0x08, 0x21, 0x05, 0x03, 0x40, 0x20, 0x05, 0x20, 0x06, 0x2e, + 0x01, 0x00, 0x20, 0x04, 0x6c, 0x36, 0x02, 0x00, 0x20, 0x06, 0x41, 0x02, + 0x6a, 0x21, 0x06, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x20, 0x07, + 0x41, 0x7f, 0x6a, 0x22, 0x07, 0x0d, 0x00, 0x0b, 0x20, 0x0a, 0x20, 0x0b, + 0x6a, 0x21, 0x0b, 0x20, 0x08, 0x20, 0x0c, 0x6a, 0x21, 0x08, 0x20, 0x09, + 0x41, 0x01, 0x6a, 0x22, 0x09, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, + 0x00, 0x41, 0x02, 0x74, 0x21, 0x0d, 0x20, 0x01, 0x21, 0x0a, 0x41, 0x00, + 0x21, 0x0c, 0x41, 0x00, 0x21, 0x08, 0x41, 0x00, 0x21, 0x07, 0x41, 0x00, + 0x21, 0x09, 0x03, 0x40, 0x20, 0x00, 0x21, 0x0b, 0x20, 0x0a, 0x21, 0x05, + 0x03, 0x40, 0x41, 0x00, 0x20, 0x05, 0x28, 0x02, 0x00, 0x22, 0x06, 0x20, + 0x09, 0x6a, 0x22, 0x09, 0x20, 0x09, 0x20, 0x10, 0x4a, 0x22, 0x0e, 0x1b, + 0x21, 0x09, 0x41, 0x0a, 0x20, 0x06, 0x20, 0x07, 0x4a, 0x20, 0x0e, 0x1b, + 0x20, 0x08, 0x6a, 0x21, 0x08, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, 0x05, + 0x20, 0x06, 0x21, 0x07, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, + 0x00, 0x0b, 0x20, 0x0a, 0x20, 0x0d, 0x6a, 0x21, 0x0a, 0x20, 0x0c, 0x41, + 0x01, 0x6a, 0x22, 0x0c, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, + 0x41, 0x01, 0x74, 0x21, 0x0a, 0x20, 0x08, 0x41, 0x10, 0x74, 0x41, 0x10, + 0x75, 0x41, 0x00, 0x10, 0x0c, 0x21, 0x0e, 0x20, 0x02, 0x21, 0x08, 0x41, + 0x00, 0x21, 0x09, 0x03, 0x40, 0x20, 0x01, 0x20, 0x09, 0x41, 0x02, 0x74, + 0x6a, 0x22, 0x0c, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x21, 0x06, + 0x20, 0x00, 0x21, 0x0b, 0x20, 0x08, 0x21, 0x05, 0x41, 0x00, 0x21, 0x07, + 0x03, 0x40, 0x20, 0x06, 0x2e, 0x01, 0x00, 0x20, 0x05, 0x2e, 0x01, 0x00, + 0x6c, 0x20, 0x07, 0x6a, 0x21, 0x07, 0x20, 0x06, 0x41, 0x02, 0x6a, 0x21, + 0x06, 0x20, 0x05, 0x41, 0x02, 0x6a, 0x21, 0x05, 0x20, 0x0b, 0x41, 0x7f, + 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x20, 0x07, 0x36, 0x02, + 0x00, 0x20, 0x08, 0x20, 0x0a, 0x6a, 0x21, 0x08, 0x20, 0x09, 0x41, 0x01, + 0x6a, 0x22, 0x09, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, 0x41, + 0x02, 0x74, 0x21, 0x0d, 0x20, 0x01, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x0c, + 0x41, 0x00, 0x21, 0x09, 0x41, 0x00, 0x21, 0x07, 0x41, 0x00, 0x21, 0x08, + 0x03, 0x40, 0x20, 0x00, 0x21, 0x0b, 0x20, 0x0a, 0x21, 0x05, 0x03, 0x40, + 0x41, 0x00, 0x20, 0x05, 0x28, 0x02, 0x00, 0x22, 0x06, 0x20, 0x08, 0x6a, + 0x22, 0x08, 0x20, 0x08, 0x20, 0x10, 0x4a, 0x22, 0x0f, 0x1b, 0x21, 0x08, + 0x41, 0x0a, 0x20, 0x06, 0x20, 0x07, 0x4a, 0x20, 0x0f, 0x1b, 0x20, 0x09, + 0x6a, 0x21, 0x09, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x20, 0x06, + 0x21, 0x07, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, + 0x20, 0x0a, 0x20, 0x0d, 0x6a, 0x21, 0x0a, 0x20, 0x0c, 0x41, 0x01, 0x6a, + 0x22, 0x0c, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, 0x41, 0x01, + 0x74, 0x21, 0x0d, 0x41, 0x00, 0x21, 0x0a, 0x20, 0x09, 0x41, 0x10, 0x74, + 0x41, 0x10, 0x75, 0x20, 0x0e, 0x10, 0x0c, 0x21, 0x0e, 0x20, 0x02, 0x21, + 0x0c, 0x03, 0x40, 0x20, 0x00, 0x20, 0x0a, 0x6c, 0x21, 0x0f, 0x20, 0x03, + 0x21, 0x09, 0x41, 0x00, 0x21, 0x08, 0x03, 0x40, 0x41, 0x00, 0x21, 0x07, + 0x20, 0x01, 0x20, 0x08, 0x20, 0x0f, 0x6a, 0x41, 0x02, 0x74, 0x6a, 0x22, + 0x11, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x21, 0x0b, 0x20, 0x0c, + 0x21, 0x06, 0x20, 0x09, 0x21, 0x05, 0x03, 0x40, 0x20, 0x05, 0x2e, 0x01, + 0x00, 0x20, 0x06, 0x2e, 0x01, 0x00, 0x6c, 0x20, 0x07, 0x6a, 0x21, 0x07, + 0x20, 0x06, 0x41, 0x02, 0x6a, 0x21, 0x06, 0x20, 0x05, 0x20, 0x0d, 0x6a, + 0x21, 0x05, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, + 0x20, 0x11, 0x20, 0x07, 0x36, 0x02, 0x00, 0x20, 0x09, 0x41, 0x02, 0x6a, + 0x21, 0x09, 0x20, 0x08, 0x41, 0x01, 0x6a, 0x22, 0x08, 0x20, 0x00, 0x47, + 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x20, 0x0d, 0x6a, 0x21, 0x0c, 0x20, 0x0a, + 0x41, 0x01, 0x6a, 0x22, 0x0a, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, + 0x00, 0x41, 0x02, 0x74, 0x21, 0x0d, 0x20, 0x01, 0x21, 0x0a, 0x41, 0x00, + 0x21, 0x0c, 0x41, 0x00, 0x21, 0x08, 0x41, 0x00, 0x21, 0x07, 0x41, 0x00, + 0x21, 0x09, 0x03, 0x40, 0x20, 0x00, 0x21, 0x0b, 0x20, 0x0a, 0x21, 0x05, + 0x03, 0x40, 0x41, 0x00, 0x20, 0x05, 0x28, 0x02, 0x00, 0x22, 0x06, 0x20, + 0x09, 0x6a, 0x22, 0x09, 0x20, 0x09, 0x20, 0x10, 0x4a, 0x22, 0x0f, 0x1b, + 0x21, 0x09, 0x41, 0x0a, 0x20, 0x06, 0x20, 0x07, 0x4a, 0x20, 0x0f, 0x1b, + 0x20, 0x08, 0x6a, 0x21, 0x08, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, 0x05, + 0x20, 0x06, 0x21, 0x07, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, + 0x00, 0x0b, 0x20, 0x0a, 0x20, 0x0d, 0x6a, 0x21, 0x0a, 0x20, 0x0c, 0x41, + 0x01, 0x6a, 0x22, 0x0c, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, + 0x41, 0x01, 0x74, 0x21, 0x0d, 0x41, 0x00, 0x21, 0x0c, 0x20, 0x08, 0x41, + 0x10, 0x74, 0x41, 0x10, 0x75, 0x20, 0x0e, 0x10, 0x0c, 0x21, 0x0e, 0x20, + 0x02, 0x21, 0x09, 0x03, 0x40, 0x20, 0x00, 0x20, 0x0c, 0x6c, 0x21, 0x0f, + 0x20, 0x03, 0x21, 0x08, 0x41, 0x00, 0x21, 0x0a, 0x03, 0x40, 0x41, 0x00, + 0x21, 0x07, 0x20, 0x01, 0x20, 0x0a, 0x20, 0x0f, 0x6a, 0x41, 0x02, 0x74, + 0x6a, 0x22, 0x11, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x21, 0x0b, + 0x20, 0x09, 0x21, 0x06, 0x20, 0x08, 0x21, 0x05, 0x03, 0x40, 0x20, 0x07, + 0x20, 0x05, 0x2f, 0x01, 0x00, 0x20, 0x06, 0x2f, 0x01, 0x00, 0x6c, 0x22, + 0x07, 0x41, 0x02, 0x76, 0x41, 0x0f, 0x71, 0x20, 0x07, 0x41, 0x05, 0x76, + 0x41, 0xff, 0x00, 0x71, 0x6c, 0x6a, 0x21, 0x07, 0x20, 0x06, 0x41, 0x02, + 0x6a, 0x21, 0x06, 0x20, 0x05, 0x20, 0x0d, 0x6a, 0x21, 0x05, 0x20, 0x0b, + 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, 0x20, 0x11, 0x20, 0x07, + 0x36, 0x02, 0x00, 0x20, 0x08, 0x41, 0x02, 0x6a, 0x21, 0x08, 0x20, 0x0a, + 0x41, 0x01, 0x6a, 0x22, 0x0a, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, + 0x09, 0x20, 0x0d, 0x6a, 0x21, 0x09, 0x20, 0x0c, 0x41, 0x01, 0x6a, 0x22, + 0x0c, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, 0x41, 0x02, 0x74, + 0x21, 0x06, 0x41, 0x00, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x08, 0x41, 0x00, + 0x21, 0x07, 0x41, 0x00, 0x21, 0x09, 0x03, 0x40, 0x20, 0x00, 0x21, 0x0b, + 0x20, 0x01, 0x21, 0x05, 0x03, 0x40, 0x41, 0x00, 0x20, 0x05, 0x28, 0x02, + 0x00, 0x22, 0x03, 0x20, 0x09, 0x6a, 0x22, 0x09, 0x20, 0x09, 0x20, 0x10, + 0x4a, 0x22, 0x0c, 0x1b, 0x21, 0x09, 0x41, 0x0a, 0x20, 0x03, 0x20, 0x07, + 0x4a, 0x20, 0x0c, 0x1b, 0x20, 0x08, 0x6a, 0x21, 0x08, 0x20, 0x05, 0x41, + 0x04, 0x6a, 0x21, 0x05, 0x20, 0x03, 0x21, 0x07, 0x20, 0x0b, 0x41, 0x7f, + 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, 0x20, 0x01, 0x20, 0x06, 0x6a, 0x21, + 0x01, 0x20, 0x0a, 0x41, 0x01, 0x6a, 0x22, 0x0a, 0x20, 0x00, 0x47, 0x0d, + 0x00, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x01, 0x41, 0x00, 0x21, + 0x07, 0x20, 0x08, 0x41, 0x10, 0x74, 0x41, 0x10, 0x75, 0x20, 0x0e, 0x10, + 0x0c, 0x21, 0x08, 0x03, 0x40, 0x20, 0x00, 0x21, 0x05, 0x20, 0x02, 0x21, + 0x06, 0x03, 0x40, 0x20, 0x06, 0x20, 0x06, 0x2f, 0x01, 0x00, 0x20, 0x04, + 0x6b, 0x3b, 0x01, 0x00, 0x20, 0x06, 0x41, 0x02, 0x6a, 0x21, 0x06, 0x20, + 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x0d, 0x00, 0x0b, 0x20, 0x01, 0x20, + 0x02, 0x6a, 0x21, 0x02, 0x20, 0x07, 0x41, 0x01, 0x6a, 0x22, 0x07, 0x20, + 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x41, 0x00, + 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x10, 0x0c, 0x10, 0x0c, 0x10, 0x0c, + 0x10, 0x0c, 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, 0x10, 0x74, 0x41, 0x10, + 0x75, 0x0b, 0x91, 0x02, 0x01, 0x0b, 0x7f, 0x02, 0x40, 0x20, 0x00, 0x45, + 0x04, 0x40, 0x41, 0x7f, 0x21, 0x04, 0x0c, 0x01, 0x0b, 0x41, 0x7f, 0x21, + 0x05, 0x41, 0x08, 0x21, 0x06, 0x03, 0x40, 0x20, 0x06, 0x20, 0x05, 0x41, + 0x02, 0x6a, 0x6c, 0x20, 0x06, 0x41, 0x08, 0x6a, 0x21, 0x06, 0x20, 0x05, + 0x41, 0x01, 0x6a, 0x22, 0x04, 0x21, 0x05, 0x20, 0x00, 0x49, 0x0d, 0x00, + 0x0b, 0x0b, 0x20, 0x01, 0x41, 0x03, 0x6a, 0x41, 0x7c, 0x71, 0x22, 0x07, + 0x20, 0x04, 0x20, 0x04, 0x6c, 0x22, 0x09, 0x41, 0x01, 0x74, 0x6a, 0x21, + 0x0a, 0x20, 0x04, 0x04, 0x40, 0x20, 0x02, 0x41, 0x01, 0x20, 0x02, 0x1b, + 0x21, 0x00, 0x20, 0x04, 0x41, 0x01, 0x74, 0x21, 0x0b, 0x20, 0x09, 0x41, + 0x01, 0x74, 0x21, 0x0c, 0x20, 0x07, 0x21, 0x02, 0x41, 0x01, 0x21, 0x01, + 0x03, 0x40, 0x20, 0x01, 0x41, 0x01, 0x74, 0x21, 0x08, 0x20, 0x02, 0x21, + 0x05, 0x41, 0x00, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x20, 0x0c, 0x6a, + 0x20, 0x01, 0x20, 0x06, 0x6a, 0x22, 0x0d, 0x20, 0x00, 0x20, 0x0d, 0x6c, + 0x41, 0x80, 0x80, 0x04, 0x6f, 0x22, 0x00, 0x6a, 0x3b, 0x01, 0x00, 0x20, + 0x05, 0x20, 0x00, 0x20, 0x08, 0x6a, 0x41, 0xff, 0x01, 0x71, 0x3b, 0x01, + 0x00, 0x20, 0x08, 0x41, 0x02, 0x6a, 0x21, 0x08, 0x20, 0x05, 0x41, 0x02, + 0x6a, 0x21, 0x05, 0x20, 0x04, 0x20, 0x06, 0x41, 0x01, 0x6a, 0x22, 0x06, + 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x01, 0x20, 0x06, 0x6a, 0x21, 0x01, 0x20, + 0x02, 0x20, 0x0b, 0x6a, 0x21, 0x02, 0x20, 0x0e, 0x41, 0x01, 0x6a, 0x22, + 0x0e, 0x20, 0x04, 0x47, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x03, 0x20, 0x0a, + 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, 0x07, 0x36, 0x02, 0x04, 0x20, 0x03, + 0x20, 0x04, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x0a, 0x20, 0x09, 0x41, + 0x01, 0x74, 0x6a, 0x41, 0x03, 0x6a, 0x41, 0x7c, 0x71, 0x36, 0x02, 0x0c, + 0x0b, 0x88, 0x04, 0x01, 0x04, 0x7f, 0x23, 0x00, 0x41, 0xd0, 0x00, 0x6b, + 0x22, 0x06, 0x24, 0x00, 0x20, 0x06, 0x41, 0x20, 0x6a, 0x42, 0x00, 0x37, + 0x03, 0x00, 0x20, 0x06, 0x41, 0x28, 0x6a, 0x42, 0x00, 0x37, 0x03, 0x00, + 0x20, 0x06, 0x41, 0x40, 0x6b, 0x42, 0x00, 0x37, 0x03, 0x00, 0x20, 0x06, + 0x41, 0xc8, 0x00, 0x6a, 0x42, 0x00, 0x37, 0x03, 0x00, 0x20, 0x06, 0x42, + 0x00, 0x37, 0x03, 0x30, 0x20, 0x06, 0x42, 0x00, 0x37, 0x03, 0x38, 0x20, + 0x06, 0x42, 0x00, 0x37, 0x03, 0x10, 0x20, 0x06, 0x42, 0x00, 0x37, 0x03, + 0x18, 0x20, 0x06, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x01, 0x2d, 0x00, + 0x00, 0x04, 0x40, 0x03, 0x40, 0x20, 0x06, 0x41, 0x30, 0x6a, 0x20, 0x06, + 0x41, 0x0c, 0x6a, 0x20, 0x06, 0x41, 0x10, 0x6a, 0x10, 0x08, 0x41, 0x02, + 0x74, 0x6a, 0x22, 0x07, 0x20, 0x07, 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, + 0x36, 0x02, 0x00, 0x20, 0x06, 0x28, 0x02, 0x0c, 0x2d, 0x00, 0x00, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x00, + 0x20, 0x01, 0x6a, 0x21, 0x08, 0x20, 0x00, 0x41, 0x01, 0x4e, 0x04, 0x40, + 0x20, 0x01, 0x21, 0x07, 0x03, 0x40, 0x20, 0x07, 0x2d, 0x00, 0x00, 0x22, + 0x09, 0x41, 0x2c, 0x47, 0x04, 0x40, 0x20, 0x07, 0x20, 0x02, 0x20, 0x09, + 0x73, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x06, 0x20, 0x04, 0x20, 0x07, 0x6a, + 0x22, 0x07, 0x36, 0x02, 0x0c, 0x20, 0x07, 0x20, 0x08, 0x49, 0x0d, 0x00, + 0x0b, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x01, 0x2d, + 0x00, 0x00, 0x04, 0x40, 0x03, 0x40, 0x20, 0x06, 0x41, 0x30, 0x6a, 0x20, + 0x06, 0x41, 0x0c, 0x6a, 0x20, 0x06, 0x41, 0x10, 0x6a, 0x10, 0x08, 0x41, + 0x02, 0x74, 0x6a, 0x22, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x41, 0x01, + 0x6a, 0x36, 0x02, 0x00, 0x20, 0x06, 0x28, 0x02, 0x0c, 0x2d, 0x00, 0x00, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x20, + 0x00, 0x41, 0x01, 0x4e, 0x04, 0x40, 0x03, 0x40, 0x20, 0x01, 0x2d, 0x00, + 0x00, 0x22, 0x00, 0x41, 0x2c, 0x47, 0x04, 0x40, 0x20, 0x01, 0x20, 0x00, + 0x20, 0x03, 0x73, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x20, + 0x04, 0x6a, 0x22, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x01, 0x20, 0x08, 0x49, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x06, 0x28, 0x02, 0x30, 0x20, 0x05, 0x10, + 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x10, 0x20, 0x00, 0x10, 0x0b, + 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x34, 0x20, 0x00, 0x10, 0x0b, 0x21, + 0x00, 0x20, 0x06, 0x28, 0x02, 0x14, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, + 0x20, 0x06, 0x28, 0x02, 0x38, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, + 0x06, 0x28, 0x02, 0x18, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, + 0x28, 0x02, 0x3c, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, + 0x02, 0x1c, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, + 0x40, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x20, + 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x44, 0x20, + 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x24, 0x20, 0x00, + 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x48, 0x20, 0x00, 0x10, + 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x28, 0x20, 0x00, 0x10, 0x0b, + 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x4c, 0x20, 0x00, 0x10, 0x0b, 0x21, + 0x00, 0x20, 0x06, 0x28, 0x02, 0x2c, 0x20, 0x00, 0x10, 0x0b, 0x20, 0x06, + 0x41, 0xd0, 0x00, 0x6a, 0x24, 0x00, 0x0b, 0x8c, 0x04, 0x01, 0x08, 0x7f, + 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x04, 0x2d, 0x00, 0x00, 0x22, 0x03, + 0x45, 0x04, 0x40, 0x20, 0x00, 0x20, 0x04, 0x36, 0x02, 0x00, 0x41, 0x00, + 0x0f, 0x0b, 0x20, 0x04, 0x41, 0x01, 0x6a, 0x21, 0x05, 0x20, 0x01, 0x41, + 0x10, 0x6a, 0x21, 0x06, 0x20, 0x01, 0x41, 0x14, 0x6a, 0x21, 0x07, 0x20, + 0x01, 0x41, 0x0c, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, + 0x08, 0x02, 0x40, 0x03, 0x40, 0x20, 0x03, 0x41, 0x2c, 0x46, 0x0d, 0x01, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x0e, 0x08, + 0x00, 0x09, 0x01, 0x04, 0x02, 0x03, 0x05, 0x06, 0x09, 0x0b, 0x41, 0x04, + 0x21, 0x02, 0x02, 0x40, 0x20, 0x03, 0x41, 0x50, 0x6a, 0x41, 0xff, 0x01, + 0x71, 0x41, 0x0a, 0x49, 0x0d, 0x00, 0x41, 0x02, 0x21, 0x02, 0x02, 0x40, + 0x02, 0x40, 0x20, 0x03, 0x41, 0x55, 0x6a, 0x0e, 0x04, 0x02, 0x01, 0x02, + 0x00, 0x01, 0x0b, 0x41, 0x05, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x41, 0x01, + 0x21, 0x02, 0x20, 0x08, 0x20, 0x08, 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, + 0x36, 0x02, 0x00, 0x0b, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x00, 0x41, + 0x01, 0x6a, 0x36, 0x02, 0x00, 0x0c, 0x08, 0x0b, 0x20, 0x03, 0x41, 0x50, + 0x6a, 0x41, 0xff, 0x01, 0x71, 0x41, 0x09, 0x4b, 0x0d, 0x06, 0x20, 0x01, + 0x20, 0x01, 0x28, 0x02, 0x08, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x08, 0x41, + 0x04, 0x21, 0x02, 0x0c, 0x07, 0x0b, 0x20, 0x03, 0x41, 0x2e, 0x46, 0x04, + 0x40, 0x20, 0x06, 0x20, 0x06, 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, 0x36, + 0x02, 0x00, 0x41, 0x05, 0x21, 0x02, 0x0c, 0x07, 0x0b, 0x41, 0x04, 0x21, + 0x02, 0x20, 0x03, 0x41, 0x50, 0x6a, 0x41, 0xff, 0x01, 0x71, 0x41, 0x09, + 0x4d, 0x0d, 0x06, 0x20, 0x06, 0x21, 0x04, 0x0c, 0x04, 0x0b, 0x20, 0x03, + 0x41, 0x20, 0x72, 0x41, 0xe5, 0x00, 0x46, 0x04, 0x40, 0x20, 0x07, 0x20, + 0x07, 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x00, 0x41, 0x03, + 0x21, 0x02, 0x0c, 0x06, 0x0b, 0x41, 0x05, 0x21, 0x02, 0x20, 0x03, 0x41, + 0x50, 0x6a, 0x41, 0xff, 0x01, 0x71, 0x41, 0x09, 0x4d, 0x0d, 0x05, 0x20, + 0x07, 0x21, 0x04, 0x0c, 0x03, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x55, + 0x6a, 0x0e, 0x03, 0x00, 0x03, 0x00, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x04, + 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x00, 0x41, 0x06, 0x21, + 0x02, 0x0c, 0x04, 0x0b, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x18, 0x41, + 0x01, 0x6a, 0x36, 0x02, 0x18, 0x41, 0x01, 0x41, 0x07, 0x20, 0x03, 0x41, + 0x50, 0x6a, 0x41, 0xff, 0x01, 0x71, 0x41, 0x09, 0x4b, 0x1b, 0x21, 0x02, + 0x0c, 0x03, 0x0b, 0x41, 0x07, 0x21, 0x02, 0x20, 0x03, 0x41, 0x50, 0x6a, + 0x41, 0xff, 0x01, 0x71, 0x41, 0x0a, 0x49, 0x0d, 0x02, 0x20, 0x08, 0x21, + 0x04, 0x0b, 0x20, 0x04, 0x20, 0x04, 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, + 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x05, 0x36, 0x02, 0x00, 0x41, 0x01, + 0x0f, 0x0b, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x08, 0x41, 0x01, 0x6a, + 0x36, 0x02, 0x08, 0x41, 0x05, 0x41, 0x01, 0x20, 0x03, 0x41, 0x2e, 0x46, + 0x1b, 0x21, 0x02, 0x0b, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x09, 0x20, + 0x02, 0x41, 0x01, 0x47, 0x04, 0x40, 0x20, 0x05, 0x2d, 0x00, 0x00, 0x21, + 0x03, 0x20, 0x09, 0x21, 0x05, 0x20, 0x03, 0x0d, 0x01, 0x0b, 0x0b, 0x20, + 0x09, 0x41, 0x7f, 0x6a, 0x21, 0x05, 0x0b, 0x20, 0x00, 0x20, 0x05, 0x36, + 0x02, 0x00, 0x20, 0x02, 0x0b, 0xad, 0x01, 0x01, 0x06, 0x7f, 0x20, 0x00, + 0x41, 0x7f, 0x6a, 0x22, 0x08, 0x41, 0x02, 0x4f, 0x04, 0x40, 0x03, 0x40, + 0x20, 0x04, 0x04, 0x40, 0x20, 0x02, 0x20, 0x03, 0x6a, 0x21, 0x06, 0x20, + 0x04, 0x21, 0x07, 0x03, 0x40, 0x20, 0x06, 0x20, 0x05, 0x2d, 0x00, 0x00, + 0x3a, 0x00, 0x00, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x05, 0x20, 0x06, + 0x41, 0x01, 0x6a, 0x21, 0x06, 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x22, 0x07, + 0x0d, 0x00, 0x0b, 0x20, 0x02, 0x20, 0x03, 0x6a, 0x20, 0x04, 0x6a, 0x41, + 0x2c, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x20, 0x04, 0x6a, 0x41, 0x01, 0x6a, + 0x21, 0x03, 0x0b, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x22, 0x01, 0x41, 0x07, + 0x71, 0x41, 0x02, 0x74, 0x22, 0x04, 0x41, 0xe0, 0x05, 0x6a, 0x28, 0x02, + 0x00, 0x20, 0x01, 0x41, 0x01, 0x76, 0x41, 0x0c, 0x71, 0x6a, 0x28, 0x02, + 0x00, 0x21, 0x05, 0x20, 0x03, 0x20, 0x04, 0x41, 0x80, 0x06, 0x6a, 0x28, + 0x02, 0x00, 0x22, 0x04, 0x6a, 0x41, 0x01, 0x6a, 0x20, 0x08, 0x49, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x03, 0x20, 0x00, 0x49, 0x04, 0x40, 0x20, 0x02, + 0x20, 0x03, 0x6a, 0x20, 0x00, 0x20, 0x03, 0x6b, 0x10, 0x0d, 0x0b, 0x0b, + 0xf2, 0x03, 0x01, 0x02, 0x7f, 0x20, 0x01, 0x41, 0x01, 0x76, 0x22, 0x02, + 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, 0x00, 0x20, 0x01, 0x73, + 0x41, 0x01, 0x71, 0x1b, 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, + 0x01, 0x71, 0x22, 0x02, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, + 0x01, 0x20, 0x00, 0x41, 0xff, 0x01, 0x71, 0x22, 0x01, 0x41, 0x01, 0x76, + 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x02, 0x41, 0x01, 0x76, 0x41, 0xff, + 0xff, 0x01, 0x71, 0x22, 0x03, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x03, + 0x20, 0x01, 0x41, 0x02, 0x76, 0x20, 0x02, 0x73, 0x41, 0x01, 0x71, 0x1b, + 0x22, 0x02, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x03, + 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x03, 0x20, 0x01, 0x41, 0x03, 0x76, + 0x20, 0x02, 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x02, 0x41, 0x01, 0x76, + 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x03, 0x41, 0x81, 0xc0, 0x7e, 0x73, + 0x20, 0x03, 0x20, 0x01, 0x41, 0x04, 0x76, 0x20, 0x02, 0x73, 0x41, 0x01, + 0x71, 0x1b, 0x22, 0x02, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, + 0x22, 0x03, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x03, 0x20, 0x01, 0x41, + 0x05, 0x76, 0x20, 0x02, 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x02, 0x41, + 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x03, 0x41, 0x81, 0xc0, + 0x7e, 0x73, 0x20, 0x03, 0x20, 0x01, 0x41, 0x06, 0x76, 0x20, 0x02, 0x73, + 0x41, 0x01, 0x71, 0x1b, 0x22, 0x02, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, + 0x01, 0x71, 0x22, 0x03, 0x20, 0x03, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, + 0x02, 0x41, 0x01, 0x71, 0x20, 0x01, 0x41, 0x07, 0x76, 0x46, 0x1b, 0x22, + 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x02, 0x41, + 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, 0x01, 0x20, 0x00, 0x41, 0x08, + 0x76, 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, + 0xff, 0xff, 0x01, 0x71, 0x22, 0x02, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, + 0x02, 0x20, 0x01, 0x20, 0x00, 0x41, 0x09, 0x76, 0x73, 0x41, 0x01, 0x71, + 0x1b, 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, + 0x02, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, 0x01, 0x20, 0x00, + 0x41, 0x0a, 0x76, 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x01, 0x41, 0x01, + 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x02, 0x41, 0x81, 0xc0, 0x7e, + 0x73, 0x20, 0x02, 0x20, 0x01, 0x20, 0x00, 0x41, 0x0b, 0x76, 0x73, 0x41, + 0x01, 0x71, 0x1b, 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, + 0x71, 0x22, 0x02, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, 0x01, + 0x20, 0x00, 0x41, 0x0c, 0x76, 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x01, + 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x02, 0x41, 0x81, + 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, 0x01, 0x20, 0x00, 0x41, 0x0d, 0x76, + 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, + 0xff, 0x01, 0x71, 0x22, 0x02, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, + 0x20, 0x01, 0x20, 0x00, 0x41, 0x0e, 0x76, 0x73, 0x41, 0x01, 0x71, 0x1b, + 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x02, + 0x20, 0x02, 0x41, 0x81, 0xc0, 0x02, 0x73, 0x20, 0x01, 0x41, 0x01, 0x71, + 0x20, 0x00, 0x41, 0x0f, 0x76, 0x46, 0x1b, 0x0b, 0x14, 0x00, 0x20, 0x00, + 0x41, 0x10, 0x76, 0x20, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x20, 0x01, + 0x10, 0x0a, 0x10, 0x0a, 0x0b, 0x0d, 0x00, 0x20, 0x00, 0x41, 0xff, 0xff, + 0x03, 0x71, 0x20, 0x01, 0x10, 0x0a, 0x0b, 0xae, 0x01, 0x01, 0x02, 0x7f, + 0x02, 0x40, 0x20, 0x01, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, + 0x22, 0x02, 0x41, 0x7f, 0x6a, 0x41, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x00, + 0x41, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x01, 0x41, 0x03, 0x49, 0x0d, 0x00, + 0x20, 0x02, 0x41, 0x7e, 0x6a, 0x41, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x00, + 0x41, 0x00, 0x3a, 0x00, 0x01, 0x20, 0x02, 0x41, 0x7d, 0x6a, 0x41, 0x00, + 0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 0x00, 0x3a, 0x00, 0x02, 0x20, 0x01, + 0x41, 0x07, 0x49, 0x0d, 0x00, 0x20, 0x02, 0x41, 0x7c, 0x6a, 0x41, 0x00, + 0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 0x00, 0x3a, 0x00, 0x03, 0x20, 0x01, + 0x41, 0x09, 0x49, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x00, 0x20, 0x00, 0x6b, + 0x41, 0x03, 0x71, 0x22, 0x01, 0x6b, 0x41, 0x02, 0x76, 0x22, 0x02, 0x45, + 0x0d, 0x00, 0x41, 0x00, 0x20, 0x02, 0x6b, 0x21, 0x02, 0x20, 0x00, 0x20, + 0x01, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x41, 0x01, + 0x6a, 0x22, 0x00, 0x20, 0x02, 0x4f, 0x20, 0x00, 0x21, 0x02, 0x0d, 0x00, + 0x0b, 0x0b, 0x0b, 0x0a, 0x00, 0x41, 0xa0, 0x16, 0x10, 0x00, 0x36, 0x02, + 0x00, 0x0b, 0x0a, 0x00, 0x41, 0xa4, 0x16, 0x10, 0x00, 0x36, 0x02, 0x00, + 0x0b, 0x0b, 0xc5, 0x02, 0x02, 0x00, 0x41, 0x80, 0x04, 0x0b, 0xb2, 0x02, + 0xb0, 0xd4, 0x40, 0x33, 0x79, 0x6a, 0x14, 0xe7, 0xc1, 0xe3, 0x52, 0xbe, + 0x99, 0x11, 0x08, 0x56, 0xd7, 0x1f, 0x47, 0x07, 0x47, 0x5e, 0xbf, 0x39, + 0xa4, 0xe5, 0x3a, 0x8e, 0x84, 0x8d, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, + 0x65, 0x02, 0x00, 0x00, 0x6a, 0x02, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x00, + 0x74, 0x02, 0x00, 0x00, 0x7d, 0x02, 0x00, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x8f, 0x02, 0x00, 0x00, 0x98, 0x02, 0x00, 0x00, 0xa1, 0x02, 0x00, 0x00, + 0xaa, 0x02, 0x00, 0x00, 0xb3, 0x02, 0x00, 0x00, 0xbc, 0x02, 0x00, 0x00, + 0xc5, 0x02, 0x00, 0x00, 0xce, 0x02, 0x00, 0x00, 0xd7, 0x02, 0x00, 0x00, + 0x35, 0x30, 0x31, 0x32, 0x00, 0x31, 0x32, 0x33, 0x34, 0x00, 0x2d, 0x38, + 0x37, 0x34, 0x00, 0x2b, 0x31, 0x32, 0x32, 0x00, 0x33, 0x35, 0x2e, 0x35, + 0x34, 0x34, 0x30, 0x30, 0x00, 0x2e, 0x31, 0x32, 0x33, 0x34, 0x35, 0x30, + 0x30, 0x00, 0x2d, 0x31, 0x31, 0x30, 0x2e, 0x37, 0x30, 0x30, 0x00, 0x2b, + 0x30, 0x2e, 0x36, 0x34, 0x34, 0x30, 0x30, 0x00, 0x35, 0x2e, 0x35, 0x30, + 0x30, 0x65, 0x2b, 0x33, 0x00, 0x2d, 0x2e, 0x31, 0x32, 0x33, 0x65, 0x2d, + 0x32, 0x00, 0x2d, 0x38, 0x37, 0x65, 0x2b, 0x38, 0x33, 0x32, 0x00, 0x2b, + 0x30, 0x2e, 0x36, 0x65, 0x2d, 0x31, 0x32, 0x00, 0x54, 0x30, 0x2e, 0x33, + 0x65, 0x2d, 0x31, 0x46, 0x00, 0x2d, 0x54, 0x2e, 0x54, 0x2b, 0x2b, 0x54, + 0x71, 0x00, 0x31, 0x54, 0x33, 0x2e, 0x34, 0x65, 0x34, 0x7a, 0x00, 0x33, + 0x34, 0x2e, 0x30, 0x65, 0x2d, 0x54, 0x5e, 0x00, 0x20, 0x02, 0x00, 0x00, + 0x20, 0x02, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, + 0x30, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, + 0x50, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x10, 0x0b, 0x00, 0x00, 0x14, 0x0b, 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, + 0x18, 0x0b, 0x00, 0x00, 0x1c, 0x0b, 0x00, 0x41, 0xb4, 0x06, 0x0b, 0x05, + 0x66, 0x00, 0x00, 0x00, 0x01 +}; +unsigned int coremark_minimal_wasm_len = 7769; diff --git a/wasm3-sys/wasm3/source/extra/fib32.wasm.h b/wasm3-sys/wasm3/source/extra/fib32.wasm.h new file mode 100644 index 0000000..f553f69 --- /dev/null +++ b/wasm3-sys/wasm3/source/extra/fib32.wasm.h @@ -0,0 +1,9 @@ +unsigned char fib32_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, + 0x01, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, + 0x66, 0x69, 0x62, 0x00, 0x00, 0x0a, 0x1f, 0x01, 0x1d, 0x00, 0x20, 0x00, + 0x41, 0x02, 0x49, 0x04, 0x40, 0x20, 0x00, 0x0f, 0x0b, 0x20, 0x00, 0x41, + 0x02, 0x6b, 0x10, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6b, 0x10, 0x00, 0x6a, + 0x0f, 0x0b +}; +unsigned int fib32_wasm_len = 62; diff --git a/wasm3-sys/wasm3/source/extra/fib32_tail.wasm.h b/wasm3-sys/wasm3/source/extra/fib32_tail.wasm.h new file mode 100644 index 0000000..132ef97 --- /dev/null +++ b/wasm3-sys/wasm3/source/extra/fib32_tail.wasm.h @@ -0,0 +1,10 @@ +unsigned char fib32_tail_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x02, 0x60, + 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x03, + 0x03, 0x02, 0x00, 0x01, 0x07, 0x07, 0x01, 0x03, 0x66, 0x69, 0x62, 0x00, + 0x01, 0x0a, 0x26, 0x02, 0x19, 0x00, 0x20, 0x00, 0x45, 0x04, 0x7f, 0x20, + 0x01, 0x05, 0x20, 0x00, 0x41, 0x01, 0x6b, 0x20, 0x02, 0x20, 0x01, 0x20, + 0x02, 0x6a, 0x12, 0x00, 0x0b, 0x0b, 0x0a, 0x00, 0x20, 0x00, 0x41, 0x00, + 0x41, 0x01, 0x12, 0x00, 0x0b +}; +unsigned int fib32_tail_wasm_len = 77; diff --git a/wasm3-sys/wasm3/source/extra/fib64.wasm.h b/wasm3-sys/wasm3/source/extra/fib64.wasm.h new file mode 100644 index 0000000..20ae6e7 --- /dev/null +++ b/wasm3-sys/wasm3/source/extra/fib64.wasm.h @@ -0,0 +1,9 @@ +unsigned char fib64_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, + 0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, + 0x66, 0x69, 0x62, 0x00, 0x00, 0x0a, 0x1f, 0x01, 0x1d, 0x00, 0x20, 0x00, + 0x42, 0x02, 0x54, 0x04, 0x40, 0x20, 0x00, 0x0f, 0x0b, 0x20, 0x00, 0x42, + 0x02, 0x7d, 0x10, 0x00, 0x20, 0x00, 0x42, 0x01, 0x7d, 0x10, 0x00, 0x7c, + 0x0f, 0x0b +}; +unsigned int fib64_wasm_len = 62; diff --git a/wasm3-sys/wasm3/source/extra/wasi_core.h b/wasm3-sys/wasm3/source/extra/wasi_core.h new file mode 100644 index 0000000..6bf42f5 --- /dev/null +++ b/wasm3-sys/wasm3/source/extra/wasi_core.h @@ -0,0 +1,2764 @@ +/** + * THIS FILE IS AUTO-GENERATED from the following files: + * typenames.witx, wasi_snapshot_preview1.witx + * + * @file + * This file describes the [WASI] interface, consisting of functions, types, + * and defined values (macros). + * + * The interface described here is greatly inspired by [CloudABI]'s clean, + * thoughtfully-designed, capability-oriented, POSIX-style API. + * + * [CloudABI]: https://github.com/NuxiNL/cloudlibc + * [WASI]: https://github.com/WebAssembly/WASI/ + */ + +/* + * File origin: + * https://github.com/CraneStation/wasi-libc/blob/master/libc-bottom-half/headers/public/wasi/api.h + * Revision: + * 2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7 + * License: + * CC0 1.0 Universal (CC0 1.0) Public Domain Dedication + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +#ifndef __wasi_api_h +#define __wasi_api_h + +#include +#include + +#ifdef __cplusplus +// Hacks alert +#undef _Static_assert +#define _Static_assert(...) +#undef _Noreturn +#define _Noreturn +#endif + +_Static_assert(_Alignof(int8_t) == 1, "non-wasi data layout"); +_Static_assert(_Alignof(uint8_t) == 1, "non-wasi data layout"); +_Static_assert(_Alignof(int16_t) == 2, "non-wasi data layout"); +_Static_assert(_Alignof(uint16_t) == 2, "non-wasi data layout"); +_Static_assert(_Alignof(int32_t) == 4, "non-wasi data layout"); +_Static_assert(_Alignof(uint32_t) == 4, "non-wasi data layout"); +_Static_assert(_Alignof(int64_t) == 8, "non-wasi data layout"); +_Static_assert(_Alignof(uint64_t) == 8, "non-wasi data layout"); +// _Static_assert(_Alignof(void*) == 4, "non-wasi data layout"); + +#ifdef __cplusplus +extern "C" { +#endif + +// TODO: Encoding this in witx. +#define __WASI_DIRCOOKIE_START (UINT64_C(0)) +// typedef __SIZE_TYPE__ __wasi_size_t; +typedef uint32_t __wasi_size_t; // fixme for wasm64 + +// _Static_assert(sizeof(__wasi_size_t) == 4, "witx calculated size"); +// _Static_assert(_Alignof(__wasi_size_t) == 4, "witx calculated align"); + +/** + * Non-negative file size or length of a region within a file. + */ +typedef uint64_t __wasi_filesize_t; + +_Static_assert(sizeof(__wasi_filesize_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_filesize_t) == 8, "witx calculated align"); + +/** + * Timestamp in nanoseconds. + */ +typedef uint64_t __wasi_timestamp_t; + +_Static_assert(sizeof(__wasi_timestamp_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_timestamp_t) == 8, "witx calculated align"); + +/** + * Identifiers for clocks. + */ +typedef uint32_t __wasi_clockid_t; + +/** + * The clock measuring real time. Time value zero corresponds with + * 1970-01-01T00:00:00Z. + */ +#define __WASI_CLOCKID_REALTIME (UINT32_C(0)) + +/** + * The store-wide monotonic clock, which is defined as a clock measuring + * real time, whose value cannot be adjusted and which cannot have negative + * clock jumps. The epoch of this clock is undefined. The absolute time + * value of this clock therefore has no meaning. + */ +#define __WASI_CLOCKID_MONOTONIC (UINT32_C(1)) + +/** + * The CPU-time clock associated with the current process. + */ +#define __WASI_CLOCKID_PROCESS_CPUTIME_ID (UINT32_C(2)) + +/** + * The CPU-time clock associated with the current thread. + */ +#define __WASI_CLOCKID_THREAD_CPUTIME_ID (UINT32_C(3)) + +_Static_assert(sizeof(__wasi_clockid_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_clockid_t) == 4, "witx calculated align"); + +/** + * Error codes returned by functions. + * Not all of these error codes are returned by the functions provided by this + * API; some are used in higher-level library layers, and others are provided + * merely for alignment with POSIX. + */ +typedef uint16_t __wasi_errno_t; + +/** + * No error occurred. System call completed successfully. + */ +#define __WASI_ERRNO_SUCCESS (UINT16_C(0)) + +/** + * Argument list too long. + */ +#define __WASI_ERRNO_2BIG (UINT16_C(1)) + +/** + * Permission denied. + */ +#define __WASI_ERRNO_ACCES (UINT16_C(2)) + +/** + * Address in use. + */ +#define __WASI_ERRNO_ADDRINUSE (UINT16_C(3)) + +/** + * Address not available. + */ +#define __WASI_ERRNO_ADDRNOTAVAIL (UINT16_C(4)) + +/** + * Address family not supported. + */ +#define __WASI_ERRNO_AFNOSUPPORT (UINT16_C(5)) + +/** + * Resource unavailable, or operation would block. + */ +#define __WASI_ERRNO_AGAIN (UINT16_C(6)) + +/** + * Connection already in progress. + */ +#define __WASI_ERRNO_ALREADY (UINT16_C(7)) + +/** + * Bad file descriptor. + */ +#define __WASI_ERRNO_BADF (UINT16_C(8)) + +/** + * Bad message. + */ +#define __WASI_ERRNO_BADMSG (UINT16_C(9)) + +/** + * Device or resource busy. + */ +#define __WASI_ERRNO_BUSY (UINT16_C(10)) + +/** + * Operation canceled. + */ +#define __WASI_ERRNO_CANCELED (UINT16_C(11)) + +/** + * No child processes. + */ +#define __WASI_ERRNO_CHILD (UINT16_C(12)) + +/** + * Connection aborted. + */ +#define __WASI_ERRNO_CONNABORTED (UINT16_C(13)) + +/** + * Connection refused. + */ +#define __WASI_ERRNO_CONNREFUSED (UINT16_C(14)) + +/** + * Connection reset. + */ +#define __WASI_ERRNO_CONNRESET (UINT16_C(15)) + +/** + * Resource deadlock would occur. + */ +#define __WASI_ERRNO_DEADLK (UINT16_C(16)) + +/** + * Destination address required. + */ +#define __WASI_ERRNO_DESTADDRREQ (UINT16_C(17)) + +/** + * Mathematics argument out of domain of function. + */ +#define __WASI_ERRNO_DOM (UINT16_C(18)) + +/** + * Reserved. + */ +#define __WASI_ERRNO_DQUOT (UINT16_C(19)) + +/** + * File exists. + */ +#define __WASI_ERRNO_EXIST (UINT16_C(20)) + +/** + * Bad address. + */ +#define __WASI_ERRNO_FAULT (UINT16_C(21)) + +/** + * File too large. + */ +#define __WASI_ERRNO_FBIG (UINT16_C(22)) + +/** + * Host is unreachable. + */ +#define __WASI_ERRNO_HOSTUNREACH (UINT16_C(23)) + +/** + * Identifier removed. + */ +#define __WASI_ERRNO_IDRM (UINT16_C(24)) + +/** + * Illegal byte sequence. + */ +#define __WASI_ERRNO_ILSEQ (UINT16_C(25)) + +/** + * Operation in progress. + */ +#define __WASI_ERRNO_INPROGRESS (UINT16_C(26)) + +/** + * Interrupted function. + */ +#define __WASI_ERRNO_INTR (UINT16_C(27)) + +/** + * Invalid argument. + */ +#define __WASI_ERRNO_INVAL (UINT16_C(28)) + +/** + * I/O error. + */ +#define __WASI_ERRNO_IO (UINT16_C(29)) + +/** + * Socket is connected. + */ +#define __WASI_ERRNO_ISCONN (UINT16_C(30)) + +/** + * Is a directory. + */ +#define __WASI_ERRNO_ISDIR (UINT16_C(31)) + +/** + * Too many levels of symbolic links. + */ +#define __WASI_ERRNO_LOOP (UINT16_C(32)) + +/** + * File descriptor value too large. + */ +#define __WASI_ERRNO_MFILE (UINT16_C(33)) + +/** + * Too many links. + */ +#define __WASI_ERRNO_MLINK (UINT16_C(34)) + +/** + * Message too large. + */ +#define __WASI_ERRNO_MSGSIZE (UINT16_C(35)) + +/** + * Reserved. + */ +#define __WASI_ERRNO_MULTIHOP (UINT16_C(36)) + +/** + * Filename too long. + */ +#define __WASI_ERRNO_NAMETOOLONG (UINT16_C(37)) + +/** + * Network is down. + */ +#define __WASI_ERRNO_NETDOWN (UINT16_C(38)) + +/** + * Connection aborted by network. + */ +#define __WASI_ERRNO_NETRESET (UINT16_C(39)) + +/** + * Network unreachable. + */ +#define __WASI_ERRNO_NETUNREACH (UINT16_C(40)) + +/** + * Too many files open in system. + */ +#define __WASI_ERRNO_NFILE (UINT16_C(41)) + +/** + * No buffer space available. + */ +#define __WASI_ERRNO_NOBUFS (UINT16_C(42)) + +/** + * No such device. + */ +#define __WASI_ERRNO_NODEV (UINT16_C(43)) + +/** + * No such file or directory. + */ +#define __WASI_ERRNO_NOENT (UINT16_C(44)) + +/** + * Executable file format error. + */ +#define __WASI_ERRNO_NOEXEC (UINT16_C(45)) + +/** + * No locks available. + */ +#define __WASI_ERRNO_NOLCK (UINT16_C(46)) + +/** + * Reserved. + */ +#define __WASI_ERRNO_NOLINK (UINT16_C(47)) + +/** + * Not enough space. + */ +#define __WASI_ERRNO_NOMEM (UINT16_C(48)) + +/** + * No message of the desired type. + */ +#define __WASI_ERRNO_NOMSG (UINT16_C(49)) + +/** + * Protocol not available. + */ +#define __WASI_ERRNO_NOPROTOOPT (UINT16_C(50)) + +/** + * No space left on device. + */ +#define __WASI_ERRNO_NOSPC (UINT16_C(51)) + +/** + * Function not supported. + */ +#define __WASI_ERRNO_NOSYS (UINT16_C(52)) + +/** + * The socket is not connected. + */ +#define __WASI_ERRNO_NOTCONN (UINT16_C(53)) + +/** + * Not a directory or a symbolic link to a directory. + */ +#define __WASI_ERRNO_NOTDIR (UINT16_C(54)) + +/** + * Directory not empty. + */ +#define __WASI_ERRNO_NOTEMPTY (UINT16_C(55)) + +/** + * State not recoverable. + */ +#define __WASI_ERRNO_NOTRECOVERABLE (UINT16_C(56)) + +/** + * Not a socket. + */ +#define __WASI_ERRNO_NOTSOCK (UINT16_C(57)) + +/** + * Not supported, or operation not supported on socket. + */ +#define __WASI_ERRNO_NOTSUP (UINT16_C(58)) + +/** + * Inappropriate I/O control operation. + */ +#define __WASI_ERRNO_NOTTY (UINT16_C(59)) + +/** + * No such device or address. + */ +#define __WASI_ERRNO_NXIO (UINT16_C(60)) + +/** + * Value too large to be stored in data type. + */ +#define __WASI_ERRNO_OVERFLOW (UINT16_C(61)) + +/** + * Previous owner died. + */ +#define __WASI_ERRNO_OWNERDEAD (UINT16_C(62)) + +/** + * Operation not permitted. + */ +#define __WASI_ERRNO_PERM (UINT16_C(63)) + +/** + * Broken pipe. + */ +#define __WASI_ERRNO_PIPE (UINT16_C(64)) + +/** + * Protocol error. + */ +#define __WASI_ERRNO_PROTO (UINT16_C(65)) + +/** + * Protocol not supported. + */ +#define __WASI_ERRNO_PROTONOSUPPORT (UINT16_C(66)) + +/** + * Protocol wrong type for socket. + */ +#define __WASI_ERRNO_PROTOTYPE (UINT16_C(67)) + +/** + * Result too large. + */ +#define __WASI_ERRNO_RANGE (UINT16_C(68)) + +/** + * Read-only file system. + */ +#define __WASI_ERRNO_ROFS (UINT16_C(69)) + +/** + * Invalid seek. + */ +#define __WASI_ERRNO_SPIPE (UINT16_C(70)) + +/** + * No such process. + */ +#define __WASI_ERRNO_SRCH (UINT16_C(71)) + +/** + * Reserved. + */ +#define __WASI_ERRNO_STALE (UINT16_C(72)) + +/** + * Connection timed out. + */ +#define __WASI_ERRNO_TIMEDOUT (UINT16_C(73)) + +/** + * Text file busy. + */ +#define __WASI_ERRNO_TXTBSY (UINT16_C(74)) + +/** + * Cross-device link. + */ +#define __WASI_ERRNO_XDEV (UINT16_C(75)) + +/** + * Extension: Capabilities insufficient. + */ +#define __WASI_ERRNO_NOTCAPABLE (UINT16_C(76)) + +_Static_assert(sizeof(__wasi_errno_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_errno_t) == 2, "witx calculated align"); + +/** + * File descriptor rights, determining which actions may be performed. + */ +typedef uint64_t __wasi_rights_t; + +/** + * The right to invoke `fd_datasync`. + * If `path_open` is set, includes the right to invoke + * `path_open` with `fdflags::dsync`. + */ +#define __WASI_RIGHTS_FD_DATASYNC (UINT64_C(1)) + +/** + * The right to invoke `fd_read` and `sock_recv`. + * If `rights::fd_seek` is set, includes the right to invoke `fd_pread`. + */ +#define __WASI_RIGHTS_FD_READ (UINT64_C(2)) + +/** + * The right to invoke `fd_seek`. This flag implies `rights::fd_tell`. + */ +#define __WASI_RIGHTS_FD_SEEK (UINT64_C(4)) + +/** + * The right to invoke `fd_fdstat_set_flags`. + */ +#define __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS (UINT64_C(8)) + +/** + * The right to invoke `fd_sync`. + * If `path_open` is set, includes the right to invoke + * `path_open` with `fdflags::rsync` and `fdflags::dsync`. + */ +#define __WASI_RIGHTS_FD_SYNC (UINT64_C(16)) + +/** + * The right to invoke `fd_seek` in such a way that the file offset + * remains unaltered (i.e., `whence::cur` with offset zero), or to + * invoke `fd_tell`. + */ +#define __WASI_RIGHTS_FD_TELL (UINT64_C(32)) + +/** + * The right to invoke `fd_write` and `sock_send`. + * If `rights::fd_seek` is set, includes the right to invoke `fd_pwrite`. + */ +#define __WASI_RIGHTS_FD_WRITE (UINT64_C(64)) + +/** + * The right to invoke `fd_advise`. + */ +#define __WASI_RIGHTS_FD_ADVISE (UINT64_C(128)) + +/** + * The right to invoke `fd_allocate`. + */ +#define __WASI_RIGHTS_FD_ALLOCATE (UINT64_C(256)) + +/** + * The right to invoke `path_create_directory`. + */ +#define __WASI_RIGHTS_PATH_CREATE_DIRECTORY (UINT64_C(512)) + +/** + * If `path_open` is set, the right to invoke `path_open` with `oflags::creat`. + */ +#define __WASI_RIGHTS_PATH_CREATE_FILE (UINT64_C(1024)) + +/** + * The right to invoke `path_link` with the file descriptor as the + * source directory. + */ +#define __WASI_RIGHTS_PATH_LINK_SOURCE (UINT64_C(2048)) + +/** + * The right to invoke `path_link` with the file descriptor as the + * target directory. + */ +#define __WASI_RIGHTS_PATH_LINK_TARGET (UINT64_C(4096)) + +/** + * The right to invoke `path_open`. + */ +#define __WASI_RIGHTS_PATH_OPEN (UINT64_C(8192)) + +/** + * The right to invoke `fd_readdir`. + */ +#define __WASI_RIGHTS_FD_READDIR (UINT64_C(16384)) + +/** + * The right to invoke `path_readlink`. + */ +#define __WASI_RIGHTS_PATH_READLINK (UINT64_C(32768)) + +/** + * The right to invoke `path_rename` with the file descriptor as the source directory. + */ +#define __WASI_RIGHTS_PATH_RENAME_SOURCE (UINT64_C(65536)) + +/** + * The right to invoke `path_rename` with the file descriptor as the target directory. + */ +#define __WASI_RIGHTS_PATH_RENAME_TARGET (UINT64_C(131072)) + +/** + * The right to invoke `path_filestat_get`. + */ +#define __WASI_RIGHTS_PATH_FILESTAT_GET (UINT64_C(262144)) + +/** + * The right to change a file's size (there is no `path_filestat_set_size`). + * If `path_open` is set, includes the right to invoke `path_open` with `oflags::trunc`. + */ +#define __WASI_RIGHTS_PATH_FILESTAT_SET_SIZE (UINT64_C(524288)) + +/** + * The right to invoke `path_filestat_set_times`. + */ +#define __WASI_RIGHTS_PATH_FILESTAT_SET_TIMES (UINT64_C(1048576)) + +/** + * The right to invoke `fd_filestat_get`. + */ +#define __WASI_RIGHTS_FD_FILESTAT_GET (UINT64_C(2097152)) + +/** + * The right to invoke `fd_filestat_set_size`. + */ +#define __WASI_RIGHTS_FD_FILESTAT_SET_SIZE (UINT64_C(4194304)) + +/** + * The right to invoke `fd_filestat_set_times`. + */ +#define __WASI_RIGHTS_FD_FILESTAT_SET_TIMES (UINT64_C(8388608)) + +/** + * The right to invoke `path_symlink`. + */ +#define __WASI_RIGHTS_PATH_SYMLINK (UINT64_C(16777216)) + +/** + * The right to invoke `path_remove_directory`. + */ +#define __WASI_RIGHTS_PATH_REMOVE_DIRECTORY (UINT64_C(33554432)) + +/** + * The right to invoke `path_unlink_file`. + */ +#define __WASI_RIGHTS_PATH_UNLINK_FILE (UINT64_C(67108864)) + +/** + * If `rights::fd_read` is set, includes the right to invoke `poll_oneoff` to subscribe to `eventtype::fd_read`. + * If `rights::fd_write` is set, includes the right to invoke `poll_oneoff` to subscribe to `eventtype::fd_write`. + */ +#define __WASI_RIGHTS_POLL_FD_READWRITE (UINT64_C(134217728)) + +/** + * The right to invoke `sock_shutdown`. + */ +#define __WASI_RIGHTS_SOCK_SHUTDOWN (UINT64_C(268435456)) + +_Static_assert(sizeof(__wasi_rights_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_rights_t) == 8, "witx calculated align"); + +/** + * A file descriptor index. + */ +typedef uint32_t __wasi_fd_t; + +_Static_assert(sizeof(__wasi_fd_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_fd_t) == 4, "witx calculated align"); + +/** + * A region of memory for scatter/gather reads. + */ +typedef struct __wasi_iovec_t { + /** + * The address of the buffer to be filled. + */ + uint8_t * buf; + + /** + * The length of the buffer to be filled. + */ + __wasi_size_t buf_len; + +} __wasi_iovec_t; + +// _Static_assert(sizeof(__wasi_iovec_t) == 8, "witx calculated size"); +// _Static_assert(_Alignof(__wasi_iovec_t) == 4, "witx calculated align"); +// _Static_assert(offsetof(__wasi_iovec_t, buf) == 0, "witx calculated offset"); +// _Static_assert(offsetof(__wasi_iovec_t, buf_len) == 4, "witx calculated offset"); + +/** + * A region of memory for scatter/gather writes. + */ +typedef struct __wasi_ciovec_t { + /** + * The address of the buffer to be written. + */ + const uint8_t * buf; + + /** + * The length of the buffer to be written. + */ + __wasi_size_t buf_len; + +} __wasi_ciovec_t; + +// _Static_assert(sizeof(__wasi_ciovec_t) == 8, "witx calculated size"); +// _Static_assert(_Alignof(__wasi_ciovec_t) == 4, "witx calculated align"); +// _Static_assert(offsetof(__wasi_ciovec_t, buf) == 0, "witx calculated offset"); +// _Static_assert(offsetof(__wasi_ciovec_t, buf_len) == 4, "witx calculated offset"); + +/** + * Relative offset within a file. + */ +typedef int64_t __wasi_filedelta_t; + +_Static_assert(sizeof(__wasi_filedelta_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_filedelta_t) == 8, "witx calculated align"); + +/** + * The position relative to which to set the offset of the file descriptor. + */ +typedef uint8_t __wasi_whence_t; + +/** + * Seek relative to start-of-file. + */ +#define __WASI_WHENCE_SET (UINT8_C(0)) + +/** + * Seek relative to current position. + */ +#define __WASI_WHENCE_CUR (UINT8_C(1)) + +/** + * Seek relative to end-of-file. + */ +#define __WASI_WHENCE_END (UINT8_C(2)) + +_Static_assert(sizeof(__wasi_whence_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_whence_t) == 1, "witx calculated align"); + +/** + * A reference to the offset of a directory entry. + * + * The value 0 signifies the start of the directory. + */ +typedef uint64_t __wasi_dircookie_t; + +_Static_assert(sizeof(__wasi_dircookie_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_dircookie_t) == 8, "witx calculated align"); + +/** + * The type for the $d_namlen field of $dirent. + */ +typedef uint32_t __wasi_dirnamlen_t; + +_Static_assert(sizeof(__wasi_dirnamlen_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_dirnamlen_t) == 4, "witx calculated align"); + +/** + * File serial number that is unique within its file system. + */ +typedef uint64_t __wasi_inode_t; + +_Static_assert(sizeof(__wasi_inode_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_inode_t) == 8, "witx calculated align"); + +/** + * The type of a file descriptor or file. + */ +typedef uint8_t __wasi_filetype_t; + +/** + * The type of the file descriptor or file is unknown or is different from any of the other types specified. + */ +#define __WASI_FILETYPE_UNKNOWN (UINT8_C(0)) + +/** + * The file descriptor or file refers to a block device inode. + */ +#define __WASI_FILETYPE_BLOCK_DEVICE (UINT8_C(1)) + +/** + * The file descriptor or file refers to a character device inode. + */ +#define __WASI_FILETYPE_CHARACTER_DEVICE (UINT8_C(2)) + +/** + * The file descriptor or file refers to a directory inode. + */ +#define __WASI_FILETYPE_DIRECTORY (UINT8_C(3)) + +/** + * The file descriptor or file refers to a regular file inode. + */ +#define __WASI_FILETYPE_REGULAR_FILE (UINT8_C(4)) + +/** + * The file descriptor or file refers to a datagram socket. + */ +#define __WASI_FILETYPE_SOCKET_DGRAM (UINT8_C(5)) + +/** + * The file descriptor or file refers to a byte-stream socket. + */ +#define __WASI_FILETYPE_SOCKET_STREAM (UINT8_C(6)) + +/** + * The file refers to a symbolic link inode. + */ +#define __WASI_FILETYPE_SYMBOLIC_LINK (UINT8_C(7)) + +_Static_assert(sizeof(__wasi_filetype_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_filetype_t) == 1, "witx calculated align"); + +/** + * A directory entry. + */ +typedef struct __wasi_dirent_t { + /** + * The offset of the next directory entry stored in this directory. + */ + __wasi_dircookie_t d_next; + + /** + * The serial number of the file referred to by this directory entry. + */ + __wasi_inode_t d_ino; + + /** + * The length of the name of the directory entry. + */ + __wasi_dirnamlen_t d_namlen; + + /** + * The type of the file referred to by this directory entry. + */ + __wasi_filetype_t d_type; + +} __wasi_dirent_t; + +_Static_assert(sizeof(__wasi_dirent_t) == 24, "witx calculated size"); +_Static_assert(_Alignof(__wasi_dirent_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_dirent_t, d_next) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_dirent_t, d_ino) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_dirent_t, d_namlen) == 16, "witx calculated offset"); +_Static_assert(offsetof(__wasi_dirent_t, d_type) == 20, "witx calculated offset"); + +/** + * File or memory access pattern advisory information. + */ +typedef uint8_t __wasi_advice_t; + +/** + * The application has no advice to give on its behavior with respect to the specified data. + */ +#define __WASI_ADVICE_NORMAL (UINT8_C(0)) + +/** + * The application expects to access the specified data sequentially from lower offsets to higher offsets. + */ +#define __WASI_ADVICE_SEQUENTIAL (UINT8_C(1)) + +/** + * The application expects to access the specified data in a random order. + */ +#define __WASI_ADVICE_RANDOM (UINT8_C(2)) + +/** + * The application expects to access the specified data in the near future. + */ +#define __WASI_ADVICE_WILLNEED (UINT8_C(3)) + +/** + * The application expects that it will not access the specified data in the near future. + */ +#define __WASI_ADVICE_DONTNEED (UINT8_C(4)) + +/** + * The application expects to access the specified data once and then not reuse it thereafter. + */ +#define __WASI_ADVICE_NOREUSE (UINT8_C(5)) + +_Static_assert(sizeof(__wasi_advice_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_advice_t) == 1, "witx calculated align"); + +/** + * File descriptor flags. + */ +typedef uint16_t __wasi_fdflags_t; + +/** + * Append mode: Data written to the file is always appended to the file's end. + */ +#define __WASI_FDFLAGS_APPEND (UINT16_C(1)) + +/** + * Write according to synchronized I/O data integrity completion. Only the data stored in the file is synchronized. + */ +#define __WASI_FDFLAGS_DSYNC (UINT16_C(2)) + +/** + * Non-blocking mode. + */ +#define __WASI_FDFLAGS_NONBLOCK (UINT16_C(4)) + +/** + * Synchronized read I/O operations. + */ +#define __WASI_FDFLAGS_RSYNC (UINT16_C(8)) + +/** + * Write according to synchronized I/O file integrity completion. In + * addition to synchronizing the data stored in the file, the implementation + * may also synchronously update the file's metadata. + */ +#define __WASI_FDFLAGS_SYNC (UINT16_C(16)) + +_Static_assert(sizeof(__wasi_fdflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_fdflags_t) == 2, "witx calculated align"); + +/** + * File descriptor attributes. + */ +typedef struct __wasi_fdstat_t { + /** + * File type. + */ + __wasi_filetype_t fs_filetype; + + /** + * File descriptor flags. + */ + __wasi_fdflags_t fs_flags; + + /** + * Rights that apply to this file descriptor. + */ + __wasi_rights_t fs_rights_base; + + /** + * Maximum set of rights that may be installed on new file descriptors that + * are created through this file descriptor, e.g., through `path_open`. + */ + __wasi_rights_t fs_rights_inheriting; + +} __wasi_fdstat_t; + +_Static_assert(sizeof(__wasi_fdstat_t) == 24, "witx calculated size"); +_Static_assert(_Alignof(__wasi_fdstat_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_fdstat_t, fs_filetype) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_fdstat_t, fs_flags) == 2, "witx calculated offset"); +_Static_assert(offsetof(__wasi_fdstat_t, fs_rights_base) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_fdstat_t, fs_rights_inheriting) == 16, "witx calculated offset"); + +/** + * Identifier for a device containing a file system. Can be used in combination + * with `inode` to uniquely identify a file or directory in the filesystem. + */ +typedef uint64_t __wasi_device_t; + +_Static_assert(sizeof(__wasi_device_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_device_t) == 8, "witx calculated align"); + +/** + * Which file time attributes to adjust. + */ +typedef uint16_t __wasi_fstflags_t; + +/** + * Adjust the last data access timestamp to the value stored in `filestat::atim`. + */ +#define __WASI_FSTFLAGS_ATIM (UINT16_C(1)) + +/** + * Adjust the last data access timestamp to the time of clock `clockid::realtime`. + */ +#define __WASI_FSTFLAGS_ATIM_NOW (UINT16_C(2)) + +/** + * Adjust the last data modification timestamp to the value stored in `filestat::mtim`. + */ +#define __WASI_FSTFLAGS_MTIM (UINT16_C(4)) + +/** + * Adjust the last data modification timestamp to the time of clock `clockid::realtime`. + */ +#define __WASI_FSTFLAGS_MTIM_NOW (UINT16_C(8)) + +_Static_assert(sizeof(__wasi_fstflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_fstflags_t) == 2, "witx calculated align"); + +/** + * Flags determining the method of how paths are resolved. + */ +typedef uint32_t __wasi_lookupflags_t; + +/** + * As long as the resolved path corresponds to a symbolic link, it is expanded. + */ +#define __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW (UINT32_C(1)) + +_Static_assert(sizeof(__wasi_lookupflags_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_lookupflags_t) == 4, "witx calculated align"); + +/** + * Open flags used by `path_open`. + */ +typedef uint16_t __wasi_oflags_t; + +/** + * Create file if it does not exist. + */ +#define __WASI_OFLAGS_CREAT (UINT16_C(1)) + +/** + * Fail if not a directory. + */ +#define __WASI_OFLAGS_DIRECTORY (UINT16_C(2)) + +/** + * Fail if file already exists. + */ +#define __WASI_OFLAGS_EXCL (UINT16_C(4)) + +/** + * Truncate file to size 0. + */ +#define __WASI_OFLAGS_TRUNC (UINT16_C(8)) + +_Static_assert(sizeof(__wasi_oflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_oflags_t) == 2, "witx calculated align"); + +/** + * Number of hard links to an inode. + */ +typedef uint64_t __wasi_linkcount_t; + +_Static_assert(sizeof(__wasi_linkcount_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_linkcount_t) == 8, "witx calculated align"); + +/** + * File attributes. + */ +typedef struct __wasi_filestat_t { + /** + * Device ID of device containing the file. + */ + __wasi_device_t dev; + + /** + * File serial number. + */ + __wasi_inode_t ino; + + /** + * File type. + */ + __wasi_filetype_t filetype; + + /** + * Number of hard links to the file. + */ + __wasi_linkcount_t nlink; + + /** + * For regular files, the file size in bytes. For symbolic links, the length in bytes of the pathname contained in the symbolic link. + */ + __wasi_filesize_t size; + + /** + * Last data access timestamp. + */ + __wasi_timestamp_t atim; + + /** + * Last data modification timestamp. + */ + __wasi_timestamp_t mtim; + + /** + * Last file status change timestamp. + */ + __wasi_timestamp_t ctim; + +} __wasi_filestat_t; + +_Static_assert(sizeof(__wasi_filestat_t) == 64, "witx calculated size"); +_Static_assert(_Alignof(__wasi_filestat_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_filestat_t, dev) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, ino) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, filetype) == 16, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, nlink) == 24, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, size) == 32, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, atim) == 40, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, mtim) == 48, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, ctim) == 56, "witx calculated offset"); + +/** + * User-provided value that may be attached to objects that is retained when + * extracted from the implementation. + */ +typedef uint64_t __wasi_userdata_t; + +_Static_assert(sizeof(__wasi_userdata_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_userdata_t) == 8, "witx calculated align"); + +/** + * Type of a subscription to an event or its occurrence. + */ +typedef uint8_t __wasi_eventtype_t; + +/** + * The time value of clock `subscription_clock::id` has + * reached timestamp `subscription_clock::timeout`. + */ +#define __WASI_EVENTTYPE_CLOCK (UINT8_C(0)) + +/** + * File descriptor `subscription_fd_readwrite::file_descriptor` has data + * available for reading. This event always triggers for regular files. + */ +#define __WASI_EVENTTYPE_FD_READ (UINT8_C(1)) + +/** + * File descriptor `subscription_fd_readwrite::file_descriptor` has capacity + * available for writing. This event always triggers for regular files. + */ +#define __WASI_EVENTTYPE_FD_WRITE (UINT8_C(2)) + +_Static_assert(sizeof(__wasi_eventtype_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_eventtype_t) == 1, "witx calculated align"); + +/** + * The state of the file descriptor subscribed to with + * `eventtype::fd_read` or `eventtype::fd_write`. + */ +typedef uint16_t __wasi_eventrwflags_t; + +/** + * The peer of this socket has closed or disconnected. + */ +#define __WASI_EVENTRWFLAGS_FD_READWRITE_HANGUP (UINT16_C(1)) + +_Static_assert(sizeof(__wasi_eventrwflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_eventrwflags_t) == 2, "witx calculated align"); + +/** + * The contents of an $event when type is `eventtype::fd_read` or + * `eventtype::fd_write`. + */ +typedef struct __wasi_event_fd_readwrite_t { + /** + * The number of bytes available for reading or writing. + */ + __wasi_filesize_t nbytes; + + /** + * The state of the file descriptor. + */ + __wasi_eventrwflags_t flags; + +} __wasi_event_fd_readwrite_t; + +_Static_assert(sizeof(__wasi_event_fd_readwrite_t) == 16, "witx calculated size"); +_Static_assert(_Alignof(__wasi_event_fd_readwrite_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_event_fd_readwrite_t, nbytes) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_event_fd_readwrite_t, flags) == 8, "witx calculated offset"); + +/** + * The contents of an $event. + */ +typedef union __wasi_event_u_t { + /** + * When type is `eventtype::fd_read` or `eventtype::fd_write`: + */ + __wasi_event_fd_readwrite_t fd_readwrite; + +} __wasi_event_u_t; + +_Static_assert(sizeof(__wasi_event_u_t) == 16, "witx calculated size"); +_Static_assert(_Alignof(__wasi_event_u_t) == 8, "witx calculated align"); + +/** + * An event that occurred. + */ +typedef struct __wasi_event_t { + /** + * User-provided value that got attached to `subscription::userdata`. + */ + __wasi_userdata_t userdata; + + /** + * If non-zero, an error that occurred while processing the subscription request. + */ + __wasi_errno_t error; + + /** + * The type of the event that occurred. + */ + __wasi_eventtype_t type; + + /** + * The contents of the event. + */ + __wasi_event_u_t u; + +} __wasi_event_t; + +_Static_assert(sizeof(__wasi_event_t) == 32, "witx calculated size"); +_Static_assert(_Alignof(__wasi_event_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_event_t, userdata) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_event_t, error) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_event_t, type) == 10, "witx calculated offset"); +_Static_assert(offsetof(__wasi_event_t, u) == 16, "witx calculated offset"); + +/** + * Flags determining how to interpret the timestamp provided in + * `subscription_clock::timeout`. + */ +typedef uint16_t __wasi_subclockflags_t; + +/** + * If set, treat the timestamp provided in + * `subscription_clock::timeout` as an absolute timestamp of clock + * `subscription_clock::id`. If clear, treat the timestamp + * provided in `subscription_clock::timeout` relative to the + * current time value of clock `subscription_clock::id`. + */ +#define __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME (UINT16_C(1)) + +_Static_assert(sizeof(__wasi_subclockflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subclockflags_t) == 2, "witx calculated align"); + +/** + * The contents of a $subscription when type is `eventtype::clock`. + */ +typedef struct __wasi_subscription_clock_t { + /** + * The clock against which to compare the timestamp. + */ + __wasi_clockid_t id; + + /** + * The absolute or relative timestamp. + */ + __wasi_timestamp_t timeout; + + /** + * The amount of time that the implementation may wait additionally + * to coalesce with other events. + */ + __wasi_timestamp_t precision; + + /** + * Flags specifying whether the timeout is absolute or relative + */ + __wasi_subclockflags_t flags; + +} __wasi_subscription_clock_t; + +_Static_assert(sizeof(__wasi_subscription_clock_t) == 32, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_clock_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_subscription_clock_t, id) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_clock_t, timeout) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_clock_t, precision) == 16, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_clock_t, flags) == 24, "witx calculated offset"); + +/** + * The contents of a $subscription when type is type is + * `eventtype::fd_read` or `eventtype::fd_write`. + */ +typedef struct __wasi_subscription_fd_readwrite_t { + /** + * The file descriptor on which to wait for it to become ready for reading or writing. + */ + __wasi_fd_t file_descriptor; + +} __wasi_subscription_fd_readwrite_t; + +_Static_assert(sizeof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated align"); +_Static_assert(offsetof(__wasi_subscription_fd_readwrite_t, file_descriptor) == 0, "witx calculated offset"); + +/** + * The contents of a $subscription. + */ +typedef union __wasi_subscription_u_t { + /** + * When type is `eventtype::clock`: + */ + __wasi_subscription_clock_t clock; + + /** + * When type is `eventtype::fd_read` or `eventtype::fd_write`: + */ + __wasi_subscription_fd_readwrite_t fd_readwrite; + +} __wasi_subscription_u_t; + +_Static_assert(sizeof(__wasi_subscription_u_t) == 32, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_u_t) == 8, "witx calculated align"); + +/** + * Subscription to an event. + */ +typedef struct __wasi_subscription_t { + /** + * User-provided value that is attached to the subscription in the + * implementation and returned through `event::userdata`. + */ + __wasi_userdata_t userdata; + + /** + * The type of the event to which to subscribe. + */ + __wasi_eventtype_t type; + + /** + * The contents of the subscription. + */ + __wasi_subscription_u_t u; + +} __wasi_subscription_t; + +_Static_assert(sizeof(__wasi_subscription_t) == 48, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_subscription_t, userdata) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_t, type) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_t, u) == 16, "witx calculated offset"); + +/** + * Exit code generated by a process when exiting. + */ +typedef uint32_t __wasi_exitcode_t; + +_Static_assert(sizeof(__wasi_exitcode_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_exitcode_t) == 4, "witx calculated align"); + +/** + * Signal condition. + */ +typedef uint8_t __wasi_signal_t; + +/** + * No signal. Note that POSIX has special semantics for `kill(pid, 0)`, + * so this value is reserved. + */ +#define __WASI_SIGNAL_NONE (UINT8_C(0)) + +/** + * Hangup. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_HUP (UINT8_C(1)) + +/** + * Terminate interrupt signal. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_INT (UINT8_C(2)) + +/** + * Terminal quit signal. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_QUIT (UINT8_C(3)) + +/** + * Illegal instruction. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_ILL (UINT8_C(4)) + +/** + * Trace/breakpoint trap. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_TRAP (UINT8_C(5)) + +/** + * Process abort signal. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_ABRT (UINT8_C(6)) + +/** + * Access to an undefined portion of a memory object. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_BUS (UINT8_C(7)) + +/** + * Erroneous arithmetic operation. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_FPE (UINT8_C(8)) + +/** + * Kill. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_KILL (UINT8_C(9)) + +/** + * User-defined signal 1. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_USR1 (UINT8_C(10)) + +/** + * Invalid memory reference. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_SEGV (UINT8_C(11)) + +/** + * User-defined signal 2. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_USR2 (UINT8_C(12)) + +/** + * Write on a pipe with no one to read it. + * Action: Ignored. + */ +#define __WASI_SIGNAL_PIPE (UINT8_C(13)) + +/** + * Alarm clock. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_ALRM (UINT8_C(14)) + +/** + * Termination signal. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_TERM (UINT8_C(15)) + +/** + * Child process terminated, stopped, or continued. + * Action: Ignored. + */ +#define __WASI_SIGNAL_CHLD (UINT8_C(16)) + +/** + * Continue executing, if stopped. + * Action: Continues executing, if stopped. + */ +#define __WASI_SIGNAL_CONT (UINT8_C(17)) + +/** + * Stop executing. + * Action: Stops executing. + */ +#define __WASI_SIGNAL_STOP (UINT8_C(18)) + +/** + * Terminal stop signal. + * Action: Stops executing. + */ +#define __WASI_SIGNAL_TSTP (UINT8_C(19)) + +/** + * Background process attempting read. + * Action: Stops executing. + */ +#define __WASI_SIGNAL_TTIN (UINT8_C(20)) + +/** + * Background process attempting write. + * Action: Stops executing. + */ +#define __WASI_SIGNAL_TTOU (UINT8_C(21)) + +/** + * High bandwidth data is available at a socket. + * Action: Ignored. + */ +#define __WASI_SIGNAL_URG (UINT8_C(22)) + +/** + * CPU time limit exceeded. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_XCPU (UINT8_C(23)) + +/** + * File size limit exceeded. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_XFSZ (UINT8_C(24)) + +/** + * Virtual timer expired. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_VTALRM (UINT8_C(25)) + +/** + * Profiling timer expired. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_PROF (UINT8_C(26)) + +/** + * Window changed. + * Action: Ignored. + */ +#define __WASI_SIGNAL_WINCH (UINT8_C(27)) + +/** + * I/O possible. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_POLL (UINT8_C(28)) + +/** + * Power failure. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_PWR (UINT8_C(29)) + +/** + * Bad system call. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_SYS (UINT8_C(30)) + +_Static_assert(sizeof(__wasi_signal_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_signal_t) == 1, "witx calculated align"); + +/** + * Flags provided to `sock_recv`. + */ +typedef uint16_t __wasi_riflags_t; + +/** + * Returns the message without removing it from the socket's receive queue. + */ +#define __WASI_RIFLAGS_RECV_PEEK (UINT16_C(1)) + +/** + * On byte-stream sockets, block until the full amount of data can be returned. + */ +#define __WASI_RIFLAGS_RECV_WAITALL (UINT16_C(2)) + +_Static_assert(sizeof(__wasi_riflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_riflags_t) == 2, "witx calculated align"); + +/** + * Flags returned by `sock_recv`. + */ +typedef uint16_t __wasi_roflags_t; + +/** + * Returned by `sock_recv`: Message data has been truncated. + */ +#define __WASI_ROFLAGS_RECV_DATA_TRUNCATED (UINT16_C(1)) + +_Static_assert(sizeof(__wasi_roflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_roflags_t) == 2, "witx calculated align"); + +/** + * Flags provided to `sock_send`. As there are currently no flags + * defined, it must be set to zero. + */ +typedef uint16_t __wasi_siflags_t; + +_Static_assert(sizeof(__wasi_siflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_siflags_t) == 2, "witx calculated align"); + +/** + * Which channels on a socket to shut down. + */ +typedef uint8_t __wasi_sdflags_t; + +/** + * Disables further receive operations. + */ +#define __WASI_SDFLAGS_RD (UINT8_C(1)) + +/** + * Disables further send operations. + */ +#define __WASI_SDFLAGS_WR (UINT8_C(2)) + +_Static_assert(sizeof(__wasi_sdflags_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_sdflags_t) == 1, "witx calculated align"); + +/** + * Identifiers for preopened capabilities. + */ +typedef uint8_t __wasi_preopentype_t; + +/** + * A pre-opened directory. + */ +#define __WASI_PREOPENTYPE_DIR (UINT8_C(0)) + +_Static_assert(sizeof(__wasi_preopentype_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_preopentype_t) == 1, "witx calculated align"); + +/** + * The contents of a $prestat when type is `preopentype::dir`. + */ +typedef struct __wasi_prestat_dir_t { + /** + * The length of the directory name for use with `fd_prestat_dir_name`. + */ + __wasi_size_t pr_name_len; + +} __wasi_prestat_dir_t; + +_Static_assert(sizeof(__wasi_prestat_dir_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_prestat_dir_t) == 4, "witx calculated align"); +_Static_assert(offsetof(__wasi_prestat_dir_t, pr_name_len) == 0, "witx calculated offset"); + +/** + * The contents of an $prestat. + */ +typedef union __wasi_prestat_u_t { + /** + * When type is `preopentype::dir`: + */ + __wasi_prestat_dir_t dir; + +} __wasi_prestat_u_t; + +_Static_assert(sizeof(__wasi_prestat_u_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_prestat_u_t) == 4, "witx calculated align"); + +/** + * Information about a pre-opened capability. + */ +typedef struct __wasi_prestat_t { + /** + * The type of the pre-opened capability. + */ + __wasi_preopentype_t pr_type; + + /** + * The contents of the information. + */ + __wasi_prestat_u_t u; + +} __wasi_prestat_t; + +_Static_assert(sizeof(__wasi_prestat_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_prestat_t) == 4, "witx calculated align"); +_Static_assert(offsetof(__wasi_prestat_t, pr_type) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_prestat_t, u) == 4, "witx calculated offset"); + +/** + * @defgroup wasi_snapshot_preview1 + * @{ + */ + +/** + * Read command-line argument data. + * The size of the array should match that returned by `args_sizes_get` + */ +__wasi_errno_t __wasi_args_get( + uint8_t * * argv, + + uint8_t * argv_buf +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("args_get"), + __warn_unused_result__ +)); + +/** + * Return command-line argument data sizes. + */ +__wasi_errno_t __wasi_args_sizes_get( + /** + * The number of arguments. + */ + __wasi_size_t *argc, + /** + * The size of the argument string data. + */ + __wasi_size_t *argv_buf_size +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("args_sizes_get"), + __warn_unused_result__ +)); + +/** + * Read environment variable data. + * The sizes of the buffers should match that returned by `environ_sizes_get`. + */ +__wasi_errno_t __wasi_environ_get( + uint8_t * * environ, + + uint8_t * environ_buf +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("environ_get"), + __warn_unused_result__ +)); + +/** + * Return command-line argument data sizes. + */ +__wasi_errno_t __wasi_environ_sizes_get( + /** + * The number of arguments. + */ + __wasi_size_t *argc, + /** + * The size of the argument string data. + */ + __wasi_size_t *argv_buf_size +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("environ_sizes_get"), + __warn_unused_result__ +)); + +/** + * Return the resolution of a clock. + * Implementations are required to provide a non-zero value for supported clocks. For unsupported clocks, + * return `errno::inval`. + * Note: This is similar to `clock_getres` in POSIX. + */ +__wasi_errno_t __wasi_clock_res_get( + /** + * The clock for which to return the resolution. + */ + __wasi_clockid_t id, + + /** + * The resolution of the clock. + */ + __wasi_timestamp_t *resolution +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("clock_res_get"), + __warn_unused_result__ +)); + +/** + * Return the time value of a clock. + * Note: This is similar to `clock_gettime` in POSIX. + */ +__wasi_errno_t __wasi_clock_time_get( + /** + * The clock for which to return the time. + */ + __wasi_clockid_t id, + + /** + * The maximum lag (exclusive) that the returned time value may have, compared to its actual value. + */ + __wasi_timestamp_t precision, + + /** + * The time value of the clock. + */ + __wasi_timestamp_t *time +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("clock_time_get"), + __warn_unused_result__ +)); + +/** + * Provide file advisory information on a file descriptor. + * Note: This is similar to `posix_fadvise` in POSIX. + */ +__wasi_errno_t __wasi_fd_advise( + __wasi_fd_t fd, + + /** + * The offset within the file to which the advisory applies. + */ + __wasi_filesize_t offset, + + /** + * The length of the region to which the advisory applies. + */ + __wasi_filesize_t len, + + /** + * The advice. + */ + __wasi_advice_t advice +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_advise"), + __warn_unused_result__ +)); + +/** + * Force the allocation of space in a file. + * Note: This is similar to `posix_fallocate` in POSIX. + */ +__wasi_errno_t __wasi_fd_allocate( + __wasi_fd_t fd, + + /** + * The offset at which to start the allocation. + */ + __wasi_filesize_t offset, + + /** + * The length of the area that is allocated. + */ + __wasi_filesize_t len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_allocate"), + __warn_unused_result__ +)); + +/** + * Close a file descriptor. + * Note: This is similar to `close` in POSIX. + */ +__wasi_errno_t __wasi_fd_close( + __wasi_fd_t fd +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_close"), + __warn_unused_result__ +)); + +/** + * Synchronize the data of a file to disk. + * Note: This is similar to `fdatasync` in POSIX. + */ +__wasi_errno_t __wasi_fd_datasync( + __wasi_fd_t fd +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_datasync"), + __warn_unused_result__ +)); + +/** + * Get the attributes of a file descriptor. + * Note: This returns similar flags to `fsync(fd, F_GETFL)` in POSIX, as well as additional fields. + */ +__wasi_errno_t __wasi_fd_fdstat_get( + __wasi_fd_t fd, + + /** + * The buffer where the file descriptor's attributes are stored. + */ + __wasi_fdstat_t *stat +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_fdstat_get"), + __warn_unused_result__ +)); + +/** + * Adjust the flags associated with a file descriptor. + * Note: This is similar to `fcntl(fd, F_SETFL, flags)` in POSIX. + */ +__wasi_errno_t __wasi_fd_fdstat_set_flags( + __wasi_fd_t fd, + + /** + * The desired values of the file descriptor flags. + */ + __wasi_fdflags_t flags +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_fdstat_set_flags"), + __warn_unused_result__ +)); + +/** + * Adjust the rights associated with a file descriptor. + * This can only be used to remove rights, and returns `errno::notcapable` if called in a way that would attempt to add rights + */ +__wasi_errno_t __wasi_fd_fdstat_set_rights( + __wasi_fd_t fd, + + /** + * The desired rights of the file descriptor. + */ + __wasi_rights_t fs_rights_base, + + __wasi_rights_t fs_rights_inheriting +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_fdstat_set_rights"), + __warn_unused_result__ +)); + +/** + * Return the attributes of an open file. + */ +__wasi_errno_t __wasi_fd_filestat_get( + __wasi_fd_t fd, + + /** + * The buffer where the file's attributes are stored. + */ + __wasi_filestat_t *buf +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_filestat_get"), + __warn_unused_result__ +)); + +/** + * Adjust the size of an open file. If this increases the file's size, the extra bytes are filled with zeros. + * Note: This is similar to `ftruncate` in POSIX. + */ +__wasi_errno_t __wasi_fd_filestat_set_size( + __wasi_fd_t fd, + + /** + * The desired file size. + */ + __wasi_filesize_t size +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_filestat_set_size"), + __warn_unused_result__ +)); + +/** + * Adjust the timestamps of an open file or directory. + * Note: This is similar to `futimens` in POSIX. + */ +__wasi_errno_t __wasi_fd_filestat_set_times( + __wasi_fd_t fd, + + /** + * The desired values of the data access timestamp. + */ + __wasi_timestamp_t atim, + + /** + * The desired values of the data modification timestamp. + */ + __wasi_timestamp_t mtim, + + /** + * A bitmask indicating which timestamps to adjust. + */ + __wasi_fstflags_t fst_flags +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_filestat_set_times"), + __warn_unused_result__ +)); + +/** + * Read from a file descriptor, without using and updating the file descriptor's offset. + * Note: This is similar to `preadv` in POSIX. + */ +__wasi_errno_t __wasi_fd_pread( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors in which to store data. + */ + const __wasi_iovec_t *iovs, + + /** + * The length of the array pointed to by `iovs`. + */ + size_t iovs_len, + + /** + * The offset within the file at which to read. + */ + __wasi_filesize_t offset, + + /** + * The number of bytes read. + */ + __wasi_size_t *nread +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_pread"), + __warn_unused_result__ +)); + +/** + * Return a description of the given preopened file descriptor. + */ +__wasi_errno_t __wasi_fd_prestat_get( + __wasi_fd_t fd, + + /** + * The buffer where the description is stored. + */ + __wasi_prestat_t *buf +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_prestat_get"), + __warn_unused_result__ +)); + +/** + * Return a description of the given preopened file descriptor. + */ +__wasi_errno_t __wasi_fd_prestat_dir_name( + __wasi_fd_t fd, + + /** + * A buffer into which to write the preopened directory name. + */ + uint8_t * path, + + __wasi_size_t path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_prestat_dir_name"), + __warn_unused_result__ +)); + +/** + * Write to a file descriptor, without using and updating the file descriptor's offset. + * Note: This is similar to `pwritev` in POSIX. + */ +__wasi_errno_t __wasi_fd_pwrite( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors from which to retrieve data. + */ + const __wasi_ciovec_t *iovs, + + /** + * The length of the array pointed to by `iovs`. + */ + size_t iovs_len, + + /** + * The offset within the file at which to write. + */ + __wasi_filesize_t offset, + + /** + * The number of bytes written. + */ + __wasi_size_t *nwritten +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_pwrite"), + __warn_unused_result__ +)); + +/** + * Read from a file descriptor. + * Note: This is similar to `readv` in POSIX. + */ +__wasi_errno_t __wasi_fd_read( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors to which to store data. + */ + const __wasi_iovec_t *iovs, + + /** + * The length of the array pointed to by `iovs`. + */ + size_t iovs_len, + + /** + * The number of bytes read. + */ + __wasi_size_t *nread +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_read"), + __warn_unused_result__ +)); + +/** + * Read directory entries from a directory. + * When successful, the contents of the output buffer consist of a sequence of + * directory entries. Each directory entry consists of a dirent_t object, + * followed by dirent_t::d_namlen bytes holding the name of the directory + * entry. + * This function fills the output buffer as much as possible, potentially + * truncating the last directory entry. This allows the caller to grow its + * read buffer size in case it's too small to fit a single large directory + * entry, or skip the oversized directory entry. + */ +__wasi_errno_t __wasi_fd_readdir( + __wasi_fd_t fd, + + /** + * The buffer where directory entries are stored + */ + uint8_t * buf, + + __wasi_size_t buf_len, + + /** + * The location within the directory to start reading + */ + __wasi_dircookie_t cookie, + + /** + * The number of bytes stored in the read buffer. If less than the size of the read buffer, the end of the directory has been reached. + */ + __wasi_size_t *bufused +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_readdir"), + __warn_unused_result__ +)); + +/** + * Atomically replace a file descriptor by renumbering another file descriptor. + * Due to the strong focus on thread safety, this environment does not provide + * a mechanism to duplicate or renumber a file descriptor to an arbitrary + * number, like `dup2()`. This would be prone to race conditions, as an actual + * file descriptor with the same number could be allocated by a different + * thread at the same time. + * This function provides a way to atomically renumber file descriptors, which + * would disappear if `dup2()` were to be removed entirely. + */ +__wasi_errno_t __wasi_fd_renumber( + __wasi_fd_t fd, + + /** + * The file descriptor to overwrite. + */ + __wasi_fd_t to +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_renumber"), + __warn_unused_result__ +)); + +/** + * Move the offset of a file descriptor. + * Note: This is similar to `lseek` in POSIX. + */ +__wasi_errno_t __wasi_fd_seek( + __wasi_fd_t fd, + + /** + * The number of bytes to move. + */ + __wasi_filedelta_t offset, + + /** + * The base from which the offset is relative. + */ + __wasi_whence_t whence, + + /** + * The new offset of the file descriptor, relative to the start of the file. + */ + __wasi_filesize_t *newoffset +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_seek"), + __warn_unused_result__ +)); + +/** + * Synchronize the data and metadata of a file to disk. + * Note: This is similar to `fsync` in POSIX. + */ +__wasi_errno_t __wasi_fd_sync( + __wasi_fd_t fd +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_sync"), + __warn_unused_result__ +)); + +/** + * Return the current offset of a file descriptor. + * Note: This is similar to `lseek(fd, 0, SEEK_CUR)` in POSIX. + */ +__wasi_errno_t __wasi_fd_tell( + __wasi_fd_t fd, + + /** + * The current offset of the file descriptor, relative to the start of the file. + */ + __wasi_filesize_t *offset +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_tell"), + __warn_unused_result__ +)); + +/** + * Write to a file descriptor. + * Note: This is similar to `writev` in POSIX. + */ +__wasi_errno_t __wasi_fd_write( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors from which to retrieve data. + */ + const __wasi_ciovec_t *iovs, + + /** + * The length of the array pointed to by `iovs`. + */ + size_t iovs_len, + + /** + * The number of bytes written. + */ + __wasi_size_t *nwritten +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_write"), + __warn_unused_result__ +)); + +/** + * Create a directory. + * Note: This is similar to `mkdirat` in POSIX. + */ +__wasi_errno_t __wasi_path_create_directory( + __wasi_fd_t fd, + + /** + * The path at which to create the directory. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_create_directory"), + __warn_unused_result__ +)); + +/** + * Return the attributes of a file or directory. + * Note: This is similar to `stat` in POSIX. + */ +__wasi_errno_t __wasi_path_filestat_get( + __wasi_fd_t fd, + + /** + * Flags determining the method of how the path is resolved. + */ + __wasi_lookupflags_t flags, + + /** + * The path of the file or directory to inspect. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len, + + /** + * The buffer where the file's attributes are stored. + */ + __wasi_filestat_t *buf +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_filestat_get"), + __warn_unused_result__ +)); + +/** + * Adjust the timestamps of a file or directory. + * Note: This is similar to `utimensat` in POSIX. + */ +__wasi_errno_t __wasi_path_filestat_set_times( + __wasi_fd_t fd, + + /** + * Flags determining the method of how the path is resolved. + */ + __wasi_lookupflags_t flags, + + /** + * The path of the file or directory to operate on. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len, + + /** + * The desired values of the data access timestamp. + */ + __wasi_timestamp_t atim, + + /** + * The desired values of the data modification timestamp. + */ + __wasi_timestamp_t mtim, + + /** + * A bitmask indicating which timestamps to adjust. + */ + __wasi_fstflags_t fst_flags +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_filestat_set_times"), + __warn_unused_result__ +)); + +/** + * Create a hard link. + * Note: This is similar to `linkat` in POSIX. + */ +__wasi_errno_t __wasi_path_link( + __wasi_fd_t old_fd, + + /** + * Flags determining the method of how the path is resolved. + */ + __wasi_lookupflags_t old_flags, + + /** + * The source path from which to link. + */ + const char *old_path, + + /** + * The length of the buffer pointed to by `old_path`. + */ + size_t old_path_len, + + /** + * The working directory at which the resolution of the new path starts. + */ + __wasi_fd_t new_fd, + + /** + * The destination path at which to create the hard link. + */ + const char *new_path, + + /** + * The length of the buffer pointed to by `new_path`. + */ + size_t new_path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_link"), + __warn_unused_result__ +)); + +/** + * Open a file or directory. + * The returned file descriptor is not guaranteed to be the lowest-numbered + * file descriptor not currently open; it is randomized to prevent + * applications from depending on making assumptions about indexes, since this + * is error-prone in multi-threaded contexts. The returned file descriptor is + * guaranteed to be less than 2**31. + * Note: This is similar to `openat` in POSIX. + */ +__wasi_errno_t __wasi_path_open( + __wasi_fd_t fd, + + /** + * Flags determining the method of how the path is resolved. + */ + __wasi_lookupflags_t dirflags, + + /** + * The relative path of the file or directory to open, relative to the + * `path_open::fd` directory. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len, + + /** + * The method by which to open the file. + */ + __wasi_oflags_t oflags, + + /** + * The initial rights of the newly created file descriptor. The + * implementation is allowed to return a file descriptor with fewer rights + * than specified, if and only if those rights do not apply to the type of + * file being opened. + * The *base* rights are rights that will apply to operations using the file + * descriptor itself, while the *inheriting* rights are rights that apply to + * file descriptors derived from it. + */ + __wasi_rights_t fs_rights_base, + + __wasi_rights_t fs_rights_inherting, + + __wasi_fdflags_t fdflags, + + /** + * The file descriptor of the file that has been opened. + */ + __wasi_fd_t *opened_fd +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_open"), + __warn_unused_result__ +)); + +/** + * Read the contents of a symbolic link. + * Note: This is similar to `readlinkat` in POSIX. + */ +__wasi_errno_t __wasi_path_readlink( + __wasi_fd_t fd, + + /** + * The path of the symbolic link from which to read. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len, + + /** + * The buffer to which to write the contents of the symbolic link. + */ + uint8_t * buf, + + __wasi_size_t buf_len, + + /** + * The number of bytes placed in the buffer. + */ + __wasi_size_t *bufused +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_readlink"), + __warn_unused_result__ +)); + +/** + * Remove a directory. + * Return `errno::notempty` if the directory is not empty. + * Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + */ +__wasi_errno_t __wasi_path_remove_directory( + __wasi_fd_t fd, + + /** + * The path to a directory to remove. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_remove_directory"), + __warn_unused_result__ +)); + +/** + * Rename a file or directory. + * Note: This is similar to `renameat` in POSIX. + */ +__wasi_errno_t __wasi_path_rename( + __wasi_fd_t fd, + + /** + * The source path of the file or directory to rename. + */ + const char *old_path, + + /** + * The length of the buffer pointed to by `old_path`. + */ + size_t old_path_len, + + /** + * The working directory at which the resolution of the new path starts. + */ + __wasi_fd_t new_fd, + + /** + * The destination path to which to rename the file or directory. + */ + const char *new_path, + + /** + * The length of the buffer pointed to by `new_path`. + */ + size_t new_path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_rename"), + __warn_unused_result__ +)); + +/** + * Create a symbolic link. + * Note: This is similar to `symlinkat` in POSIX. + */ +__wasi_errno_t __wasi_path_symlink( + /** + * The contents of the symbolic link. + */ + const char *old_path, + + /** + * The length of the buffer pointed to by `old_path`. + */ + size_t old_path_len, + + __wasi_fd_t fd, + + /** + * The destination path at which to create the symbolic link. + */ + const char *new_path, + + /** + * The length of the buffer pointed to by `new_path`. + */ + size_t new_path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_symlink"), + __warn_unused_result__ +)); + +/** + * Unlink a file. + * Return `errno::isdir` if the path refers to a directory. + * Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. + */ +__wasi_errno_t __wasi_path_unlink_file( + __wasi_fd_t fd, + + /** + * The path to a file to unlink. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_unlink_file"), + __warn_unused_result__ +)); + +/** + * Concurrently poll for the occurrence of a set of events. + */ +__wasi_errno_t __wasi_poll_oneoff( + /** + * The events to which to subscribe. + */ + const __wasi_subscription_t * in, + + /** + * The events that have occurred. + */ + __wasi_event_t * out, + + /** + * Both the number of subscriptions and events. + */ + __wasi_size_t nsubscriptions, + + /** + * The number of events stored. + */ + __wasi_size_t *nevents +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("poll_oneoff"), + __warn_unused_result__ +)); + +/** + * Terminate the process normally. An exit code of 0 indicates successful + * termination of the program. The meanings of other values is dependent on + * the environment. + */ +_Noreturn void __wasi_proc_exit( + /** + * The exit code returned by the process. + */ + __wasi_exitcode_t rval +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("proc_exit")) +)); + +/** + * Send a signal to the process of the calling thread. + * Note: This is similar to `raise` in POSIX. + */ +__wasi_errno_t __wasi_proc_raise( + /** + * The signal condition to trigger. + */ + __wasi_signal_t sig +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("proc_raise"), + __warn_unused_result__ +)); + +/** + * Temporarily yield execution of the calling thread. + * Note: This is similar to `sched_yield` in POSIX. + */ +__wasi_errno_t __wasi_sched_yield( + void +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("sched_yield"), + __warn_unused_result__ +)); + +/** + * Write high-quality random data into a buffer. + * This function blocks when the implementation is unable to immediately + * provide sufficient high-quality random data. + * This function may execute slowly, so when large mounts of random data are + * required, it's advisable to use this function to seed a pseudo-random + * number generator, rather than to provide the random data directly. + */ +__wasi_errno_t __wasi_random_get( + /** + * The buffer to fill with random data. + */ + uint8_t * buf, + + __wasi_size_t buf_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("random_get"), + __warn_unused_result__ +)); + +/** + * Receive a message from a socket. + * Note: This is similar to `recv` in POSIX, though it also supports reading + * the data into multiple buffers in the manner of `readv`. + */ +__wasi_errno_t __wasi_sock_recv( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors to which to store data. + */ + const __wasi_iovec_t *ri_data, + + /** + * The length of the array pointed to by `ri_data`. + */ + size_t ri_data_len, + + /** + * Message flags. + */ + __wasi_riflags_t ri_flags, + + /** + * Number of bytes stored in ri_data. + */ + __wasi_size_t *ro_datalen, + /** + * Message flags. + */ + __wasi_roflags_t *ro_flags +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("sock_recv"), + __warn_unused_result__ +)); + +/** + * Send a message on a socket. + * Note: This is similar to `send` in POSIX, though it also supports writing + * the data from multiple buffers in the manner of `writev`. + */ +__wasi_errno_t __wasi_sock_send( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors to which to retrieve data + */ + const __wasi_ciovec_t *si_data, + + /** + * The length of the array pointed to by `si_data`. + */ + size_t si_data_len, + + /** + * Message flags. + */ + __wasi_siflags_t si_flags, + + /** + * Number of bytes transmitted. + */ + __wasi_size_t *so_datalen +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("sock_send"), + __warn_unused_result__ +)); + +/** + * Shut down socket send and receive channels. + * Note: This is similar to `shutdown` in POSIX. + */ +__wasi_errno_t __wasi_sock_shutdown( + __wasi_fd_t fd, + + /** + * Which channels on the socket to shut down. + */ + __wasi_sdflags_t how +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // // __import_name__("sock_shutdown"), + __warn_unused_result__ +)); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wasm3-sys/wasm3/source/m3_api_defs.h b/wasm3-sys/wasm3/source/m3_api_defs.h new file mode 100644 index 0000000..9624370 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_api_defs.h @@ -0,0 +1,2 @@ +#warning "Using m3_api_defs.h is deprecated. Just include wasm3.h" + diff --git a/wasm3-sys/wasm3/source/m3_api_libc.c b/wasm3-sys/wasm3/source/m3_api_libc.c new file mode 100644 index 0000000..e0c1b18 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_api_libc.c @@ -0,0 +1,240 @@ +// +// m3_api_libc.c +// +// Created by Volodymyr Shymanskyy on 11/20/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#define _POSIX_C_SOURCE 200809L + +#include "m3_api_libc.h" + +#include "m3_env.h" +#include "m3_exception.h" + +#include +#include +#include + +typedef uint32_t wasm_ptr_t; +typedef uint32_t wasm_size_t; + +m3ApiRawFunction(m3_libc_abort) +{ + m3ApiTrap(m3Err_trapAbort); +} + +m3ApiRawFunction(m3_libc_exit) +{ + m3ApiGetArg (int32_t, code) + + m3ApiTrap(m3Err_trapExit); +} + + +m3ApiRawFunction(m3_libc_memset) +{ + m3ApiReturnType (int32_t) + + m3ApiGetArgMem (void*, i_ptr) + m3ApiGetArg (int32_t, i_value) + m3ApiGetArg (wasm_size_t, i_size) + + m3ApiCheckMem(i_ptr, i_size); + + u32 result = m3ApiPtrToOffset(memset (i_ptr, i_value, i_size)); + m3ApiReturn(result); +} + +m3ApiRawFunction(m3_libc_memmove) +{ + m3ApiReturnType (int32_t) + + m3ApiGetArgMem (void*, o_dst) + m3ApiGetArgMem (void*, i_src) + m3ApiGetArg (wasm_size_t, i_size) + + m3ApiCheckMem(o_dst, i_size); + m3ApiCheckMem(i_src, i_size); + + u32 result = m3ApiPtrToOffset(memmove (o_dst, i_src, i_size)); + m3ApiReturn(result); +} + +m3ApiRawFunction(m3_libc_print) +{ + m3ApiReturnType (uint32_t) + + m3ApiGetArgMem (void*, i_ptr) + m3ApiGetArg (wasm_size_t, i_size) + + m3ApiCheckMem(i_ptr, i_size); + + fwrite(i_ptr, i_size, 1, stdout); + fflush(stdout); + + m3ApiReturn(i_size); +} + +static +void internal_itoa(int n, char s[], int radix) +{ + static char const HEXDIGITS[0x10] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + + int i, j, sign; + char c; + + if ((sign = n) < 0) { n = -n; } + i = 0; + do { + s[i++] = HEXDIGITS[n % radix]; + } while ((n /= radix) > 0); + + if (sign < 0) { s[i++] = '-'; } + s[i] = '\0'; + + // reverse + for (i = 0, j = strlen(s)-1; i + +#elif __has_include("wasi/core.h") +# warning "Using legacy WASI headers" +# include +# define __WASI_ERRNO_SUCCESS __WASI_ESUCCESS +# define __WASI_ERRNO_INVAL __WASI_EINVAL + +#else +# error "Missing WASI headers" +#endif + +static m3_wasi_context_t* wasi_context; + +typedef size_t __wasi_size_t; + +static inline +void copy_iov_to_host(void* _mem, __wasi_iovec_t* host_iov, __wasi_iovec_t* wasi_iov, int32_t iovs_len) +{ + // Convert wasi memory offsets to host addresses + for (int i = 0; i < iovs_len; i++) { + host_iov[i].buf = m3ApiOffsetToPtr(wasi_iov[i].buf); + host_iov[i].buf_len = wasi_iov[i].buf_len; + } +} + +/* + * WASI API implementation + */ + +m3ApiRawFunction(m3_wasi_generic_args_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , argv) + m3ApiGetArgMem (char * , argv_buf) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + + m3ApiCheckMem(argv, context->argc * sizeof(uint32_t)); + + for (u32 i = 0; i < context->argc; ++i) + { + m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf)); + + size_t len = strlen (context->argv[i]); + + m3ApiCheckMem(argv_buf, len); + memcpy (argv_buf, context->argv[i], len); + argv_buf += len; + * argv_buf++ = 0; + } + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_args_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , argc) + m3ApiGetArgMem (__wasi_size_t * , argv_buf_size) + + m3ApiCheckMem(argc, sizeof(__wasi_size_t)); + m3ApiCheckMem(argv_buf_size, sizeof(__wasi_size_t)); + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + + __wasi_size_t buf_len = 0; + for (u32 i = 0; i < context->argc; ++i) + { + buf_len += strlen (context->argv[i]) + 1; + } + + m3ApiWriteMem32(argc, context->argc); + m3ApiWriteMem32(argv_buf_size, buf_len); + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , env) + m3ApiGetArgMem (char * , env_buf) + + __wasi_errno_t ret; + __wasi_size_t env_count, env_buf_size; + + ret = __wasi_environ_sizes_get(&env_count, &env_buf_size); + if (ret != __WASI_ERRNO_SUCCESS) m3ApiReturn(ret); + + m3ApiCheckMem(env, env_count * sizeof(uint32_t)); + m3ApiCheckMem(env_buf, env_buf_size); + + ret = __wasi_environ_get(env, env_buf); + if (ret != __WASI_ERRNO_SUCCESS) m3ApiReturn(ret); + + for (u32 i = 0; i < env_count; ++i) { + env[i] = m3ApiPtrToOffset (env[i]); + } + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_environ_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , env_count) + m3ApiGetArgMem (__wasi_size_t * , env_buf_size) + + m3ApiCheckMem(env_count, sizeof(__wasi_size_t)); + m3ApiCheckMem(env_buf_size, sizeof(__wasi_size_t)); + + __wasi_errno_t ret = __wasi_environ_sizes_get(env_count, env_buf_size); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_dir_name) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + __wasi_errno_t ret = __wasi_fd_prestat_dir_name(fd, path, path_len); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_prestat_t * , buf) + + m3ApiCheckMem(buf, sizeof(__wasi_prestat_t)); + + __wasi_errno_t ret = __wasi_fd_prestat_get(fd, buf); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_fdstat_t * , fdstat) + + m3ApiCheckMem(fdstat, sizeof(__wasi_fdstat_t)); + + __wasi_errno_t ret = __wasi_fd_fdstat_get(fd, fdstat); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_set_flags) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_fdflags_t , flags) + + __wasi_errno_t ret = __wasi_fd_fdstat_set_flags(fd, flags); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 56); // wasi_filestat_t + + __wasi_filestat_t stat; + + __wasi_errno_t ret = __wasi_fd_filestat_get(fd, &stat); + + if (ret != __WASI_ERRNO_SUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 56); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem32(buf+20, stat.st_nlink); + m3ApiWriteMem64(buf+24, stat.st_size); + m3ApiWriteMem64(buf+32, stat.st_atim); + m3ApiWriteMem64(buf+40, stat.st_mtim); + m3ApiWriteMem64(buf+48, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 64); // wasi_filestat_t + + __wasi_filestat_t stat; + + __wasi_errno_t ret = __wasi_fd_filestat_get(fd, &stat); + + if (ret != __WASI_ERRNO_SUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 64); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem64(buf+24, stat.st_nlink); + m3ApiWriteMem64(buf+32, stat.st_size); + m3ApiWriteMem64(buf+40, stat.st_atim); + m3ApiWriteMem64(buf+48, stat.st_mtim); + m3ApiWriteMem64(buf+56, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(__wasi_filesize_t)); + + __wasi_whence_t whence; + + switch (wasi_whence) { + case 0: whence = __WASI_WHENCE_CUR; break; + case 1: whence = __WASI_WHENCE_END; break; + case 2: whence = __WASI_WHENCE_SET; break; + default: m3ApiReturn(__WASI_ERRNO_INVAL); + } + + __wasi_errno_t ret = __wasi_fd_seek(fd, offset, whence, result); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(__wasi_filesize_t)); + + __wasi_whence_t whence; + + switch (wasi_whence) { + case 0: whence = __WASI_WHENCE_SET; break; + case 1: whence = __WASI_WHENCE_CUR; break; + case 2: whence = __WASI_WHENCE_END; break; + default: m3ApiReturn(__WASI_ERRNO_INVAL); + } + + __wasi_errno_t ret = __wasi_fd_seek(fd, offset, whence, result); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_create_directory) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + __wasi_errno_t ret = __wasi_path_create_directory(fd, path, path_len); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_readlink) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + m3ApiGetArgMem (char * , buf) + m3ApiGetArg (__wasi_size_t , buf_len) + m3ApiGetArgMem (__wasi_size_t * , bufused) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, buf_len); + m3ApiCheckMem(bufused, sizeof(__wasi_size_t)); + + __wasi_errno_t ret = __wasi_path_readlink(fd, path, path_len, buf, buf_len, bufused); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_remove_directory) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + __wasi_errno_t ret = __wasi_path_remove_directory(fd, path, path_len); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_rename) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , old_fd) + m3ApiGetArgMem (const char * , old_path) + m3ApiGetArg (__wasi_size_t , old_path_len) + m3ApiGetArg (__wasi_fd_t , new_fd) + m3ApiGetArgMem (const char * , new_path) + m3ApiGetArg (__wasi_size_t , new_path_len) + + m3ApiCheckMem(old_path, old_path_len); + m3ApiCheckMem(new_path, new_path_len); + + __wasi_errno_t ret = __wasi_path_rename(old_fd, old_path, old_path_len, + new_fd, new_path, new_path_len); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_unlink_file) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + __wasi_errno_t ret = __wasi_path_unlink_file(fd, path, path_len); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_open) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , dirfd) + m3ApiGetArg (__wasi_lookupflags_t , dirflags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + m3ApiGetArg (__wasi_oflags_t , oflags) + m3ApiGetArg (__wasi_rights_t , fs_rights_base) + m3ApiGetArg (__wasi_rights_t , fs_rights_inheriting) + m3ApiGetArg (__wasi_fdflags_t , fs_flags) + m3ApiGetArgMem (__wasi_fd_t * , fd) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(fd, sizeof(__wasi_fd_t)); + + __wasi_errno_t ret = __wasi_path_open(dirfd, + dirflags, + path, + path_len, + oflags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_unstable_path_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_lookupflags_t , flags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uint32_t , path_len) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, 56); // wasi_filestat_t + + __wasi_filestat_t stat; + + __wasi_errno_t ret = __wasi_path_filestat_get(fd, flags, path, path_len, &stat); + + if (ret != __WASI_ERRNO_SUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 56); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem32(buf+20, stat.st_nlink); + m3ApiWriteMem64(buf+24, stat.st_size); + m3ApiWriteMem64(buf+32, stat.st_atim); + m3ApiWriteMem64(buf+40, stat.st_mtim); + m3ApiWriteMem64(buf+48, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_path_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_lookupflags_t , flags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uint32_t , path_len) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, 64); // wasi_filestat_t + + __wasi_filestat_t stat; + + __wasi_errno_t ret = __wasi_path_filestat_get(fd, flags, path, path_len, &stat); + + if (ret != __WASI_ERRNO_SUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 64); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem64(buf+24, stat.st_nlink); + m3ApiWriteMem64(buf+32, stat.st_size); + m3ApiWriteMem64(buf+40, stat.st_atim); + m3ApiWriteMem64(buf+48, stat.st_mtim); + m3ApiWriteMem64(buf+56, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_pread) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArg (__wasi_filesize_t , offset) + m3ApiGetArgMem (__wasi_size_t * , nread) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(__wasi_iovec_t)); + m3ApiCheckMem(nread, sizeof(__wasi_size_t)); + + __wasi_iovec_t iovs[iovs_len]; + copy_iov_to_host(_mem, iovs, wasi_iovs, iovs_len); + + __wasi_errno_t ret = __wasi_fd_pread(fd, iovs, iovs_len, offset, nread); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_read) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nread) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(__wasi_iovec_t)); + m3ApiCheckMem(nread, sizeof(__wasi_size_t)); + + __wasi_iovec_t iovs[iovs_len]; + copy_iov_to_host(_mem, iovs, wasi_iovs, iovs_len); + + __wasi_errno_t ret = __wasi_fd_read(fd, iovs, iovs_len, nread); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_write) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nwritten) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(__wasi_iovec_t)); + m3ApiCheckMem(nwritten, sizeof(__wasi_size_t)); + + __wasi_iovec_t iovs[iovs_len]; + copy_iov_to_host(_mem, iovs, wasi_iovs, iovs_len); + + __wasi_errno_t ret = __wasi_fd_write(fd, (__wasi_ciovec_t*)iovs, iovs_len, nwritten); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_readdir) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (void * , buf) + m3ApiGetArg (__wasi_size_t , buf_len) + m3ApiGetArg (__wasi_dircookie_t , cookie) + m3ApiGetArgMem (__wasi_size_t * , bufused) + + m3ApiCheckMem(buf, buf_len); + m3ApiCheckMem(bufused, sizeof(__wasi_size_t)); + + __wasi_errno_t ret = __wasi_fd_readdir(fd, buf, buf_len, cookie, bufused); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_close) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + + __wasi_errno_t ret = __wasi_fd_close(fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_datasync) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + + __wasi_errno_t ret = __wasi_fd_datasync(fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_random_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint8_t * , buf) + m3ApiGetArg (__wasi_size_t , buf_len) + + m3ApiCheckMem(buf, buf_len); + + __wasi_errno_t ret = __wasi_random_get(buf, buf_len); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_clock_res_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArgMem (__wasi_timestamp_t * , resolution) + + m3ApiCheckMem(resolution, sizeof(__wasi_timestamp_t)); + + __wasi_errno_t ret = __wasi_clock_res_get(wasi_clk_id, resolution); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_clock_time_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArg (__wasi_timestamp_t , precision) + m3ApiGetArgMem (__wasi_timestamp_t * , time) + + m3ApiCheckMem(time, sizeof(__wasi_timestamp_t)); + + __wasi_errno_t ret = __wasi_clock_time_get(wasi_clk_id, precision, time); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_poll_oneoff) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (const __wasi_subscription_t * , in) + m3ApiGetArgMem (__wasi_event_t * , out) + m3ApiGetArg (__wasi_size_t , nsubscriptions) + m3ApiGetArgMem (__wasi_size_t * , nevents) + + m3ApiCheckMem(in, nsubscriptions * sizeof(__wasi_subscription_t)); + m3ApiCheckMem(out, nsubscriptions * sizeof(__wasi_event_t)); + m3ApiCheckMem(nevents, sizeof(__wasi_size_t)); + + __wasi_errno_t ret = __wasi_poll_oneoff(in, out, nsubscriptions, nevents); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_proc_exit) +{ + m3ApiGetArg (uint32_t, code) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context) { + context->exit_code = code; + } + + m3ApiTrap(m3Err_trapExit); +} + + +static +M3Result SuppressLookupFailure(M3Result i_result) +{ + if (i_result == m3Err_functionLookupFailed) + return m3Err_none; + else + return i_result; +} + +m3_wasi_context_t* m3_GetWasiContext() +{ + return wasi_context; +} + + +M3Result m3_LinkWASI (IM3Module module) +{ + M3Result result = m3Err_none; + + if (!wasi_context) { + wasi_context = (m3_wasi_context_t*)malloc(sizeof(m3_wasi_context_t)); + wasi_context->exit_code = 0; + wasi_context->argc = 0; + wasi_context->argv = 0; + } + + static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" }; + + // fd_seek is incompatible +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_seek", "i(iIi*)", &m3_wasi_unstable_fd_seek))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_seek", "i(iIi*)", &m3_wasi_snapshot_preview1_fd_seek))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_filestat_get", "i(i*)", &m3_wasi_unstable_fd_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_filestat_get", "i(i*)", &m3_wasi_snapshot_preview1_fd_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "path_filestat_get", "i(ii*i*)", &m3_wasi_unstable_path_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "path_filestat_get", "i(ii*i*)", &m3_wasi_snapshot_preview1_path_filestat_get))); + + for (int i=0; i<2; i++) + { + const char* wasi = namespaces[i]; + +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_get", "i(**)", &m3_wasi_generic_args_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_generic_args_sizes_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_generic_clock_res_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(iI*)", &m3_wasi_generic_clock_time_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_generic_environ_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get", "i(**)", &m3_wasi_generic_environ_sizes_get))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_advise", "i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_allocate", "i(iII)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close", "i(i)", &m3_wasi_generic_fd_close))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync", "i(i)", &m3_wasi_generic_fd_datasync))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get", "i(i*)", &m3_wasi_generic_fd_fdstat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_flags", "i(ii)", &m3_wasi_generic_fd_fdstat_set_flags))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_rights", "i(iII)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_size", "i(iI)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_times","i(iIIi)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pread", "i(i*iI*)",&m3_wasi_generic_fd_pread))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get", "i(i*)", &m3_wasi_generic_fd_prestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name", "i(i*i)", &m3_wasi_generic_fd_prestat_dir_name))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pwrite", "i(i*iI*)",))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read", "i(i*i*)", &m3_wasi_generic_fd_read))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_readdir", "i(i*iI*)",&m3_wasi_generic_fd_readdir))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_renumber", "i(ii)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_sync", "i(i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_tell", "i(i*)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write", "i(i*i*)", &m3_wasi_generic_fd_write))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_create_directory", "i(i*i)", &m3_wasi_generic_path_create_directory))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_set_times", "i(ii*iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_link", "i(ii*ii*i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", "i(ii*iiIIi*)", &m3_wasi_generic_path_open))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_readlink", "i(i*i*i*)", &m3_wasi_generic_path_readlink))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_remove_directory", "i(i*i)", &m3_wasi_generic_path_remove_directory))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_rename", "i(i*ii*i)", &m3_wasi_generic_path_rename))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_symlink", "i(*ii*i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file", "i(i*i)", &m3_wasi_generic_path_unlink_file))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff", "i(**i*)", &m3_wasi_generic_poll_oneoff))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "proc_exit", "v(i)", &m3_wasi_generic_proc_exit, wasi_context))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise", "i(i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_generic_random_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield", "i()", ))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv", "i(i*ii**)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send", "i(i*ii*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_shutdown", "i(ii)", ))); + } + +_catch: + return result; +} + +#endif // d_m3HasMetaWASI + diff --git a/wasm3-sys/wasm3/source/m3_api_tracer.c b/wasm3-sys/wasm3/source/m3_api_tracer.c new file mode 100644 index 0000000..4abedbd --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_api_tracer.c @@ -0,0 +1,168 @@ +// +// m3_api_tracer.c +// +// Created by Volodymyr Shymanskyy on 02/18/20. +// Copyright © 2020 Volodymyr Shymanskyy. All rights reserved. +// + +#include "m3_api_tracer.h" + +#include "m3_env.h" +#include "m3_exception.h" + +#if defined(d_m3HasTracer) + + +static FILE* trace = NULL; + +m3ApiRawFunction(m3_env_log_execution) +{ + m3ApiGetArg (uint32_t, id) + fprintf(trace, "exec;%d\n", id); + m3ApiSuccess(); +} + +m3ApiRawFunction(m3_env_log_exec_enter) +{ + m3ApiGetArg (uint32_t, id) + m3ApiGetArg (uint32_t, func) + fprintf(trace, "enter;%d;%d\n", id, func); + m3ApiSuccess(); +} + +m3ApiRawFunction(m3_env_log_exec_exit) +{ + m3ApiGetArg (uint32_t, id) + m3ApiGetArg (uint32_t, func) + fprintf(trace, "exit;%d;%d\n", id, func); + m3ApiSuccess(); +} + +m3ApiRawFunction(m3_env_log_exec_loop) +{ + m3ApiGetArg (uint32_t, id) + fprintf(trace, "loop;%d\n", id); + m3ApiSuccess(); +} + +m3ApiRawFunction(m3_env_load_ptr) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uint32_t, id) + m3ApiGetArg (uint32_t, align) + m3ApiGetArg (uint32_t, offset) + m3ApiGetArg (uint32_t, address) + fprintf(trace, "load ptr;%d;%d;%d;%d\n", id, align, offset, address); + m3ApiReturn(address); +} + +m3ApiRawFunction(m3_env_store_ptr) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uint32_t, id) + m3ApiGetArg (uint32_t, align) + m3ApiGetArg (uint32_t, offset) + m3ApiGetArg (uint32_t, address) + fprintf(trace, "store ptr;%d;%d;%d;%d\n", id, align, offset, address); + m3ApiReturn(address); +} + + +#define d_m3TraceMemory(FUNC, NAME, TYPE, FMT) \ +m3ApiRawFunction(m3_env_##FUNC) \ +{ \ + m3ApiReturnType (TYPE) \ + m3ApiGetArg (uint32_t, id) \ + m3ApiGetArg (TYPE, val) \ + fprintf(trace, NAME ";%d;" FMT "\n", id, val); \ + m3ApiReturn(val); \ +} + +d_m3TraceMemory( load_val_i32, "load i32", int32_t, "%" PRIi32) +d_m3TraceMemory(store_val_i32, "store i32", int32_t, "%" PRIi32) +d_m3TraceMemory( load_val_i64, "load i64", int64_t, "%" PRIi64) +d_m3TraceMemory(store_val_i64, "store i64", int64_t, "%" PRIi64) +d_m3TraceMemory( load_val_f32, "load f32", float, "%" PRIf32) +d_m3TraceMemory(store_val_f32, "store f32", float, "%" PRIf32) +d_m3TraceMemory( load_val_f64, "load f64", double, "%" PRIf64) +d_m3TraceMemory(store_val_f64, "store f64", double, "%" PRIf64) + + +#define d_m3TraceLocal(FUNC, NAME, TYPE, FMT) \ +m3ApiRawFunction(m3_env_##FUNC) \ +{ \ + m3ApiReturnType (TYPE) \ + m3ApiGetArg (uint32_t, id) \ + m3ApiGetArg (uint32_t, local) \ + m3ApiGetArg (TYPE, val) \ + fprintf(trace, NAME ";%d;%d;" FMT "\n", id, local, val); \ + m3ApiReturn(val); \ +} + + +d_m3TraceLocal(get_i32, "get i32", int32_t, "%" PRIi32) +d_m3TraceLocal(set_i32, "set i32", int32_t, "%" PRIi32) +d_m3TraceLocal(get_i64, "get i64", int64_t, "%" PRIi64) +d_m3TraceLocal(set_i64, "set i64", int64_t, "%" PRIi64) +d_m3TraceLocal(get_f32, "get f32", float, "%" PRIf32) +d_m3TraceLocal(set_f32, "set f32", float, "%" PRIf32) +d_m3TraceLocal(get_f64, "get f64", double, "%" PRIf64) +d_m3TraceLocal(set_f64, "set f64", double, "%" PRIf64) + + +static +M3Result SuppressLookupFailure(M3Result i_result) +{ + if (i_result == m3Err_none) { + // If any trace function is found in the module, open the trace file + if (!trace) { + trace = fopen ("wasm3_trace.csv","w"); + } + } else if (i_result == m3Err_functionLookupFailed) { + i_result = m3Err_none; + } + return i_result; +} + + +M3Result m3_LinkTracer (IM3Module module) +{ + M3Result result = m3Err_none; + + const char* env = "env"; + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "log_execution", "v(i)", &m3_env_log_execution))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "log_exec_enter", "v(ii)", &m3_env_log_exec_enter))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "log_exec_exit", "v(ii)", &m3_env_log_exec_exit))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "log_exec_loop", "v(i)", &m3_env_log_exec_loop))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "load_ptr", "i(iiii)", &m3_env_load_ptr))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "store_ptr", "i(iiii)", &m3_env_store_ptr))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "load_val_i32", "i(ii)", &m3_env_load_val_i32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "load_val_i64", "I(iI)", &m3_env_load_val_i64))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "load_val_f32", "f(if)", &m3_env_load_val_f32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "load_val_f64", "F(iF)", &m3_env_load_val_f64))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "store_val_i32", "i(ii)", &m3_env_store_val_i32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "store_val_i64", "I(iI)", &m3_env_store_val_i64))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "store_val_f32", "f(if)", &m3_env_store_val_f32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "store_val_f64", "F(iF)", &m3_env_store_val_f64))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "get_i32", "i(iii)", &m3_env_get_i32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "get_i64", "I(iiI)", &m3_env_get_i64))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "get_f32", "f(iif)", &m3_env_get_f32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "get_f64", "F(iiF)", &m3_env_get_f64))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "set_i32", "i(iii)", &m3_env_set_i32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "set_i64", "I(iiI)", &m3_env_set_i64))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "set_f32", "f(iif)", &m3_env_set_f32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "set_f64", "F(iiF)", &m3_env_set_f64))); + +_catch: + return result; +} + +#endif // d_m3HasTracer + diff --git a/wasm3-sys/wasm3/source/m3_api_tracer.h b/wasm3-sys/wasm3/source/m3_api_tracer.h new file mode 100644 index 0000000..5744b87 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_api_tracer.h @@ -0,0 +1,19 @@ +// +// m3_api_tracer.h +// +// Created by Volodymyr Shymanskyy on 02/18/20. +// Copyright © 2020 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef m3_api_tracer_h +#define m3_api_tracer_h + +#include "m3_core.h" + +d_m3BeginExternC + +M3Result m3_LinkTracer (IM3Module io_module); + +d_m3EndExternC + +#endif // m3_api_tracer_h diff --git a/wasm3-sys/wasm3/source/m3_api_uvwasi.c b/wasm3-sys/wasm3/source/m3_api_uvwasi.c new file mode 100644 index 0000000..a059ffa --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_api_uvwasi.c @@ -0,0 +1,1035 @@ +// +// m3_api_uvwasi.c +// +// Created by Colin J. Ihrig on 4/20/20. +// Copyright © 2020 Colin J. Ihrig, Volodymyr Shymanskyy. All rights reserved. +// + +#define _POSIX_C_SOURCE 200809L + +#include "m3_api_wasi.h" + +#include "m3_env.h" +#include "m3_exception.h" + +#if defined(d_m3HasUVWASI) + +#include +#include + +#include "uvwasi.h" + +#ifndef d_m3EnableWasiTracing +# define d_m3EnableWasiTracing 0 +#endif + +#ifdef __APPLE__ +# include +# define environ (*_NSGetEnviron()) +#elif !defined(_MSC_VER) +extern char** environ; +#endif + +static m3_wasi_context_t* wasi_context; +static uvwasi_t uvwasi; + +typedef struct wasi_iovec_t +{ + uvwasi_size_t buf; + uvwasi_size_t buf_len; +} wasi_iovec_t; + +#if d_m3EnableWasiTracing + +const char* wasi_errno2str(uvwasi_errno_t err) +{ + switch (err) { + case 0: return "ESUCCESS"; + case 1: return "E2BIG"; + case 2: return "EACCES"; + case 3: return "EADDRINUSE"; + case 4: return "EADDRNOTAVAIL"; + case 5: return "EAFNOSUPPORT"; + case 6: return "EAGAIN"; + case 7: return "EALREADY"; + case 8: return "EBADF"; + case 9: return "EBADMSG"; + case 10: return "EBUSY"; + case 11: return "ECANCELED"; + case 12: return "ECHILD"; + case 13: return "ECONNABORTED"; + case 14: return "ECONNREFUSED"; + case 15: return "ECONNRESET"; + case 16: return "EDEADLK"; + case 17: return "EDESTADDRREQ"; + case 18: return "EDOM"; + case 19: return "EDQUOT"; + case 20: return "EEXIST"; + case 21: return "EFAULT"; + case 22: return "EFBIG"; + case 23: return "EHOSTUNREACH"; + case 24: return "EIDRM"; + case 25: return "EILSEQ"; + case 26: return "EINPROGRESS"; + case 27: return "EINTR"; + case 28: return "EINVAL"; + case 29: return "EIO"; + case 30: return "EISCONN"; + case 31: return "EISDIR"; + case 32: return "ELOOP"; + case 33: return "EMFILE"; + case 34: return "EMLINK"; + case 35: return "EMSGSIZE"; + case 36: return "EMULTIHOP"; + case 37: return "ENAMETOOLONG"; + case 38: return "ENETDOWN"; + case 39: return "ENETRESET"; + case 40: return "ENETUNREACH"; + case 41: return "ENFILE"; + case 42: return "ENOBUFS"; + case 43: return "ENODEV"; + case 44: return "ENOENT"; + case 45: return "ENOEXEC"; + case 46: return "ENOLCK"; + case 47: return "ENOLINK"; + case 48: return "ENOMEM"; + case 49: return "ENOMSG"; + case 50: return "ENOPROTOOPT"; + case 51: return "ENOSPC"; + case 52: return "ENOSYS"; + case 53: return "ENOTCONN"; + case 54: return "ENOTDIR"; + case 55: return "ENOTEMPTY"; + case 56: return "ENOTRECOVERABLE"; + case 57: return "ENOTSOCK"; + case 58: return "ENOTSUP"; + case 59: return "ENOTTY"; + case 60: return "ENXIO"; + case 61: return "EOVERFLOW"; + case 62: return "EOWNERDEAD"; + case 63: return "EPERM"; + case 64: return "EPIPE"; + case 65: return "EPROTO"; + case 66: return "EPROTONOSUPPORT"; + case 67: return "EPROTOTYPE"; + case 68: return "ERANGE"; + case 69: return "EROFS"; + case 70: return "ESPIPE"; + case 71: return "ESRCH"; + case 72: return "ESTALE"; + case 73: return "ETIMEDOUT"; + case 74: return "ETXTBSY"; + case 75: return "EXDEV"; + case 76: return "ENOTCAPABLE"; + default: return ""; + } +} + +# define WASI_TRACE(fmt, ...) { fprintf(stderr, "%s " fmt, __FUNCTION__+16, ##__VA_ARGS__); fprintf(stderr, " => %s\n", wasi_errno2str(ret)); } +#else +# define WASI_TRACE(fmt, ...) +#endif + +/* + * WASI API implementation + */ + +m3ApiRawFunction(m3_wasi_generic_args_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , argv) + m3ApiGetArgMem (char * , argv_buf) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(UVWASI_EINVAL); } + + m3ApiCheckMem(argv, context->argc * sizeof(uint32_t)); + + for (u32 i = 0; i < context->argc; ++i) + { + m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf)); + + size_t len = strlen (context->argv[i]); + + m3ApiCheckMem(argv_buf, len); + memcpy (argv_buf, context->argv[i], len); + argv_buf += len; + * argv_buf++ = 0; + } + + m3ApiReturn(UVWASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_args_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uvwasi_size_t * , argc) + m3ApiGetArgMem (uvwasi_size_t * , argv_buf_size) + + m3ApiCheckMem(argc, sizeof(uvwasi_size_t)); + m3ApiCheckMem(argv_buf_size, sizeof(uvwasi_size_t)); + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(UVWASI_EINVAL); } + + uvwasi_size_t buf_len = 0; + for (u32 i = 0; i < context->argc; ++i) + { + buf_len += strlen (context->argv[i]) + 1; + } + + m3ApiWriteMem32(argc, context->argc); + m3ApiWriteMem32(argv_buf_size, buf_len); + + m3ApiReturn(UVWASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , env) + m3ApiGetArgMem (char * , env_buf) + + char **environment; + uvwasi_errno_t ret; + uvwasi_size_t env_count, env_buf_size; + + ret = uvwasi_environ_sizes_get(&uvwasi, &env_count, &env_buf_size); + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + m3ApiCheckMem(env, env_count * sizeof(uint32_t)); + m3ApiCheckMem(env_buf, env_buf_size); + + environment = calloc(env_count, sizeof(char *)); + if (environment == NULL) { + m3ApiReturn(UVWASI_ENOMEM); + } + + ret = uvwasi_environ_get(&uvwasi, environment, env_buf); + if (ret != UVWASI_ESUCCESS) { + free(environment); + m3ApiReturn(ret); + } + + uint32_t environ_buf_offset = m3ApiPtrToOffset(env_buf); + + for (u32 i = 0; i < env_count; ++i) + { + uint32_t offset = environ_buf_offset + + (environment[i] - environment[0]); + m3ApiWriteMem32(&env[i], offset); + } + + free(environment); + m3ApiReturn(UVWASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uvwasi_size_t * , env_count) + m3ApiGetArgMem (uvwasi_size_t * , env_buf_size) + + m3ApiCheckMem(env_count, sizeof(uvwasi_size_t)); + m3ApiCheckMem(env_buf_size, sizeof(uvwasi_size_t)); + + uvwasi_size_t count; + uvwasi_size_t buf_size; + + uvwasi_errno_t ret = uvwasi_environ_sizes_get(&uvwasi, &count, &buf_size); + + m3ApiWriteMem32(env_count, count); + m3ApiWriteMem32(env_buf_size, buf_size); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_dir_name) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + uvwasi_errno_t ret = uvwasi_fd_prestat_dir_name(&uvwasi, fd, path, path_len); + + WASI_TRACE("fd:%d, len:%d | path:%s", fd, path_len, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 8); + + uvwasi_prestat_t prestat; + + uvwasi_errno_t ret = uvwasi_fd_prestat_get(&uvwasi, fd, &prestat); + + WASI_TRACE("fd:%d | type:%d, name_len:%d", fd, prestat.pr_type, prestat.u.dir.pr_name_len); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + m3ApiWriteMem32(buf+0, prestat.pr_type); + m3ApiWriteMem32(buf+4, prestat.u.dir.pr_name_len); + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 24); + + uvwasi_fdstat_t stat; + uvwasi_errno_t ret = uvwasi_fd_fdstat_get(&uvwasi, fd, &stat); + + WASI_TRACE("fd:%d", fd); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 24); + m3ApiWriteMem8 (buf+0, stat.fs_filetype); + m3ApiWriteMem16(buf+2, stat.fs_flags); + m3ApiWriteMem64(buf+8, stat.fs_rights_base); + m3ApiWriteMem64(buf+16, stat.fs_rights_inheriting); + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_set_flags) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArg (uvwasi_fdflags_t , flags) + + uvwasi_errno_t ret = uvwasi_fd_fdstat_set_flags(&uvwasi, fd, flags); + + WASI_TRACE("fd:%d, flags:0x%x", fd, flags); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 56); // wasi_filestat_t + + uvwasi_filestat_t stat; + + uvwasi_errno_t ret = uvwasi_fd_filestat_get(&uvwasi, fd, &stat); + + WASI_TRACE("fd:%d | fs.size:%d", fd, stat.st_size); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 56); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem32(buf+20, stat.st_nlink); + m3ApiWriteMem64(buf+24, stat.st_size); + m3ApiWriteMem64(buf+32, stat.st_atim); + m3ApiWriteMem64(buf+40, stat.st_mtim); + m3ApiWriteMem64(buf+48, stat.st_ctim); + + m3ApiReturn(UVWASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 64); // wasi_filestat_t + + uvwasi_filestat_t stat; + + uvwasi_errno_t ret = uvwasi_fd_filestat_get(&uvwasi, fd, &stat); + + WASI_TRACE("fd:%d | fs.size:%d", fd, stat.st_size); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 64); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem64(buf+24, stat.st_nlink); + m3ApiWriteMem64(buf+32, stat.st_size); + m3ApiWriteMem64(buf+40, stat.st_atim); + m3ApiWriteMem64(buf+48, stat.st_mtim); + m3ApiWriteMem64(buf+56, stat.st_ctim); + + m3ApiReturn(UVWASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArg (uvwasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (uvwasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(uvwasi_filesize_t)); + + uvwasi_whence_t whence = -1; + const char* whstr = "???"; + + switch (wasi_whence) { + case 0: whence = UVWASI_WHENCE_CUR; whstr = "CUR"; break; + case 1: whence = UVWASI_WHENCE_END; whstr = "END"; break; + case 2: whence = UVWASI_WHENCE_SET; whstr = "SET"; break; + } + + uvwasi_errno_t ret = uvwasi_fd_seek(&uvwasi, fd, offset, whence, result); + + WASI_TRACE("fd:%d, offset:%d, whence:%s | result:%d", fd, offset, whstr, *result); + + //TODO: m3ApiWriteMem + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArg (uvwasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (uvwasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(uvwasi_filesize_t)); + + uvwasi_whence_t whence = -1; + const char* whstr = "???"; + + switch (wasi_whence) { + case 0: whence = UVWASI_WHENCE_SET; whstr = "SET"; break; + case 1: whence = UVWASI_WHENCE_CUR; whstr = "CUR"; break; + case 2: whence = UVWASI_WHENCE_END; whstr = "END"; break; + } + + uvwasi_errno_t ret = uvwasi_fd_seek(&uvwasi, fd, offset, whence, result); + + WASI_TRACE("fd:%d, offset:%d, whence:%s | result:%d", fd, offset, whstr, *result); + + //TODO: m3ApiWriteMem + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_create_directory) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + uvwasi_errno_t ret = uvwasi_path_create_directory(&uvwasi, fd, path, path_len); + + WASI_TRACE("fd:%d, path:%s", fd, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_readlink) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + m3ApiGetArgMem (char * , buf) + m3ApiGetArg (uvwasi_size_t , buf_len) + m3ApiGetArgMem (uvwasi_size_t * , bufused) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, buf_len); + m3ApiCheckMem(bufused, sizeof(uvwasi_size_t)); + + uvwasi_size_t uvbufused; + + uvwasi_errno_t ret = uvwasi_path_readlink(&uvwasi, fd, path, path_len, buf, buf_len, &uvbufused); + + WASI_TRACE("fd:%d, path:%s | buf:%s, bufused:%d", fd, path, buf, uvbufused); + + m3ApiWriteMem32(bufused, uvbufused); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_remove_directory) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + uvwasi_errno_t ret = uvwasi_path_remove_directory(&uvwasi, fd, path, path_len); + + WASI_TRACE("fd:%d, path:%s", fd, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_rename) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , old_fd) + m3ApiGetArgMem (const char * , old_path) + m3ApiGetArg (uvwasi_size_t , old_path_len) + m3ApiGetArg (uvwasi_fd_t , new_fd) + m3ApiGetArgMem (const char * , new_path) + m3ApiGetArg (uvwasi_size_t , new_path_len) + + m3ApiCheckMem(old_path, old_path_len); + m3ApiCheckMem(new_path, new_path_len); + + uvwasi_errno_t ret = uvwasi_path_rename(&uvwasi, old_fd, old_path, old_path_len, + new_fd, new_path, new_path_len); + + WASI_TRACE("old_fd:%d, old_path:%s, new_fd:%d, new_path:%s", old_fd, old_path, new_fd, new_path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_symlink) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (const char * , old_path) + m3ApiGetArg (uvwasi_size_t , old_path_len) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (const char * , new_path) + m3ApiGetArg (uvwasi_size_t , new_path_len) + + m3ApiCheckMem(old_path, old_path_len); + m3ApiCheckMem(new_path, new_path_len); + + uvwasi_errno_t ret = uvwasi_path_symlink(&uvwasi, old_path, old_path_len, + fd, new_path, new_path_len); + + WASI_TRACE("old_fd:%d, old_path:%s, fd:%d, new_path:%s", old_fd, old_path, fd, new_path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_unlink_file) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + uvwasi_errno_t ret = uvwasi_path_unlink_file(&uvwasi, fd, path, path_len); + + WASI_TRACE("fd:%d, path:%s", fd, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_open) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , dirfd) + m3ApiGetArg (uvwasi_lookupflags_t , dirflags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + m3ApiGetArg (uvwasi_oflags_t , oflags) + m3ApiGetArg (uvwasi_rights_t , fs_rights_base) + m3ApiGetArg (uvwasi_rights_t , fs_rights_inheriting) + m3ApiGetArg (uvwasi_fdflags_t , fs_flags) + m3ApiGetArgMem (uvwasi_fd_t * , fd) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(fd, sizeof(uvwasi_fd_t)); + + uvwasi_fd_t uvfd; + + uvwasi_errno_t ret = uvwasi_path_open(&uvwasi, + dirfd, + dirflags, + path, + path_len, + oflags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + &uvfd); + + WASI_TRACE("dirfd:%d, dirflags:0x%x, path:%s, oflags:0x%x, fs_flags:0x%x | fd:%d", dirfd, dirflags, path, oflags, fs_flags, uvfd); + + m3ApiWriteMem32(fd, uvfd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_unstable_path_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArg (uvwasi_lookupflags_t , flags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uint32_t , path_len) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, 56); // wasi_filestat_t + + uvwasi_filestat_t stat; + + uvwasi_errno_t ret = uvwasi_path_filestat_get(&uvwasi, fd, flags, path, path_len, &stat); + + WASI_TRACE("fd:%d, flags:0x%x, path:%s | fs.size:%d", fd, flags, path, stat.st_size); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 56); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem32(buf+20, stat.st_nlink); + m3ApiWriteMem64(buf+24, stat.st_size); + m3ApiWriteMem64(buf+32, stat.st_atim); + m3ApiWriteMem64(buf+40, stat.st_mtim); + m3ApiWriteMem64(buf+48, stat.st_ctim); + + m3ApiReturn(UVWASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_path_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArg (uvwasi_lookupflags_t , flags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uint32_t , path_len) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, 64); // wasi_filestat_t + + uvwasi_filestat_t stat; + + uvwasi_errno_t ret = uvwasi_path_filestat_get(&uvwasi, fd, flags, path, path_len, &stat); + + WASI_TRACE("fd:%d, flags:0x%x, path:%s | fs.size:%d", fd, flags, path, stat.st_size); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 64); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem64(buf+24, stat.st_nlink); + m3ApiWriteMem64(buf+32, stat.st_size); + m3ApiWriteMem64(buf+40, stat.st_atim); + m3ApiWriteMem64(buf+48, stat.st_mtim); + m3ApiWriteMem64(buf+56, stat.st_ctim); + + m3ApiReturn(UVWASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_pread) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (uvwasi_size_t , iovs_len) + m3ApiGetArg (uvwasi_filesize_t , offset) + m3ApiGetArgMem (uvwasi_size_t * , nread) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nread, sizeof(uvwasi_size_t)); + +#if defined(M3_COMPILER_MSVC) + if (iovs_len > 32) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[32]; +#else + if (iovs_len > 128) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[iovs_len]; +#endif + + for (uvwasi_size_t i = 0; i < iovs_len; ++i) { + iovs[i].buf = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + iovs[i].buf_len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + + //fprintf(stderr, "> fd_pread fd:%d iov%d.len:%d\n", fd, i, iovs[i].buf_len); + } + + uvwasi_size_t num_read; + + uvwasi_errno_t ret = uvwasi_fd_pread(&uvwasi, fd, (const uvwasi_iovec_t *) iovs, iovs_len, offset, &num_read); + + WASI_TRACE("fd:%d | nread:%d", fd, num_read); + + m3ApiWriteMem32(nread, num_read); + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_read) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (uvwasi_size_t , iovs_len) + m3ApiGetArgMem (uvwasi_size_t * , nread) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nread, sizeof(uvwasi_size_t)); + +#if defined(M3_COMPILER_MSVC) + if (iovs_len > 32) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[32]; +#else + if (iovs_len > 128) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[iovs_len]; +#endif + uvwasi_size_t num_read; + uvwasi_errno_t ret; + + for (uvwasi_size_t i = 0; i < iovs_len; ++i) { + iovs[i].buf = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + iovs[i].buf_len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + + //fprintf(stderr, "> fd_read fd:%d iov%d.len:%d\n", fd, i, iovs[i].buf_len); + } + + ret = uvwasi_fd_read(&uvwasi, fd, (const uvwasi_iovec_t *) iovs, iovs_len, &num_read); + + WASI_TRACE("fd:%d | nread:%d", fd, num_read); + + m3ApiWriteMem32(nread, num_read); + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_write) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (uvwasi_size_t , iovs_len) + m3ApiGetArgMem (uvwasi_size_t * , nwritten) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nwritten, sizeof(uvwasi_size_t)); + +#if defined(M3_COMPILER_MSVC) + if (iovs_len > 32) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[32]; +#else + if (iovs_len > 128) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[iovs_len]; +#endif + uvwasi_size_t num_written; + uvwasi_errno_t ret; + + for (uvwasi_size_t i = 0; i < iovs_len; ++i) { + iovs[i].buf = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + iovs[i].buf_len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + } + + ret = uvwasi_fd_write(&uvwasi, fd, iovs, iovs_len, &num_written); + + WASI_TRACE("fd:%d | nwritten:%d", fd, num_written); + + m3ApiWriteMem32(nwritten, num_written); + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_readdir) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (void * , buf) + m3ApiGetArg (uvwasi_size_t , buf_len) + m3ApiGetArg (uvwasi_dircookie_t , cookie) + m3ApiGetArgMem (uvwasi_size_t * , bufused) + + m3ApiCheckMem(buf, buf_len); + m3ApiCheckMem(bufused, sizeof(uvwasi_size_t)); + + uvwasi_size_t uvbufused; + uvwasi_errno_t ret = uvwasi_fd_readdir(&uvwasi, fd, buf, buf_len, cookie, &uvbufused); + + WASI_TRACE("fd:%d | bufused:%d", fd, uvbufused); + + m3ApiWriteMem32(bufused, uvbufused); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_close) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t, fd) + + uvwasi_errno_t ret = uvwasi_fd_close(&uvwasi, fd); + + WASI_TRACE("fd:%d", fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_datasync) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t, fd) + + uvwasi_errno_t ret = uvwasi_fd_datasync(&uvwasi, fd); + + WASI_TRACE("fd:%d", fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_random_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint8_t * , buf) + m3ApiGetArg (uvwasi_size_t , buf_len) + + m3ApiCheckMem(buf, buf_len); + + uvwasi_errno_t ret = uvwasi_random_get(&uvwasi, buf, buf_len); + + WASI_TRACE("len:%d", buf_len); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_clock_res_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_clockid_t , wasi_clk_id) + m3ApiGetArgMem (uvwasi_timestamp_t * , resolution) + + m3ApiCheckMem(resolution, sizeof(uvwasi_timestamp_t)); + + uvwasi_errno_t ret = uvwasi_clock_res_get(&uvwasi, wasi_clk_id, resolution); + + WASI_TRACE("clk_id:%d", wasi_clk_id); + + //TODO: m3ApiWriteMem64 + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_clock_time_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_clockid_t , wasi_clk_id) + m3ApiGetArg (uvwasi_timestamp_t , precision) + m3ApiGetArgMem (uvwasi_timestamp_t * , time) + + m3ApiCheckMem(time, sizeof(uvwasi_timestamp_t)); + + uvwasi_errno_t ret = uvwasi_clock_time_get(&uvwasi, wasi_clk_id, precision, time); + + WASI_TRACE("clk_id:%d", wasi_clk_id); + + //TODO: m3ApiWriteMem64 + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_poll_oneoff) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (const uvwasi_subscription_t * , in) + m3ApiGetArgMem (uvwasi_event_t * , out) + m3ApiGetArg (uvwasi_size_t , nsubscriptions) + m3ApiGetArgMem (uvwasi_size_t * , nevents) + + m3ApiCheckMem(in, nsubscriptions * sizeof(uvwasi_subscription_t)); + m3ApiCheckMem(out, nsubscriptions * sizeof(uvwasi_event_t)); + m3ApiCheckMem(nevents, sizeof(uvwasi_size_t)); + + // TODO: unstable/snapshot_preview1 compatibility + + uvwasi_errno_t ret = uvwasi_poll_oneoff(&uvwasi, in, out, nsubscriptions, nevents); + + WASI_TRACE("nsubscriptions:%d | nevents:%d", nsubscriptions, *nevents); + + //TODO: m3ApiWriteMem + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_proc_exit) +{ + m3ApiGetArg (uint32_t, code) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context) { + context->exit_code = code; + } + + //TODO: fprintf(stderr, "proc_exit code:%d\n", code); + + m3ApiTrap(m3Err_trapExit); +} + + +static +M3Result SuppressLookupFailure(M3Result i_result) +{ + if (i_result == m3Err_functionLookupFailed) + return m3Err_none; + else + return i_result; +} + +m3_wasi_context_t* m3_GetWasiContext() +{ + return wasi_context; +} + + +M3Result m3_LinkWASI (IM3Module module) +{ + M3Result result = m3Err_none; + + #define ENV_COUNT 9 + + char* env[ENV_COUNT]; + env[0] = "TERM=xterm-256color"; + env[1] = "COLORTERM=truecolor"; + env[2] = "LANG=en_US.UTF-8"; + env[3] = "PWD=/"; + env[4] = "HOME=/"; + env[5] = "PATH=/"; + env[6] = "WASM3=1"; + env[7] = "WASM3_ARCH=" M3_ARCH; + env[8] = NULL; + + #define PREOPENS_COUNT 2 + + uvwasi_preopen_t preopens[PREOPENS_COUNT]; + preopens[0].mapped_path = "/"; + preopens[0].real_path = "."; + preopens[1].mapped_path = "./"; + preopens[1].real_path = "."; + + uvwasi_options_t init_options; + uvwasi_options_init(&init_options); + init_options.argc = 0; // runtime->argc is not initialized at this point, so we implement args_get directly + init_options.envp = (const char **) env; + init_options.preopenc = PREOPENS_COUNT; + init_options.preopens = preopens; + + if (!wasi_context) { + wasi_context = (m3_wasi_context_t*)malloc(sizeof(m3_wasi_context_t)); + wasi_context->exit_code = 0; + wasi_context->argc = 0; + wasi_context->argv = 0; + + uvwasi_errno_t ret = uvwasi_init(&uvwasi, &init_options); + + if (ret != UVWASI_ESUCCESS) { + return "uvwasi_init failed"; + } + } + + static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" }; + + // fd_seek is incompatible +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_seek", "i(iIi*)", &m3_wasi_unstable_fd_seek))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_seek", "i(iIi*)", &m3_wasi_snapshot_preview1_fd_seek))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_filestat_get", "i(i*)", &m3_wasi_unstable_fd_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_filestat_get", "i(i*)", &m3_wasi_snapshot_preview1_fd_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "path_filestat_get", "i(ii*i*)", &m3_wasi_unstable_path_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "path_filestat_get", "i(ii*i*)", &m3_wasi_snapshot_preview1_path_filestat_get))); + + for (int i=0; i<2; i++) + { + const char* wasi = namespaces[i]; + +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_get", "i(**)", &m3_wasi_generic_args_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_generic_args_sizes_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_generic_clock_res_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(iI*)", &m3_wasi_generic_clock_time_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_generic_environ_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get", "i(**)", &m3_wasi_generic_environ_sizes_get))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_advise", "i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_allocate", "i(iII)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close", "i(i)", &m3_wasi_generic_fd_close))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync", "i(i)", &m3_wasi_generic_fd_datasync))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get", "i(i*)", &m3_wasi_generic_fd_fdstat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_flags", "i(ii)", &m3_wasi_generic_fd_fdstat_set_flags))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_rights", "i(iII)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_size", "i(iI)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_times","i(iIIi)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pread", "i(i*iI*)",&m3_wasi_generic_fd_pread))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get", "i(i*)", &m3_wasi_generic_fd_prestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name", "i(i*i)", &m3_wasi_generic_fd_prestat_dir_name))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pwrite", "i(i*iI*)",))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read", "i(i*i*)", &m3_wasi_generic_fd_read))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_readdir", "i(i*iI*)",&m3_wasi_generic_fd_readdir))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_renumber", "i(ii)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_sync", "i(i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_tell", "i(i*)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write", "i(i*i*)", &m3_wasi_generic_fd_write))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_create_directory", "i(i*i)", &m3_wasi_generic_path_create_directory))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_set_times", "i(ii*iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_link", "i(ii*ii*i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", "i(ii*iiIIi*)", &m3_wasi_generic_path_open))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_readlink", "i(i*i*i*)", &m3_wasi_generic_path_readlink))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_remove_directory", "i(i*i)", &m3_wasi_generic_path_remove_directory))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_rename", "i(i*ii*i)", &m3_wasi_generic_path_rename))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_symlink", "i(*ii*i)", &m3_wasi_generic_path_symlink))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file", "i(i*i)", &m3_wasi_generic_path_unlink_file))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff", "i(**i*)", &m3_wasi_generic_poll_oneoff))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "proc_exit", "v(i)", &m3_wasi_generic_proc_exit, wasi_context))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise", "i(i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_generic_random_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield", "i()", ))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv", "i(i*ii**)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send", "i(i*ii*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_shutdown", "i(ii)", ))); + } + +_catch: + return result; +} + +#endif // d_m3HasUVWASI + diff --git a/wasm3-sys/wasm3/source/m3_api_wasi.c b/wasm3-sys/wasm3/source/m3_api_wasi.c new file mode 100644 index 0000000..47cccff --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_api_wasi.c @@ -0,0 +1,863 @@ +// +// m3_api_wasi.c +// +// Created by Volodymyr Shymanskyy on 11/20/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#define _POSIX_C_SOURCE 200809L + +#include "m3_api_wasi.h" + +#include "m3_env.h" +#include "m3_exception.h" + +#if defined(d_m3HasWASI) + +// Fixup wasi_core.h +#if defined (M3_COMPILER_MSVC) +# define _Static_assert(...) +# define __attribute__(...) +# define _Noreturn +#endif + +#include "extra/wasi_core.h" + +#include +#include +#include +#include +#include +#include + +#if defined(APE) +// Actually Portable Executable +// All functions are already included in cosmopolitan.h +#elif defined(__wasi__) || defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__) || defined(__linux__) || defined(__EMSCRIPTEN__) +# include +# include +# if defined(__APPLE__) +# include +# if TARGET_OS_OSX // TARGET_OS_MAC includes iOS +# include +# else // iOS / Simulator +# include +# endif +# else +# include +# endif +# define HAS_IOVEC +#elif defined(_WIN32) +# include +# include +// See http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx +# define SystemFunction036 NTAPI SystemFunction036 +# include +# undef SystemFunction036 +# define ssize_t SSIZE_T + +# define open _open +# define read _read +# define write _write +# define close _close +#endif + +static m3_wasi_context_t* wasi_context; + +typedef struct wasi_iovec_t +{ + __wasi_size_t buf; + __wasi_size_t buf_len; +} wasi_iovec_t; + +#define PREOPEN_CNT 5 + +typedef struct Preopen { + int fd; + const char* path; + const char* real_path; +} Preopen; + +Preopen preopen[PREOPEN_CNT] = { + { 0, "" , "" }, + { 1, "", "" }, + { 2, "", "" }, + { -1, "/" , "." }, + { -1, "./" , "." }, +}; + +#if defined(APE) +# define APE_SWITCH_BEG +# define APE_SWITCH_END {} +# define APE_CASE_RET(e1,e2) if (errnum == e1) return e2; else +#else +# define APE_SWITCH_BEG switch (errnum) { +# define APE_SWITCH_END } +# define APE_CASE_RET(e1,e2) case e1: return e2; break; +#endif + +static +__wasi_errno_t errno_to_wasi(int errnum) { + APE_SWITCH_BEG + APE_CASE_RET( EPERM , __WASI_ERRNO_PERM ) + APE_CASE_RET( ENOENT , __WASI_ERRNO_NOENT ) + APE_CASE_RET( ESRCH , __WASI_ERRNO_SRCH ) + APE_CASE_RET( EINTR , __WASI_ERRNO_INTR ) + APE_CASE_RET( EIO , __WASI_ERRNO_IO ) + APE_CASE_RET( ENXIO , __WASI_ERRNO_NXIO ) + APE_CASE_RET( E2BIG , __WASI_ERRNO_2BIG ) + APE_CASE_RET( ENOEXEC , __WASI_ERRNO_NOEXEC ) + APE_CASE_RET( EBADF , __WASI_ERRNO_BADF ) + APE_CASE_RET( ECHILD , __WASI_ERRNO_CHILD ) + APE_CASE_RET( EAGAIN , __WASI_ERRNO_AGAIN ) + APE_CASE_RET( ENOMEM , __WASI_ERRNO_NOMEM ) + APE_CASE_RET( EACCES , __WASI_ERRNO_ACCES ) + APE_CASE_RET( EFAULT , __WASI_ERRNO_FAULT ) + APE_CASE_RET( EBUSY , __WASI_ERRNO_BUSY ) + APE_CASE_RET( EEXIST , __WASI_ERRNO_EXIST ) + APE_CASE_RET( EXDEV , __WASI_ERRNO_XDEV ) + APE_CASE_RET( ENODEV , __WASI_ERRNO_NODEV ) + APE_CASE_RET( ENOTDIR , __WASI_ERRNO_NOTDIR ) + APE_CASE_RET( EISDIR , __WASI_ERRNO_ISDIR ) + APE_CASE_RET( EINVAL , __WASI_ERRNO_INVAL ) + APE_CASE_RET( ENFILE , __WASI_ERRNO_NFILE ) + APE_CASE_RET( EMFILE , __WASI_ERRNO_MFILE ) + APE_CASE_RET( ENOTTY , __WASI_ERRNO_NOTTY ) + APE_CASE_RET( ETXTBSY , __WASI_ERRNO_TXTBSY ) + APE_CASE_RET( EFBIG , __WASI_ERRNO_FBIG ) + APE_CASE_RET( ENOSPC , __WASI_ERRNO_NOSPC ) + APE_CASE_RET( ESPIPE , __WASI_ERRNO_SPIPE ) + APE_CASE_RET( EROFS , __WASI_ERRNO_ROFS ) + APE_CASE_RET( EMLINK , __WASI_ERRNO_MLINK ) + APE_CASE_RET( EPIPE , __WASI_ERRNO_PIPE ) + APE_CASE_RET( EDOM , __WASI_ERRNO_DOM ) + APE_CASE_RET( ERANGE , __WASI_ERRNO_RANGE ) + APE_SWITCH_END + return __WASI_ERRNO_INVAL; +} + +#if defined(_WIN32) + +#if !defined(__MINGW32__) + +static inline +int clock_gettime(int clk_id, struct timespec *spec) +{ + __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); + wintime -= 116444736000000000i64; //1jan1601 to 1jan1970 + spec->tv_sec = wintime / 10000000i64; //seconds + spec->tv_nsec = wintime % 10000000i64 *100; //nano-seconds + return 0; +} + +static inline +int clock_getres(int clk_id, struct timespec *spec) { + return -1; // Defaults to 1000000 +} + +#endif + +static inline +int convert_clockid(__wasi_clockid_t in) { + return 0; +} + +#else // _WIN32 + +static inline +int convert_clockid(__wasi_clockid_t in) { + switch (in) { + case __WASI_CLOCKID_MONOTONIC: return CLOCK_MONOTONIC; + case __WASI_CLOCKID_PROCESS_CPUTIME_ID: return CLOCK_PROCESS_CPUTIME_ID; + case __WASI_CLOCKID_REALTIME: return CLOCK_REALTIME; + case __WASI_CLOCKID_THREAD_CPUTIME_ID: return CLOCK_THREAD_CPUTIME_ID; + default: return -1; + } +} + +#endif // _WIN32 + +static inline +__wasi_timestamp_t convert_timespec(const struct timespec *ts) { + if (ts->tv_sec < 0) + return 0; + if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000) + return UINT64_MAX; + return (__wasi_timestamp_t)ts->tv_sec * 1000000000 + ts->tv_nsec; +} + +#if defined(HAS_IOVEC) + +static inline +void copy_iov_to_host(void* _mem, struct iovec* host_iov, wasi_iovec_t* wasi_iov, int32_t iovs_len) +{ + // Convert wasi memory offsets to host addresses + for (int i = 0; i < iovs_len; i++) { + host_iov[i].iov_base = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iov[i].buf)); + host_iov[i].iov_len = m3ApiReadMem32(&wasi_iov[i].buf_len); + } +} + +#endif + +/* + * WASI API implementation + */ + +m3ApiRawFunction(m3_wasi_generic_args_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , argv) + m3ApiGetArgMem (char * , argv_buf) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + + m3ApiCheckMem(argv, context->argc * sizeof(uint32_t)); + + for (u32 i = 0; i < context->argc; ++i) + { + m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf)); + + size_t len = strlen (context->argv[i]); + + m3ApiCheckMem(argv_buf, len); + memcpy (argv_buf, context->argv[i], len); + argv_buf += len; + * argv_buf++ = 0; + } + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_args_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , argc) + m3ApiGetArgMem (__wasi_size_t * , argv_buf_size) + + m3ApiCheckMem(argc, sizeof(__wasi_size_t)); + m3ApiCheckMem(argv_buf_size, sizeof(__wasi_size_t)); + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + + __wasi_size_t buf_len = 0; + for (u32 i = 0; i < context->argc; ++i) + { + buf_len += strlen (context->argv[i]) + 1; + } + + m3ApiWriteMem32(argc, context->argc); + m3ApiWriteMem32(argv_buf_size, buf_len); + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , env) + m3ApiGetArgMem (char * , env_buf) + + // TODO + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , env_count) + m3ApiGetArgMem (__wasi_size_t * , env_buf_size) + + m3ApiCheckMem(env_count, sizeof(__wasi_size_t)); + m3ApiCheckMem(env_buf_size, sizeof(__wasi_size_t)); + + // TODO + m3ApiWriteMem32(env_count, 0); + m3ApiWriteMem32(env_buf_size, 0); + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_dir_name) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + if (fd < 3 || fd >= PREOPEN_CNT) { m3ApiReturn(__WASI_ERRNO_BADF); } + size_t slen = strlen(preopen[fd].path) + 1; + memcpy(path, preopen[fd].path, M3_MIN(slen, path_len)); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 8); + + if (fd < 3 || fd >= PREOPEN_CNT) { m3ApiReturn(__WASI_ERRNO_BADF); } + + m3ApiWriteMem32(buf+0, __WASI_PREOPENTYPE_DIR); + m3ApiWriteMem32(buf+4, strlen(preopen[fd].path) + 1); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_fdstat_t * , fdstat) + + m3ApiCheckMem(fdstat, sizeof(__wasi_fdstat_t)); + +#ifdef _WIN32 + + // TODO: This needs a proper implementation + if (fd < PREOPEN_CNT) { + fdstat->fs_filetype= __WASI_FILETYPE_DIRECTORY; + } else { + fdstat->fs_filetype= __WASI_FILETYPE_REGULAR_FILE; + } + + fdstat->fs_flags = 0; + fdstat->fs_rights_base = (uint64_t)-1; // all rights + fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#else + struct stat fd_stat; + +#if !defined(APE) // TODO: not implemented in Cosmopolitan + int fl = fcntl(fd, F_GETFL); + if (fl < 0) { m3ApiReturn(errno_to_wasi(errno)); } +#endif + + fstat(fd, &fd_stat); + int mode = fd_stat.st_mode; + fdstat->fs_filetype = (S_ISBLK(mode) ? __WASI_FILETYPE_BLOCK_DEVICE : 0) | + (S_ISCHR(mode) ? __WASI_FILETYPE_CHARACTER_DEVICE : 0) | + (S_ISDIR(mode) ? __WASI_FILETYPE_DIRECTORY : 0) | + (S_ISREG(mode) ? __WASI_FILETYPE_REGULAR_FILE : 0) | + //(S_ISSOCK(mode) ? __WASI_FILETYPE_SOCKET_STREAM : 0) | + (S_ISLNK(mode) ? __WASI_FILETYPE_SYMBOLIC_LINK : 0); +#if !defined(APE) + m3ApiWriteMem16(&fdstat->fs_flags, + ((fl & O_APPEND) ? __WASI_FDFLAGS_APPEND : 0) | + ((fl & O_DSYNC) ? __WASI_FDFLAGS_DSYNC : 0) | + ((fl & O_NONBLOCK) ? __WASI_FDFLAGS_NONBLOCK : 0) | + //((fl & O_RSYNC) ? __WASI_FDFLAGS_RSYNC : 0) | + ((fl & O_SYNC) ? __WASI_FDFLAGS_SYNC : 0)); +#endif // APE + + fdstat->fs_rights_base = (uint64_t)-1; // all rights + + // Make descriptors 0,1,2 look like a TTY + if (fd <= 2) { + fdstat->fs_rights_base &= ~(__WASI_RIGHTS_FD_SEEK | __WASI_RIGHTS_FD_TELL); + } + + fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#endif +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_set_flags) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_fdflags_t , flags) + + // TODO + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(__wasi_filesize_t)); + + int whence; + + switch (wasi_whence) { + case 0: whence = SEEK_CUR; break; + case 1: whence = SEEK_END; break; + case 2: whence = SEEK_SET; break; + default: m3ApiReturn(__WASI_ERRNO_INVAL); + } + + int64_t ret; +#if defined(M3_COMPILER_MSVC) || defined(__MINGW32__) + ret = _lseeki64(fd, offset, whence); +#else + ret = lseek(fd, offset, whence); +#endif + if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } + m3ApiWriteMem64(result, ret); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(__wasi_filesize_t)); + + int whence; + + switch (wasi_whence) { + case 0: whence = SEEK_SET; break; + case 1: whence = SEEK_CUR; break; + case 2: whence = SEEK_END; break; + default: m3ApiReturn(__WASI_ERRNO_INVAL); + } + + int64_t ret; +#if defined(M3_COMPILER_MSVC) || defined(__MINGW32__) + ret = _lseeki64(fd, offset, whence); +#else + ret = lseek(fd, offset, whence); +#endif + if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } + m3ApiWriteMem64(result, ret); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + + +m3ApiRawFunction(m3_wasi_generic_path_open) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , dirfd) + m3ApiGetArg (__wasi_lookupflags_t , dirflags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + m3ApiGetArg (__wasi_oflags_t , oflags) + m3ApiGetArg (__wasi_rights_t , fs_rights_base) + m3ApiGetArg (__wasi_rights_t , fs_rights_inheriting) + m3ApiGetArg (__wasi_fdflags_t , fs_flags) + m3ApiGetArgMem (__wasi_fd_t * , fd) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(fd, sizeof(__wasi_fd_t)); + + if (path_len >= 512) + m3ApiReturn(__WASI_ERRNO_INVAL); + + // copy path so we can ensure it is NULL terminated +#if defined(M3_COMPILER_MSVC) + char host_path[512]; +#else + char host_path[path_len+1]; +#endif + memcpy (host_path, path, path_len); + host_path[path_len] = '\0'; // NULL terminator + +#if defined(APE) + // TODO: This all needs a proper implementation + + int flags = ((oflags & __WASI_OFLAGS_CREAT) ? O_CREAT : 0) | + ((oflags & __WASI_OFLAGS_EXCL) ? O_EXCL : 0) | + ((oflags & __WASI_OFLAGS_TRUNC) ? O_TRUNC : 0) | + ((fs_flags & __WASI_FDFLAGS_APPEND) ? O_APPEND : 0); + + if ((fs_rights_base & __WASI_RIGHTS_FD_READ) && + (fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= O_RDWR; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= O_WRONLY; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_READ)) { + flags |= O_RDONLY; // no-op because O_RDONLY is 0 + } + int mode = 0644; + + int host_fd = open (host_path, flags, mode); + + if (host_fd < 0) + { + m3ApiReturn(errno_to_wasi (errno)); + } + else + { + m3ApiWriteMem32(fd, host_fd); + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } +#elif defined(_WIN32) + // TODO: This all needs a proper implementation + + int flags = ((oflags & __WASI_OFLAGS_CREAT) ? _O_CREAT : 0) | + ((oflags & __WASI_OFLAGS_EXCL) ? _O_EXCL : 0) | + ((oflags & __WASI_OFLAGS_TRUNC) ? _O_TRUNC : 0) | + ((fs_flags & __WASI_FDFLAGS_APPEND) ? _O_APPEND : 0) | + _O_BINARY; + + if ((fs_rights_base & __WASI_RIGHTS_FD_READ) && + (fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= _O_RDWR; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= _O_WRONLY; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_READ)) { + flags |= _O_RDONLY; // no-op because O_RDONLY is 0 + } + int mode = 0644; + + int host_fd = open (host_path, flags, mode); + + if (host_fd < 0) + { + m3ApiReturn(errno_to_wasi (errno)); + } + else + { + m3ApiWriteMem32(fd, host_fd); + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } +#else + // translate o_flags and fs_flags into flags and mode + int flags = ((oflags & __WASI_OFLAGS_CREAT) ? O_CREAT : 0) | + //((oflags & __WASI_OFLAGS_DIRECTORY) ? O_DIRECTORY : 0) | + ((oflags & __WASI_OFLAGS_EXCL) ? O_EXCL : 0) | + ((oflags & __WASI_OFLAGS_TRUNC) ? O_TRUNC : 0) | + ((fs_flags & __WASI_FDFLAGS_APPEND) ? O_APPEND : 0) | + ((fs_flags & __WASI_FDFLAGS_DSYNC) ? O_DSYNC : 0) | + ((fs_flags & __WASI_FDFLAGS_NONBLOCK) ? O_NONBLOCK : 0) | + //((fs_flags & __WASI_FDFLAGS_RSYNC) ? O_RSYNC : 0) | + ((fs_flags & __WASI_FDFLAGS_SYNC) ? O_SYNC : 0); + if ((fs_rights_base & __WASI_RIGHTS_FD_READ) && + (fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= O_RDWR; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= O_WRONLY; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_READ)) { + flags |= O_RDONLY; // no-op because O_RDONLY is 0 + } + int mode = 0644; + int host_fd = openat (preopen[dirfd].fd, host_path, flags, mode); + + if (host_fd < 0) + { + m3ApiReturn(errno_to_wasi (errno)); + } + else + { + m3ApiWriteMem32(fd, host_fd); + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } +#endif +} + +m3ApiRawFunction(m3_wasi_generic_fd_read) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nread) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nread, sizeof(__wasi_size_t)); + +#if defined(HAS_IOVEC) + struct iovec iovs[iovs_len]; + copy_iov_to_host(_mem, iovs, wasi_iovs, iovs_len); + + ssize_t ret = readv(fd, iovs, iovs_len); + if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } + m3ApiWriteMem32(nread, ret); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#else + ssize_t res = 0; + for (__wasi_size_t i = 0; i < iovs_len; i++) { + void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + if (len == 0) continue; + + int ret = read (fd, addr, len); + if (ret < 0) m3ApiReturn(errno_to_wasi(errno)); + res += ret; + if ((size_t)ret < len) break; + } + m3ApiWriteMem32(nread, res); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#endif +} + +m3ApiRawFunction(m3_wasi_generic_fd_write) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nwritten) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nwritten, sizeof(__wasi_size_t)); + +#if defined(HAS_IOVEC) + struct iovec iovs[iovs_len]; + copy_iov_to_host(_mem, iovs, wasi_iovs, iovs_len); + + ssize_t ret = writev(fd, iovs, iovs_len); + if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } + m3ApiWriteMem32(nwritten, ret); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#else + ssize_t res = 0; + for (__wasi_size_t i = 0; i < iovs_len; i++) { + void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + if (len == 0) continue; + + int ret = write (fd, addr, len); + if (ret < 0) m3ApiReturn(errno_to_wasi(errno)); + res += ret; + if ((size_t)ret < len) break; + } + m3ApiWriteMem32(nwritten, res); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#endif +} + +m3ApiRawFunction(m3_wasi_generic_fd_close) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + + int ret = close(fd); + m3ApiReturn(ret == 0 ? __WASI_ERRNO_SUCCESS : ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_datasync) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + +#if defined(_WIN32) + int ret = _commit(fd); +#elif defined(__APPLE__) + int ret = fsync(fd); +#elif defined(__ANDROID_API__) || defined(__OpenBSD__) || defined(__linux__) || defined(__EMSCRIPTEN__) + int ret = fdatasync(fd); +#else + int ret = __WASI_ERRNO_NOSYS; +#endif + m3ApiReturn(ret == 0 ? __WASI_ERRNO_SUCCESS : ret); +} + +m3ApiRawFunction(m3_wasi_generic_random_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint8_t * , buf) + m3ApiGetArg (__wasi_size_t , buf_len) + + m3ApiCheckMem(buf, buf_len); + + while (1) { + ssize_t retlen = 0; + +#if defined(__wasi__) || defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__) + size_t reqlen = M3_MIN (buf_len, 256); +# if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + retlen = SecRandomCopyBytes(kSecRandomDefault, reqlen, buf) < 0 ? -1 : reqlen; +# else + retlen = getentropy(buf, reqlen) < 0 ? -1 : reqlen; +# endif +#elif defined(__FreeBSD__) || defined(__linux__) + retlen = getrandom(buf, buf_len, 0); +#elif defined(_WIN32) + if (RtlGenRandom(buf, buf_len) == TRUE) { + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } +#else + m3ApiReturn(__WASI_ERRNO_NOSYS); +#endif + if (retlen < 0) { + if (errno == EINTR || errno == EAGAIN) { + continue; + } + m3ApiReturn(errno_to_wasi(errno)); + } else if (retlen == buf_len) { + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } else { + buf += retlen; + buf_len -= retlen; + } + } +} + +m3ApiRawFunction(m3_wasi_generic_clock_res_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArgMem (__wasi_timestamp_t * , resolution) + + m3ApiCheckMem(resolution, sizeof(__wasi_timestamp_t)); + + int clk = convert_clockid(wasi_clk_id); + if (clk < 0) m3ApiReturn(__WASI_ERRNO_INVAL); + + struct timespec tp; + if (clock_getres(clk, &tp) != 0) { + m3ApiWriteMem64(resolution, 1000000); + } else { + m3ApiWriteMem64(resolution, convert_timespec(&tp)); + } + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_clock_time_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArg (__wasi_timestamp_t , precision) + m3ApiGetArgMem (__wasi_timestamp_t * , time) + + m3ApiCheckMem(time, sizeof(__wasi_timestamp_t)); + + int clk = convert_clockid(wasi_clk_id); + if (clk < 0) m3ApiReturn(__WASI_ERRNO_INVAL); + + struct timespec tp; + if (clock_gettime(clk, &tp) != 0) { + m3ApiReturn(errno_to_wasi(errno)); + } + + m3ApiWriteMem64(time, convert_timespec(&tp)); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_proc_exit) +{ + m3ApiGetArg (uint32_t, code) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context) { + context->exit_code = code; + } + + m3ApiTrap(m3Err_trapExit); +} + + +static +M3Result SuppressLookupFailure(M3Result i_result) +{ + if (i_result == m3Err_functionLookupFailed) + return m3Err_none; + else + return i_result; +} + +m3_wasi_context_t* m3_GetWasiContext() +{ + return wasi_context; +} + + +M3Result m3_LinkWASI (IM3Module module) +{ + M3Result result = m3Err_none; + +#ifdef _WIN32 + setmode(fileno(stdin), O_BINARY); + setmode(fileno(stdout), O_BINARY); + setmode(fileno(stderr), O_BINARY); + +#else + // Preopen dirs + for (int i = 3; i < PREOPEN_CNT; i++) { + preopen[i].fd = open(preopen[i].real_path, O_RDONLY); + } +#endif + + if (!wasi_context) { + wasi_context = (m3_wasi_context_t*)malloc(sizeof(m3_wasi_context_t)); + wasi_context->exit_code = 0; + wasi_context->argc = 0; + wasi_context->argv = 0; + } + + static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" }; + + // fd_seek is incompatible +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_seek", "i(iIi*)", &m3_wasi_unstable_fd_seek))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_seek", "i(iIi*)", &m3_wasi_snapshot_preview1_fd_seek))); + + for (int i=0; i<2; i++) + { + const char* wasi = namespaces[i]; + +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_get", "i(**)", &m3_wasi_generic_args_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_generic_args_sizes_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_generic_clock_res_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(iI*)", &m3_wasi_generic_clock_time_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_generic_environ_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get", "i(**)", &m3_wasi_generic_environ_sizes_get))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_advise", "i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_allocate", "i(iII)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close", "i(i)", &m3_wasi_generic_fd_close))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync", "i(i)", &m3_wasi_generic_fd_datasync))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get", "i(i*)", &m3_wasi_generic_fd_fdstat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_flags", "i(ii)", &m3_wasi_generic_fd_fdstat_set_flags))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_rights", "i(iII)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_get", "i(i*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_size", "i(iI)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_times","i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pread", "i(i*iI*)",))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get", "i(i*)", &m3_wasi_generic_fd_prestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name", "i(i*i)", &m3_wasi_generic_fd_prestat_dir_name))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pwrite", "i(i*iI*)",))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read", "i(i*i*)", &m3_wasi_generic_fd_read))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_readdir", "i(i*iI*)",))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_renumber", "i(ii)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_sync", "i(i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_tell", "i(i*)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write", "i(i*i*)", &m3_wasi_generic_fd_write))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_create_directory", "i(i*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_get", "i(ii*i*)", &m3_wasi_generic_path_filestat_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_set_times", "i(ii*iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_link", "i(ii*ii*i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", "i(ii*iiIIi*)", &m3_wasi_generic_path_open))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_readlink", "i(i*i*i*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_remove_directory", "i(i*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_rename", "i(i*ii*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_symlink", "i(*ii*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file", "i(i*i)", ))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff", "i(**i*)", &m3_wasi_generic_poll_oneoff))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "proc_exit", "v(i)", &m3_wasi_generic_proc_exit, wasi_context))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise", "i(i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_generic_random_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield", "i()", ))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv", "i(i*ii**)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send", "i(i*ii*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_shutdown", "i(ii)", ))); + } + +_catch: + return result; +} + +#endif // d_m3HasWASI diff --git a/wasm3-sys/wasm3/source/m3_api_wasi.h b/wasm3-sys/wasm3/source/m3_api_wasi.h new file mode 100644 index 0000000..8b0edc2 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_api_wasi.h @@ -0,0 +1,28 @@ +// +// m3_api_wasi.h +// +// Created by Volodymyr Shymanskyy on 11/20/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef m3_api_wasi_h +#define m3_api_wasi_h + +#include "m3_core.h" + +d_m3BeginExternC + +typedef struct m3_wasi_context_t +{ + i32 exit_code; + u32 argc; + ccstr_t * argv; +} m3_wasi_context_t; + +M3Result m3_LinkWASI (IM3Module io_module); + +m3_wasi_context_t* m3_GetWasiContext(); + +d_m3EndExternC + +#endif // m3_api_wasi_h diff --git a/wasm3-sys/wasm3/source/m3_bind.c b/wasm3-sys/wasm3/source/m3_bind.c new file mode 100644 index 0000000..368fe83 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_bind.c @@ -0,0 +1,201 @@ +// +// m3_bind.c +// +// Created by Steven Massey on 4/29/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_exec.h" +#include "m3_env.h" +#include "m3_exception.h" +#include "m3_info.h" + + +u8 ConvertTypeCharToTypeId (char i_code) +{ + switch (i_code) { + case 'v': return c_m3Type_none; + case 'i': return c_m3Type_i32; + case 'I': return c_m3Type_i64; + case 'f': return c_m3Type_f32; + case 'F': return c_m3Type_f64; + case '*': return c_m3Type_i32; + } + return c_m3Type_unknown; +} + + +M3Result SignatureToFuncType (IM3FuncType * o_functionType, ccstr_t i_signature) +{ + M3Result result = m3Err_none; + + IM3FuncType funcType = NULL; + +_try { + if (not o_functionType) + _throw ("null function type"); + + if (not i_signature) + _throw ("null function signature"); + + cstr_t sig = i_signature; + + size_t maxNumTypes = strlen (i_signature); + + // assume min signature is "()" + _throwif (m3Err_malformedFunctionSignature, maxNumTypes < 2); + maxNumTypes -= 2; + + _throwif (m3Err_tooManyArgsRets, maxNumTypes > d_m3MaxSaneFunctionArgRetCount); + +_ (AllocFuncType (& funcType, (u32) maxNumTypes)); + + u8 * typelist = funcType->types; + + bool parsingRets = true; + while (* sig) + { + char typeChar = * sig++; + + if (typeChar == '(') + { + parsingRets = false; + continue; + } + else if ( typeChar == ' ') + continue; + else if (typeChar == ')') + break; + + u8 type = ConvertTypeCharToTypeId (typeChar); + + _throwif ("unknown argument type char", c_m3Type_unknown == type); + + if (type == c_m3Type_none) + continue; + + if (parsingRets) + { + _throwif ("malformed signature; return count overflow", funcType->numRets >= maxNumTypes); + funcType->numRets++; + *typelist++ = type; + } + else + { + _throwif ("malformed signature; arg count overflow", (u32)(funcType->numRets) + funcType->numArgs >= maxNumTypes); + funcType->numArgs++; + *typelist++ = type; + } + } + +} _catch: + + if (result) + m3_Free (funcType); + + * o_functionType = funcType; + + return result; +} + + +static +M3Result ValidateSignature (IM3Function i_function, ccstr_t i_linkingSignature) +{ + M3Result result = m3Err_none; + + IM3FuncType ftype = NULL; +_ (SignatureToFuncType (& ftype, i_linkingSignature)); + + if (not AreFuncTypesEqual (ftype, i_function->funcType)) + { + m3log (module, "expected: %s", SPrintFuncTypeSignature (ftype)); + m3log (module, " found: %s", SPrintFuncTypeSignature (i_function->funcType)); + + _throw ("function signature mismatch"); + } + + _catch: + + m3_Free (ftype); + + return result; +} + + +M3Result LinkRawFunction (IM3Module io_module, IM3Function io_function, ccstr_t signature, const void * i_function, const void * i_userdata) +{ + M3Result result = m3Err_none; d_m3Assert (io_module->runtime); + +_try { + if (signature) { +_ (ValidateSignature (io_function, signature)); + } + IM3CodePage page = AcquireCodePageWithCapacity (io_module->runtime, 4); + + if (page) + { + io_function->compiled = GetPagePC (page); + io_function->module = io_module; + + EmitWord (page, op_CallRawFunction); + EmitWord (page, i_function); + EmitWord (page, io_function); + EmitWord (page, i_userdata); + + ReleaseCodePage (io_module->runtime, page); + } + else _throw(m3Err_mallocFailedCodePage); + +} _catch: + return result; +} + +M3Result FindAndLinkFunction (IM3Module io_module, + ccstr_t i_moduleName, + ccstr_t i_functionName, + ccstr_t i_signature, + voidptr_t i_function, + voidptr_t i_userdata) +{ + M3Result result = m3Err_functionLookupFailed; + + bool wildcardModule = (strcmp (i_moduleName, "*") == 0); + + for (u32 i = 0; i < io_module->numFunctions; ++i) + { + IM3Function f = & io_module->functions [i]; + + if (f->import.moduleUtf8 and f->import.fieldUtf8) + { + if (strcmp (f->import.fieldUtf8, i_functionName) == 0 and + (wildcardModule or strcmp (f->import.moduleUtf8, i_moduleName) == 0)) + { + result = LinkRawFunction (io_module, f, i_signature, i_function, i_userdata); + if (result) return result; + } + } + } + + return result; +} + +M3Result m3_LinkRawFunctionEx (IM3Module io_module, + const char * const i_moduleName, + const char * const i_functionName, + const char * const i_signature, + M3RawCall i_function, + const void * i_userdata) +{ + return FindAndLinkFunction (io_module, i_moduleName, i_functionName, i_signature, (voidptr_t)i_function, i_userdata); +} + +M3Result m3_LinkRawFunction (IM3Module io_module, + const char * const i_moduleName, + const char * const i_functionName, + const char * const i_signature, + M3RawCall i_function) +{ + return FindAndLinkFunction (io_module, i_moduleName, i_functionName, i_signature, (voidptr_t)i_function, NULL); +} + diff --git a/wasm3-sys/wasm3/source/m3_bind.h b/wasm3-sys/wasm3/source/m3_bind.h new file mode 100644 index 0000000..a80317a --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_bind.h @@ -0,0 +1,20 @@ +// +// m3_bind.h +// +// Created by Steven Massey on 2/27/20. +// Copyright © 2020 Steven Massey. All rights reserved. +// + +#ifndef m3_bind_h +#define m3_bind_h + +#include "m3_env.h" + +d_m3BeginExternC + +u8 ConvertTypeCharToTypeId (char i_code); +M3Result SignatureToFuncType (IM3FuncType * o_functionType, ccstr_t i_signature); + +d_m3EndExternC + +#endif /* m3_bind_h */ diff --git a/wasm3-sys/wasm3/source/m3_code.c b/wasm3-sys/wasm3/source/m3_code.c new file mode 100644 index 0000000..8d52ac2 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_code.c @@ -0,0 +1,233 @@ +// +// m3_code.c +// +// Created by Steven Massey on 4/19/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_code.h" + + +//--------------------------------------------------------------------------------------------------------------------------------- + + +IM3CodePage NewCodePage (u32 i_minNumLines) +{ + static u32 s_sequence = 0; + + IM3CodePage page; + + u32 pageSize = sizeof (M3CodePageHeader) + sizeof (code_t) * i_minNumLines; + + pageSize = (pageSize + (d_m3CodePageAlignSize-1)) & ~(d_m3CodePageAlignSize-1); // align + page = (IM3CodePage)m3_Malloc (pageSize); + + if (page) + { + page->info.sequence = ++s_sequence; + page->info.numLines = (pageSize - sizeof (M3CodePageHeader)) / sizeof (code_t); + +#if d_m3RecordBacktraces + u32 pageSizeBt = sizeof (M3CodeMappingPage) + sizeof (M3CodeMapEntry) * page->info.numLines; + page->info.mapping = (M3CodeMappingPage *)m3_Malloc (pageSizeBt); + + if (page->info.mapping) + { + page->info.mapping->size = 0; + page->info.mapping->capacity = page->info.numLines; + } + else + { + m3_Free (page); + return NULL; + } + page->info.mapping->basePC = GetPageStartPC(page); +#endif // d_m3RecordBacktraces + + m3log (runtime, "new page: %p; seq: %d; bytes: %d; lines: %d", GetPagePC (page), page->info.sequence, pageSize, page->info.numLines); + } + + return page; +} + + +void FreeCodePages (IM3CodePage * io_list) +{ + IM3CodePage page = * io_list; + + while (page) + { + m3log (code, "free page: %d; %p; util: %3.1f%%", page->info.sequence, page, 100. * page->info.lineIndex / page->info.numLines); + + IM3CodePage next = page->info.next; +#if d_m3RecordBacktraces + m3_Free (page->info.mapping); +#endif // d_m3RecordBacktraces + m3_Free (page); + page = next; + } + + * io_list = NULL; +} + + +u32 NumFreeLines (IM3CodePage i_page) +{ + d_m3Assert (i_page->info.lineIndex <= i_page->info.numLines); + + return i_page->info.numLines - i_page->info.lineIndex; +} + + +void EmitWord_impl (IM3CodePage i_page, void * i_word) +{ d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); + i_page->code [i_page->info.lineIndex++] = i_word; +} + +void EmitWord32 (IM3CodePage i_page, const u32 i_word) +{ d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); + * ((u32 *) & i_page->code [i_page->info.lineIndex++]) = i_word; +} + +void EmitWord64 (IM3CodePage i_page, const u64 i_word) +{ +#if M3_SIZEOF_PTR == 4 + d_m3Assert (i_page->info.lineIndex+2 <= i_page->info.numLines); + * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word; + i_page->info.lineIndex += 2; +#else + d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); + * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word; + i_page->info.lineIndex += 1; +#endif +} + + +#if d_m3RecordBacktraces +void EmitMappingEntry (IM3CodePage i_page, u32 i_moduleOffset) +{ + M3CodeMappingPage * page = i_page->info.mapping; + d_m3Assert (page->size < page->capacity); + + M3CodeMapEntry * entry = & page->entries[page->size++]; + pc_t pc = GetPagePC (i_page); + + entry->pcOffset = pc - page->basePC; + entry->moduleOffset = i_moduleOffset; +} +#endif // d_m3RecordBacktraces + +pc_t GetPageStartPC (IM3CodePage i_page) +{ + return & i_page->code [0]; +} + + +pc_t GetPagePC (IM3CodePage i_page) +{ + if (i_page) + return & i_page->code [i_page->info.lineIndex]; + else + return NULL; +} + + +void PushCodePage (IM3CodePage * i_list, IM3CodePage i_codePage) +{ + IM3CodePage next = * i_list; + i_codePage->info.next = next; + * i_list = i_codePage; +} + + +IM3CodePage PopCodePage (IM3CodePage * i_list) +{ + IM3CodePage page = * i_list; + * i_list = page->info.next; + page->info.next = NULL; + + return page; +} + + + +u32 FindCodePageEnd (IM3CodePage i_list, IM3CodePage * o_end) +{ + u32 numPages = 0; + * o_end = NULL; + + while (i_list) + { + * o_end = i_list; + ++numPages; + i_list = i_list->info.next; + } + + return numPages; +} + + +u32 CountCodePages (IM3CodePage i_list) +{ + IM3CodePage unused; + return FindCodePageEnd (i_list, & unused); +} + + +IM3CodePage GetEndCodePage (IM3CodePage i_list) +{ + IM3CodePage end; + FindCodePageEnd (i_list, & end); + + return end; +} + +#if d_m3RecordBacktraces +bool ContainsPC (IM3CodePage i_page, pc_t i_pc) +{ + return GetPageStartPC (i_page) <= i_pc && i_pc < GetPagePC (i_page); +} + + +bool MapPCToOffset (IM3CodePage i_page, pc_t i_pc, u32 * o_moduleOffset) +{ + M3CodeMappingPage * mapping = i_page->info.mapping; + + u32 pcOffset = i_pc - mapping->basePC; + + u32 left = 0; + u32 right = mapping->size; + + while (left < right) + { + u32 mid = left + (right - left) / 2; + + if (mapping->entries[mid].pcOffset < pcOffset) + { + left = mid + 1; + } + else if (mapping->entries[mid].pcOffset > pcOffset) + { + right = mid; + } + else + { + *o_moduleOffset = mapping->entries[mid].moduleOffset; + return true; + } + } + + // Getting here means left is now one more than the element we want. + if (left > 0) + { + left--; + *o_moduleOffset = mapping->entries[left].moduleOffset; + return true; + } + else return false; +} +#endif // d_m3RecordBacktraces + +//--------------------------------------------------------------------------------------------------------------------------------- + + diff --git a/wasm3-sys/wasm3/source/m3_code.h b/wasm3-sys/wasm3/source/m3_code.h new file mode 100644 index 0000000..44bd87e --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_code.h @@ -0,0 +1,80 @@ +// +// m3_code.h +// +// Created by Steven Massey on 4/19/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_code_h +#define m3_code_h + +#include "m3_core.h" + +d_m3BeginExternC + +typedef struct M3CodePage +{ + M3CodePageHeader info; + code_t code [1]; +} +M3CodePage; + +typedef M3CodePage * IM3CodePage; + + +IM3CodePage NewCodePage (u32 i_minNumLines); + +void FreeCodePages (IM3CodePage * io_list); + +u32 NumFreeLines (IM3CodePage i_page); +pc_t GetPageStartPC (IM3CodePage i_page); +pc_t GetPagePC (IM3CodePage i_page); +void EmitWord_impl (IM3CodePage i_page, void* i_word); +void EmitWord32 (IM3CodePage i_page, u32 i_word); +void EmitWord64 (IM3CodePage i_page, u64 i_word); +# if d_m3RecordBacktraces +void EmitMappingEntry (IM3CodePage i_page, u32 i_moduleOffset); +# endif // d_m3RecordBacktraces + +void PushCodePage (IM3CodePage * io_list, IM3CodePage i_codePage); +IM3CodePage PopCodePage (IM3CodePage * io_list); + +IM3CodePage GetEndCodePage (IM3CodePage i_list); // i_list = NULL is valid +u32 CountCodePages (IM3CodePage i_list); // i_list = NULL is valid + +# if d_m3RecordBacktraces +bool ContainsPC (IM3CodePage i_page, pc_t i_pc); +bool MapPCToOffset (IM3CodePage i_page, pc_t i_pc, u32 * o_moduleOffset); +# endif // d_m3RecordBacktraces + +# ifdef DEBUG +void dump_code_page (IM3CodePage i_codePage, pc_t i_startPC); +# endif + +#define EmitWord(page, val) EmitWord_impl(page, (void*)(val)) + +//--------------------------------------------------------------------------------------------------------------------------------- + +# if d_m3RecordBacktraces + +typedef struct M3CodeMapEntry +{ + u32 pcOffset; + u32 moduleOffset; +} +M3CodeMapEntry; + +typedef struct M3CodeMappingPage +{ + pc_t basePC; + u32 size; + u32 capacity; + M3CodeMapEntry entries []; +} +M3CodeMappingPage; + +# endif // d_m3RecordBacktraces + +d_m3EndExternC + +#endif // m3_code_h diff --git a/wasm3-sys/wasm3/source/m3_compile.c b/wasm3-sys/wasm3/source/m3_compile.c new file mode 100644 index 0000000..06446ef --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_compile.c @@ -0,0 +1,2813 @@ +// +// m3_compile.c +// +// Created by Steven Massey on 4/17/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_env.h" +#include "m3_compile.h" +#include "m3_emit.h" +#include "m3_exec.h" +#include "m3_exception.h" +#include "m3_info.h" + +//------------------------------------------------------------------------------------------------------------------------- + +#define d_indent " | %s" + +// just want less letters and numbers to stare at down the way in the compiler table +#define i_32 c_m3Type_i32 +#define i_64 c_m3Type_i64 +#define f_32 c_m3Type_f32 +#define f_64 c_m3Type_f64 +#define none c_m3Type_none +#define any (u8)-1 + +#if d_m3HasFloat +# define FPOP(x) x +#else +# define FPOP(x) NULL +#endif + +static const IM3Operation c_preserveSetSlot [] = { NULL, op_PreserveSetSlot_i32, op_PreserveSetSlot_i64, + FPOP(op_PreserveSetSlot_f32), FPOP(op_PreserveSetSlot_f64) }; +static const IM3Operation c_setSetOps [] = { NULL, op_SetSlot_i32, op_SetSlot_i64, + FPOP(op_SetSlot_f32), FPOP(op_SetSlot_f64) }; +static const IM3Operation c_setGlobalOps [] = { NULL, op_SetGlobal_i32, op_SetGlobal_i64, + FPOP(op_SetGlobal_f32), FPOP(op_SetGlobal_f64) }; +static const IM3Operation c_setRegisterOps [] = { NULL, op_SetRegister_i32, op_SetRegister_i64, + FPOP(op_SetRegister_f32), FPOP(op_SetRegister_f64) }; + +static const IM3Operation c_intSelectOps [2] [4] = { { op_Select_i32_rss, op_Select_i32_srs, op_Select_i32_ssr, op_Select_i32_sss }, + { op_Select_i64_rss, op_Select_i64_srs, op_Select_i64_ssr, op_Select_i64_sss } }; +#if d_m3HasFloat +static const IM3Operation c_fpSelectOps [2] [2] [3] = { { { op_Select_f32_sss, op_Select_f32_srs, op_Select_f32_ssr }, // selector in slot + { op_Select_f32_rss, op_Select_f32_rrs, op_Select_f32_rsr } }, // selector in reg + { { op_Select_f64_sss, op_Select_f64_srs, op_Select_f64_ssr }, // selector in slot + { op_Select_f64_rss, op_Select_f64_rrs, op_Select_f64_rsr } } }; // selector in reg +#endif + +static const u16 c_m3RegisterUnallocated = 0; +static const u16 c_slotUnused = 0xffff; + +// all args & returns are 64-bit aligned, so use 2 slots for a d_m3Use32BitSlots=1 build +static const u16 c_ioSlotCount = sizeof (u64) / sizeof (m3slot_t); + +M3Result AcquireCompilationCodePage (IM3Compilation o, IM3CodePage * o_codePage) +{ + M3Result result = m3Err_none; + + IM3CodePage page = AcquireCodePage (o->runtime); + + if (page) + { +# if (d_m3EnableCodePageRefCounting) + { + if (o->function) + { + IM3Function func = o->function; + page->info.usageCount++; + + u32 index = func->numCodePageRefs++; +_ (m3ReallocArray (& func->codePageRefs, IM3CodePage, func->numCodePageRefs, index)); + func->codePageRefs [index] = page; + } + } +# endif + } + else _throw (m3Err_mallocFailedCodePage); + + _catch: + + * o_codePage = page; + + return result; +} + +void ReleaseCompilationCodePage (IM3Compilation o) +{ + ReleaseCodePage (o->runtime, o->page); +} + +bool IsRegisterSlotAlias (u16 i_slot) { return (i_slot >= d_m3Reg0SlotAlias and i_slot != c_slotUnused); } +bool IsFpRegisterSlotAlias (u16 i_slot) { return (i_slot == d_m3Fp0SlotAlias); } +bool IsIntRegisterSlotAlias (u16 i_slot) { return (i_slot == d_m3Reg0SlotAlias); } + +u16 GetTypeNumSlots (u8 i_type) +{ +# if d_m3Use32BitSlots + return Is64BitType (i_type) ? 2 : 1; +# else + return 1; +# endif +} + + +void AlignSlotToType (u16 * io_slot, u8 i_type) +{ + // align 64-bit words to even slots (if d_m3Use32BitSlots) + u16 numSlots = GetTypeNumSlots (i_type); + + u16 mask = numSlots - 1; + * io_slot = (* io_slot + mask) & ~mask; +} + + +i16 GetStackTopIndex (IM3Compilation o) +{ d_m3Assert (o->stackIndex > o->stackFirstDynamicIndex or IsStackPolymorphic (o)); + return o->stackIndex - 1; +} + + +// Items in the static portion of the stack (args/locals) are hidden from GetStackTypeFromTop () +// In other words, only "real" Wasm stack items can be inspected. This is important when +// returning values, etc. and you need an accurate wasm-view of the stack. +u8 GetStackTypeFromTop (IM3Compilation o, u16 i_offset) +{ + u8 type = c_m3Type_none; + + ++i_offset; + if (o->stackIndex >= i_offset) + { + u16 index = o->stackIndex - i_offset; + + if (index >= o->stackFirstDynamicIndex) + type = o->typeStack [index]; + } + + return type; +} + + +u8 GetStackTopType (IM3Compilation o) +{ + return GetStackTypeFromTop (o, 0); +} + + +u8 GetStackTypeFromBottom (IM3Compilation o, u16 i_offset) +{ + u8 type = c_m3Type_none; + + if (i_offset < o->stackIndex) + type = o->typeStack [i_offset]; + + return type; +} + + +bool IsConstantSlot (IM3Compilation o, u16 i_slot) { return (i_slot >= o->slotFirstConstIndex and i_slot < o->slotMaxConstIndex); } +bool IsSlotAllocated (IM3Compilation o, u16 i_slot) { return o->m3Slots [i_slot]; } + + +bool IsStackIndexInRegister (IM3Compilation o, i32 i_stackIndex) +{ d_m3Assert (i_stackIndex < o->stackIndex or IsStackPolymorphic (o)); + if (i_stackIndex >= 0 and i_stackIndex < o->stackIndex) + return (o->wasmStack [i_stackIndex] >= d_m3Reg0SlotAlias); + else + return false; +} + +u16 GetNumBlockValuesOnStack (IM3Compilation o) { return o->stackIndex - o->block.blockStackIndex; } + +bool IsStackTopInRegister (IM3Compilation o) { return IsStackIndexInRegister (o, (i32) GetStackTopIndex (o)); } +bool IsStackTopMinus1InRegister (IM3Compilation o) { return IsStackIndexInRegister (o, (i32) GetStackTopIndex (o) - 1); } +bool IsStackTopMinus2InRegister (IM3Compilation o) { return IsStackIndexInRegister (o, (i32) GetStackTopIndex (o) - 2); } + +bool IsStackTopInSlot (IM3Compilation o) { return not IsStackTopInRegister (o); } + +bool IsValidSlot (u16 i_slot) { return (i_slot < d_m3MaxFunctionSlots); } + + +u16 GetStackTopSlotNumber (IM3Compilation o) +{ + i16 i = GetStackTopIndex (o); + + u16 slot = c_slotUnused; + + if (i >= 0) + slot = o->wasmStack [i]; + + return slot; +} + + +// from bottom +u16 GetSlotForStackIndex (IM3Compilation o, u16 i_stackIndex) +{ d_m3Assert (i_stackIndex < o->stackIndex or IsStackPolymorphic (o)); + u16 slot = c_slotUnused; + + if (i_stackIndex < o->stackIndex) + slot = o->wasmStack [i_stackIndex]; + + return slot; +} + + +u16 GetExtraSlotForStackIndex (IM3Compilation o, u16 i_stackIndex) +{ + u16 baseSlot = GetSlotForStackIndex (o, i_stackIndex); + + if (baseSlot != c_slotUnused) + { + u16 extraSlot = GetTypeNumSlots (GetStackTypeFromBottom (o, i_stackIndex)) - 1; + baseSlot += extraSlot; + } + + return baseSlot; +} + + + +void TouchSlot (IM3Compilation o, u16 i_slot) +{ + if (o->function) + { + // op_Entry uses this value to track and detect stack overflow + o->maxStackSlots = M3_MAX (o->maxStackSlots, i_slot + 1); + } +} + + +void MarkSlotAllocated (IM3Compilation o, u16 i_slot) +{ d_m3Assert (o->m3Slots [i_slot] == 0); // shouldn't be already allocated + o->m3Slots [i_slot] = 1; + + o->slotMaxAllocatedIndexPlusOne = M3_MAX (o->slotMaxAllocatedIndexPlusOne, i_slot + 1); + + TouchSlot (o, i_slot); +} + + +void MarkSlotsAllocated (IM3Compilation o, u16 i_slot, u16 i_numSlots) +{ + while (i_numSlots--) + MarkSlotAllocated (o, i_slot++); +} + +void MarkSlotsAllocatedByType (IM3Compilation o, u16 i_slot, u8 i_type) +{ + u16 numSlots = GetTypeNumSlots (i_type); + MarkSlotsAllocated (o, i_slot, numSlots); +} + + + +M3Result AllocateSlotsWithinRange (IM3Compilation o, u16 * o_slot, u8 i_type, u16 i_startSlot, u16 i_endSlot) +{ + M3Result result = m3Err_functionStackOverflow; + + u16 numSlots = GetTypeNumSlots (i_type); + u16 searchOffset = numSlots - 1; + + AlignSlotToType (& i_startSlot, i_type); + + // search for 1 or 2 consecutive slots in the execution stack + u16 i = i_startSlot; + while (i + searchOffset < i_endSlot) + { + if (o->m3Slots [i] == 0 and o->m3Slots [i + searchOffset] == 0) + { + MarkSlotsAllocated (o, i, numSlots); + + * o_slot = i; + result = m3Err_none; + break; + } + + // keep 2-slot allocations even-aligned + i += numSlots; + } + + return result; +} + + +M3Result AllocateSlots (IM3Compilation o, u16 * o_slot, u8 i_type) +{ + return AllocateSlotsWithinRange (o, o_slot, i_type, o->slotFirstDynamicIndex, d_m3MaxFunctionSlots); +} + + +M3Result AllocateConstantSlots (IM3Compilation o, u16 * o_slot, u8 i_type) +{ + u16 maxTableIndex = o->slotFirstConstIndex + d_m3MaxConstantTableSize; + return AllocateSlotsWithinRange (o, o_slot, i_type, o->slotFirstConstIndex, M3_MIN(o->slotFirstDynamicIndex, maxTableIndex)); +} + + +// TOQUE: this usage count system could be eliminated. real world code doesn't frequently trigger it. just copy to multiple +// unique slots. +M3Result IncrementSlotUsageCount (IM3Compilation o, u16 i_slot) +{ d_m3Assert (i_slot < d_m3MaxFunctionSlots); + M3Result result = m3Err_none; d_m3Assert (o->m3Slots [i_slot] > 0); + + // OPTZ (memory): 'm3Slots' could still be fused with 'typeStack' if 4 bits were used to indicate: [0,1,2,many]. The many-case + // would scan 'wasmStack' to determine the actual usage count + if (o->m3Slots [i_slot] < 0xFF) + { + o->m3Slots [i_slot]++; + } + else result = "slot usage count overflow"; + + return result; +} + + +void DeallocateSlot (IM3Compilation o, i16 i_slot, u8 i_type) +{ d_m3Assert (i_slot >= o->slotFirstDynamicIndex); + d_m3Assert (i_slot < o->slotMaxAllocatedIndexPlusOne); + for (u16 i = 0; i < GetTypeNumSlots (i_type); ++i, ++i_slot) + { d_m3Assert (o->m3Slots [i_slot]); + -- o->m3Slots [i_slot]; + } +} + + +bool IsRegisterAllocated (IM3Compilation o, u32 i_register) +{ + return (o->regStackIndexPlusOne [i_register] != c_m3RegisterUnallocated); +} + + +bool IsRegisterTypeAllocated (IM3Compilation o, u8 i_type) +{ + return IsRegisterAllocated (o, IsFpType (i_type)); +} + +void AllocateRegister (IM3Compilation o, u32 i_register, u16 i_stackIndex) +{ d_m3Assert (not IsRegisterAllocated (o, i_register)); + o->regStackIndexPlusOne [i_register] = i_stackIndex + 1; +} + + +void DeallocateRegister (IM3Compilation o, u32 i_register) +{ d_m3Assert (IsRegisterAllocated (o, i_register)); + o->regStackIndexPlusOne [i_register] = c_m3RegisterUnallocated; +} + + +u16 GetRegisterStackIndex (IM3Compilation o, u32 i_register) +{ d_m3Assert (IsRegisterAllocated (o, i_register)); + return o->regStackIndexPlusOne [i_register] - 1; +} + + +u16 GetMaxUsedSlotPlusOne (IM3Compilation o) +{ + while (o->slotMaxAllocatedIndexPlusOne > o->slotFirstDynamicIndex) + { + if (IsSlotAllocated (o, o->slotMaxAllocatedIndexPlusOne - 1)) + break; + + o->slotMaxAllocatedIndexPlusOne--; + } + +# ifdef DEBUG + u16 maxSlot = o->slotMaxAllocatedIndexPlusOne; + while (maxSlot < d_m3MaxFunctionSlots) + { + d_m3Assert (o->m3Slots [maxSlot] == 0); + maxSlot++; + } +# endif + + return o->slotMaxAllocatedIndexPlusOne; +} + + +M3Result PreserveRegisterIfOccupied (IM3Compilation o, u8 i_registerType) +{ + M3Result result = m3Err_none; + + u32 regSelect = IsFpType (i_registerType); + + if (IsRegisterAllocated (o, regSelect)) + { + u16 stackIndex = GetRegisterStackIndex (o, regSelect); + DeallocateRegister (o, regSelect); + + u8 type = GetStackTypeFromBottom (o, stackIndex); + + // and point to a exec slot + u16 slot = c_slotUnused; +_ (AllocateSlots (o, & slot, type)); + o->wasmStack [stackIndex] = slot; + +_ (EmitOp (o, c_setSetOps [type])); + EmitSlotOffset (o, slot); + } + + _catch: return result; +} + + +// all values must be in slots before entering loop, if, and else blocks +// otherwise they'd end up preserve-copied in the block to probably different locations (if/else) +M3Result PreserveRegisters (IM3Compilation o) +{ + M3Result result; + +_ (PreserveRegisterIfOccupied (o, c_m3Type_f64)); +_ (PreserveRegisterIfOccupied (o, c_m3Type_i64)); + + _catch: return result; +} + + +M3Result PreserveNonTopRegisters (IM3Compilation o) +{ + M3Result result = m3Err_none; + + i16 stackTop = GetStackTopIndex (o); + + if (stackTop >= 0) + { + if (IsRegisterAllocated (o, 0)) // r0 + { + if (GetRegisterStackIndex (o, 0) != stackTop) +_ (PreserveRegisterIfOccupied (o, c_m3Type_i64)); + } + + if (IsRegisterAllocated (o, 1)) // fp0 + { + if (GetRegisterStackIndex (o, 1) != stackTop) +_ (PreserveRegisterIfOccupied (o, c_m3Type_f64)); + } + } + + _catch: return result; +} + + +//---------------------------------------------------------------------------------------------------------------------- + + +M3Result Push (IM3Compilation o, u8 i_type, u16 i_slot) +{ + M3Result result = m3Err_none; + +#if !d_m3HasFloat + if (i_type == c_m3Type_f32 || i_type == c_m3Type_f64) { + return m3Err_unknownOpcode; + } +#endif + + u16 stackIndex = o->stackIndex++; // printf ("push: %d\n", (i32) i); + + if (stackIndex < d_m3MaxFunctionStackHeight) + { + o->wasmStack [stackIndex] = i_slot; + o->typeStack [stackIndex] = i_type; + + if (IsRegisterSlotAlias (i_slot)) + { + u32 regSelect = IsFpRegisterSlotAlias (i_slot); + AllocateRegister (o, regSelect, stackIndex); + } + + if (d_m3LogWasmStack) dump_type_stack (o); + } + else result = m3Err_functionStackOverflow; + + return result; +} + + +M3Result PushRegister (IM3Compilation o, u8 i_type) +{ + M3Result result = m3Err_none; d_m3Assert ((u16) d_m3Reg0SlotAlias > (u16) d_m3MaxFunctionSlots); + u16 slot = IsFpType (i_type) ? d_m3Fp0SlotAlias : d_m3Reg0SlotAlias; d_m3Assert (i_type or IsStackPolymorphic (o)); + +_ (Push (o, i_type, slot)); + + _catch: return result; +} + + +M3Result Pop (IM3Compilation o) +{ + M3Result result = m3Err_none; + + if (o->stackIndex > o->block.blockStackIndex) + { + o->stackIndex--; // printf ("pop: %d\n", (i32) o->stackIndex); + + u16 slot = o->wasmStack [o->stackIndex]; + u8 type = o->typeStack [o->stackIndex]; + + if (IsRegisterSlotAlias (slot)) + { + u32 regSelect = IsFpRegisterSlotAlias (slot); + DeallocateRegister (o, regSelect); + } + else if (slot >= o->slotFirstDynamicIndex) + { + DeallocateSlot (o, slot, type); + } + } + else if (not IsStackPolymorphic (o)) + result = m3Err_functionStackUnderrun; + + return result; +} + + +M3Result PopType (IM3Compilation o, u8 i_type) +{ + M3Result result = m3Err_none; + + u8 topType = GetStackTopType (o); + + if (i_type == topType or o->block.isPolymorphic) + { +_ (Pop (o)); + } + else _throw (m3Err_typeMismatch); + + _catch: + return result; +} + + +M3Result _PushAllocatedSlotAndEmit (IM3Compilation o, u8 i_type, bool i_doEmit) +{ + M3Result result = m3Err_none; + + u16 slot = c_slotUnused; + +_ (AllocateSlots (o, & slot, i_type)); +_ (Push (o, i_type, slot)); + + if (i_doEmit) + EmitSlotOffset (o, slot); + +// printf ("push: %d\n", (u32) slot); + + _catch: return result; +} + + +M3Result PushAllocatedSlotAndEmit (IM3Compilation o, u8 i_type) +{ + return _PushAllocatedSlotAndEmit (o, i_type, true); +} + + +M3Result PushAllocatedSlot (IM3Compilation o, u8 i_type) +{ + return _PushAllocatedSlotAndEmit (o, i_type, false); +} + + +M3Result PushConst (IM3Compilation o, u64 i_word, u8 i_type) +{ + M3Result result = m3Err_none; + + // Early-exit if we're not emitting + if (!o->page) return result; + + bool matchFound = false; + bool is64BitType = Is64BitType (i_type); + + u16 numRequiredSlots = GetTypeNumSlots (i_type); + u16 numUsedConstSlots = o->slotMaxConstIndex - o->slotFirstConstIndex; + + // search for duplicate matching constant slot to reuse + if (numRequiredSlots == 2 and numUsedConstSlots >= 2) + { + u16 firstConstSlot = o->slotFirstConstIndex; + AlignSlotToType (& firstConstSlot, c_m3Type_i64); + + for (u16 slot = firstConstSlot; slot < o->slotMaxConstIndex - 1; slot += 2) + { + if (IsSlotAllocated (o, slot) and IsSlotAllocated (o, slot + 1)) + { + u64 constant = * (u64 *) & o->constants [slot - o->slotFirstConstIndex]; + + if (constant == i_word) + { + matchFound = true; +_ (Push (o, i_type, slot)); + break; + } + } + } + } + else if (numRequiredSlots == 1) + { + for (u16 i = 0; i < numUsedConstSlots; ++i) + { + u16 slot = o->slotFirstConstIndex + i; + + if (IsSlotAllocated (o, slot)) + { + u64 constant; + if (is64BitType) { + constant = * (u64 *) & o->constants [i]; + } else { + constant = * (u32 *) & o->constants [i]; + } + if (constant == i_word) + { + matchFound = true; +_ (Push (o, i_type, slot)); + break; + } + } + } + } + + if (not matchFound) + { + u16 slot = c_slotUnused; + result = AllocateConstantSlots (o, & slot, i_type); + + if (result) // no more constant table space; use inline constants + { + result = m3Err_none; + + if (is64BitType) { +_ (EmitOp (o, op_Const64)); + EmitWord64 (o->page, i_word); + } else { +_ (EmitOp (o, op_Const32)); + EmitWord32 (o->page, (u32) i_word); + } + +_ (PushAllocatedSlotAndEmit (o, i_type)); + } + else + { + u16 constTableIndex = slot - o->slotFirstConstIndex; + + d_m3Assert(constTableIndex < d_m3MaxConstantTableSize); + + if (is64BitType) + { + u64 * constant = (u64 *) & o->constants [constTableIndex]; + * constant = i_word; + } + else + { + u32 * constant = (u32 *) & o->constants [constTableIndex]; + * constant = (u32) i_word; + } + +_ (Push (o, i_type, slot)); + + o->slotMaxConstIndex = M3_MAX (slot + numRequiredSlots, o->slotMaxConstIndex); + } + } + + _catch: return result; +} + + +M3Result EmitSlotNumOfStackTopAndPop (IM3Compilation o) +{ + // no emit if value is in register + if (IsStackTopInSlot (o)) + EmitSlotOffset (o, GetStackTopSlotNumber (o)); + + return Pop (o); +} + + +// Or, maybe: EmitTrappingOp +M3Result AddTrapRecord (IM3Compilation o) +{ + M3Result result = m3Err_none; + + if (o->function) + { + } + + return result; +} + +M3Result UnwindBlockStack (IM3Compilation o) +{ + M3Result result = m3Err_none; + + u32 popCount = 0; + while (o->stackIndex > o->block.blockStackIndex) + { +_ (Pop (o)); + ++popCount; + } + + if (popCount) + { + m3log (compile, "unwound stack top: %d", popCount); + } + + _catch: return result; +} + + +bool IsStackPolymorphic (IM3Compilation o) +{ + return o->block.isPolymorphic; +} + + +M3Result SetStackPolymorphic (IM3Compilation o) +{ + o->block.isPolymorphic = true; m3log (compile, "stack set polymorphic"); + return UnwindBlockStack (o); +} + + +void PatchBranches (IM3Compilation o) +{ + pc_t pc = GetPC (o); + + pc_t patches = o->block.patches; + o->block.patches = NULL; + + while (patches) + { m3log (compile, "patching location: %p to pc: %p", patches, pc); + pc_t next = * (pc_t *) patches; + * (pc_t *) patches = pc; + patches = next; + } +} + +//------------------------------------------------------------------------------------------------------------------------- + + +M3Result CopyStackIndexToSlot (IM3Compilation o, u16 i_destSlot, u16 i_stackIndex) // NoPushPop +{ + M3Result result = m3Err_none; + + IM3Operation op; + + u8 type = GetStackTypeFromBottom (o, i_stackIndex); + bool inRegister = IsStackIndexInRegister (o, i_stackIndex); + + if (inRegister) + { + op = c_setSetOps [type]; + } + else op = Is64BitType (type) ? op_CopySlot_64 : op_CopySlot_32; + +_ (EmitOp (o, op)); + EmitSlotOffset (o, i_destSlot); + + if (not inRegister) + { + u16 srcSlot = GetSlotForStackIndex (o, i_stackIndex); + EmitSlotOffset (o, srcSlot); + } + + _catch: return result; +} + + +M3Result CopyStackTopToSlot (IM3Compilation o, u16 i_destSlot) // NoPushPop +{ + M3Result result; + + i16 stackTop = GetStackTopIndex (o); +_ (CopyStackIndexToSlot (o, i_destSlot, (u16) stackTop)); + + _catch: return result; +} + + +// a copy-on-write strategy is used with locals. when a get local occurs, it's not copied anywhere. the stack +// entry just has a index pointer to that local memory slot. +// then, when a previously referenced local is set, the current value needs to be preserved for those references + +// TODO: consider getting rid of these specialized operations: PreserveSetSlot & PreserveCopySlot. +// They likely just take up space (which seems to reduce performance) without improving performance. +M3Result PreservedCopyTopSlot (IM3Compilation o, u16 i_destSlot, u16 i_preserveSlot) +{ + M3Result result = m3Err_none; d_m3Assert (i_destSlot != i_preserveSlot); + + IM3Operation op; + + u8 type = GetStackTopType (o); + + if (IsStackTopInRegister (o)) + { + op = c_preserveSetSlot [type]; + } + else op = Is64BitType (type) ? op_PreserveCopySlot_64 : op_PreserveCopySlot_32; + +_ (EmitOp (o, op)); + EmitSlotOffset (o, i_destSlot); + + if (IsStackTopInSlot (o)) + EmitSlotOffset (o, GetStackTopSlotNumber (o)); + + EmitSlotOffset (o, i_preserveSlot); + + _catch: return result; +} + + +M3Result CopyStackTopToRegister (IM3Compilation o, bool i_updateStack) +{ + M3Result result = m3Err_none; + + if (IsStackTopInSlot (o)) + { + u8 type = GetStackTopType (o); + +_ (PreserveRegisterIfOccupied (o, type)); + + IM3Operation op = c_setRegisterOps [type]; + +_ (EmitOp (o, op)); + EmitSlotOffset (o, GetStackTopSlotNumber (o)); + + if (i_updateStack) + { +_ (PopType (o, type)); +_ (PushRegister (o, type)); + } + } + + _catch: return result; +} + + +// if local is unreferenced, o_preservedSlotNumber will be equal to localIndex on return +M3Result FindReferencedLocalWithinCurrentBlock (IM3Compilation o, u16 * o_preservedSlotNumber, u32 i_localSlot) +{ + M3Result result = m3Err_none; + + IM3CompilationScope scope = & o->block; + i16 startIndex = scope->blockStackIndex; + + while (scope->opcode == c_waOp_block) + { + scope = scope->outer; + if (not scope) + break; + + startIndex = scope->blockStackIndex; + } + + * o_preservedSlotNumber = (u16) i_localSlot; + + for (u32 i = startIndex; i < o->stackIndex; ++i) + { + if (o->wasmStack [i] == i_localSlot) + { + if (* o_preservedSlotNumber == i_localSlot) + { + u8 type = GetStackTypeFromBottom (o, i); d_m3Assert (type != c_m3Type_none) + +_ (AllocateSlots (o, o_preservedSlotNumber, type)); + } + else +_ (IncrementSlotUsageCount (o, * o_preservedSlotNumber)); + + o->wasmStack [i] = * o_preservedSlotNumber; + } + } + + _catch: return result; +} + + +M3Result GetBlockScope (IM3Compilation o, IM3CompilationScope * o_scope, i32 i_depth) +{ + M3Result result = m3Err_none; + + IM3CompilationScope scope = & o->block; + + while (i_depth--) + { + scope = scope->outer; + _throwif ("invalid block depth", not scope); + } + + * o_scope = scope; + + _catch: + return result; +} + + +M3Result CopyStackSlotsR (IM3Compilation o, u16 i_targetSlotStackIndex, u16 i_stackIndex, u16 i_endStackIndex, u16 i_tempSlot) +{ + M3Result result = m3Err_none; + + if (i_stackIndex < i_endStackIndex) + { + u16 srcSlot = GetSlotForStackIndex (o, i_stackIndex); + + u8 type = GetStackTypeFromBottom (o, i_stackIndex); + u16 numSlots = GetTypeNumSlots (type); + u16 extraSlot = numSlots - 1; + + u16 targetSlot = GetSlotForStackIndex (o, i_targetSlotStackIndex); + + u16 preserveIndex = i_stackIndex; + u16 collisionSlot = srcSlot; + + if (targetSlot != srcSlot) + { + // search for collisions + u16 checkIndex = i_stackIndex + 1; + while (checkIndex < i_endStackIndex) + { + u16 otherSlot1 = GetSlotForStackIndex (o, checkIndex); + u16 otherSlot2 = GetExtraSlotForStackIndex (o, checkIndex); + + if (targetSlot == otherSlot1 or + targetSlot == otherSlot2 or + targetSlot + extraSlot == otherSlot1) + { + _throwif (m3Err_functionStackOverflow, i_tempSlot >= d_m3MaxFunctionSlots); + +_ (CopyStackIndexToSlot (o, i_tempSlot, checkIndex)); + o->wasmStack [checkIndex] = i_tempSlot; + i_tempSlot += GetTypeNumSlots (c_m3Type_i64); + TouchSlot (o, i_tempSlot - 1); + + // restore this on the way back down + preserveIndex = checkIndex; + collisionSlot = otherSlot1; + + break; + } + + ++checkIndex; + } + +_ (CopyStackIndexToSlot (o, targetSlot, i_stackIndex)); m3log (compile, " copying slot: %d to slot: %d", srcSlot, targetSlot); + o->wasmStack [i_stackIndex] = targetSlot; + + } + +_ (CopyStackSlotsR (o, i_targetSlotStackIndex + 1, i_stackIndex + 1, i_endStackIndex, i_tempSlot)); + + // restore the stack state + o->wasmStack [i_stackIndex] = srcSlot; + o->wasmStack [preserveIndex] = collisionSlot; + } + + _catch: + return result; +} + + +M3Result ResolveBlockResults (IM3Compilation o, IM3CompilationScope i_targetBlock, bool i_isBranch) +{ + M3Result result = m3Err_none; if (d_m3LogWasmStack) dump_type_stack (o); + + bool isLoop = (i_targetBlock->opcode == c_waOp_loop and i_isBranch); + + u16 numParams = GetFuncTypeNumParams (i_targetBlock->type); + u16 numResults = GetFuncTypeNumResults (i_targetBlock->type); + + u16 slotRecords = i_targetBlock->exitStackIndex; + + u16 numValues; + + if (not isLoop) + { + numValues = numResults; + slotRecords += numParams; + } + else numValues = numParams; + + u16 blockHeight = GetNumBlockValuesOnStack (o); + + _throwif (m3Err_typeCountMismatch, i_isBranch ? (blockHeight < numValues) : (blockHeight != numValues)); + + if (numValues) + { + u16 endIndex = GetStackTopIndex (o) + 1; + + if (not isLoop and IsFpType (GetStackTopType (o))) + { +_ (CopyStackTopToRegister (o, false)); + --endIndex; + } + + // TODO: tempslot affects maxStackSlots, so can grow unnecess each time. + u16 tempSlot = o->maxStackSlots;// GetMaxUsedSlotPlusOne (o); doesn't work cause can collide with slotRecords + AlignSlotToType (& tempSlot, c_m3Type_i64); + +_ (CopyStackSlotsR (o, slotRecords, endIndex - numValues, endIndex, tempSlot)); + + if (d_m3LogWasmStack) dump_type_stack (o); + } + + _catch: return result; +} + + + +M3Result ReturnValues (IM3Compilation o, IM3CompilationScope i_functionBlock, bool i_isBranch) +{ + M3Result result = m3Err_none; if (d_m3LogWasmStack) dump_type_stack (o); + + u16 numReturns = GetFuncTypeNumResults (i_functionBlock->type); // could just o->function too... + u16 blockHeight = GetNumBlockValuesOnStack (o); + + if (not IsStackPolymorphic (o)) + _throwif (m3Err_typeCountMismatch, i_isBranch ? (blockHeight < numReturns) : (blockHeight != numReturns)); + + if (numReturns) + { + // return slots like args are 64-bit aligned + u16 returnSlot = numReturns * c_ioSlotCount; + u16 stackTop = GetStackTopIndex (o); + + for (u16 i = 0; i < numReturns; ++i) + { + u8 returnType = GetFuncTypeResultType (i_functionBlock->type, numReturns - 1 - i); + + u8 stackType = GetStackTypeFromTop (o, i); // using FromTop so that only dynamic items are checked + + if (IsStackPolymorphic (o) and stackType == c_m3Type_none) + stackType = returnType; + + _throwif (m3Err_typeMismatch, returnType != stackType); + + if (not IsStackPolymorphic (o)) + { + returnSlot -= c_ioSlotCount; +_ (CopyStackIndexToSlot (o, returnSlot, stackTop--)); + } + } + + if (not i_isBranch) + { + while (numReturns--) +_ (Pop (o)); + } + } + + _catch: return result; +} + + +//------------------------------------------------------------------------------------------------------------------------- + + +M3Result Compile_Const_i32 (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + i32 value; +_ (ReadLEB_i32 (& value, & o->wasm, o->wasmEnd)); +_ (PushConst (o, value, c_m3Type_i32)); m3log (compile, d_indent " (const i32 = %" PRIi32 ")", get_indention_string (o), value); + _catch: return result; +} + + +M3Result Compile_Const_i64 (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + i64 value; +_ (ReadLEB_i64 (& value, & o->wasm, o->wasmEnd)); +_ (PushConst (o, value, c_m3Type_i64)); m3log (compile, d_indent " (const i64 = %" PRIi64 ")", get_indention_string (o), value); + _catch: return result; +} + + +#if d_m3ImplementFloat +M3Result Compile_Const_f32 (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + union { u32 u; f32 f; } value = { 0 }; + +_ (Read_f32 (& value.f, & o->wasm, o->wasmEnd)); m3log (compile, d_indent " (const f32 = %" PRIf32 ")", get_indention_string (o), value.f); +_ (PushConst (o, value.u, c_m3Type_f32)); + + _catch: return result; +} + + +M3Result Compile_Const_f64 (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + union { u64 u; f64 f; } value = { 0 }; + +_ (Read_f64 (& value.f, & o->wasm, o->wasmEnd)); m3log (compile, d_indent " (const f64 = %" PRIf64 ")", get_indention_string (o), value.f); +_ (PushConst (o, value.u, c_m3Type_f64)); + + _catch: return result; +} +#endif + +#ifdef d_m3EnableExtendedOpcodes + +M3Result Compile_ExtendedOpcode (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; + +_try { + u8 opcode; +_ (Read_u8 (& opcode, & o->wasm, o->wasmEnd)); m3log (compile, d_indent " (FC: %" PRIi32 ")", get_indention_string (o), opcode); + + i_opcode = (i_opcode << 8) | opcode; + + //printf("Extended opcode: 0x%x\n", i_opcode); + + IM3OpInfo opInfo = GetOpInfo (i_opcode); + _throwif (m3Err_unknownOpcode, not opInfo); + + M3Compiler compiler = opInfo->compiler; + _throwif (m3Err_noCompiler, not compiler); + +_ ((* compiler) (o, i_opcode)); + + o->previousOpcode = i_opcode; + + } _catch: return result; +} +#endif + + +M3Result Compile_Return (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; + + if (not IsStackPolymorphic (o)) + { + IM3CompilationScope functionScope; +_ (GetBlockScope (o, & functionScope, o->block.depth)); + +_ (ReturnValues (o, functionScope, true)); + +_ (EmitOp (o, op_Return)); + +_ (SetStackPolymorphic (o)); + } + + _catch: return result; +} + + +M3Result ValidateBlockEnd (IM3Compilation o) +{ + M3Result result = m3Err_none; +/* + u16 numResults = GetFuncTypeNumResults (o->block.type); + u16 blockHeight = GetNumBlockValuesOnStack (o); + + if (IsStackPolymorphic (o)) + { + } + else + { + } + + _catch: */ return result; +} + + +M3Result Compile_End (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; //dump_type_stack (o); + + // function end: + if (o->block.depth == 0) + { + ValidateBlockEnd (o); + +// if (not IsStackPolymorphic (o)) + { + if (o->function) + { +_ (ReturnValues (o, & o->block, false)); + } + +_ (EmitOp (o, op_Return)); + } + } + + _catch: return result; +} + + + +M3Result Compile_SetLocal (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + u32 localIndex; +_ (ReadLEB_u32 (& localIndex, & o->wasm, o->wasmEnd)); // printf ("--- set local: %d \n", localSlot); + + if (localIndex < GetFunctionNumArgsAndLocals (o->function)) + { + u16 localSlot = GetSlotForStackIndex (o, localIndex); + + u16 preserveSlot; +_ (FindReferencedLocalWithinCurrentBlock (o, & preserveSlot, localSlot)); // preserve will be different than local, if referenced + + if (preserveSlot == localSlot) +_ (CopyStackTopToSlot (o, localSlot)) + else +_ (PreservedCopyTopSlot (o, localSlot, preserveSlot)) + + if (i_opcode != c_waOp_teeLocal) +_ (Pop (o)); + } + else _throw ("local index out of bounds"); + + _catch: return result; +} + + +M3Result Compile_GetLocal (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + +_try { + + u32 localIndex; +_ (ReadLEB_u32 (& localIndex, & o->wasm, o->wasmEnd)); + + if (localIndex >= GetFunctionNumArgsAndLocals (o->function)) + _throw ("local index out of bounds"); + + u8 type = GetStackTypeFromBottom (o, localIndex); + u16 slot = GetSlotForStackIndex (o, localIndex); + +_ (Push (o, type, slot)); + + } _catch: return result; +} + + +M3Result Compile_GetGlobal (IM3Compilation o, M3Global * i_global) +{ + M3Result result; + + IM3Operation op = Is64BitType (i_global->type) ? op_GetGlobal_s64 : op_GetGlobal_s32; +_ (EmitOp (o, op)); + EmitPointer (o, & i_global->intValue); +_ (PushAllocatedSlotAndEmit (o, i_global->type)); + + _catch: return result; +} + + +M3Result Compile_SetGlobal (IM3Compilation o, M3Global * i_global) +{ + M3Result result = m3Err_none; + + if (i_global->isMutable) + { + IM3Operation op; + u8 type = GetStackTopType (o); + + if (IsStackTopInRegister (o)) + { + op = c_setGlobalOps [type]; + } + else op = Is64BitType (type) ? op_SetGlobal_s64 : op_SetGlobal_s32; + +_ (EmitOp (o, op)); + EmitPointer (o, & i_global->intValue); + + if (IsStackTopInSlot (o)) + EmitSlotOffset (o, GetStackTopSlotNumber (o)); + +_ (Pop (o)); + } + else _throw (m3Err_settingImmutableGlobal); + + _catch: return result; +} + + +M3Result Compile_GetSetGlobal (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; + + u32 globalIndex; +_ (ReadLEB_u32 (& globalIndex, & o->wasm, o->wasmEnd)); + + if (globalIndex < o->module->numGlobals) + { + if (o->module->globals) + { + M3Global * global = & o->module->globals [globalIndex]; + +_ ((i_opcode == 0x23) ? Compile_GetGlobal (o, global) : Compile_SetGlobal (o, global)); + } + else _throw (ErrorCompile (m3Err_globalMemoryNotAllocated, o, "module '%s' is missing global memory", o->module->name)); + } + else _throw (m3Err_globaIndexOutOfBounds); + + _catch: return result; +} + + +void EmitPatchingBranchPointer (IM3Compilation o, IM3CompilationScope i_scope) +{ + pc_t patch = EmitPointer (o, i_scope->patches); m3log (compile, "branch patch required at: %p", patch); + i_scope->patches = patch; +} + + +M3Result EmitPatchingBranch (IM3Compilation o, IM3CompilationScope i_scope) +{ + M3Result result = m3Err_none; + +_ (EmitOp (o, op_Branch)); + EmitPatchingBranchPointer (o, i_scope); + + _catch: return result; +} + + +M3Result Compile_Branch (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + u32 depth; +_ (ReadLEB_u32 (& depth, & o->wasm, o->wasmEnd)); + + IM3CompilationScope scope; +_ (GetBlockScope (o, & scope, depth)); + + // branch target is a loop (continue) + if (scope->opcode == c_waOp_loop) + { + if (i_opcode == c_waOp_branchIf) + { + if (GetFuncTypeNumParams (scope->type)) + { + IM3Operation op = IsStackTopInRegister (o) ? op_BranchIfPrologue_r : op_BranchIfPrologue_s; + +_ (EmitOp (o, op)); +_ (EmitSlotNumOfStackTopAndPop (o)); + + pc_t * jumpTo = (pc_t *) ReservePointer (o); + +_ (ResolveBlockResults (o, scope, /* isBranch: */ true)); + +_ (EmitOp (o, op_ContinueLoop)); + EmitPointer (o, scope->pc); + + * jumpTo = GetPC (o); + } + else + { + // move the condition to a register +_ (CopyStackTopToRegister (o, false)); +_ (PopType (o, c_m3Type_i32)); + +_ (EmitOp (o, op_ContinueLoopIf)); + EmitPointer (o, scope->pc); + } + +// dump_type_stack(o); + } + else // is c_waOp_branch + { + _ (EmitOp (o, op_ContinueLoop)); + EmitPointer (o, scope->pc); + o->block.isPolymorphic = true; + } + } + else // forward branch + { + pc_t * jumpTo = NULL; + + bool isReturn = (scope->depth == 0); + bool targetHasResults = GetFuncTypeNumResults (scope->type); + + if (i_opcode == c_waOp_branchIf) + { + if (targetHasResults or isReturn) + { + IM3Operation op = IsStackTopInRegister (o) ? op_BranchIfPrologue_r : op_BranchIfPrologue_s; + + _ (EmitOp (o, op)); + _ (EmitSlotNumOfStackTopAndPop (o)); // condition + + // this is continuation point, if the branch isn't taken + jumpTo = (pc_t *) ReservePointer (o); + } + else + { + IM3Operation op = IsStackTopInRegister (o) ? op_BranchIf_r : op_BranchIf_s; + + _ (EmitOp (o, op)); + _ (EmitSlotNumOfStackTopAndPop (o)); // condition + + EmitPatchingBranchPointer (o, scope); + goto _catch; + } + } + + if (not IsStackPolymorphic (o)) + { + if (isReturn) + { +_ (ReturnValues (o, scope, true)); +_ (EmitOp (o, op_Return)); + } + else + { +_ (ResolveBlockResults (o, scope, true)); +_ (EmitPatchingBranch (o, scope)); + } + } + + if (jumpTo) + { + * jumpTo = GetPC (o); + } + + if (i_opcode == c_waOp_branch) +_ (SetStackPolymorphic (o)); + } + + _catch: return result; +} + + +M3Result Compile_BranchTable (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + +_try { + u32 targetCount; +_ (ReadLEB_u32 (& targetCount, & o->wasm, o->wasmEnd)); + +_ (PreserveRegisterIfOccupied (o, c_m3Type_i64)); // move branch operand to a slot + u16 slot = GetStackTopSlotNumber (o); +_ (Pop (o)); + + // OPTZ: according to spec: "forward branches that target a control instruction with a non-empty + // result type consume matching operands first and push them back on the operand stack after unwinding" + // So, this move-to-reg is only necessary if the target scopes have a type. + + u32 numCodeLines = targetCount + 4; // 3 => IM3Operation + slot + target_count + default_target +_ (EnsureCodePageNumLines (o, numCodeLines)); + +_ (EmitOp (o, op_BranchTable)); + EmitSlotOffset (o, slot); + EmitConstant32 (o, targetCount); + + IM3CodePage continueOpPage = NULL; + + ++targetCount; // include default + for (u32 i = 0; i < targetCount; ++i) + { + u32 target; +_ (ReadLEB_u32 (& target, & o->wasm, o->wasmEnd)); + + IM3CompilationScope scope; +_ (GetBlockScope (o, & scope, target)); + + // TODO: don't need codepage rigmarole for + // no-param forward-branch targets + +_ (AcquireCompilationCodePage (o, & continueOpPage)); + + pc_t startPC = GetPagePC (continueOpPage); + IM3CodePage savedPage = o->page; + o->page = continueOpPage; + + if (scope->opcode == c_waOp_loop) + { +_ (ResolveBlockResults (o, scope, true)); + +_ (EmitOp (o, op_ContinueLoop)); + EmitPointer (o, scope->pc); + } + else + { + // TODO: this could be fused with equivalent targets + if (not IsStackPolymorphic (o)) + { + if (scope->depth == 0) + { +_ (ReturnValues (o, scope, true)); +_ (EmitOp (o, op_Return)); + } + else + { +_ (ResolveBlockResults (o, scope, true)); + +_ (EmitPatchingBranch (o, scope)); + } + } + } + + ReleaseCompilationCodePage (o); // FIX: continueOpPage can get lost if thrown + o->page = savedPage; + + EmitPointer (o, startPC); + } + +_ (SetStackPolymorphic (o)); + + } + + _catch: return result; +} + + +M3Result CompileCallArgsAndReturn (IM3Compilation o, u16 * o_stackOffset, IM3FuncType i_type, bool i_isIndirect) +{ + M3Result result = m3Err_none; + +_try { + + u16 topSlot = GetMaxUsedSlotPlusOne (o); + + // force use of at least one stack slot; this is to help ensure + // the m3 stack overflows (and traps) before the native stack can overflow. + // e.g. see Wasm spec test 'runaway' in call.wast + topSlot = M3_MAX (1, topSlot); + + // stack frame is 64-bit aligned + AlignSlotToType (& topSlot, c_m3Type_i64); + + * o_stackOffset = topSlot; + + // wait to pop this here so that topSlot search is correct + if (i_isIndirect) +_ (Pop (o)); + + u16 numArgs = GetFuncTypeNumParams (i_type); + u16 numRets = GetFuncTypeNumResults (i_type); + + u16 argTop = topSlot + (numArgs + numRets) * c_ioSlotCount; + + while (numArgs--) + { +_ (CopyStackTopToSlot (o, argTop -= c_ioSlotCount)); +_ (Pop (o)); + } + + u16 i = 0; + while (numRets--) + { + u8 type = GetFuncTypeResultType (i_type, i++); + +_ (Push (o, type, topSlot)); + MarkSlotsAllocatedByType (o, topSlot, type); + + topSlot += c_ioSlotCount; + } + + } _catch: return result; +} + + +M3Result Compile_Call (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + +_try { + u32 functionIndex; +_ (ReadLEB_u32 (& functionIndex, & o->wasm, o->wasmEnd)); + + IM3Function function = Module_GetFunction (o->module, functionIndex); + + if (function) + { m3log (compile, d_indent " (func= [%d] '%s'; args= %d)", + get_indention_string (o), functionIndex, m3_GetFunctionName (function), function->funcType->numArgs); + if (function->module) + { + u16 slotTop; +_ (CompileCallArgsAndReturn (o, & slotTop, function->funcType, false)); + + IM3Operation op; + const void * operand; + + if (function->compiled) + { + op = op_Call; + operand = function->compiled; + } + else + { + op = op_Compile; + operand = function; + } + +_ (EmitOp (o, op)); + EmitPointer (o, operand); + EmitSlotOffset (o, slotTop); + } + else + { + _throw (ErrorCompile (m3Err_functionImportMissing, o, "'%s.%s'", GetFunctionImportModuleName (function), m3_GetFunctionName (function))); + } + } + else _throw (m3Err_functionLookupFailed); + + } _catch: return result; +} + + +M3Result Compile_CallIndirect (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + +_try { + u32 typeIndex; +_ (ReadLEB_u32 (& typeIndex, & o->wasm, o->wasmEnd)); + + i8 reserved; +_ (ReadLEB_i7 (& reserved, & o->wasm, o->wasmEnd)); + + _throwif ("function call type index out of range", typeIndex >= o->module->numFuncTypes); + + if (IsStackTopInRegister (o)) +_ (PreserveRegisterIfOccupied (o, c_m3Type_i32)); + + u16 tableIndexSlot = GetStackTopSlotNumber (o); + + u16 execTop; + IM3FuncType type = o->module->funcTypes [typeIndex]; +_ (CompileCallArgsAndReturn (o, & execTop, type, true)); + +_ (EmitOp (o, op_CallIndirect)); + EmitSlotOffset (o, tableIndexSlot); + EmitPointer (o, o->module); + EmitPointer (o, type); // TODO: unify all types in M3Environment + EmitSlotOffset (o, execTop); + +} _catch: + return result; +} + + +M3Result Compile_Memory_Size (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + i8 reserved; +_ (ReadLEB_i7 (& reserved, & o->wasm, o->wasmEnd)); + +_ (PreserveRegisterIfOccupied (o, c_m3Type_i32)); + +_ (EmitOp (o, op_MemSize)); + +_ (PushRegister (o, c_m3Type_i32)); + + _catch: return result; +} + + +M3Result Compile_Memory_Grow (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + i8 reserved; +_ (ReadLEB_i7 (& reserved, & o->wasm, o->wasmEnd)); + +_ (CopyStackTopToRegister (o, false)); +_ (PopType (o, c_m3Type_i32)); + +_ (EmitOp (o, op_MemGrow)); + +_ (PushRegister (o, c_m3Type_i32)); + + _catch: return result; +} + + +M3Result Compile_Memory_CopyFill (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; + + i8 reserved; +_ (ReadLEB_i7 (& reserved, & o->wasm, o->wasmEnd)); + + IM3Operation op; + if (i_opcode == c_waOp_memoryCopy) + { +_ (ReadLEB_i7 (& reserved, & o->wasm, o->wasmEnd)); + op = op_MemCopy; + } + else op = op_MemFill; + +_ (CopyStackTopToRegister (o, false)); + +_ (EmitOp (o, op)); +_ (PopType (o, c_m3Type_i32)); +_ (EmitSlotNumOfStackTopAndPop (o)); +_ (EmitSlotNumOfStackTopAndPop (o)); + + _catch: return result; +} + + +static +M3Result ReadBlockType (IM3Compilation o, IM3FuncType * o_blockType) +{ + M3Result result; + + i64 type; +_ (ReadLebSigned (& type, 33, & o->wasm, o->wasmEnd)); + + if (type < 0) + { + u8 valueType; +_ (NormalizeType (&valueType, type)); m3log (compile, d_indent " (type: %s)", get_indention_string (o), c_waTypes [valueType]); + *o_blockType = o->module->environment->retFuncTypes[valueType]; + } + else + { + _throwif("func type out of bounds", type >= o->module->numFuncTypes); + *o_blockType = o->module->funcTypes[type]; m3log (compile, d_indent " (type: %s)", get_indention_string (o), SPrintFuncTypeSignature (*o_blockType)); + } + _catch: return result; +} + + +M3Result PreserveArgsAndLocals (IM3Compilation o) +{ + M3Result result = m3Err_none; + + if (o->stackIndex > o->stackFirstDynamicIndex) + { + u32 numArgsAndLocals = GetFunctionNumArgsAndLocals (o->function); + + for (u32 i = 0; i < numArgsAndLocals; ++i) + { + u16 slot = GetSlotForStackIndex (o, i); + + u16 preservedSlotNumber; +_ (FindReferencedLocalWithinCurrentBlock (o, & preservedSlotNumber, slot)); + + if (preservedSlotNumber != slot) + { + u8 type = GetStackTypeFromBottom (o, i); d_m3Assert (type != c_m3Type_none) + IM3Operation op = Is64BitType (type) ? op_CopySlot_64 : op_CopySlot_32; + + EmitOp (o, op); + EmitSlotOffset (o, preservedSlotNumber); + EmitSlotOffset (o, slot); + } + } + } + + _catch: + return result; +} + + +M3Result Compile_LoopOrBlock (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + // TODO: these shouldn't be necessary for non-loop blocks? +_ (PreserveRegisters (o)); +_ (PreserveArgsAndLocals (o)); + + IM3FuncType blockType; +_ (ReadBlockType (o, & blockType)); + + if (i_opcode == c_waOp_loop) + { + u16 numParams = GetFuncTypeNumParams (blockType); + if (numParams) + { + // instantiate constants + u16 numValues = GetNumBlockValuesOnStack (o); // CompileBlock enforces this at comptime + d_m3Assert (numValues >= numParams); + if (numValues >= numParams) + { + u16 stackTop = GetStackTopIndex (o) + 1; + + for (u16 i = stackTop - numParams; i < stackTop; ++i) + { + u16 slot = GetSlotForStackIndex (o, i); + u8 type = GetStackTypeFromBottom (o, i); + + if (IsConstantSlot (o, slot)) + { + u16 newSlot; +_ (AllocateSlots (o, & newSlot, type)); +_ (CopyStackIndexToSlot (o, newSlot, i)); + o->wasmStack [i] = newSlot; + } + } + } + } + +_ (EmitOp (o, op_Loop)); + } + else + { + } + +_ (CompileBlock (o, blockType, i_opcode)); + + _catch: return result; +} + + +M3Result CompileElseBlock (IM3Compilation o, pc_t * o_startPC, IM3FuncType i_blockType) +{ + M3Result result; + +_try { + + IM3CodePage elsePage; +_ (AcquireCompilationCodePage (o, & elsePage)); + + * o_startPC = GetPagePC (elsePage); + + IM3CodePage savedPage = o->page; + o->page = elsePage; + +_ (CompileBlock (o, i_blockType, c_waOp_else)); + +_ (EmitOp (o, op_Branch)); + EmitPointer (o, GetPagePC (savedPage)); + + ReleaseCompilationCodePage (o); + + o->page = savedPage; + +} _catch: + return result; +} + + +M3Result Compile_If (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + /* [ op_If ] + [ ] ----> [ ..else.. ] + [ ..if.. ] [ ..block.. ] + [ ..block.. ] [ op_Branch ] + [ end ] <----- [ ] */ + +_try { + +_ (PreserveNonTopRegisters (o)); +_ (PreserveArgsAndLocals (o)); + + IM3Operation op = IsStackTopInRegister (o) ? op_If_r : op_If_s; + +_ (EmitOp (o, op)); +_ (EmitSlotNumOfStackTopAndPop (o)); + + pc_t * pc = (pc_t *) ReservePointer (o); + + IM3FuncType blockType; +_ (ReadBlockType (o, & blockType)); + +// dump_type_stack (o); + + u16 stackIndex = o->stackIndex; + +_ (CompileBlock (o, blockType, i_opcode)); + + if (o->previousOpcode == c_waOp_else) + { + o->stackIndex = stackIndex; +_ (CompileElseBlock (o, pc, blockType)); + } + else + { + // if block produces values and there isn't a defined else + // case, then we need to make one up so that the pass-through + // results end up in the right place + if (GetFuncTypeNumResults (blockType)) + { + // rewind to the if's end to create a fake else block + o->wasm--; + o->stackIndex = stackIndex; + +// dump_type_stack (o); + +_ (CompileElseBlock (o, pc, blockType)); + } + else * pc = GetPC (o); + } + + } _catch: return result; +} + + +M3Result Compile_Select (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; + + u16 slots [3] = { c_slotUnused, c_slotUnused, c_slotUnused }; + + u8 type = GetStackTypeFromTop (o, 1); // get type of selection + + IM3Operation op = NULL; + + if (IsFpType (type)) + { +# if d_m3HasFloat + // not consuming a fp reg, so preserve + if (not IsStackTopMinus1InRegister (o) and + not IsStackTopMinus2InRegister (o)) + { +_ (PreserveRegisterIfOccupied (o, type)); + } + + bool selectorInReg = IsStackTopInRegister (o); + slots [0] = GetStackTopSlotNumber (o); +_ (Pop (o)); + + u32 opIndex = 0; + + for (u32 i = 1; i <= 2; ++i) + { + if (IsStackTopInRegister (o)) + opIndex = i; + else + slots [i] = GetStackTopSlotNumber (o); + +_ (Pop (o)); + } + + op = c_fpSelectOps [type - c_m3Type_f32] [selectorInReg] [opIndex]; +# else + _throw (m3Err_unknownOpcode); +# endif + } + else if (IsIntType (type)) + { + // 'sss' operation doesn't consume a register, so might have to protected its contents + if (not IsStackTopInRegister (o) and + not IsStackTopMinus1InRegister (o) and + not IsStackTopMinus2InRegister (o)) + { +_ (PreserveRegisterIfOccupied (o, type)); + } + + u32 opIndex = 3; // op_Select_*_sss + + for (u32 i = 0; i < 3; ++i) + { + if (IsStackTopInRegister (o)) + opIndex = i; + else + slots [i] = GetStackTopSlotNumber (o); + +_ (Pop (o)); + } + + op = c_intSelectOps [type - c_m3Type_i32] [opIndex]; + } + else if (not IsStackPolymorphic (o)) + _throw (m3Err_functionStackUnderrun); + + EmitOp (o, op); + for (u32 i = 0; i < 3; i++) + { + if (IsValidSlot (slots [i])) + EmitSlotOffset (o, slots [i]); + } +_ (PushRegister (o, type)); + + _catch: return result; +} + + +M3Result Compile_Drop (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = Pop (o); if (d_m3LogWasmStack) dump_type_stack (o); + return result; +} + + +M3Result Compile_Nop (IM3Compilation o, m3opcode_t i_opcode) +{ + return m3Err_none; +} + + +M3Result Compile_Unreachable (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + +_ (AddTrapRecord (o)); + +_ (EmitOp (o, op_Unreachable)); +_ (SetStackPolymorphic (o)); + + _catch: + return result; +} + + +// OPTZ: currently all stack slot indices take up a full word, but +// dual stack source operands could be packed together +M3Result Compile_Operator (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + IM3OpInfo opInfo = GetOpInfo (i_opcode); + _throwif (m3Err_unknownOpcode, not opInfo); + + IM3Operation op; + + // This preserve is for for FP compare operations. + // either need additional slot destination operations or the + // easy fix, move _r0 out of the way. + // moving out the way might be the optimal solution most often? + // otherwise, the _r0 reg can get buried down in the stack + // and be idle & wasted for a moment. + if (IsFpType (GetStackTopType (o)) and IsIntType (opInfo->type)) + { +_ (PreserveRegisterIfOccupied (o, opInfo->type)); + } + + if (opInfo->stackOffset == 0) + { + if (IsStackTopInRegister (o)) + { + op = opInfo->operations [0]; // _s + } + else + { +_ (PreserveRegisterIfOccupied (o, opInfo->type)); + op = opInfo->operations [1]; // _r + } + } + else + { + if (IsStackTopInRegister (o)) + { + op = opInfo->operations [0]; // _rs + + if (IsStackTopMinus1InRegister (o)) + { d_m3Assert (i_opcode == 0x38 or i_opcode == 0x39); + op = opInfo->operations [3]; // _rr for fp.store + } + } + else if (IsStackTopMinus1InRegister (o)) + { + op = opInfo->operations [1]; // _sr + + if (not op) // must be commutative, then + op = opInfo->operations [0]; + } + else + { +_ (PreserveRegisterIfOccupied (o, opInfo->type)); // _ss + op = opInfo->operations [2]; + } + } + + if (op) + { +_ (EmitOp (o, op)); + +_ (EmitSlotNumOfStackTopAndPop (o)); + + if (opInfo->stackOffset < 0) +_ (EmitSlotNumOfStackTopAndPop (o)); + + if (opInfo->type != c_m3Type_none) +_ (PushRegister (o, opInfo->type)); + } + else + { +# ifdef DEBUG + result = ErrorCompile ("no operation found for opcode", o, "'%s'", opInfo->name); +# else + result = ErrorCompile ("no operation found for opcode", o, "%x", i_opcode); +# endif + _throw (result); + } + + _catch: return result; +} + + +M3Result Compile_Convert (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; + +_try { + IM3OpInfo opInfo = GetOpInfo (i_opcode); + _throwif (m3Err_unknownOpcode, not opInfo); + + bool destInSlot = IsRegisterTypeAllocated (o, opInfo->type); + bool sourceInSlot = IsStackTopInSlot (o); + + IM3Operation op = opInfo->operations [destInSlot * 2 + sourceInSlot]; + +_ (EmitOp (o, op)); +_ (EmitSlotNumOfStackTopAndPop (o)); + + if (destInSlot) +_ (PushAllocatedSlotAndEmit (o, opInfo->type)) + else +_ (PushRegister (o, opInfo->type)) + +} + _catch: return result; +} + + +M3Result Compile_Load_Store (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + +_try { + u32 alignHint, memoryOffset; + +_ (ReadLEB_u32 (& alignHint, & o->wasm, o->wasmEnd)); +_ (ReadLEB_u32 (& memoryOffset, & o->wasm, o->wasmEnd)); + m3log (compile, d_indent " (offset = %d)", get_indention_string (o), memoryOffset); + IM3OpInfo opInfo = GetOpInfo (i_opcode); + _throwif (m3Err_unknownOpcode, not opInfo); + + if (IsFpType (opInfo->type)) +_ (PreserveRegisterIfOccupied (o, c_m3Type_f64)); + +_ (Compile_Operator (o, i_opcode)); + + EmitConstant32 (o, memoryOffset); +} + _catch: return result; +} + + +// d_logOp, d_logOp2 macros aren't actually used by the compiler, just codepage decoding (d_m3LogCodePages = 1) +#define d_logOp(OP) { op_##OP, NULL, NULL, NULL } +#define d_logOp2(OP1,OP2) { op_##OP1, op_##OP2, NULL, NULL } + +#define d_emptyOpList { NULL, NULL, NULL, NULL } +#define d_unaryOpList(TYPE, NAME) { op_##TYPE##_##NAME##_r, op_##TYPE##_##NAME##_s, NULL, NULL } +#define d_binOpList(TYPE, NAME) { op_##TYPE##_##NAME##_rs, op_##TYPE##_##NAME##_sr, op_##TYPE##_##NAME##_ss, NULL } +#define d_storeFpOpList(TYPE, NAME) { op_##TYPE##_##NAME##_rs, op_##TYPE##_##NAME##_sr, op_##TYPE##_##NAME##_ss, op_##TYPE##_##NAME##_rr } +#define d_commutativeBinOpList(TYPE, NAME) { op_##TYPE##_##NAME##_rs, NULL, op_##TYPE##_##NAME##_ss, NULL } +#define d_convertOpList(OP) { op_##OP##_r_r, op_##OP##_r_s, op_##OP##_s_r, op_##OP##_s_s } + + +const M3OpInfo c_operations [] = +{ + M3OP( "unreachable", 0, none, d_logOp (Unreachable), Compile_Unreachable ), // 0x00 + M3OP( "nop", 0, none, d_emptyOpList, Compile_Nop ), // 0x01 . + M3OP( "block", 0, none, d_emptyOpList, Compile_LoopOrBlock ), // 0x02 + M3OP( "loop", 0, none, d_logOp (Loop), Compile_LoopOrBlock ), // 0x03 + M3OP( "if", -1, none, d_emptyOpList, Compile_If ), // 0x04 + M3OP( "else", 0, none, d_emptyOpList, Compile_Nop ), // 0x05 + + M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, // 0x06 - 0x0a + + M3OP( "end", 0, none, d_emptyOpList, Compile_End ), // 0x0b + M3OP( "br", 0, none, d_logOp (Branch), Compile_Branch ), // 0x0c + M3OP( "br_if", -1, none, d_logOp2 (BranchIf_r, BranchIf_s), Compile_Branch ), // 0x0d + M3OP( "br_table", -1, none, d_logOp (BranchTable), Compile_BranchTable ), // 0x0e + M3OP( "return", 0, any, d_logOp (Return), Compile_Return ), // 0x0f + M3OP( "call", 0, any, d_logOp (Call), Compile_Call ), // 0x10 + M3OP( "call_indirect", 0, any, d_logOp (CallIndirect), Compile_CallIndirect ), // 0x11 + M3OP( "return_call", 0, any, d_emptyOpList, Compile_Call ), // 0x12 TODO: Optimize + M3OP( "return_call_indirect",0, any, d_emptyOpList, Compile_CallIndirect ), // 0x13 + + M3OP_RESERVED, M3OP_RESERVED, // 0x14 - 0x15 + M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, // 0x16 - 0x19 + + M3OP( "drop", -1, none, d_emptyOpList, Compile_Drop ), // 0x1a + M3OP( "select", -2, any, d_emptyOpList, Compile_Select ), // 0x1b + + M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, // 0x1c - 0x1f + + M3OP( "local.get", 1, any, d_emptyOpList, Compile_GetLocal ), // 0x20 + M3OP( "local.set", 1, none, d_emptyOpList, Compile_SetLocal ), // 0x21 + M3OP( "local.tee", 0, any, d_emptyOpList, Compile_SetLocal ), // 0x22 + M3OP( "global.get", 1, none, d_emptyOpList, Compile_GetSetGlobal ), // 0x23 + M3OP( "global.set", 1, none, d_emptyOpList, Compile_GetSetGlobal ), // 0x24 + + M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, // 0x25 - 0x27 + + M3OP( "i32.load", 0, i_32, d_unaryOpList (i32, Load_i32), Compile_Load_Store ), // 0x28 + M3OP( "i64.load", 0, i_64, d_unaryOpList (i64, Load_i64), Compile_Load_Store ), // 0x29 + M3OP_F( "f32.load", 0, f_32, d_unaryOpList (f32, Load_f32), Compile_Load_Store ), // 0x2a + M3OP_F( "f64.load", 0, f_64, d_unaryOpList (f64, Load_f64), Compile_Load_Store ), // 0x2b + + M3OP( "i32.load8_s", 0, i_32, d_unaryOpList (i32, Load_i8), Compile_Load_Store ), // 0x2c + M3OP( "i32.load8_u", 0, i_32, d_unaryOpList (i32, Load_u8), Compile_Load_Store ), // 0x2d + M3OP( "i32.load16_s", 0, i_32, d_unaryOpList (i32, Load_i16), Compile_Load_Store ), // 0x2e + M3OP( "i32.load16_u", 0, i_32, d_unaryOpList (i32, Load_u16), Compile_Load_Store ), // 0x2f + + M3OP( "i64.load8_s", 0, i_64, d_unaryOpList (i64, Load_i8), Compile_Load_Store ), // 0x30 + M3OP( "i64.load8_u", 0, i_64, d_unaryOpList (i64, Load_u8), Compile_Load_Store ), // 0x31 + M3OP( "i64.load16_s", 0, i_64, d_unaryOpList (i64, Load_i16), Compile_Load_Store ), // 0x32 + M3OP( "i64.load16_u", 0, i_64, d_unaryOpList (i64, Load_u16), Compile_Load_Store ), // 0x33 + M3OP( "i64.load32_s", 0, i_64, d_unaryOpList (i64, Load_i32), Compile_Load_Store ), // 0x34 + M3OP( "i64.load32_u", 0, i_64, d_unaryOpList (i64, Load_u32), Compile_Load_Store ), // 0x35 + + M3OP( "i32.store", -2, none, d_binOpList (i32, Store_i32), Compile_Load_Store ), // 0x36 + M3OP( "i64.store", -2, none, d_binOpList (i64, Store_i64), Compile_Load_Store ), // 0x37 + M3OP_F( "f32.store", -2, none, d_storeFpOpList (f32, Store_f32), Compile_Load_Store ), // 0x38 + M3OP_F( "f64.store", -2, none, d_storeFpOpList (f64, Store_f64), Compile_Load_Store ), // 0x39 + + M3OP( "i32.store8", -2, none, d_binOpList (i32, Store_u8), Compile_Load_Store ), // 0x3a + M3OP( "i32.store16", -2, none, d_binOpList (i32, Store_i16), Compile_Load_Store ), // 0x3b + + M3OP( "i64.store8", -2, none, d_binOpList (i64, Store_u8), Compile_Load_Store ), // 0x3c + M3OP( "i64.store16", -2, none, d_binOpList (i64, Store_i16), Compile_Load_Store ), // 0x3d + M3OP( "i64.store32", -2, none, d_binOpList (i64, Store_i32), Compile_Load_Store ), // 0x3e + + M3OP( "memory.size", 1, i_32, d_logOp (MemSize), Compile_Memory_Size ), // 0x3f + M3OP( "memory.grow", 1, i_32, d_logOp (MemGrow), Compile_Memory_Grow ), // 0x40 + + M3OP( "i32.const", 1, i_32, d_logOp (Const32), Compile_Const_i32 ), // 0x41 + M3OP( "i64.const", 1, i_64, d_logOp (Const64), Compile_Const_i64 ), // 0x42 + M3OP_F( "f32.const", 1, f_32, d_emptyOpList, Compile_Const_f32 ), // 0x43 + M3OP_F( "f64.const", 1, f_64, d_emptyOpList, Compile_Const_f64 ), // 0x44 + + M3OP( "i32.eqz", 0, i_32, d_unaryOpList (i32, EqualToZero) , NULL ), // 0x45 + M3OP( "i32.eq", -1, i_32, d_commutativeBinOpList (i32, Equal) , NULL ), // 0x46 + M3OP( "i32.ne", -1, i_32, d_commutativeBinOpList (i32, NotEqual) , NULL ), // 0x47 + M3OP( "i32.lt_s", -1, i_32, d_binOpList (i32, LessThan) , NULL ), // 0x48 + M3OP( "i32.lt_u", -1, i_32, d_binOpList (u32, LessThan) , NULL ), // 0x49 + M3OP( "i32.gt_s", -1, i_32, d_binOpList (i32, GreaterThan) , NULL ), // 0x4a + M3OP( "i32.gt_u", -1, i_32, d_binOpList (u32, GreaterThan) , NULL ), // 0x4b + M3OP( "i32.le_s", -1, i_32, d_binOpList (i32, LessThanOrEqual) , NULL ), // 0x4c + M3OP( "i32.le_u", -1, i_32, d_binOpList (u32, LessThanOrEqual) , NULL ), // 0x4d + M3OP( "i32.ge_s", -1, i_32, d_binOpList (i32, GreaterThanOrEqual) , NULL ), // 0x4e + M3OP( "i32.ge_u", -1, i_32, d_binOpList (u32, GreaterThanOrEqual) , NULL ), // 0x4f + + M3OP( "i64.eqz", 0, i_32, d_unaryOpList (i64, EqualToZero) , NULL ), // 0x50 + M3OP( "i64.eq", -1, i_32, d_commutativeBinOpList (i64, Equal) , NULL ), // 0x51 + M3OP( "i64.ne", -1, i_32, d_commutativeBinOpList (i64, NotEqual) , NULL ), // 0x52 + M3OP( "i64.lt_s", -1, i_32, d_binOpList (i64, LessThan) , NULL ), // 0x53 + M3OP( "i64.lt_u", -1, i_32, d_binOpList (u64, LessThan) , NULL ), // 0x54 + M3OP( "i64.gt_s", -1, i_32, d_binOpList (i64, GreaterThan) , NULL ), // 0x55 + M3OP( "i64.gt_u", -1, i_32, d_binOpList (u64, GreaterThan) , NULL ), // 0x56 + M3OP( "i64.le_s", -1, i_32, d_binOpList (i64, LessThanOrEqual) , NULL ), // 0x57 + M3OP( "i64.le_u", -1, i_32, d_binOpList (u64, LessThanOrEqual) , NULL ), // 0x58 + M3OP( "i64.ge_s", -1, i_32, d_binOpList (i64, GreaterThanOrEqual) , NULL ), // 0x59 + M3OP( "i64.ge_u", -1, i_32, d_binOpList (u64, GreaterThanOrEqual) , NULL ), // 0x5a + + M3OP_F( "f32.eq", -1, i_32, d_commutativeBinOpList (f32, Equal) , NULL ), // 0x5b + M3OP_F( "f32.ne", -1, i_32, d_commutativeBinOpList (f32, NotEqual) , NULL ), // 0x5c + M3OP_F( "f32.lt", -1, i_32, d_binOpList (f32, LessThan) , NULL ), // 0x5d + M3OP_F( "f32.gt", -1, i_32, d_binOpList (f32, GreaterThan) , NULL ), // 0x5e + M3OP_F( "f32.le", -1, i_32, d_binOpList (f32, LessThanOrEqual) , NULL ), // 0x5f + M3OP_F( "f32.ge", -1, i_32, d_binOpList (f32, GreaterThanOrEqual) , NULL ), // 0x60 + + M3OP_F( "f64.eq", -1, i_32, d_commutativeBinOpList (f64, Equal) , NULL ), // 0x61 + M3OP_F( "f64.ne", -1, i_32, d_commutativeBinOpList (f64, NotEqual) , NULL ), // 0x62 + M3OP_F( "f64.lt", -1, i_32, d_binOpList (f64, LessThan) , NULL ), // 0x63 + M3OP_F( "f64.gt", -1, i_32, d_binOpList (f64, GreaterThan) , NULL ), // 0x64 + M3OP_F( "f64.le", -1, i_32, d_binOpList (f64, LessThanOrEqual) , NULL ), // 0x65 + M3OP_F( "f64.ge", -1, i_32, d_binOpList (f64, GreaterThanOrEqual) , NULL ), // 0x66 + + M3OP( "i32.clz", 0, i_32, d_unaryOpList (u32, Clz) , NULL ), // 0x67 + M3OP( "i32.ctz", 0, i_32, d_unaryOpList (u32, Ctz) , NULL ), // 0x68 + M3OP( "i32.popcnt", 0, i_32, d_unaryOpList (u32, Popcnt) , NULL ), // 0x69 + + M3OP( "i32.add", -1, i_32, d_commutativeBinOpList (i32, Add) , NULL ), // 0x6a + M3OP( "i32.sub", -1, i_32, d_binOpList (i32, Subtract) , NULL ), // 0x6b + M3OP( "i32.mul", -1, i_32, d_commutativeBinOpList (i32, Multiply) , NULL ), // 0x6c + M3OP( "i32.div_s", -1, i_32, d_binOpList (i32, Divide) , NULL ), // 0x6d + M3OP( "i32.div_u", -1, i_32, d_binOpList (u32, Divide) , NULL ), // 0x6e + M3OP( "i32.rem_s", -1, i_32, d_binOpList (i32, Remainder) , NULL ), // 0x6f + M3OP( "i32.rem_u", -1, i_32, d_binOpList (u32, Remainder) , NULL ), // 0x70 + M3OP( "i32.and", -1, i_32, d_commutativeBinOpList (u32, And) , NULL ), // 0x71 + M3OP( "i32.or", -1, i_32, d_commutativeBinOpList (u32, Or) , NULL ), // 0x72 + M3OP( "i32.xor", -1, i_32, d_commutativeBinOpList (u32, Xor) , NULL ), // 0x73 + M3OP( "i32.shl", -1, i_32, d_binOpList (u32, ShiftLeft) , NULL ), // 0x74 + M3OP( "i32.shr_s", -1, i_32, d_binOpList (i32, ShiftRight) , NULL ), // 0x75 + M3OP( "i32.shr_u", -1, i_32, d_binOpList (u32, ShiftRight) , NULL ), // 0x76 + M3OP( "i32.rotl", -1, i_32, d_binOpList (u32, Rotl) , NULL ), // 0x77 + M3OP( "i32.rotr", -1, i_32, d_binOpList (u32, Rotr) , NULL ), // 0x78 + + M3OP( "i64.clz", 0, i_64, d_unaryOpList (u64, Clz) , NULL ), // 0x79 + M3OP( "i64.ctz", 0, i_64, d_unaryOpList (u64, Ctz) , NULL ), // 0x7a + M3OP( "i64.popcnt", 0, i_64, d_unaryOpList (u64, Popcnt) , NULL ), // 0x7b + + M3OP( "i64.add", -1, i_64, d_commutativeBinOpList (i64, Add) , NULL ), // 0x7c + M3OP( "i64.sub", -1, i_64, d_binOpList (i64, Subtract) , NULL ), // 0x7d + M3OP( "i64.mul", -1, i_64, d_commutativeBinOpList (i64, Multiply) , NULL ), // 0x7e + M3OP( "i64.div_s", -1, i_64, d_binOpList (i64, Divide) , NULL ), // 0x7f + M3OP( "i64.div_u", -1, i_64, d_binOpList (u64, Divide) , NULL ), // 0x80 + M3OP( "i64.rem_s", -1, i_64, d_binOpList (i64, Remainder) , NULL ), // 0x81 + M3OP( "i64.rem_u", -1, i_64, d_binOpList (u64, Remainder) , NULL ), // 0x82 + M3OP( "i64.and", -1, i_64, d_commutativeBinOpList (u64, And) , NULL ), // 0x83 + M3OP( "i64.or", -1, i_64, d_commutativeBinOpList (u64, Or) , NULL ), // 0x84 + M3OP( "i64.xor", -1, i_64, d_commutativeBinOpList (u64, Xor) , NULL ), // 0x85 + M3OP( "i64.shl", -1, i_64, d_binOpList (u64, ShiftLeft) , NULL ), // 0x86 + M3OP( "i64.shr_s", -1, i_64, d_binOpList (i64, ShiftRight) , NULL ), // 0x87 + M3OP( "i64.shr_u", -1, i_64, d_binOpList (u64, ShiftRight) , NULL ), // 0x88 + M3OP( "i64.rotl", -1, i_64, d_binOpList (u64, Rotl) , NULL ), // 0x89 + M3OP( "i64.rotr", -1, i_64, d_binOpList (u64, Rotr) , NULL ), // 0x8a + + M3OP_F( "f32.abs", 0, f_32, d_unaryOpList(f32, Abs) , NULL ), // 0x8b + M3OP_F( "f32.neg", 0, f_32, d_unaryOpList(f32, Negate) , NULL ), // 0x8c + M3OP_F( "f32.ceil", 0, f_32, d_unaryOpList(f32, Ceil) , NULL ), // 0x8d + M3OP_F( "f32.floor", 0, f_32, d_unaryOpList(f32, Floor) , NULL ), // 0x8e + M3OP_F( "f32.trunc", 0, f_32, d_unaryOpList(f32, Trunc) , NULL ), // 0x8f + M3OP_F( "f32.nearest", 0, f_32, d_unaryOpList(f32, Nearest) , NULL ), // 0x90 + M3OP_F( "f32.sqrt", 0, f_32, d_unaryOpList(f32, Sqrt) , NULL ), // 0x91 + + M3OP_F( "f32.add", -1, f_32, d_commutativeBinOpList (f32, Add) , NULL ), // 0x92 + M3OP_F( "f32.sub", -1, f_32, d_binOpList (f32, Subtract) , NULL ), // 0x93 + M3OP_F( "f32.mul", -1, f_32, d_commutativeBinOpList (f32, Multiply) , NULL ), // 0x94 + M3OP_F( "f32.div", -1, f_32, d_binOpList (f32, Divide) , NULL ), // 0x95 + M3OP_F( "f32.min", -1, f_32, d_commutativeBinOpList (f32, Min) , NULL ), // 0x96 + M3OP_F( "f32.max", -1, f_32, d_commutativeBinOpList (f32, Max) , NULL ), // 0x97 + M3OP_F( "f32.copysign", -1, f_32, d_binOpList (f32, CopySign) , NULL ), // 0x98 + + M3OP_F( "f64.abs", 0, f_64, d_unaryOpList(f64, Abs) , NULL ), // 0x99 + M3OP_F( "f64.neg", 0, f_64, d_unaryOpList(f64, Negate) , NULL ), // 0x9a + M3OP_F( "f64.ceil", 0, f_64, d_unaryOpList(f64, Ceil) , NULL ), // 0x9b + M3OP_F( "f64.floor", 0, f_64, d_unaryOpList(f64, Floor) , NULL ), // 0x9c + M3OP_F( "f64.trunc", 0, f_64, d_unaryOpList(f64, Trunc) , NULL ), // 0x9d + M3OP_F( "f64.nearest", 0, f_64, d_unaryOpList(f64, Nearest) , NULL ), // 0x9e + M3OP_F( "f64.sqrt", 0, f_64, d_unaryOpList(f64, Sqrt) , NULL ), // 0x9f + + M3OP_F( "f64.add", -1, f_64, d_commutativeBinOpList (f64, Add) , NULL ), // 0xa0 + M3OP_F( "f64.sub", -1, f_64, d_binOpList (f64, Subtract) , NULL ), // 0xa1 + M3OP_F( "f64.mul", -1, f_64, d_commutativeBinOpList (f64, Multiply) , NULL ), // 0xa2 + M3OP_F( "f64.div", -1, f_64, d_binOpList (f64, Divide) , NULL ), // 0xa3 + M3OP_F( "f64.min", -1, f_64, d_commutativeBinOpList (f64, Min) , NULL ), // 0xa4 + M3OP_F( "f64.max", -1, f_64, d_commutativeBinOpList (f64, Max) , NULL ), // 0xa5 + M3OP_F( "f64.copysign", -1, f_64, d_binOpList (f64, CopySign) , NULL ), // 0xa6 + + M3OP( "i32.wrap/i64", 0, i_32, d_unaryOpList (i32, Wrap_i64), NULL ), // 0xa7 + M3OP_F( "i32.trunc_s/f32", 0, i_32, d_convertOpList (i32_Trunc_f32), Compile_Convert ), // 0xa8 + M3OP_F( "i32.trunc_u/f32", 0, i_32, d_convertOpList (u32_Trunc_f32), Compile_Convert ), // 0xa9 + M3OP_F( "i32.trunc_s/f64", 0, i_32, d_convertOpList (i32_Trunc_f64), Compile_Convert ), // 0xaa + M3OP_F( "i32.trunc_u/f64", 0, i_32, d_convertOpList (u32_Trunc_f64), Compile_Convert ), // 0xab + + M3OP( "i64.extend_s/i32", 0, i_64, d_unaryOpList (i64, Extend_i32), NULL ), // 0xac + M3OP( "i64.extend_u/i32", 0, i_64, d_unaryOpList (i64, Extend_u32), NULL ), // 0xad + + M3OP_F( "i64.trunc_s/f32", 0, i_64, d_convertOpList (i64_Trunc_f32), Compile_Convert ), // 0xae + M3OP_F( "i64.trunc_u/f32", 0, i_64, d_convertOpList (u64_Trunc_f32), Compile_Convert ), // 0xaf + M3OP_F( "i64.trunc_s/f64", 0, i_64, d_convertOpList (i64_Trunc_f64), Compile_Convert ), // 0xb0 + M3OP_F( "i64.trunc_u/f64", 0, i_64, d_convertOpList (u64_Trunc_f64), Compile_Convert ), // 0xb1 + + M3OP_F( "f32.convert_s/i32",0, f_32, d_convertOpList (f32_Convert_i32), Compile_Convert ), // 0xb2 + M3OP_F( "f32.convert_u/i32",0, f_32, d_convertOpList (f32_Convert_u32), Compile_Convert ), // 0xb3 + M3OP_F( "f32.convert_s/i64",0, f_32, d_convertOpList (f32_Convert_i64), Compile_Convert ), // 0xb4 + M3OP_F( "f32.convert_u/i64",0, f_32, d_convertOpList (f32_Convert_u64), Compile_Convert ), // 0xb5 + + M3OP_F( "f32.demote/f64", 0, f_32, d_unaryOpList (f32, Demote_f64), NULL ), // 0xb6 + + M3OP_F( "f64.convert_s/i32",0, f_64, d_convertOpList (f64_Convert_i32), Compile_Convert ), // 0xb7 + M3OP_F( "f64.convert_u/i32",0, f_64, d_convertOpList (f64_Convert_u32), Compile_Convert ), // 0xb8 + M3OP_F( "f64.convert_s/i64",0, f_64, d_convertOpList (f64_Convert_i64), Compile_Convert ), // 0xb9 + M3OP_F( "f64.convert_u/i64",0, f_64, d_convertOpList (f64_Convert_u64), Compile_Convert ), // 0xba + + M3OP_F( "f64.promote/f32", 0, f_64, d_unaryOpList (f64, Promote_f32), NULL ), // 0xbb + + M3OP_F( "i32.reinterpret/f32",0,i_32, d_convertOpList (i32_Reinterpret_f32), Compile_Convert ), // 0xbc + M3OP_F( "i64.reinterpret/f64",0,i_64, d_convertOpList (i64_Reinterpret_f64), Compile_Convert ), // 0xbd + M3OP_F( "f32.reinterpret/i32",0,f_32, d_convertOpList (f32_Reinterpret_i32), Compile_Convert ), // 0xbe + M3OP_F( "f64.reinterpret/i64",0,f_64, d_convertOpList (f64_Reinterpret_i64), Compile_Convert ), // 0xbf + + M3OP( "i32.extend8_s", 0, i_32, d_unaryOpList (i32, Extend8_s), NULL ), // 0xc0 + M3OP( "i32.extend16_s", 0, i_32, d_unaryOpList (i32, Extend16_s), NULL ), // 0xc1 + M3OP( "i64.extend8_s", 0, i_64, d_unaryOpList (i64, Extend8_s), NULL ), // 0xc2 + M3OP( "i64.extend16_s", 0, i_64, d_unaryOpList (i64, Extend16_s), NULL ), // 0xc3 + M3OP( "i64.extend32_s", 0, i_64, d_unaryOpList (i64, Extend32_s), NULL ), // 0xc4 + +# ifdef DEBUG // for codepage logging. the order doesn't matter: +# define d_m3DebugOp(OP) M3OP (#OP, 0, none, { op_##OP }) + +# if d_m3HasFloat +# define d_m3DebugTypedOp(OP) M3OP (#OP, 0, none, { op_##OP##_i32, op_##OP##_i64, op_##OP##_f32, op_##OP##_f64, }) +# else +# define d_m3DebugTypedOp(OP) M3OP (#OP, 0, none, { op_##OP##_i32, op_##OP##_i64 }) +# endif + + d_m3DebugOp (Compile), d_m3DebugOp (Entry), d_m3DebugOp (End), + d_m3DebugOp (Unsupported), d_m3DebugOp (CallRawFunction), + + d_m3DebugOp (GetGlobal_s32), d_m3DebugOp (GetGlobal_s64), d_m3DebugOp (ContinueLoop), d_m3DebugOp (ContinueLoopIf), + + d_m3DebugOp (CopySlot_32), d_m3DebugOp (PreserveCopySlot_32), d_m3DebugOp (If_s), d_m3DebugOp (BranchIfPrologue_s), + d_m3DebugOp (CopySlot_64), d_m3DebugOp (PreserveCopySlot_64), d_m3DebugOp (If_r), d_m3DebugOp (BranchIfPrologue_r), + + d_m3DebugOp (Select_i32_rss), d_m3DebugOp (Select_i32_srs), d_m3DebugOp (Select_i32_ssr), d_m3DebugOp (Select_i32_sss), + d_m3DebugOp (Select_i64_rss), d_m3DebugOp (Select_i64_srs), d_m3DebugOp (Select_i64_ssr), d_m3DebugOp (Select_i64_sss), + +# if d_m3HasFloat + d_m3DebugOp (Select_f32_sss), d_m3DebugOp (Select_f32_srs), d_m3DebugOp (Select_f32_ssr), + d_m3DebugOp (Select_f32_rss), d_m3DebugOp (Select_f32_rrs), d_m3DebugOp (Select_f32_rsr), + + d_m3DebugOp (Select_f64_sss), d_m3DebugOp (Select_f64_srs), d_m3DebugOp (Select_f64_ssr), + d_m3DebugOp (Select_f64_rss), d_m3DebugOp (Select_f64_rrs), d_m3DebugOp (Select_f64_rsr), +# endif + + d_m3DebugTypedOp (SetGlobal), d_m3DebugOp (SetGlobal_s32), d_m3DebugOp (SetGlobal_s64), + + d_m3DebugTypedOp (SetRegister), d_m3DebugTypedOp (SetSlot), d_m3DebugTypedOp (PreserveSetSlot), +# endif + +# ifdef d_m3EnableExtendedOpcodes +# ifdef DEBUG + d_m3DebugOp (MemFill), + d_m3DebugOp (MemCopy), +#endif + + [0xFC] = M3OP( "0xFC", 0, c_m3Type_unknown, d_emptyOpList, Compile_ExtendedOpcode ), +# endif + +# ifdef DEBUG + M3OP( "termination", 0, c_m3Type_unknown ) // for find_operation_info +# endif +}; + +const M3OpInfo c_operationsFC [] = +{ + M3OP_F( "i32.trunc_s:sat/f32",0, i_32, d_convertOpList (i32_TruncSat_f32), Compile_Convert ), // 0x00 + M3OP_F( "i32.trunc_u:sat/f32",0, i_32, d_convertOpList (u32_TruncSat_f32), Compile_Convert ), // 0x01 + M3OP_F( "i32.trunc_s:sat/f64",0, i_32, d_convertOpList (i32_TruncSat_f64), Compile_Convert ), // 0x02 + M3OP_F( "i32.trunc_u:sat/f64",0, i_32, d_convertOpList (u32_TruncSat_f64), Compile_Convert ), // 0x03 + M3OP_F( "i64.trunc_s:sat/f32",0, i_64, d_convertOpList (i64_TruncSat_f32), Compile_Convert ), // 0x04 + M3OP_F( "i64.trunc_u:sat/f32",0, i_64, d_convertOpList (u64_TruncSat_f32), Compile_Convert ), // 0x05 + M3OP_F( "i64.trunc_s:sat/f64",0, i_64, d_convertOpList (i64_TruncSat_f64), Compile_Convert ), // 0x06 + M3OP_F( "i64.trunc_u:sat/f64",0, i_64, d_convertOpList (u64_TruncSat_f64), Compile_Convert ), // 0x07 + + M3OP_RESERVED, M3OP_RESERVED, + + M3OP( "memory.copy", 0, none, d_emptyOpList, Compile_Memory_CopyFill ), // 0x0a + M3OP( "memory.fill", 0, none, d_emptyOpList, Compile_Memory_CopyFill ), // 0x0b + + +# ifdef DEBUG + M3OP( "termination", 0, c_m3Type_unknown ) // for find_operation_info +# endif +}; + + +IM3OpInfo GetOpInfo (m3opcode_t opcode) +{ + switch (opcode >> 8) { + case 0x00: + if (opcode < M3_COUNT_OF(c_operations)) { + return &c_operations[opcode]; + } + break; + case 0xFC: + opcode &= 0xFF; + if (opcode < M3_COUNT_OF(c_operationsFC)) { + return &c_operationsFC[opcode]; + } + break; + } + return NULL; +} + +M3Result CompileBlockStatements (IM3Compilation o) +{ + M3Result result = m3Err_none; + bool validEnd = false; + + while (o->wasm < o->wasmEnd) + { emit_stack_dump (o); + m3opcode_t opcode; + o->lastOpcodeStart = o->wasm; +_ (Read_opcode (& opcode, & o->wasm, o->wasmEnd)); log_opcode (o, opcode); + + // Restrict opcodes when evaluating expressions + if (not o->function) { + switch (opcode) { + case c_waOp_i32_const: case c_waOp_i64_const: + case c_waOp_f32_const: case c_waOp_f64_const: + case c_waOp_getGlobal: case c_waOp_end: + break; + default: + _throw(m3Err_restictedOpcode); + } + } + + IM3OpInfo opinfo = GetOpInfo (opcode); + + if (opinfo == NULL) + _throw (ErrorCompile (m3Err_unknownOpcode, o, "opcode '%x' not available", opcode)); + + if (opinfo->compiler) { +_ ((* opinfo->compiler) (o, opcode)) + } else { +_ (Compile_Operator (o, opcode)); + } + + o->previousOpcode = opcode; + + if (opcode == c_waOp_else) + { + _throwif (m3Err_wasmMalformed, o->block.opcode != c_waOp_if); + validEnd = true; + break; + } + else if (opcode == c_waOp_end) + { + validEnd = true; + break; + } + } + _throwif(m3Err_wasmMalformed, !(validEnd)); + +_catch: + return result; +} + + +M3Result PushBlockResults (IM3Compilation o) +{ + M3Result result = m3Err_none; + + u16 numResults = GetFuncTypeNumResults (o->block.type); + + for (u16 i = 0; i < numResults; ++i) + { + u8 type = GetFuncTypeResultType (o->block.type, i); + + if (i == numResults - 1 and IsFpType (type)) + { +_ (PushRegister (o, type)); + } + else +_ (PushAllocatedSlot (o, type)); + } + + _catch: return result; +} + + + +M3Result CompileBlock (IM3Compilation o, IM3FuncType i_blockType, m3opcode_t i_blockOpcode) +{ + M3Result result = m3Err_none; d_m3Assert (not IsRegisterAllocated (o, 0)); + d_m3Assert (not IsRegisterAllocated (o, 1)); + M3CompilationScope outerScope = o->block; + M3CompilationScope * block = & o->block; + + block->outer = & outerScope; + block->pc = GetPagePC (o->page); + block->patches = NULL; + block->type = i_blockType; + block->depth ++; + block->opcode = i_blockOpcode; + + /* + The block stack frame is a little strange but for good reasons. Because blocks need to be restarted to + compile different pathways (if/else), the incoming params must be saved. The parameters are popped + and validated. But, then the stack top is readjusted so they aren't subsequently overwritten. + Next, the result are preallocated to find destination slots. But again these are immediately popped + (deallocated) and the stack top is readjusted to keep these records in pace. This allows branch instructions + to find their result landing pads. Finally, the params are copied from the "dead" records and pushed back + onto the stack as active stack items for the CompileBlockStatements () call. + + [ block ] + [ params ] + ------------------ + [ result ] <---- blockStackIndex + [ slots ] + ------------------ + [ saved param ] + [ records ] + <----- exitStackIndex + */ + +_try { + // validate and dealloc params ---------------------------- + + u16 stackIndex = o->stackIndex; + + u16 numParams = GetFuncTypeNumParams (i_blockType); + + if (i_blockOpcode != c_waOp_else) + { + for (u16 i = 0; i < numParams; ++i) + { + u8 type = GetFuncTypeParamType (i_blockType, numParams - 1 - i); +_ (PopType (o, type)); + } + } + else o->stackIndex -= numParams; + + u16 paramIndex = o->stackIndex; + block->exitStackIndex = paramIndex; // consume the params at block exit + + // keep copies of param slots in the stack + o->stackIndex = stackIndex; + + // find slots for the results ---------------------------- + PushBlockResults (o); + + stackIndex = o->stackIndex; + + // dealloc but keep record of the result slots in the stack + u16 numResults = GetFuncTypeNumResults (i_blockType); + while (numResults--) + Pop (o); + + block->blockStackIndex = o->stackIndex = stackIndex; + + // push the params back onto the stack ------------------- + for (u16 i = 0; i < numParams; ++i) + { + u8 type = GetFuncTypeParamType (i_blockType, i); + + u16 slot = GetSlotForStackIndex (o, paramIndex + i); + Push (o, type, slot); + + if (slot >= o->slotFirstDynamicIndex) + MarkSlotsAllocatedByType (o, slot, type); + } + + //-------------------------------------------------------- + +_ (CompileBlockStatements (o)); + +_ (ValidateBlockEnd (o)); + + if (o->function) // skip for expressions + { + if (not IsStackPolymorphic (o)) +_ (ResolveBlockResults (o, & o->block, /* isBranch: */ false)); + +_ (UnwindBlockStack (o)) + + if (not ((i_blockOpcode == c_waOp_if and numResults) or o->previousOpcode == c_waOp_else)) + { + o->stackIndex = o->block.exitStackIndex; +_ (PushBlockResults (o)); + } + } + + PatchBranches (o); + + o->block = outerScope; + +} _catch: return result; +} + + +M3Result CompileLocals (IM3Compilation o) +{ + M3Result result; + + u32 numLocals = 0; + u32 numLocalBlocks; +_ (ReadLEB_u32 (& numLocalBlocks, & o->wasm, o->wasmEnd)); + + for (u32 l = 0; l < numLocalBlocks; ++l) + { + u32 varCount; + i8 waType; + u8 localType; + +_ (ReadLEB_u32 (& varCount, & o->wasm, o->wasmEnd)); +_ (ReadLEB_i7 (& waType, & o->wasm, o->wasmEnd)); +_ (NormalizeType (& localType, waType)); + numLocals += varCount; m3log (compile, "pushing locals. count: %d; type: %s", varCount, c_waTypes [localType]); + while (varCount--) +_ (PushAllocatedSlot (o, localType)); + } + + if (o->function) + o->function->numLocals = numLocals; + + _catch: return result; +} + + +M3Result ReserveConstants (IM3Compilation o) +{ + M3Result result = m3Err_none; + + // in the interest of speed, this blindly scans the Wasm code looking for any byte + // that looks like an const opcode. + u16 numConstantSlots = 0; + + bytes_t wa = o->wasm; + while (wa < o->wasmEnd) + { + u8 code = * wa++; + + if (code == c_waOp_i32_const or code == c_waOp_f32_const) + numConstantSlots += 1; + else if (code == c_waOp_i64_const or code == c_waOp_f64_const) + numConstantSlots += GetTypeNumSlots (c_m3Type_i64); + + if (numConstantSlots >= d_m3MaxConstantTableSize) + break; + } + + // if constants overflow their reserved stack space, the compiler simply emits op_Const + // operations as needed. Compiled expressions (global inits) don't pass through this + // ReserveConstants function and thus always produce inline constants. + + AlignSlotToType (& numConstantSlots, c_m3Type_i64); m3log (compile, "reserved constant slots: %d", numConstantSlots); + + o->slotFirstDynamicIndex = o->slotFirstConstIndex + numConstantSlots; + + if (o->slotFirstDynamicIndex >= d_m3MaxFunctionSlots) + _throw (m3Err_functionStackOverflow); + + _catch: + return result; +} + + +M3Result CompileFunction (IM3Function io_function) +{ + M3Result result = m3Err_none; + + if (!io_function->wasm) return "function body is missing"; + + IM3FuncType funcType = io_function->funcType; m3log (compile, "compiling: [%d] %s %s; wasm-size: %d", + io_function->index, m3_GetFunctionName (io_function), SPrintFuncTypeSignature (funcType), (u32) (io_function->wasmEnd - io_function->wasm)); + IM3Runtime runtime = io_function->module->runtime; + + IM3Compilation o = & runtime->compilation; d_m3Assert (d_m3MaxFunctionSlots >= d_m3MaxFunctionStackHeight * (d_m3Use32BitSlots + 1)) // need twice as many slots in 32-bit mode + memset (o, 0x0, sizeof (M3Compilation)); + + o->runtime = runtime; + o->module = io_function->module; + o->function = io_function; + o->wasm = io_function->wasm; + o->wasmEnd = io_function->wasmEnd; + o->block.type = funcType; + +_try { + // skip over code size. the end was already calculated during parse phase + u32 size; +_ (ReadLEB_u32 (& size, & o->wasm, o->wasmEnd)); d_m3Assert (size == (o->wasmEnd - o->wasm)) + +_ (AcquireCompilationCodePage (o, & o->page)); + + pc_t pc = GetPagePC (o->page); + + u16 numRetSlots = GetFunctionNumReturns (o->function) * c_ioSlotCount; + + for (u16 i = 0; i < numRetSlots; ++i) + MarkSlotAllocated (o, i); + + o->function->numRetSlots = o->slotFirstDynamicIndex = numRetSlots; + + u16 numArgs = GetFunctionNumArgs (o->function); + + // push the arg types to the type stack + for (u16 i = 0; i < numArgs; ++i) + { + u8 type = GetFunctionArgType (o->function, i); +_ (PushAllocatedSlot (o, type)); + + // prevent allocator fill-in + o->slotFirstDynamicIndex += c_ioSlotCount; + } + + o->slotMaxAllocatedIndexPlusOne = o->function->numRetAndArgSlots = o->slotFirstLocalIndex = o->slotFirstDynamicIndex; + +_ (CompileLocals (o)); + + u16 maxSlot = GetMaxUsedSlotPlusOne (o); + + o->function->numLocalBytes = (maxSlot - o->slotFirstLocalIndex) * sizeof (m3slot_t); + + o->slotFirstConstIndex = o->slotMaxConstIndex = maxSlot; + + // ReserveConstants initializes o->firstDynamicSlotNumber +_ (ReserveConstants (o)); + + // start tracking the max stack used (Push() also updates this value) so that op_Entry can precisely detect stack overflow + o->maxStackSlots = o->slotMaxAllocatedIndexPlusOne = o->slotFirstDynamicIndex; + + o->block.blockStackIndex = o->stackFirstDynamicIndex = o->stackIndex; m3log (compile, "start stack index: %d", + (u32) o->stackFirstDynamicIndex); +_ (EmitOp (o, op_Entry)); + EmitPointer (o, io_function); + +_ (CompileBlockStatements (o)); + + // TODO: validate opcode sequences + _throwif(m3Err_wasmMalformed, o->previousOpcode != c_waOp_end); + + io_function->compiled = pc; + io_function->maxStackSlots = o->maxStackSlots; + + u16 numConstantSlots = o->slotMaxConstIndex - o->slotFirstConstIndex; m3log (compile, "unique constant slots: %d; unused slots: %d", + numConstantSlots, o->slotFirstDynamicIndex - o->slotMaxConstIndex); + io_function->numConstantBytes = numConstantSlots * sizeof (m3slot_t); + + if (numConstantSlots) + { + io_function->constants = m3_CopyMem (o->constants, io_function->numConstantBytes); + _throwifnull(io_function->constants); + } + +} _catch: + + ReleaseCompilationCodePage (o); + + return result; +} diff --git a/wasm3-sys/wasm3/source/m3_compile.h b/wasm3-sys/wasm3/source/m3_compile.h new file mode 100644 index 0000000..89fa201 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_compile.h @@ -0,0 +1,189 @@ +// +// m3_compile.h +// +// Created by Steven Massey on 4/17/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_compile_h +#define m3_compile_h + +#include "m3_code.h" +#include "m3_exec_defs.h" +#include "m3_function.h" + +d_m3BeginExternC + +enum +{ + c_waOp_block = 0x02, + c_waOp_loop = 0x03, + c_waOp_if = 0x04, + c_waOp_else = 0x05, + c_waOp_end = 0x0b, + c_waOp_branch = 0x0c, + c_waOp_branchTable = 0x0e, + c_waOp_branchIf = 0x0d, + c_waOp_call = 0x10, + c_waOp_getLocal = 0x20, + c_waOp_setLocal = 0x21, + c_waOp_teeLocal = 0x22, + + c_waOp_getGlobal = 0x23, + + c_waOp_i32_const = 0x41, + c_waOp_i64_const = 0x42, + c_waOp_f32_const = 0x43, + c_waOp_f64_const = 0x44, + + c_waOp_memoryCopy = 0xfc0a, + c_waOp_memoryFill = 0xfc0b +}; + + +#define d_FuncRetType(ftype,i) ((ftype)->types[(i)]) +#define d_FuncArgType(ftype,i) ((ftype)->types[(ftype)->numRets + (i)]) + +//----------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3CompilationScope +{ + struct M3CompilationScope * outer; + + pc_t pc; // used by ContinueLoop's + pc_t patches; + i32 depth; + u16 exitStackIndex; + i16 blockStackIndex; +// u16 topSlot; + IM3FuncType type; + m3opcode_t opcode; + bool isPolymorphic; +} +M3CompilationScope; + +typedef M3CompilationScope * IM3CompilationScope; + +typedef struct +{ + IM3Runtime runtime; + IM3Module module; + + bytes_t wasm; + bytes_t wasmEnd; + bytes_t lastOpcodeStart; + + M3CompilationScope block; + + IM3Function function; + + IM3CodePage page; + +#ifdef DEBUG + u32 numEmits; + u32 numOpcodes; +#endif + + u16 stackFirstDynamicIndex; // args and locals are pushed to the stack so that their slot locations can be tracked. the wasm model itself doesn't + // treat these values as being on the stack, so stackFirstDynamicIndex marks the start of the real Wasm stack + u16 stackIndex; // current stack top + + u16 slotFirstConstIndex; + u16 slotMaxConstIndex; // as const's are encountered during compilation this tracks their location in the "real" stack + + u16 slotFirstLocalIndex; + u16 slotFirstDynamicIndex; // numArgs + numLocals + numReservedConstants. the first mutable slot available to the compiler. + + u16 maxStackSlots; + + m3slot_t constants [d_m3MaxConstantTableSize]; + + // 'wasmStack' holds slot locations + u16 wasmStack [d_m3MaxFunctionStackHeight]; + u8 typeStack [d_m3MaxFunctionStackHeight]; + + // 'm3Slots' contains allocation usage counts + u8 m3Slots [d_m3MaxFunctionSlots]; + + u16 slotMaxAllocatedIndexPlusOne; + + u16 regStackIndexPlusOne [2]; + + m3opcode_t previousOpcode; +} +M3Compilation; + +typedef M3Compilation * IM3Compilation; + +typedef M3Result (* M3Compiler) (IM3Compilation, m3opcode_t); + + +//----------------------------------------------------------------------------------------------------------------------------------- + + +typedef struct M3OpInfo +{ +#ifdef DEBUG + const char * const name; +#endif + + i8 stackOffset; + u8 type; + + // for most operations: + // [0]= top operand in register, [1]= top operand in stack, [2]= both operands in stack + IM3Operation operations [4]; + + M3Compiler compiler; +} +M3OpInfo; + +typedef const M3OpInfo * IM3OpInfo; + +IM3OpInfo GetOpInfo (m3opcode_t opcode); + +// TODO: This helper should be removed, when MultiValue is implemented +static inline +u8 GetSingleRetType(IM3FuncType ftype) { + return (ftype && ftype->numRets) ? ftype->types[0] : (u8)c_m3Type_none; +} + +#ifdef DEBUG + #define M3OP(...) { __VA_ARGS__ } + #define M3OP_RESERVED { "reserved" } +#else + // Strip-off name + #define M3OP(name, ...) { __VA_ARGS__ } + #define M3OP_RESERVED { 0 } +#endif + +#if d_m3HasFloat + #define M3OP_F M3OP +#elif d_m3NoFloatDynamic + #define M3OP_F(n,o,t,op,...) M3OP(n, o, t, { op_Unsupported, op_Unsupported, op_Unsupported, op_Unsupported }, __VA_ARGS__) +#else + #define M3OP_F(...) { 0 } +#endif + +//----------------------------------------------------------------------------------------------------------------------------------- + +u16 GetTypeNumSlots (u8 i_type); +void AlignSlotToType (u16 * io_slotIndex, u8 i_type); + +bool IsRegisterAllocated (IM3Compilation o, u32 i_register); +bool IsRegisterSlotAlias (u16 i_slot); +bool IsFpRegisterSlotAlias (u16 i_slot); +bool IsIntRegisterSlotAlias (u16 i_slot); + +bool IsStackPolymorphic (IM3Compilation o); + +M3Result CompileBlock (IM3Compilation io, IM3FuncType i_blockType, m3opcode_t i_blockOpcode); + +M3Result CompileBlockStatements (IM3Compilation io); +M3Result CompileFunction (IM3Function io_function); + +u16 GetMaxUsedSlotPlusOne (IM3Compilation o); + +d_m3EndExternC + +#endif // m3_compile_h diff --git a/wasm3-sys/wasm3/source/m3_config.h b/wasm3-sys/wasm3/source/m3_config.h new file mode 100644 index 0000000..6a204a3 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_config.h @@ -0,0 +1,147 @@ +// +// m3_config.h +// +// Created by Steven Massey on 5/4/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_config_h +#define m3_config_h + +#include "m3_config_platforms.h" + +// general -------------------------------------------------------------------- + +# ifndef d_m3CodePageAlignSize +# define d_m3CodePageAlignSize 4096 +# endif + +# ifndef d_m3EnableCodePageRefCounting +# define d_m3EnableCodePageRefCounting 0 +# endif + +# ifndef d_m3MaxFunctionStackHeight +# define d_m3MaxFunctionStackHeight 2000 // TODO: comment on upper limit +# endif + +# ifndef d_m3MaxLinearMemoryPages +# define d_m3MaxLinearMemoryPages 32768 +# endif + +# ifndef d_m3MaxFunctionSlots +# define d_m3MaxFunctionSlots ((d_m3MaxFunctionStackHeight)*2) +# endif + +# ifndef d_m3MaxConstantTableSize +# define d_m3MaxConstantTableSize 120 +# endif + +# ifndef d_m3MaxDuplicateFunctionImpl +# define d_m3MaxDuplicateFunctionImpl 3 +# endif + +# ifndef d_m3EnableExtendedOpcodes +# define d_m3EnableExtendedOpcodes 1 +# endif + +# ifndef d_m3VerboseErrorMessages +# define d_m3VerboseErrorMessages 1 +# endif + +# ifndef d_m3FixedHeap +# define d_m3FixedHeap false +//# define d_m3FixedHeap (32*1024) +# endif + +# ifndef d_m3FixedHeapAlign +# define d_m3FixedHeapAlign 16 +# endif + +# ifndef d_m3Use32BitSlots +# define d_m3Use32BitSlots 1 +# endif + +# ifndef d_m3ProfilerSlotMask +# define d_m3ProfilerSlotMask 0xFFFF +# endif + +# ifndef d_m3RecordBacktraces +# define d_m3RecordBacktraces 0 +# endif + +# ifndef d_m3EnableExceptionBreakpoint +# define d_m3EnableExceptionBreakpoint 0 // see m3_exception.h +# endif + + +// profiling and tracing ------------------------------------------------------ + +# ifndef d_m3EnableOpProfiling +# define d_m3EnableOpProfiling 0 // opcode usage counters +# endif + +# ifndef d_m3EnableOpTracing +# define d_m3EnableOpTracing 0 // only works with DEBUG +# endif + +# ifndef d_m3EnableStrace +# define d_m3EnableStrace 0 // 1 - trace exported function calls + // 2 - trace all calls (structured) - requires DEBUG + // 3 - all calls + loops + memory operations +# endif + + +// logging -------------------------------------------------------------------- + +# ifndef d_m3LogParse +# define d_m3LogParse 0 // .wasm binary decoding info +# endif + +# ifndef d_m3LogModule +# define d_m3LogModule 0 // wasm module info +# endif + +# ifndef d_m3LogCompile +# define d_m3LogCompile 0 // wasm -> metacode generation phase +# endif + +# ifndef d_m3LogWasmStack +# define d_m3LogWasmStack 0 // dump the wasm stack when pushed or popped +# endif + +# ifndef d_m3LogEmit +# define d_m3LogEmit 0 // metacode generation info +# endif + +# ifndef d_m3LogCodePages +# define d_m3LogCodePages 0 // dump metacode pages when released +# endif + +# ifndef d_m3LogRuntime +# define d_m3LogRuntime 0 // higher-level runtime information +# endif + +# ifndef d_m3LogNativeStack +# define d_m3LogNativeStack 0 // track the memory usage of the C-stack +# endif + + +// other ---------------------------------------------------------------------- + +# ifndef d_m3HasFloat +# define d_m3HasFloat 1 // implement floating point ops +# endif + +#if !d_m3HasFloat && !defined(d_m3NoFloatDynamic) +# define d_m3NoFloatDynamic 1 // if no floats, do not fail until flops are actually executed +#endif + +# ifndef d_m3SkipStackCheck +# define d_m3SkipStackCheck 0 // skip stack overrun checks +# endif + +# ifndef d_m3SkipMemoryBoundsCheck +# define d_m3SkipMemoryBoundsCheck 0 // skip memory bounds checks +# endif + +#endif // m3_config_h diff --git a/wasm3-sys/wasm3/source/m3_config_platforms.h b/wasm3-sys/wasm3/source/m3_config_platforms.h new file mode 100644 index 0000000..b3b8e8b --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_config_platforms.h @@ -0,0 +1,189 @@ +// +// m3_config_platforms.h +// +// Created by Volodymyr Shymanskyy on 11/20/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef m3_config_platforms_h +#define m3_config_platforms_h + +#include "wasm3_defs.h" + +/* + * Internal helpers + */ + +# if !defined(__cplusplus) || defined(_MSC_VER) +# define not ! +# define and && +# define or || +# endif + +/* + * Detect/define features + */ + +# if defined(M3_COMPILER_MSVC) +# include +# if UINTPTR_MAX == 0xFFFFFFFF +# define M3_SIZEOF_PTR 4 +# elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu +# define M3_SIZEOF_PTR 8 +# else +# error "Pointer size not supported" +# endif +# elif defined(__SIZEOF_POINTER__) +# define M3_SIZEOF_PTR __SIZEOF_POINTER__ +#else +# error "Pointer size not detected" +# endif + +# if defined(M3_BIG_ENDIAN) +# define M3_BSWAP_u8(X) {} +# define M3_BSWAP_u16(X) { (X)=m3_bswap16((X)); } +# define M3_BSWAP_u32(X) { (X)=m3_bswap32((X)); } +# define M3_BSWAP_u64(X) { (X)=m3_bswap64((X)); } +# define M3_BSWAP_i8(X) {} +# define M3_BSWAP_i16(X) M3_BSWAP_u16(X) +# define M3_BSWAP_i32(X) M3_BSWAP_u32(X) +# define M3_BSWAP_i64(X) M3_BSWAP_u64(X) +# define M3_BSWAP_f32(X) { union { f32 f; u32 i; } u; u.f = (X); M3_BSWAP_u32(u.i); (X) = u.f; } +# define M3_BSWAP_f64(X) { union { f64 f; u64 i; } u; u.f = (X); M3_BSWAP_u64(u.i); (X) = u.f; } +# else +# define M3_BSWAP_u8(X) {} +# define M3_BSWAP_u16(x) {} +# define M3_BSWAP_u32(x) {} +# define M3_BSWAP_u64(x) {} +# define M3_BSWAP_i8(X) {} +# define M3_BSWAP_i16(X) {} +# define M3_BSWAP_i32(X) {} +# define M3_BSWAP_i64(X) {} +# define M3_BSWAP_f32(X) {} +# define M3_BSWAP_f64(X) {} +# endif + +# if defined(M3_COMPILER_MSVC) +# define M3_WEAK //__declspec(selectany) +# define M3_NO_UBSAN +# elif defined(__MINGW32__) +# define M3_WEAK //__attribute__((selectany)) +# define M3_NO_UBSAN +# else +# define M3_WEAK __attribute__((weak)) +# define M3_NO_UBSAN //__attribute__((no_sanitize("undefined"))) +# endif + +# ifndef M3_MIN +# define M3_MIN(A,B) (((A) < (B)) ? (A) : (B)) +# endif +# ifndef M3_MAX +# define M3_MAX(A,B) (((A) > (B)) ? (A) : (B)) +# endif + +#define M3_INIT(field) memset(&field, 0, sizeof(field)) + +#define M3_COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + +#if defined(__AVR__) + +# define PRIu64 "llu" +# define PRIi64 "lli" + +# define d_m3ShortTypesDefined +typedef double f64; +typedef float f32; +typedef uint64_t u64; +typedef int64_t i64; +typedef uint32_t u32; +typedef int32_t i32; +typedef short unsigned u16; +typedef short i16; +typedef uint8_t u8; +typedef int8_t i8; + +#endif + +/* + * Apply settings + */ + +# if defined (M3_COMPILER_MSVC) +# define vectorcall // For MSVC, better not to specify any call convention +# elif defined(__MINGW32__) +# define vectorcall +# elif defined(WIN32) +# define vectorcall __vectorcall +# elif defined (ESP8266) +# include +# define op_section //ICACHE_FLASH_ATTR +# elif defined (ESP32) +# if defined(M3_IN_IRAM) // the interpreter is in IRAM, attribute not needed +# define op_section +# else +# include "esp_system.h" +# define op_section IRAM_ATTR +# endif +# elif defined (FOMU) +# define op_section __attribute__((section(".ramtext"))) +# endif + +#ifndef vectorcall +#define vectorcall +#endif + +#ifndef op_section +#define op_section +#endif + + +/* + * Device-specific defaults + */ + +# ifndef d_m3MaxFunctionStackHeight +# if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AMEBA) || defined(TEENSYDUINO) +# define d_m3MaxFunctionStackHeight 128 +# endif +# endif + +# ifndef d_m3FixedHeap +# if defined(ARDUINO_AMEBA) +# define d_m3FixedHeap (128*1024) +# elif defined(BLUE_PILL) || defined(FOMU) +# define d_m3FixedHeap (12*1024) +# elif defined(ARDUINO_ARCH_ARC32) // Arduino 101 +# define d_m3FixedHeap (10*1024) +# endif +# endif + +/* + * Platform-specific defaults + */ + +# if defined(ARDUINO) || defined(PARTICLE) || defined(PLATFORMIO) || defined(__MBED__) || \ + defined(ESP8266) || defined(ESP32) || defined(BLUE_PILL) || defined(WM_W600) || defined(FOMU) +# ifndef d_m3VerboseErrorMessages +# define d_m3VerboseErrorMessages 0 +# endif +# ifndef d_m3MaxConstantTableSize +# define d_m3MaxConstantTableSize 64 +# endif +# ifndef d_m3MaxFunctionStackHeight +# define d_m3MaxFunctionStackHeight 64 +# endif +# ifndef d_m3CodePageAlignSize +# define d_m3CodePageAlignSize 1024 +# endif +# endif + +/* + * Arch-specific defaults + */ +#if defined(__riscv) && __riscv_xlen == 64 +# ifndef d_m3Use32BitSlots +# define d_m3Use32BitSlots 0 +# endif +#endif + +#endif // m3_config_platforms_h diff --git a/wasm3-sys/wasm3/source/m3_core.c b/wasm3-sys/wasm3/source/m3_core.c new file mode 100644 index 0000000..e21faf3 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_core.c @@ -0,0 +1,601 @@ +// +// m3_core.c +// +// Created by Steven Massey on 4/15/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#define M3_IMPLEMENT_ERROR_STRINGS +#include "wasm3.h" + +#include "m3_core.h" +#include "m3_env.h" + +void m3_Abort(const char* message) { +#ifdef DEBUG + fprintf(stderr, "Error: %s\n", message); +#endif + abort(); +} + +M3_WEAK +M3Result m3_Yield () +{ + return m3Err_none; +} + +#if d_m3FixedHeap + +static u8 fixedHeap[d_m3FixedHeap]; +static u8* fixedHeapPtr = fixedHeap; +static u8* const fixedHeapEnd = fixedHeap + d_m3FixedHeap; +static u8* fixedHeapLast = NULL; + +#if d_m3FixedHeapAlign > 1 +# define HEAP_ALIGN_PTR(P) P = (u8*)(((size_t)(P)+(d_m3FixedHeapAlign-1)) & ~ (d_m3FixedHeapAlign-1)); +#else +# define HEAP_ALIGN_PTR(P) +#endif + +void * m3_Malloc (size_t i_size) +{ + u8 * ptr = fixedHeapPtr; + + fixedHeapPtr += i_size; + HEAP_ALIGN_PTR(fixedHeapPtr); + + if (fixedHeapPtr >= fixedHeapEnd) + { + return NULL; + } + + memset (ptr, 0x0, i_size); + fixedHeapLast = ptr; + + //printf("== alloc %d => %p\n", i_size, ptr); + + return ptr; +} + +void m3_FreeImpl (void * i_ptr) +{ + // Handle the last chunk + if (i_ptr && i_ptr == fixedHeapLast) { + fixedHeapPtr = fixedHeapLast; + fixedHeapLast = NULL; + //printf("== free %p\n", io_ptr); + } else { + //printf("== free %p [failed]\n", io_ptr); + } +} + +void * m3_Realloc (void * i_ptr, size_t i_newSize, size_t i_oldSize) +{ + //printf("== realloc %p => %d\n", io_ptr, i_newSize); + + if (UNLIKELY(i_newSize == i_oldSize)) return i_ptr; + + void * newPtr; + + // Handle the last chunk + if (i_ptr && i_ptr == fixedHeapLast) { + fixedHeapPtr = fixedHeapLast + i_newSize; + HEAP_ALIGN_PTR(fixedHeapPtr); + if (fixedHeapPtr >= fixedHeapEnd) + { + return NULL; + } + newPtr = i_ptr; + } else { + newPtr = m3_Malloc(i_newSize); + if (!newPtr) { + return NULL; + } + if (i_ptr) { + memcpy(newPtr, i_ptr, i_oldSize); + } + } + + if (i_newSize > i_oldSize) { + memset ((u8 *) newPtr + i_oldSize, 0x0, i_newSize - i_oldSize); + } + + return newPtr; +} + +#else + +void * m3_Malloc (size_t i_size) +{ + void * ptr = calloc (i_size, 1); + +// printf("== alloc %d => %p\n", (u32) i_size, ptr); + + return ptr; +} + +void m3_FreeImpl (void * io_ptr) +{ +// if (io_ptr) printf("== free %p\n", io_ptr); + free (io_ptr); +} + +void * m3_Realloc (void * i_ptr, size_t i_newSize, size_t i_oldSize) +{ + if (UNLIKELY(i_newSize == i_oldSize)) return i_ptr; + + void * newPtr = realloc (i_ptr, i_newSize); + + if (LIKELY(newPtr)) + { + if (i_newSize > i_oldSize) { + memset ((u8 *) newPtr + i_oldSize, 0x0, i_newSize - i_oldSize); + } + return newPtr; + } + return NULL; +} + +#endif + +void * m3_CopyMem (const void * i_from, size_t i_size) +{ + void * ptr = m3_Malloc(i_size); + if (ptr) { + memcpy (ptr, i_from, i_size); + } + return ptr; +} + +//-------------------------------------------------------------------------------------------- + +#if d_m3LogNativeStack + +static size_t stack_start; +static size_t stack_end; + +void m3StackCheckInit () +{ + char stack; + stack_end = stack_start = (size_t)&stack; +} + +void m3StackCheck () +{ + char stack; + size_t addr = (size_t)&stack; + + size_t stackEnd = stack_end; + stack_end = M3_MIN (stack_end, addr); + +// if (stackEnd != stack_end) +// printf ("maxStack: %ld\n", m3StackGetMax ()); +} + +int m3StackGetMax () +{ + return stack_start - stack_end; +} + +#endif + +//-------------------------------------------------------------------------------------------- + +M3Result NormalizeType (u8 * o_type, i8 i_convolutedWasmType) +{ + M3Result result = m3Err_none; + + u8 type = -i_convolutedWasmType; + + if (type == 0x40) + type = c_m3Type_none; + else if (type < c_m3Type_i32 or type > c_m3Type_f64) + result = m3Err_invalidTypeId; + + * o_type = type; + + return result; +} + + +bool IsFpType (u8 i_m3Type) +{ + return (i_m3Type == c_m3Type_f32 or i_m3Type == c_m3Type_f64); +} + + +bool IsIntType (u8 i_m3Type) +{ + return (i_m3Type == c_m3Type_i32 or i_m3Type == c_m3Type_i64); +} + + +bool Is64BitType (u8 i_m3Type) +{ + if (i_m3Type == c_m3Type_i64 or i_m3Type == c_m3Type_f64) + return true; + else if (i_m3Type == c_m3Type_i32 or i_m3Type == c_m3Type_f32 or i_m3Type == c_m3Type_none) + return false; + else + return (sizeof (voidptr_t) == 8); // all other cases are pointers +} + +u32 SizeOfType (u8 i_m3Type) +{ + if (i_m3Type == c_m3Type_i32 or i_m3Type == c_m3Type_f32) + return sizeof (i32); + + return sizeof (i64); +} + + +//-- Binary Wasm parsing utils ------------------------------------------------------------------------------------------ + + +M3Result Read_u64 (u64 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + ptr += sizeof (u64); + + if (ptr <= i_end) + { + memcpy(o_value, * io_bytes, sizeof(u64)); + M3_BSWAP_u64(*o_value); + * io_bytes = ptr; + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + + +M3Result Read_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + ptr += sizeof (u32); + + if (ptr <= i_end) + { + memcpy(o_value, * io_bytes, sizeof(u32)); + M3_BSWAP_u32(*o_value); + * io_bytes = ptr; + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + +#if d_m3ImplementFloat + +M3Result Read_f64 (f64 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + ptr += sizeof (f64); + + if (ptr <= i_end) + { + memcpy(o_value, * io_bytes, sizeof(f64)); + M3_BSWAP_f64(*o_value); + * io_bytes = ptr; + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + + +M3Result Read_f32 (f32 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + ptr += sizeof (f32); + + if (ptr <= i_end) + { + memcpy(o_value, * io_bytes, sizeof(f32)); + M3_BSWAP_f32(*o_value); + * io_bytes = ptr; + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + +#endif + +M3Result Read_u8 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + + if (ptr < i_end) + { + * o_value = * ptr; + * io_bytes = ptr + 1; + + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + +M3Result Read_opcode (m3opcode_t * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + + if (ptr < i_end) + { + m3opcode_t opcode = * ptr++; + +#ifndef d_m3EnableExtendedOpcodes + if (UNLIKELY(opcode == 0xFC)) + { + if (ptr < i_end) + { + opcode = (opcode << 8) | (* ptr++); + } + else return m3Err_wasmUnderrun; + } +#endif + * o_value = opcode; + * io_bytes = ptr; + + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + + +M3Result ReadLebUnsigned (u64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_wasmUnderrun; + + u64 value = 0; + + u32 shift = 0; + const u8 * ptr = * io_bytes; + + while (ptr < i_end) + { + u64 byte = * (ptr++); + + value |= ((byte & 0x7f) << shift); + shift += 7; + + if ((byte & 0x80) == 0) + { + result = m3Err_none; + break; + } + + if (shift >= i_maxNumBits) + { + result = m3Err_lebOverflow; + break; + } + } + + * o_value = value; + * io_bytes = ptr; + + return result; +} + + +M3Result ReadLebSigned (i64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_wasmUnderrun; + + i64 value = 0; + + u32 shift = 0; + const u8 * ptr = * io_bytes; + + while (ptr < i_end) + { + u64 byte = * (ptr++); + + value |= ((byte & 0x7f) << shift); + shift += 7; + + if ((byte & 0x80) == 0) + { + result = m3Err_none; + + if ((byte & 0x40) and (shift < 64)) // do sign extension + { + u64 extend = 0; + value |= (~extend << shift); + } + + break; + } + + if (shift >= i_maxNumBits) + { + result = m3Err_lebOverflow; + break; + } + } + + * o_value = value; + * io_bytes = ptr; + + return result; +} + + +M3Result ReadLEB_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + u64 value; + M3Result result = ReadLebUnsigned (& value, 32, io_bytes, i_end); + * o_value = (u32) value; + + return result; +} + + +M3Result ReadLEB_u7 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + u64 value; + M3Result result = ReadLebUnsigned (& value, 7, io_bytes, i_end); + * o_value = (u8) value; + + return result; +} + + +M3Result ReadLEB_i7 (i8 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + i64 value; + M3Result result = ReadLebSigned (& value, 7, io_bytes, i_end); + * o_value = (i8) value; + + return result; +} + + +M3Result ReadLEB_i32 (i32 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + i64 value; + M3Result result = ReadLebSigned (& value, 32, io_bytes, i_end); + * o_value = (i32) value; + + return result; +} + + +M3Result ReadLEB_i64 (i64 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + i64 value; + M3Result result = ReadLebSigned (& value, 64, io_bytes, i_end); + * o_value = value; + + return result; +} + + +M3Result Read_utf8 (cstr_t * o_utf8, bytes_t * io_bytes, cbytes_t i_end) +{ + *o_utf8 = NULL; + + u32 utf8Length; + M3Result result = ReadLEB_u32 (& utf8Length, io_bytes, i_end); + + if (not result) + { + if (utf8Length <= d_m3MaxSaneUtf8Length) + { + const u8 * ptr = * io_bytes; + const u8 * end = ptr + utf8Length; + + if (end <= i_end) + { + char * utf8 = (char *)m3_Malloc (utf8Length + 1); + + if (utf8) + { + memcpy (utf8, ptr, utf8Length); + utf8 [utf8Length] = 0; + * o_utf8 = utf8; + } + + * io_bytes = end; + } + else result = m3Err_wasmUnderrun; + } + else result = m3Err_missingUTF8; + } + + return result; +} + +#if d_m3RecordBacktraces +u32 FindModuleOffset (IM3Runtime i_runtime, pc_t i_pc) +{ + // walk the code pages + IM3CodePage curr = i_runtime->pagesOpen; + bool pageFound = false; + + while (curr) + { + if (ContainsPC (curr, i_pc)) + { + pageFound = true; + break; + } + curr = curr->info.next; + } + + if (!pageFound) + { + curr = i_runtime->pagesFull; + while (curr) + { + if (ContainsPC (curr, i_pc)) + { + pageFound = true; + break; + } + curr = curr->info.next; + } + } + + if (pageFound) + { + u32 result = 0; + + bool pcFound = MapPCToOffset (curr, i_pc, & result); + d_m3Assert (pcFound); + + return result; + } + else return 0; +} + + +void PushBacktraceFrame (IM3Runtime io_runtime, pc_t i_pc) +{ + // don't try to push any more frames if we've already had an alloc failure + if (UNLIKELY (io_runtime->backtrace.lastFrame == M3_BACKTRACE_TRUNCATED)) + return; + + M3BacktraceFrame * newFrame = m3_AllocStruct(M3BacktraceFrame); + + if (!newFrame) + { + io_runtime->backtrace.lastFrame = M3_BACKTRACE_TRUNCATED; + return; + } + + newFrame->moduleOffset = FindModuleOffset (io_runtime, i_pc); + + if (!io_runtime->backtrace.frames || !io_runtime->backtrace.lastFrame) + io_runtime->backtrace.frames = newFrame; + else + io_runtime->backtrace.lastFrame->next = newFrame; + io_runtime->backtrace.lastFrame = newFrame; +} + + +void FillBacktraceFunctionInfo (IM3Runtime io_runtime, IM3Function i_function) +{ + // If we've had an alloc failure then the last frame doesn't refer to the + // frame we want to fill in the function info for. + if (UNLIKELY (io_runtime->backtrace.lastFrame == M3_BACKTRACE_TRUNCATED)) + return; + + if (!io_runtime->backtrace.lastFrame) + return; + + io_runtime->backtrace.lastFrame->function = i_function; +} + + +void ClearBacktrace (IM3Runtime io_runtime) +{ + M3BacktraceFrame * currentFrame = io_runtime->backtrace.frames; + while (currentFrame) + { + M3BacktraceFrame * nextFrame = currentFrame->next; + m3_Free (currentFrame); + currentFrame = nextFrame; + } + + io_runtime->backtrace.frames = NULL; + io_runtime->backtrace.lastFrame = NULL; +} +#endif // d_m3RecordBacktraces diff --git a/wasm3-sys/wasm3/source/m3_core.h b/wasm3-sys/wasm3/source/m3_core.h new file mode 100644 index 0000000..86c5853 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_core.h @@ -0,0 +1,260 @@ +// +// m3_core.h +// +// Created by Steven Massey on 4/15/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_core_h +#define m3_core_h + +#include +#include +#include +#include +#include + +#include "wasm3.h" +#include "m3_config.h" + +# if defined(__cplusplus) +# define d_m3BeginExternC extern "C" { +# define d_m3EndExternC } +# else +# define d_m3BeginExternC +# define d_m3EndExternC +# endif + +d_m3BeginExternC + +#define d_m3ImplementFloat (d_m3HasFloat || d_m3NoFloatDynamic) + +#if !defined(d_m3ShortTypesDefined) + +typedef uint64_t u64; +typedef int64_t i64; +typedef uint32_t u32; +typedef int32_t i32; +typedef uint16_t u16; +typedef int16_t i16; +typedef uint8_t u8; +typedef int8_t i8; + +#if d_m3ImplementFloat +typedef double f64; +typedef float f32; +#endif + +#endif // d_m3ShortTypesDefined + +#define PRIf32 "f" +#define PRIf64 "lf" + +typedef const void * m3ret_t; +typedef const void * voidptr_t; +typedef const char * cstr_t; +typedef const char * const ccstr_t; +typedef const u8 * bytes_t; +typedef const u8 * const cbytes_t; + +typedef u16 m3opcode_t; + +typedef i64 m3reg_t; + +# if d_m3Use32BitSlots +typedef u32 m3slot_t; +# else +typedef u64 m3slot_t; +# endif + +typedef m3slot_t * m3stack_t; + +typedef +const void * const cvptr_t; + +# if defined (DEBUG) + +# define d_m3Log(CATEGORY, FMT, ...) printf (" %8s | " FMT, #CATEGORY, ##__VA_ARGS__); + +# if d_m3LogParse +# define m3log_parse(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_parse(...) {} +# endif + +# if d_m3LogCompile +# define m3log_compile(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_compile(...) {} +# endif + +# if d_m3LogEmit +# define m3log_emit(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_emit(...) {} +# endif + +# if d_m3LogCodePages +# define m3log_code(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_code(...) {} +# endif + +# if d_m3LogModule +# define m3log_module(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_module(...) {} +# endif + +# if d_m3LogRuntime +# define m3log_runtime(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_runtime(...) {} +# endif + +# define m3log(CATEGORY, FMT, ...) m3log_##CATEGORY (CATEGORY, FMT "\n", ##__VA_ARGS__) +# else +# define d_m3Log(CATEGORY, FMT, ...) {} +# define m3log(CATEGORY, FMT, ...) {} +# endif + + +# if defined(ASSERTS) || (defined(DEBUG) && !defined(NASSERTS)) +# define d_m3Assert(ASS) if (!(ASS)) { printf("Assertion failed at %s:%d : %s\n", __FILE__, __LINE__, #ASS); abort(); } +# else +# define d_m3Assert(ASS) +# endif + +typedef void /*const*/ * code_t; +typedef code_t const * /*__restrict__*/ pc_t; + + +typedef struct M3MemoryHeader +{ + IM3Runtime runtime; + void * maxStack; + size_t length; +} +M3MemoryHeader; + +struct M3CodeMappingPage; + +typedef struct M3CodePageHeader +{ + struct M3CodePage * next; + + u32 lineIndex; + u32 numLines; + u32 sequence; // this is just used for debugging; could be removed + u32 usageCount; + +# if d_m3RecordBacktraces + struct M3CodeMappingPage * mapping; +# endif // d_m3RecordBacktraces +} +M3CodePageHeader; + + +#define d_m3CodePageFreeLinesThreshold 4+2 // max is: select _sss & CallIndirect + 2 for bridge + +#define d_m3MemPageSize 65536 + +#define d_m3Reg0SlotAlias 60000 +#define d_m3Fp0SlotAlias (d_m3Reg0SlotAlias + 2) + +#define d_m3MaxSaneTypesCount 100000 +#define d_m3MaxSaneFunctionsCount 100000 +#define d_m3MaxSaneImportsCount 10000 +#define d_m3MaxSaneExportsCount 10000 +#define d_m3MaxSaneGlobalsCount 100000 +#define d_m3MaxSaneElementSegments 100000 +#define d_m3MaxSaneDataSegments 100000 +#define d_m3MaxSaneTableSize 100000 +#define d_m3MaxSaneUtf8Length 10000 +#define d_m3MaxSaneFunctionArgRetCount 1000 // still insane, but whatever + +#define d_externalKind_function 0 +#define d_externalKind_table 1 +#define d_externalKind_memory 2 +#define d_externalKind_global 3 + +static const char * const c_waTypes [] = { "nil", "i32", "i64", "f32", "f64", "unknown" }; +static const char * const c_waCompactTypes [] = { "_", "i", "I", "f", "F", "?" }; + + +# if d_m3VerboseErrorMessages + +M3Result m3Error (M3Result i_result, IM3Runtime i_runtime, IM3Module i_module, IM3Function i_function, + const char * const i_file, u32 i_lineNum, const char * const i_errorMessage, ...); + +# define _m3Error(RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ...) \ + m3Error (RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ##__VA_ARGS__) + +# else +# define _m3Error(RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ...) (RESULT) +# endif + +#define ErrorRuntime(RESULT, RUNTIME, FORMAT, ...) _m3Error (RESULT, RUNTIME, NULL, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__) +#define ErrorModule(RESULT, MOD, FORMAT, ...) _m3Error (RESULT, MOD->runtime, MOD, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__) +#define ErrorCompile(RESULT, COMP, FORMAT, ...) _m3Error (RESULT, COMP->runtime, COMP->module, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__) + +#if d_m3LogNativeStack +void m3StackCheckInit (); +void m3StackCheck (); +int m3StackGetMax (); +#else +#define m3StackCheckInit() +#define m3StackCheck() +#define m3StackGetMax() 0 +#endif + +void m3_Abort (const char* message); +void * m3_Malloc (size_t i_size); +void * m3_Realloc (void *i_ptr, size_t i_newSize, size_t i_oldSize); +void m3_FreeImpl (void * i_ptr); +void * m3_CopyMem (const void * i_from, size_t i_size); + +#define m3_AllocStruct(STRUCT) (STRUCT *)m3_Malloc (sizeof (STRUCT)) +#define m3_AllocArray(STRUCT, NUM) (STRUCT *)m3_Malloc (sizeof (STRUCT) * (NUM)) +#define m3_ReallocArray(STRUCT, PTR, NEW, OLD) (STRUCT *)m3_Realloc ((void *)(PTR), sizeof (STRUCT) * (NEW), sizeof (STRUCT) * (OLD)) +#define m3_Free(P) do { m3_FreeImpl ((void*)(P)); (P) = NULL; } while(0) + +M3Result NormalizeType (u8 * o_type, i8 i_convolutedWasmType); + +bool IsIntType (u8 i_wasmType); +bool IsFpType (u8 i_wasmType); +bool Is64BitType (u8 i_m3Type); +u32 SizeOfType (u8 i_m3Type); + +M3Result Read_u64 (u64 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result Read_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end); +#if d_m3ImplementFloat +M3Result Read_f64 (f64 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result Read_f32 (f32 * o_value, bytes_t * io_bytes, cbytes_t i_end); +#endif +M3Result Read_u8 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result Read_opcode (m3opcode_t * o_value, bytes_t * io_bytes, cbytes_t i_end); + +M3Result ReadLebUnsigned (u64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLebSigned (i64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLEB_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLEB_u7 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLEB_i7 (i8 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLEB_i32 (i32 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLEB_i64 (i64 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result Read_utf8 (cstr_t * o_utf8, bytes_t * io_bytes, cbytes_t i_end); + +cstr_t SPrintValue (void * i_value, u8 i_type); +size_t SPrintArg (char * o_string, size_t i_stringBufferSize, voidptr_t i_sp, u8 i_type); + +void ReportError (IM3Runtime io_runtime, IM3Module i_module, IM3Function i_function, ccstr_t i_errorMessage, ccstr_t i_file, u32 i_lineNum); + +# if d_m3RecordBacktraces +void PushBacktraceFrame (IM3Runtime io_runtime, pc_t i_pc); +void FillBacktraceFunctionInfo (IM3Runtime io_runtime, IM3Function i_function); +void ClearBacktrace (IM3Runtime io_runtime); +# endif + +d_m3EndExternC + +#endif // m3_core_h diff --git a/wasm3-sys/wasm3/source/m3_emit.c b/wasm3-sys/wasm3/source/m3_emit.c new file mode 100644 index 0000000..4a96a75 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_emit.c @@ -0,0 +1,111 @@ +// +// m3_emit.c +// +// Created by Steven Massey on 7/9/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_env.h" +#include "m3_emit.h" +#include "m3_info.h" +#include "m3_exec.h" + +M3Result EnsureCodePageNumLines (IM3Compilation o, u32 i_numLines) +{ + M3Result result = m3Err_none; + + i_numLines += 2; // room for Bridge + + if (NumFreeLines (o->page) < i_numLines) + { + IM3CodePage page = AcquireCodePageWithCapacity (o->runtime, i_numLines); + + if (page) + { + m3log (emit, "bridging new code page from: %d %p (free slots: %d) to: %d", o->page->info.sequence, GetPC (o), NumFreeLines (o->page), page->info.sequence); + d_m3Assert (NumFreeLines (o->page) >= 2); + + EmitWord (o->page, op_Branch); + EmitWord (o->page, GetPagePC (page)); + + ReleaseCodePage (o->runtime, o->page); + + o->page = page; + } + else result = m3Err_mallocFailedCodePage; + } + + return result; +} + + +// have execution jump to a new page if slots are critically low +M3Result BridgeToNewPageIfNecessary (IM3Compilation o) +{ + return EnsureCodePageNumLines (o, d_m3CodePageFreeLinesThreshold); +} + + +M3Result EmitOp (IM3Compilation o, IM3Operation i_operation) +{ + M3Result result = m3Err_none; d_m3Assert (i_operation or IsStackPolymorphic (o)); + + // it's OK for page to be null; when compile-walking the bytecode without emitting + if (o->page) + { +# if d_m3EnableOpTracing + if (i_operation != op_DumpStack) + o->numEmits++; +# endif + + result = BridgeToNewPageIfNecessary (o); + + if (not result) + { if (d_m3LogEmit) log_emit (o, i_operation); +# if d_m3RecordBacktraces + EmitMappingEntry (o->page, o->lastOpcodeStart - o->module->wasmStart); +# endif // d_m3RecordBacktraces + EmitWord (o->page, i_operation); + } + } + + return result; +} + + +// Push an immediate constant into the M3 codestream +void EmitConstant32 (IM3Compilation o, const u32 i_immediate) +{ + if (o->page) + EmitWord32 (o->page, i_immediate); +} + +void EmitSlotOffset (IM3Compilation o, const i32 i_offset) +{ + if (o->page) + EmitWord32 (o->page, i_offset); +} + + +pc_t EmitPointer (IM3Compilation o, const void * const i_pointer) +{ + pc_t ptr = GetPagePC (o->page); + + if (o->page) + EmitWord (o->page, i_pointer); + + return ptr; +} + +void * ReservePointer (IM3Compilation o) +{ + pc_t ptr = GetPagePC (o->page); + EmitPointer (o, NULL); + return (void *) ptr; +} + + +pc_t GetPC (IM3Compilation o) +{ + return GetPagePC (o->page); +} diff --git a/wasm3-sys/wasm3/source/m3_emit.h b/wasm3-sys/wasm3/source/m3_emit.h new file mode 100644 index 0000000..8b3711f --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_emit.h @@ -0,0 +1,28 @@ +// +// m3_emit.h +// +// Created by Steven Massey on 7/9/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_emit_h +#define m3_emit_h + +#include "m3_compile.h" + +d_m3BeginExternC + +M3Result BridgeToNewPageIfNecessary (IM3Compilation o); +M3Result EnsureCodePageNumLines (IM3Compilation o, u32 i_numLines); + +M3Result EmitOp (IM3Compilation o, IM3Operation i_operation); +void EmitConstant32 (IM3Compilation o, const u32 i_immediate); +void EmitSlotOffset (IM3Compilation o, const i32 i_offset); +pc_t EmitPointer (IM3Compilation o, const void * const i_pointer); +void * ReservePointer (IM3Compilation o); + +pc_t GetPC (IM3Compilation o); + +d_m3EndExternC + +#endif // m3_emit_h diff --git a/wasm3-sys/wasm3/source/m3_env.c b/wasm3-sys/wasm3/source/m3_env.c new file mode 100644 index 0000000..3a159fd --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_env.c @@ -0,0 +1,1145 @@ +// +// m3_env.c +// +// Created by Steven Massey on 4/19/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include +#include + +#include "m3_env.h" +#include "m3_compile.h" +#include "m3_exec.h" +#include "m3_exception.h" +#include "m3_info.h" + + +IM3Environment m3_NewEnvironment () +{ + M3Result result = m3Err_none; + + IM3Environment env = m3_AllocStruct (M3Environment); + + if (env) + { + _try + { + // create FuncTypes for all simple block return ValueTypes + for (u8 t = c_m3Type_none; t <= c_m3Type_f64; t++) + { + IM3FuncType ftype; +_ (AllocFuncType (& ftype, 1)); + + ftype->numArgs = 0; + ftype->numRets = (t == c_m3Type_none) ? 0 : 1; + ftype->types [0] = t; + + Environment_AddFuncType (env, & ftype); + + d_m3Assert (t < 5); + env->retFuncTypes [t] = ftype; + } + } + + _catch: + if (result) + { + m3_FreeEnvironment (env); + env = NULL; + } + } + + return env; +} + + +void Environment_Release (IM3Environment i_environment) +{ + IM3FuncType ftype = i_environment->funcTypes; + + while (ftype) + { + IM3FuncType next = ftype->next; + m3_Free (ftype); + ftype = next; + } + + m3log (runtime, "freeing %d pages from environment", CountCodePages (i_environment->pagesReleased)); + FreeCodePages (& i_environment->pagesReleased); +} + + +void m3_FreeEnvironment (IM3Environment i_environment) +{ + if (i_environment) + { + Environment_Release (i_environment); + m3_Free (i_environment); + } +} + + +// returns the same io_funcType or replaces it with an equivalent that's already in the type linked list +void Environment_AddFuncType (IM3Environment i_environment, IM3FuncType * io_funcType) +{ + IM3FuncType addType = * io_funcType; + IM3FuncType newType = i_environment->funcTypes; + + while (newType) + { + if (AreFuncTypesEqual (newType, addType)) + { + m3_Free (addType); + break; + } + + newType = newType->next; + } + + if (newType == NULL) + { + newType = addType; + newType->next = i_environment->funcTypes; + i_environment->funcTypes = newType; + } + + * io_funcType = newType; +} + + +IM3CodePage RemoveCodePageOfCapacity (M3CodePage ** io_list, u32 i_minimumLineCount) +{ + IM3CodePage prev = NULL; + IM3CodePage page = * io_list; + + while (page) + { + if (NumFreeLines (page) >= i_minimumLineCount) + { d_m3Assert (page->info.usageCount == 0); + IM3CodePage next = page->info.next; + if (prev) + prev->info.next = next; // mid-list + else + * io_list = next; // front of list + + break; + } + + prev = page; + page = page->info.next; + } + + return page; +} + + +IM3CodePage Environment_AcquireCodePage (IM3Environment i_environment, u32 i_minimumLineCount) +{ + return RemoveCodePageOfCapacity (& i_environment->pagesReleased, i_minimumLineCount); +} + + +void Environment_ReleaseCodePages (IM3Environment i_environment, IM3CodePage i_codePageList) +{ + IM3CodePage end = i_codePageList; + + while (end) + { + end->info.lineIndex = 0; // reset page +#if d_m3RecordBacktraces + end->info.mapping->size = 0; +#endif // d_m3RecordBacktraces + + IM3CodePage next = end->info.next; + if (not next) + break; + + end = next; + } + + if (end) + { + // push list to front + end->info.next = i_environment->pagesReleased; + i_environment->pagesReleased = i_codePageList; + } +} + + +IM3Runtime m3_NewRuntime (IM3Environment i_environment, u32 i_stackSizeInBytes, void * i_userdata) +{ + IM3Runtime runtime = m3_AllocStruct (M3Runtime); + + if (runtime) + { + m3_ResetErrorInfo(runtime); + + runtime->environment = i_environment; + runtime->userdata = i_userdata; + + runtime->stack = m3_Malloc (i_stackSizeInBytes + 4*sizeof (m3slot_t)); // TODO: more precise stack checks + + if (runtime->stack) + { + runtime->numStackSlots = i_stackSizeInBytes / sizeof (m3slot_t); m3log (runtime, "new stack: %p", runtime->stack); + } + else m3_Free (runtime); + } + + return runtime; +} + +void * m3_GetUserData (IM3Runtime i_runtime) +{ + return i_runtime ? i_runtime->userdata : NULL; +} + + +void * ForEachModule (IM3Runtime i_runtime, ModuleVisitor i_visitor, void * i_info) +{ + void * r = NULL; + + IM3Module module = i_runtime->modules; + + while (module) + { + IM3Module next = module->next; + r = i_visitor (module, i_info); + if (r) + break; + + module = next; + } + + return r; +} + + +void * _FreeModule (IM3Module i_module, void * i_info) +{ + m3_FreeModule (i_module); + return NULL; +} + + +void Runtime_Release (IM3Runtime i_runtime) +{ + ForEachModule (i_runtime, _FreeModule, NULL); d_m3Assert (i_runtime->numActiveCodePages == 0); + + Environment_ReleaseCodePages (i_runtime->environment, i_runtime->pagesOpen); + Environment_ReleaseCodePages (i_runtime->environment, i_runtime->pagesFull); + + m3_Free (i_runtime->stack); + m3_Free (i_runtime->memory.mallocated); +} + + +void m3_FreeRuntime (IM3Runtime i_runtime) +{ + if (i_runtime) + { + m3_PrintProfilerInfo (); + + Runtime_Release (i_runtime); + m3_Free (i_runtime); + } +} + +M3Result EvaluateExpression (IM3Module i_module, void * o_expressed, u8 i_type, bytes_t * io_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + // OPTZ: use a simplified interpreter for expressions + + // create a temporary runtime context +#if defined(d_m3PreferStaticAlloc) + static M3Runtime runtime; +#else + M3Runtime runtime; +#endif + M3_INIT (runtime); + + runtime.environment = i_module->runtime->environment; + runtime.numStackSlots = i_module->runtime->numStackSlots; + runtime.stack = i_module->runtime->stack; + + m3stack_t stack = (m3stack_t)runtime.stack; + + IM3Runtime savedRuntime = i_module->runtime; + i_module->runtime = & runtime; + + IM3Compilation o = & runtime.compilation; + o->runtime = & runtime; + o->module = i_module; + o->wasm = * io_bytes; + o->wasmEnd = i_end; + o->lastOpcodeStart = o->wasm; + + o->block.depth = -1; // so that root compilation depth = 0 + + // OPTZ: this code page could be erased after use. maybe have 'empty' list in addition to full and open? + o->page = AcquireCodePage (& runtime); // AcquireUnusedCodePage (...) + + if (o->page) + { + IM3FuncType ftype = runtime.environment->retFuncTypes[i_type]; + + pc_t m3code = GetPagePC (o->page); + result = CompileBlock (o, ftype, c_waOp_block); + + if (not result && o->maxStackSlots >= runtime.numStackSlots) { + result = m3Err_trapStackOverflow; + } + + if (not result) + { + m3ret_t r = Call (m3code, stack, NULL, d_m3OpDefaultArgs); + + if (r == 0) + { m3log (runtime, "expression result: %s", SPrintValue (stack, i_type)); + if (SizeOfType (i_type) == sizeof (u32)) + { + * (u32 *) o_expressed = * ((u32 *) stack); + } + else + { + * (u64 *) o_expressed = * ((u64 *) stack); + } + } + } + + // TODO: EraseCodePage (...) see OPTZ above + ReleaseCodePage (& runtime, o->page); + } + else result = m3Err_mallocFailedCodePage; + + runtime.stack = NULL; // prevent free(stack) in ReleaseRuntime + Runtime_Release (& runtime); + i_module->runtime = savedRuntime; + + * io_bytes = o->wasm; + + return result; +} + + +M3Result InitMemory (IM3Runtime io_runtime, IM3Module i_module) +{ + M3Result result = m3Err_none; //d_m3Assert (not io_runtime->memory.wasmPages); + + if (not i_module->memoryImported) + { + u32 maxPages = i_module->memoryInfo.maxPages; + io_runtime->memory.maxPages = maxPages ? maxPages : 65536; + + result = ResizeMemory (io_runtime, i_module->memoryInfo.initPages); + } + + return result; +} + + +M3Result ResizeMemory (IM3Runtime io_runtime, u32 i_numPages) +{ + M3Result result = m3Err_none; + + u32 numPagesToAlloc = i_numPages; + + M3Memory * memory = & io_runtime->memory; + +#if 0 // Temporary fix for memory allocation + if (memory->mallocated) { + memory->numPages = i_numPages; + memory->mallocated->end = memory->wasmPages + (memory->numPages * c_m3MemPageSize); + return result; + } + + i_numPagesToAlloc = 256; +#endif + + if (numPagesToAlloc <= memory->maxPages) + { + size_t numPageBytes = numPagesToAlloc * d_m3MemPageSize; + +#if d_m3MaxLinearMemoryPages > 0 + _throwif("linear memory limitation exceeded", numPagesToAlloc > d_m3MaxLinearMemoryPages); +#endif + + // Limit the amount of memory that gets actually allocated + if (io_runtime->memoryLimit) { + numPageBytes = M3_MIN (numPageBytes, io_runtime->memoryLimit); + } + + size_t numBytes = numPageBytes + sizeof (M3MemoryHeader); + + size_t numPreviousBytes = memory->numPages * d_m3MemPageSize; + if (numPreviousBytes) + numPreviousBytes += sizeof (M3MemoryHeader); + + void* newMem = m3_Realloc (memory->mallocated, numBytes, numPreviousBytes); + _throwifnull(newMem); + + memory->mallocated = (M3MemoryHeader*)newMem; + +# if d_m3LogRuntime + M3MemoryHeader * oldMallocated = memory->mallocated; +# endif + + memory->numPages = numPagesToAlloc; + + memory->mallocated->length = numPageBytes; + memory->mallocated->runtime = io_runtime; + + memory->mallocated->maxStack = (m3slot_t *) io_runtime->stack + io_runtime->numStackSlots; + + m3log (runtime, "resized old: %p; mem: %p; length: %zu; pages: %d", oldMallocated, memory->mallocated, memory->mallocated->length, memory->numPages); + } + else result = m3Err_wasmMemoryOverflow; + + _catch: return result; +} + + +M3Result InitGlobals (IM3Module io_module) +{ + M3Result result = m3Err_none; + + if (io_module->numGlobals) + { + // placing the globals in their structs isn't good for cache locality, but i don't really know what the global + // access patterns typcially look like yet. + + // io_module->globalMemory = m3Alloc (m3reg_t, io_module->numGlobals); + + // if (io_module->globalMemory) + { + for (u32 i = 0; i < io_module->numGlobals; ++i) + { + M3Global * g = & io_module->globals [i]; m3log (runtime, "initializing global: %d", i); + + if (g->initExpr) + { + bytes_t start = g->initExpr; + result = EvaluateExpression (io_module, & g->intValue, g->type, & start, g->initExpr + g->initExprSize); + + if (not result) + { + // io_module->globalMemory [i] = initValue; + } + else break; + } + else + { m3log (runtime, "importing global"); + + } + } + } + // else result = ErrorModule (m3Err_mallocFailed, io_module, "could allocate globals for module: '%s", io_module->name); + } + + return result; +} + + +M3Result InitDataSegments (M3Memory * io_memory, IM3Module io_module) +{ + M3Result result = m3Err_none; + + _throwif ("unallocated linear memory", !(io_memory->mallocated)); + + for (u32 i = 0; i < io_module->numDataSegments; ++i) + { + M3DataSegment * segment = & io_module->dataSegments [i]; + + i32 segmentOffset; + bytes_t start = segment->initExpr; +_ (EvaluateExpression (io_module, & segmentOffset, c_m3Type_i32, & start, segment->initExpr + segment->initExprSize)); + + m3log (runtime, "loading data segment: %d; size: %d; offset: %d", i, segment->size, segmentOffset); + + if (segmentOffset >= 0 && (size_t)(segmentOffset) + segment->size <= io_memory->mallocated->length) + { + u8 * dest = m3MemData (io_memory->mallocated) + segmentOffset; + memcpy (dest, segment->data, segment->size); + } else { + _throw ("data segment out of bounds"); + } + } + + _catch: return result; +} + + +M3Result InitElements (IM3Module io_module) +{ + M3Result result = m3Err_none; + + bytes_t bytes = io_module->elementSection; + cbytes_t end = io_module->elementSectionEnd; + + for (u32 i = 0; i < io_module->numElementSegments; ++i) + { + u32 index; +_ (ReadLEB_u32 (& index, & bytes, end)); + + if (index == 0) + { + i32 offset; +_ (EvaluateExpression (io_module, & offset, c_m3Type_i32, & bytes, end)); + _throwif ("table underflow", offset < 0); + + u32 numElements; +_ (ReadLEB_u32 (& numElements, & bytes, end)); + + size_t endElement = (size_t) numElements + offset; + _throwif ("table overflow", endElement > d_m3MaxSaneTableSize); + + // is there any requirement that elements must be in increasing sequence? + // make sure the table isn't shrunk. + if (endElement > io_module->table0Size) + { + io_module->table0 = m3_ReallocArray (IM3Function, io_module->table0, endElement, io_module->table0Size); + io_module->table0Size = (u32) endElement; + } + _throwifnull(io_module->table0); + + for (u32 e = 0; e < numElements; ++e) + { + u32 functionIndex; +_ (ReadLEB_u32 (& functionIndex, & bytes, end)); + _throwif ("function index out of range", functionIndex >= io_module->numFunctions); + IM3Function function = & io_module->functions [functionIndex]; d_m3Assert (function); //printf ("table: %s\n", m3_GetFunctionName(function)); + io_module->table0 [e + offset] = function; + } + } + else _throw ("element table index must be zero for MVP"); + } + + _catch: return result; +} + +M3Result m3_CompileModule (IM3Module io_module) +{ + M3Result result = m3Err_none; + + for (u32 i = 0; i < io_module->numFunctions; ++i) + { + IM3Function f = & io_module->functions [i]; + if (f->wasm and not f->compiled) + { +_ (CompileFunction (f)); + } + } + + _catch: return result; +} + +M3Result m3_RunStart (IM3Module io_module) +{ +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + // Execution disabled for fuzzing builds + return m3Err_none; +#endif + + M3Result result = m3Err_none; + + if (io_module and io_module->startFunction >= 0) + { + IM3Function function = & io_module->functions [io_module->startFunction]; + + if (not function->compiled) + { +_ (CompileFunction (function)); + } + + IM3FuncType ftype = function->funcType; + if (ftype->numArgs != 0 || ftype->numRets != 0) + _throw (m3Err_argumentCountMismatch); + + IM3Module module = function->module; + IM3Runtime runtime = module->runtime; + +_ ((M3Result) Call (function->compiled, (m3stack_t) runtime->stack, runtime->memory.mallocated, d_m3OpDefaultArgs)); + + io_module->startFunction = -1; + } + + _catch: return result; +} + +// TODO: deal with main + side-modules loading efforcement +M3Result m3_LoadModule (IM3Runtime io_runtime, IM3Module io_module) +{ + M3Result result = m3Err_none; + + if (UNLIKELY(io_module->runtime)) { + return m3Err_moduleAlreadyLinked; + } + + io_module->runtime = io_runtime; + M3Memory * memory = & io_runtime->memory; + +_ (InitMemory (io_runtime, io_module)); +_ (InitGlobals (io_module)); +_ (InitDataSegments (memory, io_module)); +_ (InitElements (io_module)); + + // Start func might use imported functions, which are not liked here yet, + // so it will be called before a function call is attempted (in m3_FindFunction) + +#ifdef DEBUG + Module_GenerateNames(io_module); +#endif + + io_module->next = io_runtime->modules; + io_runtime->modules = io_module; + return result; // ok + +_catch: + io_module->runtime = NULL; + return result; +} + +IM3Global m3_FindGlobal (IM3Module io_module, + const char * const i_globalName) +{ + // Search exports + for (u32 i = 0; i < io_module->numGlobals; ++i) + { + IM3Global g = & io_module->globals [i]; + if (g->name and strcmp (g->name, i_globalName) == 0) + { + return g; + } + } + + // Search imports + for (u32 i = 0; i < io_module->numGlobals; ++i) + { + IM3Global g = & io_module->globals [i]; + + if (g->import.moduleUtf8 and g->import.fieldUtf8) + { + if (strcmp (g->import.fieldUtf8, i_globalName) == 0) + { + return g; + } + } + } + return NULL; +} + +M3Result m3_GetGlobal (IM3Global i_global, + IM3TaggedValue o_value) +{ + if (not i_global) return m3Err_globalLookupFailed; + + switch (i_global->type) { + case c_m3Type_i32: o_value->value.i32 = i_global->intValue; break; + case c_m3Type_i64: o_value->value.i64 = i_global->intValue; break; +# if d_m3HasFloat + case c_m3Type_f32: o_value->value.f32 = i_global->f32Value; break; + case c_m3Type_f64: o_value->value.f64 = i_global->f64Value; break; +# endif + default: return m3Err_invalidTypeId; + } + + o_value->type = (M3ValueType)(i_global->type); + return m3Err_none; +} + +M3Result m3_SetGlobal (IM3Global i_global, + const IM3TaggedValue i_value) +{ + if (not i_global) return m3Err_globalLookupFailed; + // TODO: if (not g->isMutable) return m3Err_globalNotMutable; + + if (i_global->type != i_value->type) return m3Err_globalTypeMismatch; + + switch (i_value->type) { + case c_m3Type_i32: i_global->intValue = i_value->value.i32; break; + case c_m3Type_i64: i_global->intValue = i_value->value.i64; break; +# if d_m3HasFloat + case c_m3Type_f32: i_global->f32Value = i_value->value.f32; break; + case c_m3Type_f64: i_global->f64Value = i_value->value.f64; break; +# endif + default: return m3Err_invalidTypeId; + } + + return m3Err_none; +} + +M3ValueType m3_GetGlobalType (IM3Global i_global) +{ + return (i_global) ? (M3ValueType)(i_global->type) : c_m3Type_none; +} + + +void * v_FindFunction (IM3Module i_module, const char * const i_name) +{ + for (u32 i = 0; i < i_module->numFunctions; ++i) + { + IM3Function f = & i_module->functions [i]; + + bool isImported = f->import.moduleUtf8 or f->import.fieldUtf8; + + if (isImported) + continue; + + for (int j = 0; j < f->numNames; j++) + { + if (f->names [j] and strcmp (f->names [j], i_name) == 0) + return f; + } + } + + return NULL; +} + + +M3Result m3_FindFunction (IM3Function * o_function, IM3Runtime i_runtime, const char * const i_functionName) +{ + M3Result result = m3Err_none; d_m3Assert (o_function and i_runtime and i_functionName); + + IM3Function function = NULL; + + if (not i_runtime->modules) { + _throw ("no modules loaded"); + } + + function = (IM3Function) ForEachModule (i_runtime, (ModuleVisitor) v_FindFunction, (void *) i_functionName); + + if (function) + { + if (not function->compiled) + { +_ (CompileFunction (function)) + } + + // Check if start function needs to be called + if (function->module->startFunction) + { +_ (m3_RunStart (function->module)) + } + } + else _throw (ErrorModule (m3Err_functionLookupFailed, i_runtime->modules, "'%s'", i_functionName)); + + _catch: + if (result) + function = NULL; + + * o_function = function; + + return result; +} + + +uint32_t m3_GetArgCount (IM3Function i_function) +{ + if (i_function) { + IM3FuncType ft = i_function->funcType; + if (ft) { + return ft->numArgs; + } + } + return 0; +} + +uint32_t m3_GetRetCount (IM3Function i_function) +{ + if (i_function) { + IM3FuncType ft = i_function->funcType; + if (ft) { + return ft->numRets; + } + } + return 0; +} + + +M3ValueType m3_GetArgType (IM3Function i_function, uint32_t index) +{ + if (i_function) { + IM3FuncType ft = i_function->funcType; + if (ft and index < ft->numArgs) { + return (M3ValueType)d_FuncArgType(ft, index); + } + } + return c_m3Type_none; +} + +M3ValueType m3_GetRetType (IM3Function i_function, uint32_t index) +{ + if (i_function) { + IM3FuncType ft = i_function->funcType; + if (ft and index < ft->numRets) { + return (M3ValueType) d_FuncRetType (ft, index); + } + } + return c_m3Type_none; +} + + +u8 * GetStackPointerForArgs (IM3Function i_function) +{ + u64 * stack = (u64 *) i_function->module->runtime->stack; + IM3FuncType ftype = i_function->funcType; + + stack += ftype->numRets; + + return (u8 *) stack; +} + + +M3Result m3_CallV (IM3Function i_function, ...) +{ + va_list ap; + va_start(ap, i_function); + M3Result r = m3_CallVL(i_function, ap); + va_end(ap); + return r; +} + +static +void ReportNativeStackUsage () +{ +# if d_m3LogNativeStack + int stackUsed = m3StackGetMax(); + fprintf (stderr, "Native stack used: %d\n", stackUsed); +# endif +} + + +M3Result m3_CallVL (IM3Function i_function, va_list i_args) +{ + IM3Runtime runtime = i_function->module->runtime; + IM3FuncType ftype = i_function->funcType; + + if (!i_function->compiled) { + return m3Err_missingCompiledCode; + } + +# if d_m3RecordBacktraces + ClearBacktrace (runtime); +# endif + + u8* s = GetStackPointerForArgs (i_function); + + for (u32 i = 0; i < ftype->numArgs; ++i) + { + switch (d_FuncArgType(ftype, i)) { + case c_m3Type_i32: *(i32*)(s) = va_arg(i_args, i32); s += 8; break; + case c_m3Type_i64: *(i64*)(s) = va_arg(i_args, i64); s += 8; break; +# if d_m3HasFloat + case c_m3Type_f32: *(f32*)(s) = va_arg(i_args, f64); s += 8; break; // f32 is passed as f64 + case c_m3Type_f64: *(f64*)(s) = va_arg(i_args, f64); s += 8; break; +# endif + default: return "unknown argument type"; + } + } + m3StackCheckInit(); + M3Result r = (M3Result) Call (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); + ReportNativeStackUsage (); + + runtime->lastCalled = r ? NULL : i_function; + + return r; +} + +M3Result m3_Call (IM3Function i_function, uint32_t i_argc, const void * i_argptrs[]) +{ + IM3Runtime runtime = i_function->module->runtime; + IM3FuncType ftype = i_function->funcType; + + if (i_argc != ftype->numArgs) { + return m3Err_argumentCountMismatch; + } + if (!i_function->compiled) { + return m3Err_missingCompiledCode; + } + +# if d_m3RecordBacktraces + ClearBacktrace (runtime); +# endif + + u8* s = GetStackPointerForArgs (i_function); + + for (u32 i = 0; i < ftype->numArgs; ++i) + { + switch (d_FuncArgType(ftype, i)) { + case c_m3Type_i32: *(i32*)(s) = *(i32*)i_argptrs[i]; s += 8; break; + case c_m3Type_i64: *(i64*)(s) = *(i64*)i_argptrs[i]; s += 8; break; +# if d_m3HasFloat + case c_m3Type_f32: *(f32*)(s) = *(f32*)i_argptrs[i]; s += 8; break; + case c_m3Type_f64: *(f64*)(s) = *(f64*)i_argptrs[i]; s += 8; break; +# endif + default: return "unknown argument type"; + } + } + + m3StackCheckInit(); + M3Result r = (M3Result) Call (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); + ReportNativeStackUsage (); + + runtime->lastCalled = r ? NULL : i_function; + + + return r; +} + +M3Result m3_CallArgv (IM3Function i_function, uint32_t i_argc, const char * i_argv[]) +{ + IM3FuncType ftype = i_function->funcType; + IM3Runtime runtime = i_function->module->runtime; + + if (i_argc != ftype->numArgs) { + return m3Err_argumentCountMismatch; + } + if (!i_function->compiled) { + return m3Err_missingCompiledCode; + } + +# if d_m3RecordBacktraces + ClearBacktrace (runtime); +# endif + + u8* s = GetStackPointerForArgs (i_function); + + for (u32 i = 0; i < ftype->numArgs; ++i) + { + switch (d_FuncArgType(ftype, i)) { + case c_m3Type_i32: *(i32*)(s) = strtoul(i_argv[i], NULL, 10); s += 8; break; + case c_m3Type_i64: *(i64*)(s) = strtoull(i_argv[i], NULL, 10); s += 8; break; +# if d_m3HasFloat + case c_m3Type_f32: *(f32*)(s) = strtod(i_argv[i], NULL); s += 8; break; // strtof would be less portable + case c_m3Type_f64: *(f64*)(s) = strtod(i_argv[i], NULL); s += 8; break; +# endif + default: return "unknown argument type"; + } + } + + m3StackCheckInit(); + M3Result r = (M3Result) Call (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); + ReportNativeStackUsage (); + + runtime->lastCalled = r ? NULL : i_function; + + return r; +} + + +//u8 * AlignStackPointerTo64Bits (const u8 * i_stack) +//{ +// uintptr_t ptr = (uintptr_t) i_stack; +// return (u8 *) ((ptr + 7) & ~7); +//} + + +M3Result m3_GetResults (IM3Function i_function, uint32_t i_retc, const void * o_retptrs[]) +{ + IM3FuncType ftype = i_function->funcType; + IM3Runtime runtime = i_function->module->runtime; + + if (i_retc != ftype->numRets) { + return m3Err_argumentCountMismatch; + } + if (i_function != runtime->lastCalled) { + return "function not called"; + } + + u8* s = (u8*) runtime->stack; + + for (u32 i = 0; i < ftype->numRets; ++i) + { + switch (d_FuncRetType(ftype, i)) { + case c_m3Type_i32: *(i32*)o_retptrs[i] = *(i32*)(s); s += 8; break; + case c_m3Type_i64: *(i64*)o_retptrs[i] = *(i64*)(s); s += 8; break; +# if d_m3HasFloat + case c_m3Type_f32: *(f32*)o_retptrs[i] = *(f32*)(s); s += 8; break; + case c_m3Type_f64: *(f64*)o_retptrs[i] = *(f64*)(s); s += 8; break; +# endif + default: return "unknown return type"; + } + } + return m3Err_none; +} + +M3Result m3_GetResultsV (IM3Function i_function, ...) +{ + va_list ap; + va_start(ap, i_function); + M3Result r = m3_GetResultsVL(i_function, ap); + va_end(ap); + return r; +} + +M3Result m3_GetResultsVL (IM3Function i_function, va_list o_rets) +{ + IM3Runtime runtime = i_function->module->runtime; + IM3FuncType ftype = i_function->funcType; + + if (i_function != runtime->lastCalled) { + return "function not called"; + } + + u8* s = (u8*) runtime->stack; + for (u32 i = 0; i < ftype->numRets; ++i) + { + switch (d_FuncRetType(ftype, i)) { + case c_m3Type_i32: *va_arg(o_rets, i32*) = *(i32*)(s); s += 8; break; + case c_m3Type_i64: *va_arg(o_rets, i64*) = *(i64*)(s); s += 8; break; +# if d_m3HasFloat + case c_m3Type_f32: *va_arg(o_rets, f32*) = *(f32*)(s); s += 8; break; + case c_m3Type_f64: *va_arg(o_rets, f64*) = *(f64*)(s); s += 8; break; +# endif + default: return "unknown argument type"; + } + } + return m3Err_none; +} + +void ReleaseCodePageNoTrack (IM3Runtime i_runtime, IM3CodePage i_codePage) +{ + if (i_codePage) + { + IM3CodePage * list; + + bool pageFull = (NumFreeLines (i_codePage) < d_m3CodePageFreeLinesThreshold); + if (pageFull) + list = & i_runtime->pagesFull; + else + list = & i_runtime->pagesOpen; + + PushCodePage (list, i_codePage); m3log (emit, "release page: %d to queue: '%s'", i_codePage->info.sequence, pageFull ? "full" : "open") + } +} + + +IM3CodePage AcquireCodePageWithCapacity (IM3Runtime i_runtime, u32 i_minLineCount) +{ + IM3CodePage page = RemoveCodePageOfCapacity (& i_runtime->pagesOpen, i_minLineCount); + + if (not page) + { + page = Environment_AcquireCodePage (i_runtime->environment, i_minLineCount); + + if (not page) + page = NewCodePage (i_minLineCount); + + if (page) + i_runtime->numCodePages++; + } + + if (page) + { m3log (emit, "acquire page: %d", page->info.sequence); + i_runtime->numActiveCodePages++; + } + + return page; +} + + +IM3CodePage AcquireCodePage (IM3Runtime i_runtime) +{ + return AcquireCodePageWithCapacity (i_runtime, d_m3CodePageFreeLinesThreshold); +} + + +void ReleaseCodePage (IM3Runtime i_runtime, IM3CodePage i_codePage) +{ + if (i_codePage) + { + ReleaseCodePageNoTrack (i_runtime, i_codePage); + i_runtime->numActiveCodePages--; + +# if defined (DEBUG) + u32 numOpen = CountCodePages (i_runtime->pagesOpen); + u32 numFull = CountCodePages (i_runtime->pagesFull); + + m3log (runtime, "runtime: %p; open-pages: %d; full-pages: %d; active: %d; total: %d", i_runtime, numOpen, numFull, i_runtime->numActiveCodePages, i_runtime->numCodePages); + + d_m3Assert (numOpen + numFull + i_runtime->numActiveCodePages == i_runtime->numCodePages); + +# if d_m3LogCodePages + dump_code_page (i_codePage, /* startPC: */ NULL); +# endif +# endif + } +} + + +#if d_m3VerboseErrorMessages +M3Result m3Error (M3Result i_result, IM3Runtime i_runtime, IM3Module i_module, IM3Function i_function, + const char * const i_file, u32 i_lineNum, const char * const i_errorMessage, ...) +{ + if (i_runtime) + { + i_runtime->error = (M3ErrorInfo){ .result = i_result, .runtime = i_runtime, .module = i_module, + .function = i_function, .file = i_file, .line = i_lineNum }; + i_runtime->error.message = i_runtime->error_message; + + va_list args; + va_start (args, i_errorMessage); + vsnprintf (i_runtime->error_message, sizeof(i_runtime->error_message), i_errorMessage, args); + va_end (args); + } + + return i_result; +} +#endif + + +void m3_GetErrorInfo (IM3Runtime i_runtime, M3ErrorInfo* o_info) +{ + if (i_runtime) + { + *o_info = i_runtime->error; + m3_ResetErrorInfo (i_runtime); + } +} + + +void m3_ResetErrorInfo (IM3Runtime i_runtime) +{ + if (i_runtime) + { + M3_INIT(i_runtime->error); + i_runtime->error.message = ""; + } +} + +uint8_t * m3_GetMemory (IM3Runtime i_runtime, uint32_t * o_memorySizeInBytes, uint32_t i_memoryIndex) +{ + uint8_t * memory = NULL; d_m3Assert (i_memoryIndex == 0); + + if (i_runtime) + { + u32 size = (u32) i_runtime->memory.mallocated->length; + + if (o_memorySizeInBytes) + * o_memorySizeInBytes = size; + + if (size) + memory = m3MemData (i_runtime->memory.mallocated); + } + + return memory; +} + + +uint32_t m3_GetMemorySize (IM3Runtime i_runtime) +{ + return i_runtime->memory.mallocated->length; +} + + +M3BacktraceInfo * m3_GetBacktrace (IM3Runtime i_runtime) +{ +# if d_m3RecordBacktraces + return & i_runtime->backtrace; +# else + return NULL; +# endif +} + diff --git a/wasm3-sys/wasm3/source/m3_env.h b/wasm3-sys/wasm3/source/m3_env.h new file mode 100644 index 0000000..15e8bde --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_env.h @@ -0,0 +1,206 @@ +// +// m3_env.h +// +// Created by Steven Massey on 4/19/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_env_h +#define m3_env_h + +#include "wasm3.h" +#include "m3_code.h" +#include "m3_compile.h" + +d_m3BeginExternC + + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3MemoryInfo +{ + u32 initPages; + u32 maxPages; +} +M3MemoryInfo; + + +typedef struct M3Memory +{ + M3MemoryHeader * mallocated; + + u32 numPages; + u32 maxPages; +} +M3Memory; + +typedef M3Memory * IM3Memory; + + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3DataSegment +{ + const u8 * initExpr; // wasm code + const u8 * data; + + u32 initExprSize; + u32 memoryRegion; + u32 size; +} +M3DataSegment; + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3Global +{ + M3ImportInfo import; + + union + { + i64 intValue; +#if d_m3HasFloat + f64 f64Value; + f32 f32Value; +#endif + }; + + cstr_t name; + bytes_t initExpr; // wasm code + u32 initExprSize; + u8 type; + bool imported; + bool isMutable; +} +M3Global; + + +//--------------------------------------------------------------------------------------------------------------------------------- +typedef struct M3Module +{ + struct M3Runtime * runtime; + struct M3Environment * environment; + + bytes_t wasmStart; + bytes_t wasmEnd; + + cstr_t name; + + u32 numFuncTypes; + IM3FuncType * funcTypes; // array of pointers to list of FuncTypes + + u32 numFuncImports; + u32 numFunctions; + M3Function * functions; + + i32 startFunction; + + u32 numDataSegments; + M3DataSegment * dataSegments; + + //u32 importedGlobals; + u32 numGlobals; + M3Global * globals; + + u32 numElementSegments; + bytes_t elementSection; + bytes_t elementSectionEnd; + + IM3Function * table0; + u32 table0Size; + + M3MemoryInfo memoryInfo; + bool memoryImported; + + //bool hasWasmCodeCopy; + + struct M3Module * next; +} +M3Module; + +M3Result Module_AddGlobal (IM3Module io_module, IM3Global * o_global, u8 i_type, bool i_mutable, bool i_isImported); + +M3Result Module_AddFunction (IM3Module io_module, u32 i_typeIndex, IM3ImportInfo i_importInfo /* can be null */); +IM3Function Module_GetFunction (IM3Module i_module, u32 i_functionIndex); + +void Module_GenerateNames (IM3Module i_module); + +void FreeImportInfo (M3ImportInfo * i_info); + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3Environment +{ +// struct M3Runtime * runtimes; + + IM3FuncType funcTypes; // linked list of unique M3FuncType structs that can be compared using pointer-equivalence + + IM3FuncType retFuncTypes [c_m3Type_unknown]; // these 'point' to elements in the linked list above. + // the number of elements must match the basic types as per M3ValueType + M3CodePage * pagesReleased; +} +M3Environment; + +void Environment_Release (IM3Environment i_environment); + +// takes ownership of io_funcType and returns a pointer to the persistent version (could be same or different) +void Environment_AddFuncType (IM3Environment i_environment, IM3FuncType * io_funcType); + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3Runtime +{ + M3Compilation compilation; + + IM3Environment environment; + + M3CodePage * pagesOpen; // linked list of code pages with writable space on them + M3CodePage * pagesFull; // linked list of at-capacity pages + + u32 numCodePages; + u32 numActiveCodePages; + + IM3Module modules; // linked list of imported modules + + void * stack; + u32 stackSize; + u32 numStackSlots; + IM3Function lastCalled; // last function that successfully executed + + void * userdata; + + M3Memory memory; + u32 memoryLimit; + +#if d_m3EnableStrace >= 2 + u32 callDepth; +#endif + + M3ErrorInfo error; +#if d_m3VerboseErrorMessages + char error_message[256]; // the actual buffer. M3ErrorInfo can point to this +#endif + +#if d_m3RecordBacktraces + M3BacktraceInfo backtrace; +#endif +} +M3Runtime; + +void InitRuntime (IM3Runtime io_runtime, u32 i_stackSizeInBytes); +void Runtime_Release (IM3Runtime io_runtime); + +M3Result ResizeMemory (IM3Runtime io_runtime, u32 i_numPages); + +typedef void * (* ModuleVisitor) (IM3Module i_module, void * i_info); +void * ForEachModule (IM3Runtime i_runtime, ModuleVisitor i_visitor, void * i_info); + +void * v_FindFunction (IM3Module i_module, const char * const i_name); + +IM3CodePage AcquireCodePage (IM3Runtime io_runtime); +IM3CodePage AcquireCodePageWithCapacity (IM3Runtime io_runtime, u32 i_lineCount); +void ReleaseCodePage (IM3Runtime io_runtime, IM3CodePage i_codePage); + +d_m3EndExternC + +#endif // m3_env_h diff --git a/wasm3-sys/wasm3/source/m3_exception.h b/wasm3-sys/wasm3/source/m3_exception.h new file mode 100644 index 0000000..fa49e4e --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_exception.h @@ -0,0 +1,34 @@ +// +// m3_exception.h +// +// Created by Steven Massey on 7/5/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// +// some macros to emulate try/catch + +#ifndef m3_exception_h +#define m3_exception_h + +#include "m3_config.h" + +# if d_m3EnableExceptionBreakpoint + +// declared in m3_info.c +void ExceptionBreakpoint (cstr_t i_exception, cstr_t i_message); + +# define EXCEPTION_PRINT(ERROR) ExceptionBreakpoint (ERROR, (__FILE__ ":" M3_STR(__LINE__))) + +# else +# define EXCEPTION_PRINT(...) +# endif + + +#define _try +#define _(TRY) { result = TRY; if (result) { EXCEPTION_PRINT (result); goto _catch; } } +#define _throw(ERROR) { result = ERROR; EXCEPTION_PRINT (result); goto _catch; } +#define _throwif(ERROR, COND) if (UNLIKELY(COND)) \ + { result = ERROR; EXCEPTION_PRINT (result); goto _catch; } + +#define _throwifnull(PTR) _throwif (m3Err_mallocFailed, !(PTR)) + +#endif // m3_exception_h diff --git a/wasm3-sys/wasm3/source/m3_exec.c b/wasm3-sys/wasm3/source/m3_exec.c new file mode 100644 index 0000000..7ca770c --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_exec.c @@ -0,0 +1,69 @@ +// +// m3_exec.c +// +// Created by Steven Massey on 4/17/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_env.h" +#include "m3_exec.h" +#include "m3_compile.h" + + +# if d_m3EnableOpProfiling +//-------------------------------------------------------------------------------------------------------- +static M3ProfilerSlot s_opProfilerCounts [d_m3ProfilerSlotMask + 1] = {}; + +void ProfileHit (cstr_t i_operationName) +{ + u64 ptr = (u64) i_operationName; + + M3ProfilerSlot * slot = & s_opProfilerCounts [ptr & d_m3ProfilerSlotMask]; + + if (slot->opName) + { + if (slot->opName != i_operationName) + { + m3_Abort ("profiler slot collision; increase d_m3ProfilerSlotMask"); + } + } + + slot->opName = i_operationName; + slot->hitCount++; +} + + +void m3_PrintProfilerInfo () +{ + M3ProfilerSlot dummy; + M3ProfilerSlot * maxSlot = & dummy; + + do + { + maxSlot->hitCount = 0; + + for (u32 i = 0; i <= d_m3ProfilerSlotMask; ++i) + { + M3ProfilerSlot * slot = & s_opProfilerCounts [i]; + + if (slot->opName) + { + if (slot->hitCount > maxSlot->hitCount) + maxSlot = slot; + } + } + + if (maxSlot->opName) + { + fprintf (stderr, "%13llu %s\n", maxSlot->hitCount, maxSlot->opName); + maxSlot->opName = NULL; + } + } + while (maxSlot->hitCount); +} + +# else + +void m3_PrintProfilerInfo () {} + +# endif diff --git a/wasm3-sys/wasm3/source/m3_exec.h b/wasm3-sys/wasm3/source/m3_exec.h new file mode 100644 index 0000000..1ebeead --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_exec.h @@ -0,0 +1,1495 @@ +// +// m3_exec.h +// +// Created by Steven Massey on 4/17/19. +// Copyright © 2019 Steven Massey. All rights reserved. + + +#ifndef m3_exec_h +#define m3_exec_h + +// TODO: all these functions could move over to the .c at some point. normally, I'd say screw it, +// but it might prove useful to be able to compile m3_exec alone w/ optimizations while the remaining +// code is at debug O0 + + +// About the naming convention of these operations/macros (_rs, _sr_, _ss, _srs, etc.) +//------------------------------------------------------------------------------------------------------ +// - 'r' means register and 's' means slot +// - the first letter is the top of the stack +// +// so, for example, _rs means the first operand (the first thing pushed to the stack) is in a slot +// and the second operand (the top of the stack) is in a register +//------------------------------------------------------------------------------------------------------ + + +#include "m3_math_utils.h" +#include "m3_compile.h" +#include "m3_env.h" +#include "m3_info.h" +#include "m3_exec_defs.h" + +#include + +d_m3BeginExternC + +# define rewrite_op(OP) * ((void **) (_pc-1)) = (void*)(OP) + +# define immediate(TYPE) * ((TYPE *) _pc++) +# define skip_immediate(TYPE) (_pc++) + +# define slot(TYPE) * (TYPE *) (_sp + immediate (i32)) +# define slot_ptr(TYPE) (TYPE *) (_sp + immediate (i32)) + + +# if d_m3EnableOpProfiling + d_m3RetSig profileOp (d_m3OpSig, cstr_t i_operationName); +# define nextOp() return profileOp (d_m3OpAllArgs, __FUNCTION__) +# elif d_m3EnableOpTracing + d_m3RetSig debugOp (d_m3OpSig, cstr_t i_operationName); +# define nextOp() return debugOp (d_m3OpAllArgs, __FUNCTION__) +# else +# define nextOp() nextOpDirect() +# endif + +#define jumpOp(PC) jumpOpDirect(PC) + +#if d_m3RecordBacktraces + #define pushBacktraceFrame() (PushBacktraceFrame (_mem->runtime, _pc - 1)) + #define fillBacktraceFrame(FUNCTION) (FillBacktraceFunctionInfo (_mem->runtime, function)) + + #define newTrap(err) return (pushBacktraceFrame (), err) + #define forwardTrap(err) return err +#else + #define pushBacktraceFrame() do {} while (0) + #define fillBacktraceFrame(FUNCTION) do {} while (0) + + #define newTrap(err) return err + #define forwardTrap(err) return err +#endif + + +#if d_m3EnableStrace == 1 + // Flat trace + #define d_m3TracePrepare + #define d_m3TracePrint(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__) +#elif d_m3EnableStrace >= 2 + // Structured trace + #define d_m3TracePrepare const IM3Runtime trace_rt = m3MemRuntime(_mem); + #define d_m3TracePrint(fmt, ...) fprintf(stderr, "%*s" fmt "\n", (trace_rt->callDepth)*2, "", ##__VA_ARGS__) +#else + #define d_m3TracePrepare + #define d_m3TracePrint(fmt, ...) +#endif + +#if d_m3EnableStrace >= 3 + #define d_m3TraceLoad(TYPE,offset,val) d_m3TracePrint("load." #TYPE " 0x%x = %" PRI##TYPE, offset, val) + #define d_m3TraceStore(TYPE,offset,val) d_m3TracePrint("store." #TYPE " 0x%x , %" PRI##TYPE, offset, val) +#else + #define d_m3TraceLoad(TYPE,offset,val) + #define d_m3TraceStore(TYPE,offset,val) +#endif + +#ifdef DEBUG + #define d_outOfBounds newTrap (ErrorRuntime (m3Err_trapOutOfBoundsMemoryAccess, \ + _mem->runtime, "memory size: %zu; access offset: %zu", \ + _mem->length, operand)) + +# define d_outOfBoundsMemOp(OFFSET, SIZE) newTrap (ErrorRuntime (m3Err_trapOutOfBoundsMemoryAccess, \ + _mem->runtime, "memory size: %zu; access offset: %zu; size: %u", \ + _mem->length, OFFSET, SIZE)) +#else + #define d_outOfBounds newTrap (m3Err_trapOutOfBoundsMemoryAccess) + +# define d_outOfBoundsMemOp(OFFSET, SIZE) newTrap (m3Err_trapOutOfBoundsMemoryAccess) + +#endif + + +d_m3RetSig Call (d_m3OpSig) +{ + m3ret_t possible_trap = m3_Yield (); + if (UNLIKELY(possible_trap)) return possible_trap; + + nextOpDirect(); +} + +// TODO: OK, this needs some explanation here ;0 + +#define d_m3CommutativeOpMacro(RES, REG, TYPE, NAME, OP, ...) \ +d_m3Op(TYPE##_##NAME##_rs) \ +{ \ + TYPE operand = slot (TYPE); \ + OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_ss) \ +{ \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = slot (TYPE); \ + OP((RES), operand1, operand2, ##__VA_ARGS__); \ + nextOp (); \ +} + +#define d_m3OpMacro(RES, REG, TYPE, NAME, OP, ...) \ +d_m3Op(TYPE##_##NAME##_sr) \ +{ \ + TYPE operand = slot (TYPE); \ + OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3CommutativeOpMacro(RES, REG, TYPE,NAME, OP, ##__VA_ARGS__) + +// Accept macros +#define d_m3CommutativeOpMacro_i(TYPE, NAME, MACRO, ...) d_m3CommutativeOpMacro ( _r0, _r0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3OpMacro_i(TYPE, NAME, MACRO, ...) d_m3OpMacro ( _r0, _r0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3CommutativeOpMacro_f(TYPE, NAME, MACRO, ...) d_m3CommutativeOpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3OpMacro_f(TYPE, NAME, MACRO, ...) d_m3OpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) + +#define M3_FUNC(RES, A, B, OP) (RES) = OP((A), (B)) // Accept functions: res = OP(a,b) +#define M3_OPER(RES, A, B, OP) (RES) = ((A) OP (B)) // Accept operators: res = a OP b + +#define d_m3CommutativeOpFunc_i(TYPE, NAME, OP) d_m3CommutativeOpMacro_i (TYPE, NAME, M3_FUNC, OP) +#define d_m3OpFunc_i(TYPE, NAME, OP) d_m3OpMacro_i (TYPE, NAME, M3_FUNC, OP) +#define d_m3CommutativeOpFunc_f(TYPE, NAME, OP) d_m3CommutativeOpMacro_f (TYPE, NAME, M3_FUNC, OP) +#define d_m3OpFunc_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_FUNC, OP) + +#define d_m3CommutativeOp_i(TYPE, NAME, OP) d_m3CommutativeOpMacro_i (TYPE, NAME, M3_OPER, OP) +#define d_m3Op_i(TYPE, NAME, OP) d_m3OpMacro_i (TYPE, NAME, M3_OPER, OP) +#define d_m3CommutativeOp_f(TYPE, NAME, OP) d_m3CommutativeOpMacro_f (TYPE, NAME, M3_OPER, OP) +#define d_m3Op_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_OPER, OP) + +// compare needs to be distinct for fp 'cause the result must be _r0 +#define d_m3CompareOp_f(TYPE, NAME, OP) d_m3OpMacro (_r0, _fp0, TYPE, NAME, M3_OPER, OP) +#define d_m3CommutativeCmpOp_f(TYPE, NAME, OP) d_m3CommutativeOpMacro (_r0, _fp0, TYPE, NAME, M3_OPER, OP) + + +//----------------------- + +// signed +d_m3CommutativeOp_i (i32, Equal, ==) d_m3CommutativeOp_i (i64, Equal, ==) +d_m3CommutativeOp_i (i32, NotEqual, !=) d_m3CommutativeOp_i (i64, NotEqual, !=) + +d_m3Op_i (i32, LessThan, < ) d_m3Op_i (i64, LessThan, < ) +d_m3Op_i (i32, GreaterThan, > ) d_m3Op_i (i64, GreaterThan, > ) +d_m3Op_i (i32, LessThanOrEqual, <=) d_m3Op_i (i64, LessThanOrEqual, <=) +d_m3Op_i (i32, GreaterThanOrEqual, >=) d_m3Op_i (i64, GreaterThanOrEqual, >=) + +// unsigned +d_m3Op_i (u32, LessThan, < ) d_m3Op_i (u64, LessThan, < ) +d_m3Op_i (u32, GreaterThan, > ) d_m3Op_i (u64, GreaterThan, > ) +d_m3Op_i (u32, LessThanOrEqual, <=) d_m3Op_i (u64, LessThanOrEqual, <=) +d_m3Op_i (u32, GreaterThanOrEqual, >=) d_m3Op_i (u64, GreaterThanOrEqual, >=) + +#if d_m3HasFloat +d_m3CommutativeCmpOp_f (f32, Equal, ==) d_m3CommutativeCmpOp_f (f64, Equal, ==) +d_m3CommutativeCmpOp_f (f32, NotEqual, !=) d_m3CommutativeCmpOp_f (f64, NotEqual, !=) +d_m3CompareOp_f (f32, LessThan, < ) d_m3CompareOp_f (f64, LessThan, < ) +d_m3CompareOp_f (f32, GreaterThan, > ) d_m3CompareOp_f (f64, GreaterThan, > ) +d_m3CompareOp_f (f32, LessThanOrEqual, <=) d_m3CompareOp_f (f64, LessThanOrEqual, <=) +d_m3CompareOp_f (f32, GreaterThanOrEqual, >=) d_m3CompareOp_f (f64, GreaterThanOrEqual, >=) +#endif + +d_m3CommutativeOp_i (i32, Add, +) d_m3CommutativeOp_i (i64, Add, +) +d_m3CommutativeOp_i (i32, Multiply, *) d_m3CommutativeOp_i (i64, Multiply, *) + +d_m3Op_i (i32, Subtract, -) d_m3Op_i (i64, Subtract, -) + +#define OP_SHL_32(X,N) ((X) << ((u32)(N) % 32)) +#define OP_SHL_64(X,N) ((X) << ((u64)(N) % 64)) +#define OP_SHR_32(X,N) ((X) >> ((u32)(N) % 32)) +#define OP_SHR_64(X,N) ((X) >> ((u64)(N) % 64)) + +d_m3OpFunc_i (u32, ShiftLeft, OP_SHL_32) d_m3OpFunc_i (u64, ShiftLeft, OP_SHL_64) +d_m3OpFunc_i (i32, ShiftRight, OP_SHR_32) d_m3OpFunc_i (i64, ShiftRight, OP_SHR_64) +d_m3OpFunc_i (u32, ShiftRight, OP_SHR_32) d_m3OpFunc_i (u64, ShiftRight, OP_SHR_64) + +d_m3CommutativeOp_i (u32, And, &) +d_m3CommutativeOp_i (u32, Or, |) +d_m3CommutativeOp_i (u32, Xor, ^) + +d_m3CommutativeOp_i (u64, And, &) +d_m3CommutativeOp_i (u64, Or, |) +d_m3CommutativeOp_i (u64, Xor, ^) + +#if d_m3HasFloat +d_m3CommutativeOp_f (f32, Add, +) d_m3CommutativeOp_f (f64, Add, +) +d_m3CommutativeOp_f (f32, Multiply, *) d_m3CommutativeOp_f (f64, Multiply, *) +d_m3Op_f (f32, Subtract, -) d_m3Op_f (f64, Subtract, -) +d_m3Op_f (f32, Divide, /) d_m3Op_f (f64, Divide, /) +#endif + +d_m3OpFunc_i(u32, Rotl, rotl32) +d_m3OpFunc_i(u32, Rotr, rotr32) +d_m3OpFunc_i(u64, Rotl, rotl64) +d_m3OpFunc_i(u64, Rotr, rotr64) + +d_m3OpMacro_i(u32, Divide, OP_DIV_U); +d_m3OpMacro_i(i32, Divide, OP_DIV_S, INT32_MIN); +d_m3OpMacro_i(u64, Divide, OP_DIV_U); +d_m3OpMacro_i(i64, Divide, OP_DIV_S, INT64_MIN); + +d_m3OpMacro_i(u32, Remainder, OP_REM_U); +d_m3OpMacro_i(i32, Remainder, OP_REM_S, INT32_MIN); +d_m3OpMacro_i(u64, Remainder, OP_REM_U); +d_m3OpMacro_i(i64, Remainder, OP_REM_S, INT64_MIN); + +#if d_m3HasFloat +d_m3OpFunc_f(f32, Min, min_f32); +d_m3OpFunc_f(f32, Max, max_f32); +d_m3OpFunc_f(f64, Min, min_f64); +d_m3OpFunc_f(f64, Max, max_f64); + +d_m3OpFunc_f(f32, CopySign, copysignf); +d_m3OpFunc_f(f64, CopySign, copysign); +#endif + +// Unary operations +// Note: This macro follows the principle of d_m3OpMacro + +#define d_m3UnaryMacro(RES, REG, TYPE, NAME, OP, ...) \ +d_m3Op(TYPE##_##NAME##_r) \ +{ \ + OP((RES), (TYPE) REG, ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_s) \ +{ \ + TYPE operand = slot (TYPE); \ + OP((RES), operand, ##__VA_ARGS__); \ + nextOp (); \ +} + +#define M3_UNARY(RES, X, OP) (RES) = OP(X) +#define d_m3UnaryOp_i(TYPE, NAME, OPERATION) d_m3UnaryMacro( _r0, _r0, TYPE, NAME, M3_UNARY, OPERATION) +#define d_m3UnaryOp_f(TYPE, NAME, OPERATION) d_m3UnaryMacro(_fp0, _fp0, TYPE, NAME, M3_UNARY, OPERATION) + +#if d_m3HasFloat +d_m3UnaryOp_f (f32, Abs, fabsf); d_m3UnaryOp_f (f64, Abs, fabs); +d_m3UnaryOp_f (f32, Ceil, ceilf); d_m3UnaryOp_f (f64, Ceil, ceil); +d_m3UnaryOp_f (f32, Floor, floorf); d_m3UnaryOp_f (f64, Floor, floor); +d_m3UnaryOp_f (f32, Trunc, truncf); d_m3UnaryOp_f (f64, Trunc, trunc); +d_m3UnaryOp_f (f32, Sqrt, sqrtf); d_m3UnaryOp_f (f64, Sqrt, sqrt); +d_m3UnaryOp_f (f32, Nearest, rintf); d_m3UnaryOp_f (f64, Nearest, rint); +d_m3UnaryOp_f (f32, Negate, -); d_m3UnaryOp_f (f64, Negate, -); +#endif + +#define OP_EQZ(x) ((x) == 0) + +d_m3UnaryOp_i (i32, EqualToZero, OP_EQZ) +d_m3UnaryOp_i (i64, EqualToZero, OP_EQZ) + +// clz(0), ctz(0) results are undefined for rest platforms, fix it +#if (defined(__i386__) || defined(__x86_64__)) && !(defined(__AVX2__) || (defined(__ABM__) && defined(__BMI__))) + #define OP_CLZ_32(x) (UNLIKELY((x) == 0) ? 32 : __builtin_clz(x)) + #define OP_CTZ_32(x) (UNLIKELY((x) == 0) ? 32 : __builtin_ctz(x)) + // for 64-bit instructions branchless approach more preferable + #define OP_CLZ_64(x) (__builtin_clzll((x) | (1LL << 0)) + OP_EQZ(x)) + #define OP_CTZ_64(x) (__builtin_ctzll((x) | (1LL << 63)) + OP_EQZ(x)) +#elif defined(__ppc__) || defined(__ppc64__) +// PowerPC is defined for __builtin_clz(0) and __builtin_ctz(0). +// See (https://github.com/aquynh/capstone/blob/master/MathExtras.h#L99) + #define OP_CLZ_32(x) __builtin_clz(x) + #define OP_CTZ_32(x) __builtin_ctz(x) + #define OP_CLZ_64(x) __builtin_clzll(x) + #define OP_CTZ_64(x) __builtin_ctzll(x) +#else + #define OP_CLZ_32(x) (UNLIKELY((x) == 0) ? 32 : __builtin_clz(x)) + #define OP_CTZ_32(x) (UNLIKELY((x) == 0) ? 32 : __builtin_ctz(x)) + #define OP_CLZ_64(x) (UNLIKELY((x) == 0) ? 64 : __builtin_clzll(x)) + #define OP_CTZ_64(x) (UNLIKELY((x) == 0) ? 64 : __builtin_ctzll(x)) +#endif + +d_m3UnaryOp_i (u32, Clz, OP_CLZ_32) +d_m3UnaryOp_i (u64, Clz, OP_CLZ_64) + +d_m3UnaryOp_i (u32, Ctz, OP_CTZ_32) +d_m3UnaryOp_i (u64, Ctz, OP_CTZ_64) + +d_m3UnaryOp_i (u32, Popcnt, __builtin_popcount) +d_m3UnaryOp_i (u64, Popcnt, __builtin_popcountll) + +#define OP_WRAP_I64(X) ((X) & 0x00000000ffffffff) + +d_m3Op(i32_Wrap_i64_r) +{ + _r0 = OP_WRAP_I64((i64) _r0); + nextOp (); +} + +d_m3Op(i32_Wrap_i64_s) +{ + i64 operand = slot (i64); + _r0 = OP_WRAP_I64(operand); + nextOp (); +} + +// Integer sign extension operations +#define OP_EXTEND8_S_I32(X) ((int32_t)(int8_t)(X)) +#define OP_EXTEND16_S_I32(X) ((int32_t)(int16_t)(X)) +#define OP_EXTEND8_S_I64(X) ((int64_t)(int8_t)(X)) +#define OP_EXTEND16_S_I64(X) ((int64_t)(int16_t)(X)) +#define OP_EXTEND32_S_I64(X) ((int64_t)(int32_t)(X)) + +d_m3UnaryOp_i (i32, Extend8_s, OP_EXTEND8_S_I32) +d_m3UnaryOp_i (i32, Extend16_s, OP_EXTEND16_S_I32) +d_m3UnaryOp_i (i64, Extend8_s, OP_EXTEND8_S_I64) +d_m3UnaryOp_i (i64, Extend16_s, OP_EXTEND16_S_I64) +d_m3UnaryOp_i (i64, Extend32_s, OP_EXTEND32_S_I64) + +#define d_m3TruncMacro(DEST, SRC, TYPE, NAME, FROM, OP, ...) \ +d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ +{ \ + OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ +{ \ + FROM * stack = slot_ptr (FROM); \ + OP((DEST), (* stack), ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ +{ \ + TYPE * dest = slot_ptr (TYPE); \ + OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ +{ \ + FROM * stack = slot_ptr (FROM); \ + TYPE * dest = slot_ptr (TYPE); \ + OP((* dest), (* stack), ##__VA_ARGS__); \ + nextOp (); \ +} + +#if d_m3HasFloat +d_m3TruncMacro(_r0, _fp0, i32, Trunc, f32, OP_I32_TRUNC_F32) +d_m3TruncMacro(_r0, _fp0, u32, Trunc, f32, OP_U32_TRUNC_F32) +d_m3TruncMacro(_r0, _fp0, i32, Trunc, f64, OP_I32_TRUNC_F64) +d_m3TruncMacro(_r0, _fp0, u32, Trunc, f64, OP_U32_TRUNC_F64) + +d_m3TruncMacro(_r0, _fp0, i64, Trunc, f32, OP_I64_TRUNC_F32) +d_m3TruncMacro(_r0, _fp0, u64, Trunc, f32, OP_U64_TRUNC_F32) +d_m3TruncMacro(_r0, _fp0, i64, Trunc, f64, OP_I64_TRUNC_F64) +d_m3TruncMacro(_r0, _fp0, u64, Trunc, f64, OP_U64_TRUNC_F64) + +d_m3TruncMacro(_r0, _fp0, i32, TruncSat, f32, OP_I32_TRUNC_SAT_F32) +d_m3TruncMacro(_r0, _fp0, u32, TruncSat, f32, OP_U32_TRUNC_SAT_F32) +d_m3TruncMacro(_r0, _fp0, i32, TruncSat, f64, OP_I32_TRUNC_SAT_F64) +d_m3TruncMacro(_r0, _fp0, u32, TruncSat, f64, OP_U32_TRUNC_SAT_F64) + +d_m3TruncMacro(_r0, _fp0, i64, TruncSat, f32, OP_I64_TRUNC_SAT_F32) +d_m3TruncMacro(_r0, _fp0, u64, TruncSat, f32, OP_U64_TRUNC_SAT_F32) +d_m3TruncMacro(_r0, _fp0, i64, TruncSat, f64, OP_I64_TRUNC_SAT_F64) +d_m3TruncMacro(_r0, _fp0, u64, TruncSat, f64, OP_U64_TRUNC_SAT_F64) +#endif + +#define d_m3TypeModifyOp(REG_TO, REG_FROM, TO, NAME, FROM) \ +d_m3Op(TO##_##NAME##_##FROM##_r) \ +{ \ + REG_TO = (TO) ((FROM) REG_FROM); \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_##NAME##_##FROM##_s) \ +{ \ + FROM from = slot (FROM); \ + REG_TO = (TO) (from); \ + nextOp (); \ +} + +// Int to int +d_m3TypeModifyOp (_r0, _r0, i64, Extend, i32); +d_m3TypeModifyOp (_r0, _r0, i64, Extend, u32); + +// Float to float +#if d_m3HasFloat +d_m3TypeModifyOp (_fp0, _fp0, f32, Demote, f64); +d_m3TypeModifyOp (_fp0, _fp0, f64, Promote, f32); +#endif + +#define d_m3TypeConvertOp(REG_TO, REG_FROM, TO, NAME, FROM) \ +d_m3Op(TO##_##NAME##_##FROM##_r_r) \ +{ \ + REG_TO = (TO) ((FROM) REG_FROM); \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_##NAME##_##FROM##_s_r) \ +{ \ + slot (TO) = (TO) ((FROM) REG_FROM); \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_##NAME##_##FROM##_r_s) \ +{ \ + FROM from = slot (FROM); \ + REG_TO = (TO) (from); \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_##NAME##_##FROM##_s_s) \ +{ \ + FROM from = slot (FROM); \ + slot (TO) = (TO) (from); \ + nextOp (); \ +} + +// Int to float +#if d_m3HasFloat +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i32); +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u32); +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i64); +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u64); + +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i32); +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u32); +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i64); +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u64); +#endif + +#define d_m3ReinterpretOp(REG, TO, SRC, FROM) \ +d_m3Op(TO##_Reinterpret_##FROM##_r_r) \ +{ \ + union { FROM c; TO t; } u; \ + u.c = (FROM) SRC; \ + REG = u.t; \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_Reinterpret_##FROM##_r_s) \ +{ \ + union { FROM c; TO t; } u; \ + u.c = slot (FROM); \ + REG = u.t; \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_Reinterpret_##FROM##_s_r) \ +{ \ + union { FROM c; TO t; } u; \ + u.c = (FROM) SRC; \ + slot (TO) = u.t; \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_Reinterpret_##FROM##_s_s) \ +{ \ + union { FROM c; TO t; } u; \ + u.c = slot (FROM); \ + slot (TO) = u.t; \ + nextOp (); \ +} + +#if d_m3HasFloat +d_m3ReinterpretOp (_r0, i32, _fp0, f32) +d_m3ReinterpretOp (_r0, i64, _fp0, f64) +d_m3ReinterpretOp (_fp0, f32, _r0, i32) +d_m3ReinterpretOp (_fp0, f64, _r0, i64) +#endif + + +d_m3Op (GetGlobal_s32) +{ + u32 * global = immediate (u32 *); + slot (u32) = * global; // printf ("get global: %p %" PRIi64 "\n", global, *global); + + nextOp (); +} + + +d_m3Op (GetGlobal_s64) +{ + u64 * global = immediate (u64 *); + slot (u64) = * global; // printf ("get global: %p %" PRIi64 "\n", global, *global); + + nextOp (); +} + + +d_m3Op (SetGlobal_i32) +{ + u32 * global = immediate (u32 *); + * global = (u32) _r0; // printf ("set global: %p %" PRIi64 "\n", global, _r0); + + nextOp (); +} + + +d_m3Op (SetGlobal_i64) +{ + u64 * global = immediate (u64 *); + * global = (u64) _r0; // printf ("set global: %p %" PRIi64 "\n", global, _r0); + + nextOp (); +} + + +d_m3Op (Call) +{ + pc_t callPC = immediate (pc_t); + i32 stackOffset = immediate (i32); + IM3Memory memory = m3MemInfo (_mem); + + m3stack_t sp = _sp + stackOffset; + + m3ret_t r = Call (callPC, sp, _mem, d_m3OpDefaultArgs); + _mem = memory->mallocated; + + if (LIKELY(not r)) + nextOp (); + else + { + pushBacktraceFrame (); + forwardTrap (r); + } +} + + +d_m3Op (CallIndirect) +{ + u32 tableIndex = slot (u32); + IM3Module module = immediate (IM3Module); + IM3FuncType type = immediate (IM3FuncType); + i32 stackOffset = immediate (i32); + IM3Memory memory = m3MemInfo (_mem); + + m3stack_t sp = _sp + stackOffset; + + m3ret_t r = m3Err_none; + + if (LIKELY(tableIndex < module->table0Size)) + { + IM3Function function = module->table0 [tableIndex]; + + if (LIKELY(function)) + { + if (LIKELY(type == function->funcType)) + { + if (UNLIKELY(not function->compiled)) + r = CompileFunction (function); + + if (LIKELY(not r)) + { + r = Call (function->compiled, sp, _mem, d_m3OpDefaultArgs); + _mem = memory->mallocated; + + if (LIKELY(not r)) + nextOpDirect (); + else + { + pushBacktraceFrame (); + forwardTrap (r); + } + } + } + else r = m3Err_trapIndirectCallTypeMismatch; + } + else r = m3Err_trapTableElementIsNull; + } + else r = m3Err_trapTableIndexOutOfRange; + + if (UNLIKELY(r)) + newTrap (r); + else forwardTrap (r); +} + + +d_m3Op (CallRawFunction) +{ + d_m3TracePrepare + + M3ImportContext ctx; + + M3RawCall call = (M3RawCall) (* _pc++); + ctx.function = immediate (IM3Function); + ctx.userdata = immediate (void *); + u64* const sp = ((u64*)_sp); + IM3Memory memory = m3MemInfo (_mem); + + IM3Runtime runtime = m3MemRuntime(_mem); + +#if d_m3EnableStrace + IM3FuncType ftype = ctx.function->funcType; + + FILE* out = stderr; + char outbuff[1024]; + char* outp = outbuff; + char* oute = outbuff+1024; + + outp += snprintf(outp, oute-outp, "%s!%s(", ctx.function->import.moduleUtf8, ctx.function->import.fieldUtf8); + + const int nArgs = ftype->numArgs; + const int nRets = ftype->numRets; + u64 * args = sp + nRets; + for (int i=0; itypes[nRets + i]; + switch (type) { + case c_m3Type_i32: outp += snprintf(outp, oute-outp, "%" PRIi32, *(i32*)(args+i)); break; + case c_m3Type_i64: outp += snprintf(outp, oute-outp, "%" PRIi64, *(i64*)(args+i)); break; + case c_m3Type_f32: outp += snprintf(outp, oute-outp, "%" PRIf32, *(f32*)(args+i)); break; + case c_m3Type_f64: outp += snprintf(outp, oute-outp, "%" PRIf64, *(f64*)(args+i)); break; + default: outp += snprintf(outp, oute-outp, "", type); break; + } + outp += snprintf(outp, oute-outp, (i < nArgs-1) ? ", " : ")"); + } +# if d_m3EnableStrace >= 2 + outp += snprintf(outp, oute-outp, " { }"); +# endif +#endif + + // m3_Call uses runtime->stack to set-up initial exported function stack. + // Reconfigure the stack to enable recursive invocations of m3_Call. + // I.e. exported/table function can be called from an impoted function. + void* stack_backup = runtime->stack; + runtime->stack = sp; + m3ret_t possible_trap = call (runtime, &ctx, sp, m3MemData(_mem)); + runtime->stack = stack_backup; + +#if d_m3EnableStrace + if (UNLIKELY(possible_trap)) { + d_m3TracePrint("%s -> %s", outbuff, (char*)possible_trap); + } else { + switch (GetSingleRetType(ftype)) { + case c_m3Type_none: d_m3TracePrint("%s", outbuff); break; + case c_m3Type_i32: d_m3TracePrint("%s = %" PRIi32, outbuff, *(i32*)sp); break; + case c_m3Type_i64: d_m3TracePrint("%s = %" PRIi64, outbuff, *(i64*)sp); break; + case c_m3Type_f32: d_m3TracePrint("%s = %" PRIf32, outbuff, *(f32*)sp); break; + case c_m3Type_f64: d_m3TracePrint("%s = %" PRIf64, outbuff, *(f64*)sp); break; + } + } +#endif + + if (UNLIKELY(possible_trap)) { + _mem = memory->mallocated; + pushBacktraceFrame (); + } + forwardTrap (possible_trap); +} + + +d_m3Op (MemSize) +{ + IM3Memory memory = m3MemInfo (_mem); + + _r0 = memory->numPages; + + nextOp (); +} + + +d_m3Op (MemGrow) +{ + IM3Runtime runtime = m3MemRuntime(_mem); + IM3Memory memory = & runtime->memory; + + u32 numPagesToGrow = (u32) _r0; + _r0 = memory->numPages; + + if (numPagesToGrow) + { + u32 requiredPages = memory->numPages + numPagesToGrow; + + M3Result r = ResizeMemory (runtime, requiredPages); + if (r) + _r0 = -1; + + _mem = memory->mallocated; + } + + nextOp (); +} + + +d_m3Op (MemCopy) +{ + u32 size = (u32) _r0; + u64 source = slot (u32); + u64 destination = slot (u32); + + if (destination + size <= _mem->length) + { + if (source + size <= _mem->length) + { + u8 * dst = m3MemData (_mem) + destination; + u8 * src = m3MemData (_mem) + source; + memmove (dst, src, size); + + nextOp (); + } + else d_outOfBoundsMemOp (source, size); + } + else d_outOfBoundsMemOp (destination, size); +} + + +d_m3Op (MemFill) +{ + u32 size = (u32) _r0; + u32 byte = slot (u32); + u64 destination = slot (u32); + + if (destination + size <= _mem->length) + { + u8 * mem8 = m3MemData (_mem) + destination; + memset (mem8, (u8) byte, size); + nextOp (); + } + else d_outOfBoundsMemOp (destination, size); +} + + +// it's a debate: should the compilation be trigger be the caller or callee page. +// it's a much easier to put it in the caller pager. if it's in the callee, either the entire page +// has be left dangling or it's just a stub that jumps to a newly acquired page. In Gestalt, I opted +// for the stub approach. Stubbing makes it easier to dynamically free the compilation. You can also +// do both. +d_m3Op (Compile) +{ + rewrite_op (op_Call); + + IM3Function function = immediate (IM3Function); + + m3ret_t result = m3Err_none; + + if (UNLIKELY(not function->compiled)) // check to see if function was compiled since this operation was emitted. + result = CompileFunction (function); + + if (not result) + { + // patch up compiled pc and call rewritten op_Call + * ((void**) --_pc) = (void*) (function->compiled); + --_pc; + nextOpDirect (); + } + + newTrap (result); +} + + + +d_m3Op (Entry) +{ + d_m3ClearRegisters + + d_m3TracePrepare + + IM3Function function = immediate (IM3Function); + IM3Memory memory = m3MemInfo (_mem); + +#if d_m3SkipStackCheck + if (true) +#else + if (LIKELY ((void *) (_sp + function->maxStackSlots) < _mem->maxStack)) +#endif + { +#if defined(DEBUG) + function->hits++; +#endif + u8 * stack = (u8 *) ((m3slot_t *) _sp + function->numRetAndArgSlots); + + memset (stack, 0x0, function->numLocalBytes); + stack += function->numLocalBytes; + + if (function->constants) + { + memcpy (stack, function->constants, function->numConstantBytes); + } + +#if d_m3EnableStrace >= 2 + d_m3TracePrint("%s %s {", m3_GetFunctionName(function), SPrintFunctionArgList (function, _sp + function->numRetSlots)); + trace_rt->callDepth++; +#endif + + m3ret_t r = nextOpImpl (); + +#if d_m3EnableStrace >= 2 + trace_rt->callDepth--; + + if (r) { + d_m3TracePrint("} !trap = %s", (char*)r); + } else { + int rettype = GetSingleRetType(function->funcType); + if (rettype != c_m3Type_none) { + char str [128] = { 0 }; + SPrintArg (str, 127, _sp, rettype); + d_m3TracePrint("} = %s", str); + } else { + d_m3TracePrint("}"); + } + } +#endif + + if (UNLIKELY(r)) { + _mem = memory->mallocated; + fillBacktraceFrame (); + } + forwardTrap (r); + } + else newTrap (m3Err_trapStackOverflow); +} + + +d_m3Op (Loop) +{ + d_m3TracePrepare + + // regs are unused coming into a loop anyway + // this reduces code size & stack usage + d_m3ClearRegisters + + m3ret_t r; + + IM3Memory memory = m3MemInfo (_mem); + + do + { +#if d_m3EnableStrace >= 3 + d_m3TracePrint("iter {"); + trace_rt->callDepth++; +#endif + r = nextOpImpl (); + +#if d_m3EnableStrace >= 3 + trace_rt->callDepth--; + d_m3TracePrint("}"); +#endif + // linear memory pointer needs refreshed here because the block it's looping over + // can potentially invoke the grow operation. + _mem = memory->mallocated; + } + while (r == _pc); + + forwardTrap (r); +} + + +d_m3Op (Branch) +{ + jumpOp (* _pc); +} + + +d_m3Op (If_r) +{ + i32 condition = (i32) _r0; + + pc_t elsePC = immediate (pc_t); + + if (condition) + nextOp (); + else + jumpOp (elsePC); +} + + +d_m3Op (If_s) +{ + i32 condition = slot (i32); + + pc_t elsePC = immediate (pc_t); + + if (condition) + nextOp (); + else + jumpOp (elsePC); +} + + +d_m3Op (BranchTable) +{ + u32 branchIndex = slot (u32); // branch index is always in a slot + u32 numTargets = immediate (u32); + + pc_t * branches = (pc_t *) _pc; + + if (branchIndex > numTargets) + branchIndex = numTargets; // the default index + + jumpOp (branches [branchIndex]); +} + + +#define d_m3SetRegisterSetSlot(TYPE, REG) \ +d_m3Op (SetRegister_##TYPE) \ +{ \ + REG = slot (TYPE); \ + nextOp (); \ +} \ + \ +d_m3Op (SetSlot_##TYPE) \ +{ \ + slot (TYPE) = (TYPE) REG; \ + nextOp (); \ +} \ + \ +d_m3Op (PreserveSetSlot_##TYPE) \ +{ \ + TYPE * stack = slot_ptr (TYPE); \ + TYPE * preserve = slot_ptr (TYPE); \ + \ + * preserve = * stack; \ + * stack = (TYPE) REG; \ + \ + nextOp (); \ +} + +d_m3SetRegisterSetSlot (i32, _r0) +d_m3SetRegisterSetSlot (i64, _r0) +#if d_m3HasFloat +d_m3SetRegisterSetSlot (f32, _fp0) +d_m3SetRegisterSetSlot (f64, _fp0) +#endif + +d_m3Op (CopySlot_32) +{ + u32 * dst = slot_ptr (u32); + u32 * src = slot_ptr (u32); + + * dst = * src; + + nextOp (); +} + + +d_m3Op (PreserveCopySlot_32) +{ + u32 * dest = slot_ptr (u32); + u32 * src = slot_ptr (u32); + u32 * preserve = slot_ptr (u32); + + * preserve = * dest; + * dest = * src; + + nextOp (); +} + + +d_m3Op (CopySlot_64) +{ + u64 * dst = slot_ptr (u64); + u64 * src = slot_ptr (u64); + + * dst = * src; // printf ("copy: %p <- %" PRIi64 " <- %p\n", dst, * dst, src); + + nextOp (); +} + + +d_m3Op (PreserveCopySlot_64) +{ + u64 * dest = slot_ptr (u64); + u64 * src = slot_ptr (u64); + u64 * preserve = slot_ptr (u64); + + * preserve = * dest; + * dest = * src; + + nextOp (); +} + + +#if d_m3EnableOpTracing +//-------------------------------------------------------------------------------------------------------- +d_m3Op (DumpStack) +{ + u32 opcodeIndex = immediate (u32); + u32 stackHeight = immediate (u32); + IM3Function function = immediate (IM3Function); + + cstr_t funcName = (function) ? m3_GetFunctionName(function) : ""; + + printf (" %4d ", opcodeIndex); + printf (" %-25s r0: 0x%016" PRIx64 " i:%" PRIi64 " u:%" PRIu64 "\n", funcName, _r0, _r0, _r0); +#if d_m3HasFloat + printf (" fp0: %" PRIf64 "\n", _fp0); +#endif + m3stack_t sp = _sp; + + for (u32 i = 0; i < stackHeight; ++i) + { + cstr_t kind = ""; + + printf ("%p %5s %2d: 0x%" PRIx64 " i:%" PRIi64 "\n", sp, kind, i, (u64) *(sp), (i64) *(sp)); + + ++sp; + } + printf ("---------------------------------------------------------------------------------------------------------\n"); + + nextOpDirect(); +} +#endif + + +#define d_m3Select_i(TYPE, REG) \ +d_m3Op (Select_##TYPE##_rss) \ +{ \ + i32 condition = (i32) _r0; \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_srs) \ +{ \ + i32 condition = slot (i32); \ + \ + TYPE operand2 = (TYPE) REG; \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_ssr) \ +{ \ + i32 condition = slot (i32); \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = (TYPE) REG; \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_sss) \ +{ \ + i32 condition = slot (i32); \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} + + +d_m3Select_i (i32, _r0) +d_m3Select_i (i64, _r0) + + +#define d_m3Select_f(TYPE, REG, LABEL, SELECTOR) \ +d_m3Op (Select_##TYPE##_##LABEL##ss) \ +{ \ + i32 condition = (i32) SELECTOR; \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_##LABEL##rs) \ +{ \ + i32 condition = (i32) SELECTOR; \ + \ + TYPE operand2 = (TYPE) REG; \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_##LABEL##sr) \ +{ \ + i32 condition = (i32) SELECTOR; \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = (TYPE) REG; \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} + +#if d_m3HasFloat +d_m3Select_f (f32, _fp0, r, _r0) +d_m3Select_f (f32, _fp0, s, slot (i32)) + +d_m3Select_f (f64, _fp0, r, _r0) +d_m3Select_f (f64, _fp0, s, slot (i32)) +#endif + +d_m3Op (Return) +{ + m3StackCheck(); + return m3Err_none; +} + + +d_m3Op (BranchIf_r) +{ + i32 condition = (i32) _r0; + pc_t branch = immediate (pc_t); + + if (condition) + { + jumpOp (branch); + } + else nextOp (); +} + + +d_m3Op (BranchIf_s) +{ + i32 condition = slot (i32); + pc_t branch = immediate (pc_t); + + if (condition) + { + jumpOp (branch); + } + else nextOp (); +} + + +d_m3Op (BranchIfPrologue_r) +{ + i32 condition = (i32) _r0; + pc_t branch = immediate (pc_t); + + if (condition) + { + // this is the "prologue" that ends with + // a plain branch to the actual target + nextOp (); + } + else jumpOp (branch); // jump over the prologue +} + + +d_m3Op (BranchIfPrologue_s) +{ + i32 condition = slot (i32); + pc_t branch = immediate (pc_t); + + if (condition) + { + nextOp (); + } + else jumpOp (branch); +} + + +d_m3Op (ContinueLoop) +{ + m3StackCheck(); + + // TODO: this is where execution can "escape" the M3 code and callback to the client / fiber switch + // OR it can go in the Loop operation. I think it's best to do here. adding code to the loop operation + // has the potential to increase its native-stack usage. (don't forget ContinueLoopIf too.) + + void * loopId = immediate (void *); + return loopId; +} + + +d_m3Op (ContinueLoopIf) +{ + i32 condition = (i32) _r0; + void * loopId = immediate (void *); + + if (condition) + { + return loopId; + } + else nextOp (); +} + + +d_m3Op (Const32) +{ + u32 value = * (u32 *)_pc++; + slot (u32) = value; + nextOp (); +} + + +d_m3Op (Const64) +{ + u64 value = * (u64 *)_pc; + _pc += (M3_SIZEOF_PTR == 4) ? 2 : 1; + slot (u64) = value; + nextOp (); +} + +d_m3Op (Unsupported) +{ + newTrap ("unsupported instruction executed"); +} + +d_m3Op (Unreachable) +{ + m3StackCheck(); + newTrap (m3Err_trapUnreachable); +} + + +d_m3Op (End) +{ + m3StackCheck(); + return m3Err_none; +} + + +d_m3Op (SetGlobal_s32) +{ + u32 * global = immediate (u32 *); + * global = slot (u32); + + nextOp (); +} + + +d_m3Op (SetGlobal_s64) +{ + u64 * global = immediate (u64 *); + * global = slot (u64); + + nextOp (); +} + +#if d_m3HasFloat +d_m3Op (SetGlobal_f32) +{ + f32 * global = immediate (f32 *); + * global = _fp0; + + nextOp (); +} + + +d_m3Op (SetGlobal_f64) +{ + f64 * global = immediate (f64 *); + * global = _fp0; + + nextOp (); +} +#endif + + +#if d_m3SkipMemoryBoundsCheck +# define m3MemCheck(x) true +#else +# define m3MemCheck(x) LIKELY(x) +#endif + +// memcpy here is to support non-aligned access on some platforms. + +#define d_m3Load(REG,DEST_TYPE,SRC_TYPE) \ +d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_r) \ +{ \ + d_m3TracePrepare \ + u32 offset = immediate (u32); \ + u64 operand = (u32) _r0; \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (SRC_TYPE) <= _mem->length \ + )) { \ + u8* src8 = m3MemData(_mem) + operand; \ + SRC_TYPE value; \ + memcpy(&value, src8, sizeof(value)); \ + M3_BSWAP_##SRC_TYPE(value); \ + REG = (DEST_TYPE)value; \ + d_m3TraceLoad(DEST_TYPE, operand, REG); \ + nextOp (); \ + } else d_outOfBounds; \ +} \ +d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_s) \ +{ \ + d_m3TracePrepare \ + u64 operand = slot (u32); \ + u32 offset = immediate (u32); \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (SRC_TYPE) <= _mem->length \ + )) { \ + u8* src8 = m3MemData(_mem) + operand; \ + SRC_TYPE value; \ + memcpy(&value, src8, sizeof(value)); \ + M3_BSWAP_##SRC_TYPE(value); \ + REG = (DEST_TYPE)value; \ + d_m3TraceLoad(DEST_TYPE, operand, REG); \ + nextOp (); \ + } else d_outOfBounds; \ +} + +// printf ("get: %d -> %d\n", operand + offset, (i64) REG); + + +#define d_m3Load_i(DEST_TYPE, SRC_TYPE) d_m3Load(_r0, DEST_TYPE, SRC_TYPE) +#define d_m3Load_f(DEST_TYPE, SRC_TYPE) d_m3Load(_fp0, DEST_TYPE, SRC_TYPE) + +#if d_m3HasFloat +d_m3Load_f (f32, f32); +d_m3Load_f (f64, f64); +#endif + +d_m3Load_i (i32, i8); +d_m3Load_i (i32, u8); +d_m3Load_i (i32, i16); +d_m3Load_i (i32, u16); +d_m3Load_i (i32, i32); + +d_m3Load_i (i64, i8); +d_m3Load_i (i64, u8); +d_m3Load_i (i64, i16); +d_m3Load_i (i64, u16); +d_m3Load_i (i64, i32); +d_m3Load_i (i64, u32); +d_m3Load_i (i64, i64); + +#define d_m3Store(REG, SRC_TYPE, DEST_TYPE) \ +d_m3Op (SRC_TYPE##_Store_##DEST_TYPE##_rs) \ +{ \ + d_m3TracePrepare \ + u64 operand = slot (u32); \ + u32 offset = immediate (u32); \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (DEST_TYPE) <= _mem->length \ + )) { \ + d_m3TraceStore(SRC_TYPE, operand, REG); \ + u8* mem8 = m3MemData(_mem) + operand; \ + DEST_TYPE val = (DEST_TYPE) REG; \ + M3_BSWAP_##DEST_TYPE(val); \ + memcpy(mem8, &val, sizeof(val)); \ + nextOp (); \ + } else d_outOfBounds; \ +} \ +d_m3Op (SRC_TYPE##_Store_##DEST_TYPE##_sr) \ +{ \ + d_m3TracePrepare \ + const SRC_TYPE value = slot (SRC_TYPE); \ + u64 operand = (u32) _r0; \ + u32 offset = immediate (u32); \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (DEST_TYPE) <= _mem->length \ + )) { \ + d_m3TraceStore(SRC_TYPE, operand, value); \ + u8* mem8 = m3MemData(_mem) + operand; \ + DEST_TYPE val = (DEST_TYPE) value; \ + M3_BSWAP_##DEST_TYPE(val); \ + memcpy(mem8, &val, sizeof(val)); \ + nextOp (); \ + } else d_outOfBounds; \ +} \ +d_m3Op (SRC_TYPE##_Store_##DEST_TYPE##_ss) \ +{ \ + d_m3TracePrepare \ + const SRC_TYPE value = slot (SRC_TYPE); \ + u64 operand = slot (u32); \ + u32 offset = immediate (u32); \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (DEST_TYPE) <= _mem->length \ + )) { \ + d_m3TraceStore(SRC_TYPE, operand, value); \ + u8* mem8 = m3MemData(_mem) + operand; \ + DEST_TYPE val = (DEST_TYPE) value; \ + M3_BSWAP_##DEST_TYPE(val); \ + memcpy(mem8, &val, sizeof(val)); \ + nextOp (); \ + } else d_outOfBounds; \ +} + +// both operands can be in regs when storing a float +#define d_m3StoreFp(REG, TYPE) \ +d_m3Op (TYPE##_Store_##TYPE##_rr) \ +{ \ + d_m3TracePrepare \ + u64 operand = (u32) _r0; \ + u32 offset = immediate (u32); \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (TYPE) <= _mem->length \ + )) { \ + d_m3TraceStore(TYPE, operand, REG); \ + u8* mem8 = m3MemData(_mem) + operand; \ + TYPE val = (TYPE) REG; \ + M3_BSWAP_##TYPE(val); \ + memcpy(mem8, &val, sizeof(val)); \ + nextOp (); \ + } else d_outOfBounds; \ +} + + +#define d_m3Store_i(SRC_TYPE, DEST_TYPE) d_m3Store(_r0, SRC_TYPE, DEST_TYPE) +#define d_m3Store_f(SRC_TYPE, DEST_TYPE) d_m3Store(_fp0, SRC_TYPE, DEST_TYPE) d_m3StoreFp (_fp0, SRC_TYPE); + +#if d_m3HasFloat +d_m3Store_f (f32, f32) +d_m3Store_f (f64, f64) +#endif + +d_m3Store_i (i32, u8) +d_m3Store_i (i32, i16) +d_m3Store_i (i32, i32) + +d_m3Store_i (i64, u8) +d_m3Store_i (i64, i16) +d_m3Store_i (i64, i32) +d_m3Store_i (i64, i64) + +#undef m3MemCheck + + +//--------------------------------------------------------------------------------------------------------------------- +// debug/profiling +//--------------------------------------------------------------------------------------------------------------------- +#if d_m3EnableOpTracing +d_m3RetSig debugOp (d_m3OpSig, cstr_t i_opcode) +{ + char name [100]; + strcpy (name, strstr (i_opcode, "op_") + 3); + char * bracket = strstr (name, "("); + if (bracket) { + *bracket = 0; + } + + puts (name); + nextOpDirect(); +} +# endif + +# if d_m3EnableOpProfiling + +typedef struct M3ProfilerSlot +{ + cstr_t opName; + u64 hitCount; +} +M3ProfilerSlot; + +void ProfileHit (cstr_t i_operationName); + +d_m3RetSig profileOp (d_m3OpSig, cstr_t i_operationName) +{ + ProfileHit (i_operationName); + + nextOpDirect(); +} +# endif + +d_m3EndExternC + +#endif // m3_exec_h diff --git a/wasm3-sys/wasm3/source/m3_exec_defs.h b/wasm3-sys/wasm3/source/m3_exec_defs.h new file mode 100644 index 0000000..991ce59 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_exec_defs.h @@ -0,0 +1,58 @@ +// +// m3_exec_defs.h +// +// Created by Steven Massey on 5/1/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_exec_defs_h +#define m3_exec_defs_h + +#include "m3_core.h" + +d_m3BeginExternC + +# define m3MemData(mem) (u8*)(((M3MemoryHeader*)(mem))+1) +# define m3MemRuntime(mem) (((M3MemoryHeader*)(mem))->runtime) +# define m3MemInfo(mem) (&(((M3MemoryHeader*)(mem))->runtime->memory)) + +# define d_m3BaseOpSig pc_t _pc, m3stack_t _sp, M3MemoryHeader * _mem, m3reg_t _r0 +# define d_m3BaseOpArgs _sp, _mem, _r0 +# define d_m3BaseOpAllArgs _pc, _sp, _mem, _r0 +# define d_m3BaseOpDefaultArgs 0 +# define d_m3BaseClearRegisters _r0 = 0; + +# define d_m3ExpOpSig(...) d_m3BaseOpSig, __VA_ARGS__ +# define d_m3ExpOpArgs(...) d_m3BaseOpArgs, __VA_ARGS__ +# define d_m3ExpOpAllArgs(...) d_m3BaseOpAllArgs, __VA_ARGS__ +# define d_m3ExpOpDefaultArgs(...) d_m3BaseOpDefaultArgs, __VA_ARGS__ +# define d_m3ExpClearRegisters(...) d_m3BaseClearRegisters; __VA_ARGS__ + +# if d_m3HasFloat +# define d_m3OpSig d_m3ExpOpSig (f64 _fp0) +# define d_m3OpArgs d_m3ExpOpArgs (_fp0) +# define d_m3OpAllArgs d_m3ExpOpAllArgs (_fp0) +# define d_m3OpDefaultArgs d_m3ExpOpDefaultArgs (0.) +# define d_m3ClearRegisters d_m3ExpClearRegisters (_fp0 = 0.;) +# else +# define d_m3OpSig d_m3BaseOpSig +# define d_m3OpArgs d_m3BaseOpArgs +# define d_m3OpAllArgs d_m3BaseOpAllArgs +# define d_m3OpDefaultArgs d_m3BaseOpDefaultArgs +# define d_m3ClearRegisters d_m3BaseClearRegisters +# endif + +typedef m3ret_t (vectorcall * IM3Operation) (d_m3OpSig); + +#define d_m3RetSig static inline m3ret_t vectorcall +#define d_m3Op(NAME) M3_NO_UBSAN op_section d_m3RetSig op_##NAME (d_m3OpSig) + +#define nextOpImpl() ((IM3Operation)(* _pc))(_pc + 1, d_m3OpArgs) +#define jumpOpImpl(PC) ((IM3Operation)(* PC))( PC + 1, d_m3OpArgs) + +#define nextOpDirect() return nextOpImpl() +#define jumpOpDirect(PC) return jumpOpImpl((pc_t)(PC)) + +d_m3EndExternC + +#endif // m3_exec_defs_h diff --git a/wasm3-sys/wasm3/source/m3_function.c b/wasm3-sys/wasm3/source/m3_function.c new file mode 100644 index 0000000..8823db4 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_function.c @@ -0,0 +1,233 @@ +// +// m3_function.c +// +// Created by Steven Massey on 4/7/21. +// Copyright © 2021 Steven Massey. All rights reserved. +// + +#include "m3_function.h" +#include "m3_env.h" + + +M3Result AllocFuncType (IM3FuncType * o_functionType, u32 i_numTypes) +{ + *o_functionType = (IM3FuncType) m3_Malloc (sizeof (M3FuncType) + i_numTypes); + return (*o_functionType) ? m3Err_none : m3Err_mallocFailed; +} + + +bool AreFuncTypesEqual (const IM3FuncType i_typeA, const IM3FuncType i_typeB) +{ + if (i_typeA->numRets == i_typeB->numRets && i_typeA->numArgs == i_typeB->numArgs) + { + return (memcmp (i_typeA->types, i_typeB->types, i_typeA->numRets + i_typeA->numArgs) == 0); + } + + return false; +} + +u16 GetFuncTypeNumParams (const IM3FuncType i_funcType) +{ + return i_funcType ? i_funcType->numArgs : 0; +} + + +u8 GetFuncTypeParamType (const IM3FuncType i_funcType, u16 i_index) +{ + u8 type = c_m3Type_unknown; + + if (i_funcType) + { + if (i_index < i_funcType->numArgs) + { + type = i_funcType->types [i_funcType->numRets + i_index]; + } + } + + return type; +} + + + +u16 GetFuncTypeNumResults (const IM3FuncType i_funcType) +{ + return i_funcType ? i_funcType->numRets : 0; +} + + +u8 GetFuncTypeResultType (const IM3FuncType i_funcType, u16 i_index) +{ + u8 type = c_m3Type_unknown; + + if (i_funcType) + { + if (i_index < i_funcType->numRets) + { + type = i_funcType->types [i_index]; + } + } + + return type; +} + + +//--------------------------------------------------------------------------------------------------------------- + + +void FreeImportInfo (M3ImportInfo * i_info) +{ + m3_Free (i_info->moduleUtf8); + m3_Free (i_info->fieldUtf8); +} + + +void Function_Release (IM3Function i_function) +{ + m3_Free (i_function->constants); + + for (int i = 0; i < i_function->numNames; i++) + { + // name can be an alias of fieldUtf8 + if (i_function->names[i] != i_function->import.fieldUtf8) + { + m3_Free (i_function->names[i]); + } + } + + FreeImportInfo (& i_function->import); + + if (i_function->ownsWasmCode) + m3_Free (i_function->wasm); + + // Function_FreeCompiledCode (func); + +# if (d_m3EnableCodePageRefCounting) + { + m3_Free (i_function->codePageRefs); + i_function->numCodePageRefs = 0; + } +# endif +} + + +void Function_FreeCompiledCode (IM3Function i_function) +{ +# if (d_m3EnableCodePageRefCounting) + { + i_function->compiled = NULL; + + while (i_function->numCodePageRefs--) + { + IM3CodePage page = i_function->codePageRefs [i_function->numCodePageRefs]; + + if (--(page->info.usageCount) == 0) + { +// printf ("free %p\n", page); + } + } + + m3_Free (i_function->codePageRefs); + + Runtime_ReleaseCodePages (i_function->module->runtime); + } +# endif +} + + +cstr_t m3_GetFunctionName (IM3Function i_function) +{ + u16 numNames = 0; + cstr_t *names = GetFunctionNames(i_function, &numNames); + if (numNames > 0) + return names[0]; + else + return ""; +} + + +IM3Module m3_GetFunctionModule (IM3Function i_function) +{ + return i_function ? i_function->module : NULL; +} + + +cstr_t * GetFunctionNames (IM3Function i_function, u16 * o_numNames) +{ + if (!i_function || !o_numNames) + return NULL; + + if (i_function->import.fieldUtf8) + { + *o_numNames = 1; + return &i_function->import.fieldUtf8; + } + else + { + *o_numNames = i_function->numNames; + return i_function->names; + } +} + + +cstr_t GetFunctionImportModuleName (IM3Function i_function) +{ + return (i_function->import.moduleUtf8) ? i_function->import.moduleUtf8 : ""; +} + + +u16 GetFunctionNumArgs (IM3Function i_function) +{ + u16 numArgs = 0; + + if (i_function) + { + if (i_function->funcType) + numArgs = i_function->funcType->numArgs; + } + + return numArgs; +} + +u8 GetFunctionArgType (IM3Function i_function, u32 i_index) +{ + u8 type = c_m3Type_none; + + if (i_index < GetFunctionNumArgs (i_function)) + { + u32 numReturns = i_function->funcType->numRets; + + type = i_function->funcType->types [numReturns + i_index]; + } + + return type; +} + + +u16 GetFunctionNumReturns (IM3Function i_function) +{ + u16 numReturns = 0; + + if (i_function) + { + if (i_function->funcType) + numReturns = i_function->funcType->numRets; + } + + return numReturns; +} + + +u8 GetFunctionReturnType (const IM3Function i_function, u16 i_index) +{ + return i_function ? GetFuncTypeResultType (i_function->funcType, i_index) : c_m3Type_unknown; +} + + +u32 GetFunctionNumArgsAndLocals (IM3Function i_function) +{ + if (i_function) + return i_function->numLocals + GetFunctionNumArgs (i_function); + else + return 0; +} + diff --git a/wasm3-sys/wasm3/source/m3_function.h b/wasm3-sys/wasm3/source/m3_function.h new file mode 100644 index 0000000..e25b3f8 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_function.h @@ -0,0 +1,102 @@ +// +// m3_function.h +// +// Created by Steven Massey on 4/7/21. +// Copyright © 2021 Steven Massey. All rights reserved. +// + +#ifndef m3_function_h +#define m3_function_h + +#include "m3_core.h" + +d_m3BeginExternC + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3FuncType +{ + struct M3FuncType * next; + + u16 numRets; + u16 numArgs; + u8 types []; // returns, then args +} +M3FuncType; + +typedef M3FuncType * IM3FuncType; + + +M3Result AllocFuncType (IM3FuncType * o_functionType, u32 i_numTypes); +bool AreFuncTypesEqual (const IM3FuncType i_typeA, const IM3FuncType i_typeB); + +u16 GetFuncTypeNumParams (const IM3FuncType i_funcType); +u8 GetFuncTypeParamType (const IM3FuncType i_funcType, u16 i_index); + +u16 GetFuncTypeNumResults (const IM3FuncType i_funcType); +u8 GetFuncTypeResultType (const IM3FuncType i_funcType, u16 i_index); + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3Function +{ + struct M3Module * module; + + M3ImportInfo import; + + bytes_t wasm; + bytes_t wasmEnd; + + cstr_t names[d_m3MaxDuplicateFunctionImpl]; + u16 numNames; // maximum of d_m3MaxDuplicateFunctionImpl + + IM3FuncType funcType; + + pc_t compiled; + +# if (d_m3EnableCodePageRefCounting) + IM3CodePage * codePageRefs; // array of all pages used + u32 numCodePageRefs; +# endif + +# if defined (DEBUG) + u32 hits; + u32 index; +# endif + + u16 maxStackSlots; + + u16 numRetSlots; + u16 numRetAndArgSlots; + + u16 numLocals; // not including args + u16 numLocalBytes; + + bool ownsWasmCode; + + u16 numConstantBytes; + void * constants; +} +M3Function; + +void Function_Release (IM3Function i_function); +void Function_FreeCompiledCode (IM3Function i_function); + +cstr_t GetFunctionImportModuleName (IM3Function i_function); +cstr_t * GetFunctionNames (IM3Function i_function, u16 * o_numNames); +u16 GetFunctionNumArgs (IM3Function i_function); +u8 GetFunctionArgType (IM3Function i_function, u32 i_index); + +u16 GetFunctionNumReturns (IM3Function i_function); +u8 GetFunctionReturnType (const IM3Function i_function, u16 i_index); + +u32 GetFunctionNumArgsAndLocals (IM3Function i_function); + +cstr_t SPrintFunctionArgList (IM3Function i_function, m3stack_t i_sp); + +//--------------------------------------------------------------------------------------------------------------------------------- + + +d_m3EndExternC + +#endif /* m3_function_h */ diff --git a/wasm3-sys/wasm3/source/m3_info.c b/wasm3-sys/wasm3/source/m3_info.c new file mode 100644 index 0000000..2364296 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_info.c @@ -0,0 +1,513 @@ +// +// m3_info.c +// +// Created by Steven Massey on 4/27/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_env.h" +#include "m3_info.h" +#include "m3_emit.h" +#include "m3_compile.h" +#include "m3_exec.h" + +#ifdef DEBUG + +// a central function you can be breakpoint: +void ExceptionBreakpoint (cstr_t i_exception, cstr_t i_message) +{ + printf ("\nexception: '%s' @ %s\n", i_exception, i_message); + return; +} + + +typedef struct OpInfo +{ + IM3OpInfo info; + m3opcode_t opcode; +} +OpInfo; + +void m3_PrintM3Info () +{ + printf ("\n-- m3 configuration --------------------------------------------\n"); +// printf (" sizeof M3CodePage : %zu bytes (%d slots) \n", sizeof (M3CodePage), c_m3CodePageNumSlots); + printf (" sizeof M3MemPage : %u bytes \n", d_m3MemPageSize); + printf (" sizeof M3Compilation : %zu bytes \n", sizeof (M3Compilation)); + printf (" sizeof M3Function : %zu bytes \n", sizeof (M3Function)); + printf ("----------------------------------------------------------------\n\n"); +} + + +void * v_PrintEnvModuleInfo (IM3Module i_module, u32 * io_index) +{ + printf (" module [%u] name: '%s'; funcs: %d \n", * io_index++, i_module->name, i_module->numFunctions); + + return NULL; +} + + +void m3_PrintRuntimeInfo (IM3Runtime i_runtime) +{ + printf ("\n-- m3 runtime -------------------------------------------------\n"); + + printf (" stack-size: %zu \n\n", i_runtime->numStackSlots * sizeof (m3slot_t)); + + u32 moduleIndex = 0; + ForEachModule (i_runtime, (ModuleVisitor) v_PrintEnvModuleInfo, & moduleIndex); + + printf ("----------------------------------------------------------------\n\n"); +} + + +cstr_t GetTypeName (u8 i_m3Type) +{ + if (i_m3Type < 5) + return c_waTypes [i_m3Type]; + else + return "?"; +} + + +// TODO: these 'static char string []' aren't thread-friendly. though these functions are +// mainly for simple diagnostics during development, it'd be nice if they were fully reliable. + +cstr_t SPrintFuncTypeSignature (IM3FuncType i_funcType) +{ + static char string [256]; + + sprintf (string, "("); + + for (u32 i = 0; i < i_funcType->numArgs; ++i) + { + if (i != 0) + strcat (string, ", "); + + strcat (string, GetTypeName (d_FuncArgType(i_funcType, i))); + } + + strcat (string, ") -> "); + + for (u32 i = 0; i < i_funcType->numRets; ++i) + { + if (i != 0) + strcat (string, ", "); + + strcat (string, GetTypeName (d_FuncRetType(i_funcType, i))); + } + + return string; +} + + +size_t SPrintArg (char * o_string, size_t i_stringBufferSize, voidptr_t i_sp, u8 i_type) +{ + int len = 0; + + * o_string = 0; + + if (i_type == c_m3Type_i32) + len = snprintf (o_string, i_stringBufferSize, "%" PRIi32, * (i32 *) i_sp); + else if (i_type == c_m3Type_i64) + len = snprintf (o_string, i_stringBufferSize, "%" PRIi64, * (i64 *) i_sp); +#if d_m3HasFloat + else if (i_type == c_m3Type_f32) + len = snprintf (o_string, i_stringBufferSize, "%" PRIf32, * (f32 *) i_sp); + else if (i_type == c_m3Type_f64) + len = snprintf (o_string, i_stringBufferSize, "%" PRIf64, * (f64 *) i_sp); +#endif + + len = M3_MAX (0, len); + + return len; +} + + +cstr_t SPrintValue (void * i_value, u8 i_type) +{ + static char string [100]; + SPrintArg (string, 100, (m3stack_t) i_value, i_type); + return string; +} + + +cstr_t SPrintFunctionArgList (IM3Function i_function, m3stack_t i_sp) +{ + int ret; + static char string [256]; + + char * s = string; + ccstr_t e = string + sizeof(string) - 1; + + ret = snprintf (s, e-s, "("); + s += M3_MAX (0, ret); + + u64 * argSp = (u64 *) i_sp; + + IM3FuncType funcType = i_function->funcType; + if (funcType) + { + u32 numArgs = funcType->numArgs; + + for (u32 i = 0; i < numArgs; ++i) + { + u8 type = d_FuncArgType(funcType, i); + + ret = snprintf (s, e-s, "%s: ", c_waTypes [type]); + s += M3_MAX (0, ret); + + s += SPrintArg (s, e-s, argSp + i, type); + + if (i != numArgs - 1) { + ret = snprintf (s, e-s, ", "); + s += M3_MAX (0, ret); + } + } + } + else printf ("null signature"); + + ret = snprintf (s, e-s, ")"); + s += M3_MAX (0, ret); + + return string; +} + +static +OpInfo find_operation_info (IM3Operation i_operation) +{ + OpInfo opInfo = { NULL, 0 }; + + if (!i_operation) return opInfo; + + // TODO: find also extended opcodes + for (u32 i = 0; i <= 0xff; ++i) + { + IM3OpInfo oi = GetOpInfo (i); + + if (oi->type != c_m3Type_unknown) + { + for (u32 o = 0; o < 4; ++o) + { + if (oi->operations [o] == i_operation) + { + opInfo.info = oi; + opInfo.opcode = i; + break; + } + } + } + else break; + } + + return opInfo; +} + + +#undef fetch +#define fetch(TYPE) (* (TYPE *) ((*o_pc)++)) + +#define d_m3Decoder(FUNC) void Decode_##FUNC (char * o_string, u8 i_opcode, IM3Operation i_operation, IM3OpInfo i_opInfo, pc_t * o_pc) + +d_m3Decoder (Call) +{ + void * function = fetch (void *); + i32 stackOffset = fetch (i32); + + sprintf (o_string, "%p; stack-offset: %d", function, stackOffset); +} + + +d_m3Decoder (Entry) +{ + IM3Function function = fetch (IM3Function); + + // only prints out the first registered name for the function + sprintf (o_string, "%s", m3_GetFunctionName(function)); +} + + +d_m3Decoder (f64_Store) +{ + if (i_operation == i_opInfo->operations [0]) + { + u32 operand = fetch (u32); + u32 offset = fetch (u32); + + sprintf (o_string, "offset= slot:%d + immediate:%d", operand, offset); + } + +// sprintf (o_string, "%s", function->name); +} + + +d_m3Decoder (Branch) +{ + void * target = fetch (void *); + sprintf (o_string, "%p", target); +} + +d_m3Decoder (BranchTable) +{ + u32 slot = fetch (u32); + + o_string += sprintf (o_string, "slot: %" PRIu32 "; targets: ", slot); + +// IM3Function function = fetch2 (IM3Function); + + i32 targets = fetch (i32); + + for (i32 i = 0; i < targets; ++i) + { + pc_t addr = fetch (pc_t); + o_string += sprintf (o_string, "%" PRIi32 "=%p, ", i, addr); + } + + pc_t addr = fetch (pc_t); + sprintf (o_string, "def=%p ", addr); +} + + +d_m3Decoder (Const) +{ + u64 value = fetch (u64); i32 offset = fetch (i32); + sprintf (o_string, " slot [%d] = %" PRIu64, offset, value); +} + + +#undef fetch + +void DecodeOperation (char * o_string, u8 i_opcode, IM3Operation i_operation, IM3OpInfo i_opInfo, pc_t * o_pc) +{ + #define d_m3Decode(OPCODE, FUNC) case OPCODE: Decode_##FUNC (o_string, i_opcode, i_operation, i_opInfo, o_pc); break; + + switch (i_opcode) + { +// d_m3Decode (0xc0, Const) + d_m3Decode (0xc5, Entry) + d_m3Decode (c_waOp_call, Call) + d_m3Decode (c_waOp_branch, Branch) + d_m3Decode (c_waOp_branchTable, BranchTable) + d_m3Decode (0x39, f64_Store) + } +} + +// WARNING/TODO: this isn't fully implemented. it blindly assumes each word is a Operation pointer +// and, if an operation happens to missing from the c_operations table it won't be recognized here +void dump_code_page (IM3CodePage i_codePage, pc_t i_startPC) +{ + m3log (code, "code page seq: %d", i_codePage->info.sequence); + + pc_t pc = i_startPC ? i_startPC : GetPageStartPC (i_codePage); + pc_t end = GetPagePC (i_codePage); + + m3log (code, "---------------------------------------------------------------------------------------"); + + while (pc < end) + { + pc_t operationPC = pc; + IM3Operation op = (IM3Operation) (* pc++); + + OpInfo i = find_operation_info (op); + + if (i.info) + { + char infoString [8*1024] = { 0 }; + + DecodeOperation (infoString, i.opcode, op, i.info, & pc); + + m3log (code, "%p | %20s %s", operationPC, i.info->name, infoString); + } + else + m3log (code, "%p | %p", operationPC, op); + + } + + m3log (code, "---------------------------------------------------------------------------------------"); + + m3log (code, "free-lines: %d", i_codePage->info.numLines - i_codePage->info.lineIndex); +} + + +void dump_type_stack (IM3Compilation o) +{ + /* Reminders about how the stack works! :) + -- args & locals remain on the type stack for duration of the function. Denoted with a constant 'A' and 'L' in this dump. + -- the initial stack dumps originate from the CompileLocals () function, so these identifiers won't/can't be + applied until this compilation stage is finished + -- constants are not statically represented in the type stack (like args & constants) since they don't have/need + write counts + + -- the number shown for static args and locals (value in wasmStack [i]) represents the write count for the variable + + -- (does Wasm ever write to an arg? I dunno/don't remember.) + -- the number for the dynamic stack values represents the slot number. + -- if the slot index points to arg, local or constant it's denoted with a lowercase 'a', 'l' or 'c' + + */ + + // for the assert at end of dump: + i32 regAllocated [2] = { (i32) IsRegisterAllocated (o, 0), (i32) IsRegisterAllocated (o, 1) }; + + // display whether r0 or fp0 is allocated. these should then also be reflected somewhere in the stack too. + d_m3Log(stack, "\n"); + d_m3Log(stack, " "); + printf ("%s %s ", regAllocated [0] ? "(r0)" : " ", regAllocated [1] ? "(fp0)" : " "); + printf("\n"); + + for (u32 p = 1; p <= 2; ++p) + { + d_m3Log(stack, " "); + + for (u32 i = 0; i < o->stackIndex; ++i) + { + if (i > 0 and i == o->stackFirstDynamicIndex) + printf ("#"); + + if (i == o->block.blockStackIndex) + printf (">"); + + const char * type = c_waCompactTypes [o->typeStack [i]]; + + const char * location = ""; + + i32 slot = o->wasmStack [i]; + + if (IsRegisterSlotAlias (slot)) + { + bool isFp = IsFpRegisterSlotAlias (slot); + location = isFp ? "/f" : "/r"; + + regAllocated [isFp]--; + slot = -1; + } + else + { + if (slot < o->slotFirstDynamicIndex) + { + if (slot >= o->slotFirstConstIndex) + location = "c"; + else if (slot >= o->function->numRetAndArgSlots) + location = "L"; + else + location = "a"; + } + } + + char item [100]; + + if (slot >= 0) + sprintf (item, "%s%s%d", type, location, slot); + else + sprintf (item, "%s%s", type, location); + + if (p == 1) + { + size_t s = strlen (item); + + sprintf (item, "%d", i); + + while (strlen (item) < s) + strcat (item, " "); + } + + printf ("|%s ", item); + + } + printf ("\n"); + } + +// for (u32 r = 0; r < 2; ++r) +// d_m3Assert (regAllocated [r] == 0); // reg allocation & stack out of sync + + u16 maxSlot = GetMaxUsedSlotPlusOne (o); + + if (maxSlot > o->slotFirstDynamicIndex) + { + d_m3Log (stack, " -"); + + for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) + printf ("----"); + + printf ("\n"); + + d_m3Log (stack, " slot |"); + for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) + printf ("%3d|", i); + + printf ("\n"); + d_m3Log (stack, " alloc |"); + + for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) + { + printf ("%3d|", o->m3Slots [i]); + } + + printf ("\n"); + } + d_m3Log(stack, "\n"); +} + + +static const char * GetOpcodeIndentionString (i32 blockDepth) +{ + blockDepth += 1; + + if (blockDepth < 0) + blockDepth = 0; + + static const char * s_spaces = "......................................................................................."; + const char * indent = s_spaces + strlen (s_spaces); + indent -= (blockDepth * 2); + if (indent < s_spaces) + indent = s_spaces; + + return indent; +} + + +const char * get_indention_string (IM3Compilation o) +{ + return GetOpcodeIndentionString (o->block.depth+4); +} + + +void log_opcode (IM3Compilation o, m3opcode_t i_opcode) +{ + i32 depth = o->block.depth; + if (i_opcode == c_waOp_end or i_opcode == c_waOp_else) + depth--; + + m3log (compile, "%4d | 0x%02x %s %s", o->numOpcodes++, i_opcode, GetOpcodeIndentionString (depth), GetOpInfo(i_opcode)->name); +} + + +void emit_stack_dump (IM3Compilation o) +{ +# if d_m3EnableOpTracing + if (o->numEmits) + { + EmitOp (o, op_DumpStack); + EmitConstant32 (o, o->numOpcodes); + EmitConstant32 (o, GetMaxUsedSlotPlusOne(o)); + EmitPointer (o, o->function); + + o->numEmits = 0; + } +# endif +} + + +void log_emit (IM3Compilation o, IM3Operation i_operation) +{ + OpInfo i = find_operation_info (i_operation); + + d_m3Log(emit, ""); + if (i.info) + { + printf ("%p: %s\n", GetPC (o), i.info->name); + } + else printf ("not found: %p\n", i_operation); +} + +#endif // DEBUG + diff --git a/wasm3-sys/wasm3/source/m3_info.h b/wasm3-sys/wasm3/source/m3_info.h new file mode 100644 index 0000000..19f36cc --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_info.h @@ -0,0 +1,37 @@ +// +// m3_info.h +// +// Created by Steven Massey on 12/6/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_info_h +#define m3_info_h + +#include "m3_compile.h" + +d_m3BeginExternC + +#ifdef DEBUG + +void dump_type_stack (IM3Compilation o); +void log_opcode (IM3Compilation o, m3opcode_t i_opcode); +const char * get_indention_string (IM3Compilation o); +void emit_stack_dump (IM3Compilation o); +void log_emit (IM3Compilation o, IM3Operation i_operation); + +cstr_t SPrintFuncTypeSignature (IM3FuncType i_funcType); + +#else // DEBUG + +#define dump_type_stack(...) {} +#define log_opcode(...) {} +#define get_indention_string(...) "" +#define emit_stack_dump(...) {} +#define log_emit(...) {} + +#endif // DEBUG + +d_m3EndExternC + +#endif // m3_info_h diff --git a/wasm3-sys/wasm3/source/m3_math_utils.h b/wasm3-sys/wasm3/source/m3_math_utils.h new file mode 100644 index 0000000..8c1b091 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_math_utils.h @@ -0,0 +1,268 @@ +// +// m3_math_utils.h +// +// Created by Volodymyr Shymanksyy on 8/10/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef m3_math_utils_h +#define m3_math_utils_h + +#include "m3_core.h" + +#include + +#if defined(M3_COMPILER_MSVC) + +#include + +#define __builtin_popcount __popcnt + +static inline +int __builtin_ctz(uint32_t x) { + unsigned long ret; + _BitScanForward(&ret, x); + return (int)ret; +} + +static inline +int __builtin_clz(uint32_t x) { + unsigned long ret; + _BitScanReverse(&ret, x); + return (int)(31 ^ ret); +} + + + +#ifdef _WIN64 + +#define __builtin_popcountll __popcnt64 + +static inline +int __builtin_ctzll(uint64_t value) { + unsigned long ret; + _BitScanForward64(&ret, value); + return (int)ret; +} + +static inline +int __builtin_clzll(uint64_t value) { + unsigned long ret; + _BitScanReverse64(&ret, value); + return (int)(63 ^ ret); +} + +#else // _WIN64 + +#define __builtin_popcountll(x) (__popcnt((x) & 0xFFFFFFFF) + __popcnt((x) >> 32)) + +static inline +int __builtin_ctzll(uint64_t value) { + //if (value == 0) return 64; // Note: ctz(0) result is undefined anyway + uint32_t msh = (uint32_t)(value >> 32); + uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); + if (lsh != 0) return __builtin_ctz(lsh); + return 32 + __builtin_ctz(msh); +} + +static inline +int __builtin_clzll(uint64_t value) { + //if (value == 0) return 64; // Note: clz(0) result is undefined anyway + uint32_t msh = (uint32_t)(value >> 32); + uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); + if (msh != 0) return __builtin_clz(msh); + return 32 + __builtin_clz(lsh); +} + +#endif // _WIN64 + +#endif // defined(M3_COMPILER_MSVC) + + +// TODO: not sure why, signbit is actually defined in math.h +#if (defined(ESP8266) || defined(ESP32)) && !defined(signbit) + #define signbit(__x) \ + ((sizeof(__x) == sizeof(float)) ? __signbitf(__x) : __signbitd(__x)) +#endif + +#if defined(__AVR__) + +static inline +float rintf( float arg ) { + union { float f; uint32_t i; } u; + u.f = arg; + uint32_t ux = u.i & 0x7FFFFFFF; + if (UNLIKELY(ux == 0 || ux > 0x5A000000)) { + return arg; + } + return (float)lrint(arg); +} + +static inline +double rint( double arg ) { + union { double f; uint32_t i[2]; } u; + u.f = arg; + uint32_t ux = u.i[1] & 0x7FFFFFFF; + if (UNLIKELY((ux == 0 && u.i[0] == 0) || ux > 0x433FFFFF)) { + return arg; + } + return (double)lrint(arg); +} + +//TODO +static inline +uint64_t strtoull(const char* str, char** endptr, int base) { + return 0; +} + +#endif + +/* + * Rotr, Rotl + */ + +static inline +u32 rotl32(u32 n, unsigned c) { + const unsigned mask = CHAR_BIT * sizeof(n) - 1; + c &= mask & 31; + return (n << c) | (n >> ((-c) & mask)); +} + +static inline +u32 rotr32(u32 n, unsigned c) { + const unsigned mask = CHAR_BIT * sizeof(n) - 1; + c &= mask & 31; + return (n >> c) | (n << ((-c) & mask)); +} + +static inline +u64 rotl64(u64 n, unsigned c) { + const unsigned mask = CHAR_BIT * sizeof(n) - 1; + c &= mask & 63; + return (n << c) | (n >> ((-c) & mask)); +} + +static inline +u64 rotr64(u64 n, unsigned c) { + const unsigned mask = CHAR_BIT * sizeof(n) - 1; + c &= mask & 63; + return (n >> c) | (n << ((-c) & mask)); +} + +/* + * Integer Div, Rem + */ + +#define OP_DIV_U(RES, A, B) \ + if (UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ + RES = A / B; + +#define OP_REM_U(RES, A, B) \ + if (UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ + RES = A % B; + +// 2's complement detection +#if (INT_MIN != -INT_MAX) + + #define OP_DIV_S(RES, A, B, TYPE_MIN) \ + if (UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ + if (UNLIKELY(B == -1 and A == TYPE_MIN)) { \ + newTrap (m3Err_trapIntegerOverflow); \ + } \ + RES = A / B; + + #define OP_REM_S(RES, A, B, TYPE_MIN) \ + if (UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ + if (UNLIKELY(B == -1 and A == TYPE_MIN)) RES = 0; \ + else RES = A % B; + +#else + + #define OP_DIV_S(RES, A, B, TYPE_MIN) OP_DIV_U(RES, A, B) + #define OP_REM_S(RES, A, B, TYPE_MIN) OP_REM_U(RES, A, B) + +#endif + +/* + * Trunc + */ + +#define OP_TRUNC(RES, A, TYPE, RMIN, RMAX) \ + if (UNLIKELY(isnan(A))) { \ + newTrap (m3Err_trapIntegerConversion); \ + } \ + if (UNLIKELY(A <= RMIN or A >= RMAX)) { \ + newTrap (m3Err_trapIntegerOverflow); \ + } \ + RES = (TYPE)A; + + +#define OP_I32_TRUNC_F32(RES, A) OP_TRUNC(RES, A, i32, -2147483904.0f, 2147483648.0f) +#define OP_U32_TRUNC_F32(RES, A) OP_TRUNC(RES, A, u32, -1.0f, 4294967296.0f) +#define OP_I32_TRUNC_F64(RES, A) OP_TRUNC(RES, A, i32, -2147483649.0 , 2147483648.0 ) +#define OP_U32_TRUNC_F64(RES, A) OP_TRUNC(RES, A, u32, -1.0 , 4294967296.0 ) + +#define OP_I64_TRUNC_F32(RES, A) OP_TRUNC(RES, A, i64, -9223373136366403584.0f, 9223372036854775808.0f) +#define OP_U64_TRUNC_F32(RES, A) OP_TRUNC(RES, A, u64, -1.0f, 18446744073709551616.0f) +#define OP_I64_TRUNC_F64(RES, A) OP_TRUNC(RES, A, i64, -9223372036854777856.0 , 9223372036854775808.0 ) +#define OP_U64_TRUNC_F64(RES, A) OP_TRUNC(RES, A, u64, -1.0 , 18446744073709551616.0 ) + +#define OP_TRUNC_SAT(RES, A, TYPE, RMIN, RMAX, IMIN, IMAX) \ + if (UNLIKELY(isnan(A))) { \ + RES = 0; \ + } else if (UNLIKELY(A <= RMIN)) { \ + RES = IMIN; \ + } else if (UNLIKELY(A >= RMAX)) { \ + RES = IMAX; \ + } else { \ + RES = (TYPE)A; \ + } + +#define OP_I32_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, i32, -2147483904.0f, 2147483648.0f, INT32_MIN, INT32_MAX) +#define OP_U32_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, u32, -1.0f, 4294967296.0f, 0UL, UINT32_MAX) +#define OP_I32_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, i32, -2147483649.0 , 2147483648.0, INT32_MIN, INT32_MAX) +#define OP_U32_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, u32, -1.0 , 4294967296.0, 0UL, UINT32_MAX) + +#define OP_I64_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, i64, -9223373136366403584.0f, 9223372036854775808.0f, INT64_MIN, INT64_MAX) +#define OP_U64_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, u64, -1.0f, 18446744073709551616.0f, 0ULL, UINT64_MAX) +#define OP_I64_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, i64, -9223372036854777856.0 , 9223372036854775808.0, INT64_MIN, INT64_MAX) +#define OP_U64_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, u64, -1.0 , 18446744073709551616.0, 0ULL, UINT64_MAX) + +/* + * Min, Max + */ + +#if d_m3HasFloat + +#include + +static inline +f32 min_f32(f32 a, f32 b) { + if (UNLIKELY(isnan(a) or isnan(b))) return NAN; + if (UNLIKELY(a == 0 and a == b)) return signbit(a) ? a : b; + return a > b ? b : a; +} + +static inline +f32 max_f32(f32 a, f32 b) { + if (UNLIKELY(isnan(a) or isnan(b))) return NAN; + if (UNLIKELY(a == 0 and a == b)) return signbit(a) ? b : a; + return a > b ? a : b; +} + +static inline +f64 min_f64(f64 a, f64 b) { + if (UNLIKELY(isnan(a) or isnan(b))) return NAN; + if (UNLIKELY(a == 0 and a == b)) return signbit(a) ? a : b; + return a > b ? b : a; +} + +static inline +f64 max_f64(f64 a, f64 b) { + if (UNLIKELY(isnan(a) or isnan(b))) return NAN; + if (UNLIKELY(a == 0 and a == b)) return signbit(a) ? b : a; + return a > b ? a : b; +} +#endif + +#endif // m3_math_utils_h diff --git a/wasm3-sys/wasm3/source/m3_module.c b/wasm3-sys/wasm3/source/m3_module.c new file mode 100644 index 0000000..d6ba8d8 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_module.c @@ -0,0 +1,164 @@ +// +// m3_module.c +// +// Created by Steven Massey on 5/7/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_env.h" +#include "m3_exception.h" + + +void Module_FreeFunctions (IM3Module i_module) +{ + for (u32 i = 0; i < i_module->numFunctions; ++i) + { + IM3Function func = & i_module->functions [i]; + Function_Release (func); + } +} + + +void m3_FreeModule (IM3Module i_module) +{ + if (i_module) + { + m3log (module, "freeing module: %s (funcs: %d; segments: %d)", + i_module->name, i_module->numFunctions, i_module->numDataSegments); + + Module_FreeFunctions (i_module); + + m3_Free (i_module->functions); + //m3_Free (i_module->imports); + m3_Free (i_module->funcTypes); + m3_Free (i_module->dataSegments); + m3_Free (i_module->table0); + + for (u32 i = 0; i < i_module->numGlobals; ++i) + { + m3_Free (i_module->globals[i].name); + FreeImportInfo(&(i_module->globals[i].import)); + } + m3_Free (i_module->globals); + + m3_Free (i_module); + } +} + + +M3Result Module_AddGlobal (IM3Module io_module, IM3Global * o_global, u8 i_type, bool i_mutable, bool i_isImported) +{ + M3Result result = m3Err_none; +_try { + u32 index = io_module->numGlobals++; + io_module->globals = m3_ReallocArray (M3Global, io_module->globals, io_module->numGlobals, index); + _throwifnull(io_module->globals); + M3Global * global = & io_module->globals [index]; + + global->type = i_type; + global->imported = i_isImported; + global->isMutable = i_mutable; + + if (o_global) + * o_global = global; + +} _catch: + return result; +} + + +M3Result Module_AddFunction (IM3Module io_module, u32 i_typeIndex, IM3ImportInfo i_importInfo) +{ + M3Result result = m3Err_none; + +_try { + + u32 index = io_module->numFunctions++; + io_module->functions = m3_ReallocArray (M3Function, io_module->functions, io_module->numFunctions, index); + + _throwifnull (io_module->functions); + _throwif ("type sig index out of bounds", i_typeIndex >= io_module->numFuncTypes); + + IM3FuncType ft = io_module->funcTypes [i_typeIndex]; + + IM3Function func = Module_GetFunction (io_module, index); + func->funcType = ft; + +# ifdef DEBUG + func->index = index; +# endif + + if (i_importInfo and func->numNames == 0) + { + func->import = * i_importInfo; + func->names[0] = i_importInfo->fieldUtf8; + func->numNames = 1; + } + + m3log (module, " added function: %3d; sig: %d", index, i_typeIndex); + +} _catch: + return result; +} + +#ifdef DEBUG +void Module_GenerateNames (IM3Module i_module) +{ + for (u32 i = 0; i < i_module->numFunctions; ++i) + { + IM3Function func = & i_module->functions [i]; + + if (func->numNames == 0) + { + char* buff = m3_AllocArray(char, 16); + snprintf(buff, 16, "$func%d", i); + func->names[0] = buff; + func->numNames = 1; + } + } + for (u32 i = 0; i < i_module->numGlobals; ++i) + { + IM3Global global = & i_module->globals [i]; + + if (global->name == NULL) + { + char* buff = m3_AllocArray(char, 16); + snprintf(buff, 16, "$global%d", i); + global->name = buff; + } + } +} +#endif + +IM3Function Module_GetFunction (IM3Module i_module, u32 i_functionIndex) +{ + IM3Function func = NULL; + + if (i_functionIndex < i_module->numFunctions) + { + func = & i_module->functions [i_functionIndex]; + //func->module = i_module; + } + + return func; +} + + +const char* m3_GetModuleName (IM3Module i_module) +{ + if (!i_module || !i_module->name) + return ".unnamed"; + + return i_module->name; +} + +void m3_SetModuleName (IM3Module i_module, const char* name) +{ + if (i_module) i_module->name = name; +} + +IM3Runtime m3_GetModuleRuntime (IM3Module i_module) +{ + return i_module ? i_module->runtime : NULL; +} + diff --git a/wasm3-sys/wasm3/source/m3_optimize.c b/wasm3-sys/wasm3/source/m3_optimize.c new file mode 100644 index 0000000..7730b5a --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_optimize.c @@ -0,0 +1,12 @@ +// +// m3_optimize.c +// +// Created by Steven Massey on 4/27/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_compile.h" +#include "m3_exec.h" + + +// not currently used diff --git a/wasm3-sys/wasm3/source/m3_parse.c b/wasm3-sys/wasm3/source/m3_parse.c new file mode 100644 index 0000000..00e01b0 --- /dev/null +++ b/wasm3-sys/wasm3/source/m3_parse.c @@ -0,0 +1,639 @@ +// +// m3_parse.c +// +// Created by Steven Massey on 4/19/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_env.h" +#include "m3_compile.h" +#include "m3_exec.h" +#include "m3_exception.h" +#include "m3_info.h" + + +M3Result ParseType_Table (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + return result; +} + + +M3Result ParseType_Memory (M3MemoryInfo * o_memory, bytes_t * io_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u8 flag; + +_ (ReadLEB_u7 (& flag, io_bytes, i_end)); // really a u1 +_ (ReadLEB_u32 (& o_memory->initPages, io_bytes, i_end)); + + o_memory->maxPages = 0; + if (flag) +_ (ReadLEB_u32 (& o_memory->maxPages, io_bytes, i_end)); + + _catch: return result; +} + + +M3Result ParseSection_Type (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + IM3FuncType ftype = NULL; + +_try { + u32 numTypes; +_ (ReadLEB_u32 (& numTypes, & i_bytes, i_end)); m3log (parse, "** Type [%d]", numTypes); + + _throwif("too many types", numTypes > d_m3MaxSaneTypesCount); + + if (numTypes) + { + // table of IM3FuncType (that point to the actual M3FuncType struct in the Environment) + io_module->funcTypes = m3_AllocArray (IM3FuncType, numTypes); + _throwifnull (io_module->funcTypes); + io_module->numFuncTypes = numTypes; + + for (u32 i = 0; i < numTypes; ++i) + { + i8 form; +_ (ReadLEB_i7 (& form, & i_bytes, i_end)); + _throwif (m3Err_wasmMalformed, form != -32); // for Wasm MVP + + u32 numArgs; +_ (ReadLEB_u32 (& numArgs, & i_bytes, i_end)); + + _throwif (m3Err_tooManyArgsRets, numArgs > d_m3MaxSaneFunctionArgRetCount); +#if defined(M3_COMPILER_MSVC) + u8 argTypes [d_m3MaxSaneFunctionArgRetCount]; +#else + u8 argTypes[numArgs+1]; // make ubsan happy +#endif + for (u32 a = 0; a < numArgs; ++a) + { + i8 wasmType; + u8 argType; +_ (ReadLEB_i7 (& wasmType, & i_bytes, i_end)); +_ (NormalizeType (& argType, wasmType)); + + argTypes[a] = argType; + } + + u32 numRets; +_ (ReadLEB_u32 (& numRets, & i_bytes, i_end)); + _throwif (m3Err_tooManyArgsRets, (u64)(numRets) + numArgs > d_m3MaxSaneFunctionArgRetCount); + +_ (AllocFuncType (& ftype, numRets + numArgs)); + ftype->numArgs = numArgs; + ftype->numRets = numRets; + + for (u32 r = 0; r < numRets; ++r) + { + i8 wasmType; + u8 retType; +_ (ReadLEB_i7 (& wasmType, & i_bytes, i_end)); +_ (NormalizeType (& retType, wasmType)); + + ftype->types[r] = retType; + } + memcpy (ftype->types + numRets, argTypes, numArgs); m3log (parse, " type %2d: %s", i, SPrintFuncTypeSignature (ftype)); + + Environment_AddFuncType (io_module->environment, & ftype); + io_module->funcTypes [i] = ftype; + ftype = NULL; // ownership transfered to environment + } + } + +} _catch: + + if (result) + { + m3_Free (ftype); + // FIX: M3FuncTypes in the table are leaked + m3_Free (io_module->funcTypes); + io_module->numFuncTypes = 0; + } + + return result; +} + + +M3Result ParseSection_Function (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u32 numFunctions; +_ (ReadLEB_u32 (& numFunctions, & i_bytes, i_end)); m3log (parse, "** Function [%d]", numFunctions); + + _throwif("too many functions", numFunctions > d_m3MaxSaneFunctionsCount); + + // TODO: prealloc functions + + for (u32 i = 0; i < numFunctions; ++i) + { + u32 funcTypeIndex; +_ (ReadLEB_u32 (& funcTypeIndex, & i_bytes, i_end)); + +_ (Module_AddFunction (io_module, funcTypeIndex, NULL /* import info */)); + } + + _catch: return result; +} + + +M3Result ParseSection_Import (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + M3ImportInfo import = { NULL, NULL }, clearImport = { NULL, NULL }; + + u32 numImports; +_ (ReadLEB_u32 (& numImports, & i_bytes, i_end)); m3log (parse, "** Import [%d]", numImports); + + _throwif("too many imports", numImports > d_m3MaxSaneImportsCount); + + for (u32 i = 0; i < numImports; ++i) + { + u8 importKind; + +_ (Read_utf8 (& import.moduleUtf8, & i_bytes, i_end)); +_ (Read_utf8 (& import.fieldUtf8, & i_bytes, i_end)); +_ (Read_u8 (& importKind, & i_bytes, i_end)); m3log (parse, " kind: %d '%s.%s' ", + (u32) importKind, import.moduleUtf8, import.fieldUtf8); + switch (importKind) + { + case d_externalKind_function: + { + u32 typeIndex; +_ (ReadLEB_u32 (& typeIndex, & i_bytes, i_end)) + +_ (Module_AddFunction (io_module, typeIndex, & import)) + import = clearImport; + + io_module->numFuncImports++; + } + break; + + case d_externalKind_table: +// result = ParseType_Table (& i_bytes, i_end); + break; + + case d_externalKind_memory: + { +_ (ParseType_Memory (& io_module->memoryInfo, & i_bytes, i_end)); + io_module->memoryImported = true; + } + break; + + case d_externalKind_global: + { + i8 waType; + u8 type, isMutable; + +_ (ReadLEB_i7 (& waType, & i_bytes, i_end)); +_ (NormalizeType (& type, waType)); +_ (ReadLEB_u7 (& isMutable, & i_bytes, i_end)); m3log (parse, " global: %s mutable=%d", c_waTypes [type], (u32) isMutable); + + IM3Global global; +_ (Module_AddGlobal (io_module, & global, type, isMutable, true /* isImport */)); + global->import = import; + import = clearImport; + } + break; + + default: + _throw (m3Err_wasmMalformed); + } + + FreeImportInfo (& import); + } + + _catch: + + FreeImportInfo (& import); + + return result; +} + + +M3Result ParseSection_Export (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + const char * utf8 = NULL; + + u32 numExports; +_ (ReadLEB_u32 (& numExports, & i_bytes, i_end)); m3log (parse, "** Export [%d]", numExports); + + _throwif("too many exports", numExports > d_m3MaxSaneExportsCount); + + for (u32 i = 0; i < numExports; ++i) + { + u8 exportKind; + u32 index; + +_ (Read_utf8 (& utf8, & i_bytes, i_end)); +_ (Read_u8 (& exportKind, & i_bytes, i_end)); +_ (ReadLEB_u32 (& index, & i_bytes, i_end)); m3log (parse, " index: %3d; kind: %d; export: '%s'; ", index, (u32) exportKind, utf8); + + if (exportKind == d_externalKind_function) + { + _throwif(m3Err_wasmMalformed, index >= io_module->numFunctions); + IM3Function func = &(io_module->functions [index]); + if (func->numNames < d_m3MaxDuplicateFunctionImpl) + { + func->names[func->numNames++] = utf8; + utf8 = NULL; // ownership transferred to M3Function + } + } + else if (exportKind == d_externalKind_global) + { + _throwif(m3Err_wasmMalformed, index >= io_module->numGlobals); + IM3Global global = &(io_module->globals [index]); + m3_Free (global->name); + global->name = utf8; + utf8 = NULL; // ownership transferred to M3Global + } + + m3_Free (utf8); + } + +_catch: + m3_Free (utf8); + return result; +} + + +M3Result ParseSection_Start (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u32 startFuncIndex; +_ (ReadLEB_u32 (& startFuncIndex, & i_bytes, i_end)); m3log (parse, "** Start Function: %d", startFuncIndex); + + if (startFuncIndex < io_module->numFunctions) + { + io_module->startFunction = startFuncIndex; + } + else result = "start function index out of bounds"; + + _catch: return result; +} + + +M3Result Parse_InitExpr (M3Module * io_module, bytes_t * io_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + // this doesn't generate code pages. just walks the wasm bytecode to find the end + +#if defined(d_m3PreferStaticAlloc) + static M3Compilation compilation; +#else + M3Compilation compilation; +#endif + compilation = (M3Compilation){ .runtime = NULL, .module = io_module, .wasm = * io_bytes, .wasmEnd = i_end }; + + result = CompileBlockStatements (& compilation); + + * io_bytes = compilation.wasm; + + return result; +} + + +M3Result ParseSection_Element (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u32 numSegments; + result = ReadLEB_u32 (& numSegments, & i_bytes, i_end); m3log (parse, "** Element [%d]", numSegments); + + _throwif ("error parsing Element section", result); + + _throwif ("too many element segments", numSegments > d_m3MaxSaneElementSegments); + + io_module->elementSection = i_bytes; + io_module->elementSectionEnd = i_end; + io_module->numElementSegments = numSegments; + + _catch: return result; +} + + +M3Result ParseSection_Code (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result; + + u32 numFunctions; +_ (ReadLEB_u32 (& numFunctions, & i_bytes, i_end)); m3log (parse, "** Code [%d]", numFunctions); + + if (numFunctions != io_module->numFunctions - io_module->numFuncImports) + { + _throw ("mismatched function count in code section"); + } + + for (u32 f = 0; f < numFunctions; ++f) + { + const u8 * start = i_bytes; + + u32 size; +_ (ReadLEB_u32 (& size, & i_bytes, i_end)); + + if (size) + { + const u8 * ptr = i_bytes; + i_bytes += size; + + if (i_bytes <= i_end) + { + /* + u32 numLocalBlocks; +_ (ReadLEB_u32 (& numLocalBlocks, & ptr, i_end)); m3log (parse, " code size: %-4d", size); + + u32 numLocals = 0; + + for (u32 l = 0; l < numLocalBlocks; ++l) + { + u32 varCount; + i8 wasmType; + u8 normalType; + +_ (ReadLEB_u32 (& varCount, & ptr, i_end)); +_ (ReadLEB_i7 (& wasmType, & ptr, i_end)); +_ (NormalizeType (& normalType, wasmType)); + + numLocals += varCount; m3log (parse, " %2d locals; type: '%s'", varCount, c_waTypes [normalType]); + } + */ + + IM3Function func = Module_GetFunction (io_module, f + io_module->numFuncImports); + + func->module = io_module; + func->wasm = start; + func->wasmEnd = i_bytes; + //func->ownsWasmCode = io_module->hasWasmCodeCopy; +// func->numLocals = numLocals; + } + else _throw (m3Err_wasmSectionOverrun); + } + } + + _catch: + + if (not result and i_bytes != i_end) + result = m3Err_wasmSectionUnderrun; + + return result; +} + + +M3Result ParseSection_Data (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u32 numDataSegments; +_ (ReadLEB_u32 (& numDataSegments, & i_bytes, i_end)); m3log (parse, "** Data [%d]", numDataSegments); + + _throwif("too many data segments", numDataSegments > d_m3MaxSaneDataSegments); + + io_module->dataSegments = m3_AllocArray (M3DataSegment, numDataSegments); + _throwifnull(io_module->dataSegments); + io_module->numDataSegments = numDataSegments; + + for (u32 i = 0; i < numDataSegments; ++i) + { + M3DataSegment * segment = & io_module->dataSegments [i]; + +_ (ReadLEB_u32 (& segment->memoryRegion, & i_bytes, i_end)); + + segment->initExpr = i_bytes; +_ (Parse_InitExpr (io_module, & i_bytes, i_end)); + segment->initExprSize = (u32) (i_bytes - segment->initExpr); + + _throwif (m3Err_wasmMissingInitExpr, segment->initExprSize <= 1); + +_ (ReadLEB_u32 (& segment->size, & i_bytes, i_end)); + segment->data = i_bytes; m3log (parse, " segment [%u] memory: %u; expr-size: %d; size: %d", + i, segment->memoryRegion, segment->initExprSize, segment->size); + i_bytes += segment->size; + + _throwif("data segment underflow", i_bytes > i_end); + } + + _catch: + + return result; +} + + +M3Result ParseSection_Memory (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + // TODO: MVP; assert no memory imported + + u32 numMemories; +_ (ReadLEB_u32 (& numMemories, & i_bytes, i_end)); m3log (parse, "** Memory [%d]", numMemories); + + _throwif (m3Err_tooManyMemorySections, numMemories != 1); + + ParseType_Memory (& io_module->memoryInfo, & i_bytes, i_end); + + _catch: return result; +} + + +M3Result ParseSection_Global (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u32 numGlobals; +_ (ReadLEB_u32 (& numGlobals, & i_bytes, i_end)); m3log (parse, "** Global [%d]", numGlobals); + + _throwif("too many globals", numGlobals > d_m3MaxSaneGlobalsCount); + + for (u32 i = 0; i < numGlobals; ++i) + { + i8 waType; + u8 type, isMutable; + +_ (ReadLEB_i7 (& waType, & i_bytes, i_end)); +_ (NormalizeType (& type, waType)); +_ (ReadLEB_u7 (& isMutable, & i_bytes, i_end)); m3log (parse, " global: [%d] %s mutable: %d", i, c_waTypes [type], (u32) isMutable); + + IM3Global global; +_ (Module_AddGlobal (io_module, & global, type, isMutable, false /* isImport */)); + + global->initExpr = i_bytes; +_ (Parse_InitExpr (io_module, & i_bytes, i_end)); + global->initExprSize = (u32) (i_bytes - global->initExpr); + + _throwif (m3Err_wasmMissingInitExpr, global->initExprSize <= 1); + } + + _catch: return result; +} + + +M3Result ParseSection_Custom (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result; + + cstr_t name; +_ (Read_utf8 (& name, & i_bytes, i_end)); + m3log (parse, "** Custom: '%s'", name); + if (strcmp (name, "name") != 0) + i_bytes = i_end; + + m3_Free (name); + + while (i_bytes < i_end) + { + u8 nameType; + u32 payloadLength; + +_ (ReadLEB_u7 (& nameType, & i_bytes, i_end)); +_ (ReadLEB_u32 (& payloadLength, & i_bytes, i_end)); + + bytes_t start = i_bytes; + if (nameType == 1) + { + u32 numNames; +_ (ReadLEB_u32 (& numNames, & i_bytes, i_end)); + + _throwif("too many names", numNames > d_m3MaxSaneFunctionsCount); + + for (u32 i = 0; i < numNames; ++i) + { + u32 index; +_ (ReadLEB_u32 (& index, & i_bytes, i_end)); +_ (Read_utf8 (& name, & i_bytes, i_end)); + + if (index < io_module->numFunctions) + { + IM3Function func = &(io_module->functions [index]); + if (func->numNames == 0) + { + func->names[0] = name; m3log (parse, " naming function%5d: %s", index, name); + func->numNames = 1; + name = NULL; // transfer ownership + } +// else m3log (parse, "prenamed: %s", io_module->functions [index].name); + } + + m3_Free (name); + } + } + + i_bytes = start + payloadLength; + } + + _catch: return result; +} + + +M3Result ParseModuleSection (M3Module * o_module, u8 i_sectionType, bytes_t i_bytes, u32 i_numBytes) +{ + M3Result result = m3Err_none; + + typedef M3Result (* M3Parser) (M3Module *, bytes_t, cbytes_t); + + static M3Parser s_parsers [] = + { + ParseSection_Custom, // 0 + ParseSection_Type, // 1 + ParseSection_Import, // 2 + ParseSection_Function, // 3 + NULL, // 4: TODO Table + ParseSection_Memory, // 5 + ParseSection_Global, // 6 + ParseSection_Export, // 7 + ParseSection_Start, // 8 + ParseSection_Element, // 9 + ParseSection_Code, // 10 + ParseSection_Data, // 11 + NULL, // 12: TODO DataCount + }; + + M3Parser parser = NULL; + + if (i_sectionType <= 12) + parser = s_parsers [i_sectionType]; + + if (parser) + { + cbytes_t end = i_bytes + i_numBytes; + result = parser (o_module, i_bytes, end); + } + else + { + m3log (parse, " skipped section type: %d", (u32) i_sectionType); + } + + return result; +} + + +M3Result m3_ParseModule (IM3Environment i_environment, IM3Module * o_module, cbytes_t i_bytes, u32 i_numBytes) +{ + M3Result result; m3log (parse, "load module: %d bytes", i_numBytes); + + IM3Module module; +_try { + module = m3_AllocStruct (M3Module); + _throwifnull (module); + module->name = ".unnamed"; m3log (parse, "load module: %d bytes", i_numBytes); + module->startFunction = -1; + //module->hasWasmCodeCopy = false; + module->environment = i_environment; + + const u8 * pos = i_bytes; + const u8 * end = pos + i_numBytes; + + module->wasmStart = pos; + module->wasmEnd = end; + + u32 magic, version; +_ (Read_u32 (& magic, & pos, end)); +_ (Read_u32 (& version, & pos, end)); + + _throwif (m3Err_wasmMalformed, magic != 0x6d736100); + _throwif (m3Err_incompatibleWasmVersion, version != 1); + + static const u8 sectionsOrder[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 10, 11, 0 }; // 0 is a placeholder + u8 expectedSection = 0; + + while (pos < end) + { + u8 section; +_ (ReadLEB_u7 (& section, & pos, end)); + + if (section != 0) { + // Ensure sections appear only once and in order + while (sectionsOrder[expectedSection++] != section) { + _throwif(m3Err_misorderedWasmSection, expectedSection >= 12); + } + } + + u32 sectionLength; +_ (ReadLEB_u32 (& sectionLength, & pos, end)); + _throwif(m3Err_wasmMalformed, pos + sectionLength > end); + +_ (ParseModuleSection (module, section, pos, sectionLength)); + + pos += sectionLength; + } + +} _catch: + + if (result) + { + m3_FreeModule (module); + module = NULL; + } + + * o_module = module; + + return result; +} diff --git a/wasm3-sys/wasm3/source/wasm3.h b/wasm3-sys/wasm3/source/wasm3.h new file mode 100644 index 0000000..30f00df --- /dev/null +++ b/wasm3-sys/wasm3/source/wasm3.h @@ -0,0 +1,359 @@ +// +// Wasm3, high performance WebAssembly interpreter +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#ifndef wasm3_h +#define wasm3_h + +#define M3_VERSION_MAJOR 0 +#define M3_VERSION_MINOR 5 +#define M3_VERSION_REV 0 +#define M3_VERSION "0.5.0" + +#include +#include +#include +#include + +#include "wasm3_defs.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef const char * M3Result; + +struct M3Environment; typedef struct M3Environment * IM3Environment; +struct M3Runtime; typedef struct M3Runtime * IM3Runtime; +struct M3Module; typedef struct M3Module * IM3Module; +struct M3Function; typedef struct M3Function * IM3Function; +struct M3Global; typedef struct M3Global * IM3Global; + +typedef struct M3ErrorInfo +{ + M3Result result; + + IM3Runtime runtime; + IM3Module module; + IM3Function function; + + const char * file; + uint32_t line; + + const char * message; +} M3ErrorInfo; + +typedef struct M3BacktraceFrame +{ + uint32_t moduleOffset; + IM3Function function; + + struct M3BacktraceFrame * next; +} +M3BacktraceFrame, * IM3BacktraceFrame; + +typedef struct M3BacktraceInfo +{ + IM3BacktraceFrame frames; + IM3BacktraceFrame lastFrame; // can be M3_BACKTRACE_TRUNCATED +} +M3BacktraceInfo, * IM3BacktraceInfo; + +// Constants +#define M3_BACKTRACE_TRUNCATED (void*)(SIZE_MAX) + +typedef enum M3ValueType +{ + c_m3Type_none = 0, + c_m3Type_i32 = 1, + c_m3Type_i64 = 2, + c_m3Type_f32 = 3, + c_m3Type_f64 = 4, + + c_m3Type_unknown +} M3ValueType; + +typedef struct M3TaggedValue +{ + M3ValueType type; + union M3ValueUnion + { + uint32_t i32; + uint64_t i64; + float f32; + double f64; + } value; +} +M3TaggedValue, * IM3TaggedValue; + +typedef struct M3ImportInfo +{ + const char * moduleUtf8; + const char * fieldUtf8; +} +M3ImportInfo, * IM3ImportInfo; + + +typedef struct M3ImportContext +{ + void * userdata; + IM3Function function; +} +M3ImportContext, * IM3ImportContext; + +// ------------------------------------------------------------------------------------------------------------------------------- +// error codes +// ------------------------------------------------------------------------------------------------------------------------------- + +# if defined(M3_IMPLEMENT_ERROR_STRINGS) +# define d_m3ErrorConst(LABEL, STRING) M3Result m3Err_##LABEL = { STRING }; +# else +# define d_m3ErrorConst(LABEL, STRING) extern M3Result m3Err_##LABEL; +# endif + +// ------------------------------------------------------------------------------------------------------------------------------- + +d_m3ErrorConst (none, NULL) + +// general errors +d_m3ErrorConst (mallocFailed, "memory allocation failed") + +// parse errors +d_m3ErrorConst (incompatibleWasmVersion, "incompatible Wasm binary version") +d_m3ErrorConst (wasmMalformed, "malformed Wasm binary") +d_m3ErrorConst (misorderedWasmSection, "out of order Wasm section") +d_m3ErrorConst (wasmUnderrun, "underrun while parsing Wasm binary") +d_m3ErrorConst (wasmOverrun, "overrun while parsing Wasm binary") +d_m3ErrorConst (wasmMissingInitExpr, "missing init_expr in Wasm binary") +d_m3ErrorConst (lebOverflow, "LEB encoded value overflow") +d_m3ErrorConst (missingUTF8, "invalid length UTF-8 string") +d_m3ErrorConst (wasmSectionUnderrun, "section underrun while parsing Wasm binary") +d_m3ErrorConst (wasmSectionOverrun, "section overrun while parsing Wasm binary") +d_m3ErrorConst (invalidTypeId, "unknown value_type") +d_m3ErrorConst (tooManyMemorySections, "only one memory per module is supported") +d_m3ErrorConst (tooManyArgsRets, "too many arguments or return values") + +// link errors +d_m3ErrorConst (moduleAlreadyLinked, "attempting to bind module to multiple runtimes") +d_m3ErrorConst (functionLookupFailed, "function lookup failed") +d_m3ErrorConst (functionImportMissing, "missing imported function") + +d_m3ErrorConst (malformedFunctionSignature, "malformed function signature") + +// compilation errors +d_m3ErrorConst (noCompiler, "no compiler found for opcode") +d_m3ErrorConst (unknownOpcode, "unknown opcode") +d_m3ErrorConst (restictedOpcode, "restricted opcode") +d_m3ErrorConst (functionStackOverflow, "compiling function overran its stack height limit") +d_m3ErrorConst (functionStackUnderrun, "compiling function underran the stack") +d_m3ErrorConst (mallocFailedCodePage, "memory allocation failed when acquiring a new M3 code page") +d_m3ErrorConst (settingImmutableGlobal, "attempting to set an immutable global") +d_m3ErrorConst (typeMismatch, "incorrect type on stack") +d_m3ErrorConst (typeCountMismatch, "incorrect value count on stack") + +// runtime errors +d_m3ErrorConst (missingCompiledCode, "function is missing compiled m3 code") +d_m3ErrorConst (wasmMemoryOverflow, "runtime ran out of memory") +d_m3ErrorConst (globalMemoryNotAllocated, "global memory is missing from a module") +d_m3ErrorConst (globaIndexOutOfBounds, "global index is too large") +d_m3ErrorConst (argumentCountMismatch, "argument count mismatch") +d_m3ErrorConst (argumentTypeMismatch, "argument type mismatch") +d_m3ErrorConst (globalLookupFailed, "global lookup failed") +d_m3ErrorConst (globalTypeMismatch, "global type mismatch") +d_m3ErrorConst (globalNotMutable, "global is not mutable") + +// traps +d_m3ErrorConst (trapOutOfBoundsMemoryAccess, "[trap] out of bounds memory access") +d_m3ErrorConst (trapDivisionByZero, "[trap] integer divide by zero") +d_m3ErrorConst (trapIntegerOverflow, "[trap] integer overflow") +d_m3ErrorConst (trapIntegerConversion, "[trap] invalid conversion to integer") +d_m3ErrorConst (trapIndirectCallTypeMismatch, "[trap] indirect call type mismatch") +d_m3ErrorConst (trapTableIndexOutOfRange, "[trap] undefined element") +d_m3ErrorConst (trapTableElementIsNull, "[trap] null table element") +d_m3ErrorConst (trapExit, "[trap] program called exit") +d_m3ErrorConst (trapAbort, "[trap] program called abort") +d_m3ErrorConst (trapUnreachable, "[trap] unreachable executed") +d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow") + + +//------------------------------------------------------------------------------------------------------------------------------- +// configuration, can be found in m3_config.h, m3_config_platforms.h, m3_core.h) +//------------------------------------------------------------------------------------------------------------------------------- + +//------------------------------------------------------------------------------------------------------------------------------- +// global environment than can host multiple runtimes +//------------------------------------------------------------------------------------------------------------------------------- + IM3Environment m3_NewEnvironment (void); + + void m3_FreeEnvironment (IM3Environment i_environment); + +//------------------------------------------------------------------------------------------------------------------------------- +// execution context +//------------------------------------------------------------------------------------------------------------------------------- + + IM3Runtime m3_NewRuntime (IM3Environment io_environment, + uint32_t i_stackSizeInBytes, + void * i_userdata); + + void m3_FreeRuntime (IM3Runtime i_runtime); + + // Wasm currently only supports one memory region. i_memoryIndex should be zero. + uint8_t * m3_GetMemory (IM3Runtime i_runtime, + uint32_t * o_memorySizeInBytes, + uint32_t i_memoryIndex); + + // This is used internally by Raw Function helpers + uint32_t m3_GetMemorySize (IM3Runtime i_runtime); + + void * m3_GetUserData (IM3Runtime i_runtime); + + +//------------------------------------------------------------------------------------------------------------------------------- +// modules +//------------------------------------------------------------------------------------------------------------------------------- + + // i_wasmBytes data must be persistent during the lifetime of the module + M3Result m3_ParseModule (IM3Environment i_environment, + IM3Module * o_module, + const uint8_t * const i_wasmBytes, + uint32_t i_numWasmBytes); + + // Only modules not loaded into a M3Runtime need to be freed. A module is considered unloaded if + // a. m3_LoadModule has not yet been called on that module. Or, + // b. m3_LoadModule returned a result. + void m3_FreeModule (IM3Module i_module); + + // LoadModule transfers ownership of a module to the runtime. Do not free modules once successfully loaded into the runtime + M3Result m3_LoadModule (IM3Runtime io_runtime, IM3Module io_module); + + // Optional, compiles all functions in the module + M3Result m3_CompileModule (IM3Module io_module); + + // Calling m3_RunStart is optional + M3Result m3_RunStart (IM3Module i_module); + + // Arguments and return values are passed in and out through the stack pointer _sp. + // Placeholder return value slots are first and arguments after. So, the first argument is at _sp [numReturns] + // Return values should be written into _sp [0] to _sp [num_returns - 1] + typedef const void * (* M3RawCall) (IM3Runtime runtime, IM3ImportContext _ctx, uint64_t * _sp, void * _mem); + + M3Result m3_LinkRawFunction (IM3Module io_module, + const char * const i_moduleName, + const char * const i_functionName, + const char * const i_signature, + M3RawCall i_function); + + M3Result m3_LinkRawFunctionEx (IM3Module io_module, + const char * const i_moduleName, + const char * const i_functionName, + const char * const i_signature, + M3RawCall i_function, + const void * i_userdata); + + const char* m3_GetModuleName (IM3Module i_module); + void m3_SetModuleName (IM3Module i_module, const char* name); + IM3Runtime m3_GetModuleRuntime (IM3Module i_module); + +//------------------------------------------------------------------------------------------------------------------------------- +// globals +//------------------------------------------------------------------------------------------------------------------------------- + IM3Global m3_FindGlobal (IM3Module io_module, + const char * const i_globalName); + + M3Result m3_GetGlobal (IM3Global i_global, + IM3TaggedValue o_value); + + M3Result m3_SetGlobal (IM3Global i_global, + const IM3TaggedValue i_value); + + M3ValueType m3_GetGlobalType (IM3Global i_global); + +//------------------------------------------------------------------------------------------------------------------------------- +// functions +//------------------------------------------------------------------------------------------------------------------------------- + M3Result m3_Yield (void); + + // o_function is valid during the lifetime of the originating runtime + M3Result m3_FindFunction (IM3Function * o_function, + IM3Runtime i_runtime, + const char * const i_functionName); + + uint32_t m3_GetArgCount (IM3Function i_function); + uint32_t m3_GetRetCount (IM3Function i_function); + M3ValueType m3_GetArgType (IM3Function i_function, uint32_t i_index); + M3ValueType m3_GetRetType (IM3Function i_function, uint32_t i_index); + + M3Result m3_CallV (IM3Function i_function, ...); + M3Result m3_CallVL (IM3Function i_function, va_list i_args); + M3Result m3_Call (IM3Function i_function, uint32_t i_argc, const void * i_argptrs[]); + M3Result m3_CallArgv (IM3Function i_function, uint32_t i_argc, const char * i_argv[]); + + M3Result m3_GetResultsV (IM3Function i_function, ...); + M3Result m3_GetResultsVL (IM3Function i_function, va_list o_rets); + M3Result m3_GetResults (IM3Function i_function, uint32_t i_retc, const void * o_retptrs[]); + + + void m3_GetErrorInfo (IM3Runtime i_runtime, M3ErrorInfo* o_info); + void m3_ResetErrorInfo (IM3Runtime i_runtime); + + const char* m3_GetFunctionName (IM3Function i_function); + IM3Module m3_GetFunctionModule (IM3Function i_function); + +//------------------------------------------------------------------------------------------------------------------------------- +// debug info +//------------------------------------------------------------------------------------------------------------------------------- + + void m3_PrintRuntimeInfo (IM3Runtime i_runtime); + void m3_PrintM3Info (void); + void m3_PrintProfilerInfo (void); + + // The runtime owns the backtrace, do not free the backtrace you obtain. Returns NULL if there's no backtrace. + IM3BacktraceInfo m3_GetBacktrace (IM3Runtime i_runtime); + +//------------------------------------------------------------------------------------------------------------------------------- +// raw function definition helpers +//------------------------------------------------------------------------------------------------------------------------------- + +# define m3ApiOffsetToPtr(offset) (void*)((uint8_t*)_mem + (uint32_t)(offset)) +# define m3ApiPtrToOffset(ptr) (uint32_t)((uint8_t*)ptr - (uint8_t*)_mem) + +# define m3ApiReturnType(TYPE) TYPE* raw_return = ((TYPE*) (_sp++)); +# define m3ApiGetArg(TYPE, NAME) TYPE NAME = * ((TYPE *) (_sp++)); +# define m3ApiGetArgMem(TYPE, NAME) TYPE NAME = (TYPE)m3ApiOffsetToPtr(* ((uint32_t *) (_sp++))); + +# define m3ApiIsNullPtr(addr) ((void*)(addr) <= _mem) +# define m3ApiCheckMem(addr, len) { if (M3_UNLIKELY(m3ApiIsNullPtr(addr) || ((uint64_t)(uintptr_t)(addr) + (len)) > ((uint64_t)(uintptr_t)(_mem)+m3_GetMemorySize(runtime)))) m3ApiTrap(m3Err_trapOutOfBoundsMemoryAccess); } + +# define m3ApiRawFunction(NAME) const void * NAME (IM3Runtime runtime, IM3ImportContext _ctx, uint64_t * _sp, void * _mem) +# define m3ApiReturn(VALUE) { *raw_return = (VALUE); return m3Err_none; } +# define m3ApiTrap(VALUE) { return VALUE; } +# define m3ApiSuccess() { return m3Err_none; } + +# if defined(M3_BIG_ENDIAN) +# define m3ApiReadMem8(ptr) (* (uint8_t *)(ptr)) +# define m3ApiReadMem16(ptr) m3_bswap16((* (uint16_t *)(ptr))) +# define m3ApiReadMem32(ptr) m3_bswap32((* (uint32_t *)(ptr))) +# define m3ApiReadMem64(ptr) m3_bswap64((* (uint64_t *)(ptr))) +# define m3ApiWriteMem8(ptr, val) { * (uint8_t *)(ptr) = (val); } +# define m3ApiWriteMem16(ptr, val) { * (uint16_t *)(ptr) = m3_bswap16((val)); } +# define m3ApiWriteMem32(ptr, val) { * (uint32_t *)(ptr) = m3_bswap32((val)); } +# define m3ApiWriteMem64(ptr, val) { * (uint64_t *)(ptr) = m3_bswap64((val)); } +# else +# define m3ApiReadMem8(ptr) (* (uint8_t *)(ptr)) +# define m3ApiReadMem16(ptr) (* (uint16_t *)(ptr)) +# define m3ApiReadMem32(ptr) (* (uint32_t *)(ptr)) +# define m3ApiReadMem64(ptr) (* (uint64_t *)(ptr)) +# define m3ApiWriteMem8(ptr, val) { * (uint8_t *)(ptr) = (val); } +# define m3ApiWriteMem16(ptr, val) { * (uint16_t *)(ptr) = (val); } +# define m3ApiWriteMem32(ptr, val) { * (uint32_t *)(ptr) = (val); } +# define m3ApiWriteMem64(ptr, val) { * (uint64_t *)(ptr) = (val); } +# endif + +#if defined(__cplusplus) +} +#endif + +#endif // wasm3_h diff --git a/wasm3-sys/wasm3/source/wasm3_defs.h b/wasm3-sys/wasm3/source/wasm3_defs.h new file mode 100644 index 0000000..77bccb1 --- /dev/null +++ b/wasm3-sys/wasm3/source/wasm3_defs.h @@ -0,0 +1,282 @@ +// +// wasm3_defs.h +// +// Created by Volodymyr Shymanskyy on 11/20/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef wasm3_defs_h +#define wasm3_defs_h + +#define M3_STR__(x) #x +#define M3_STR(x) M3_STR__(x) + +#define M3_CONCAT__(a,b) a##b +#define M3_CONCAT(a,b) M3_CONCAT__(a,b) + +/* + * Detect compiler + */ + +# if defined(__clang__) +# define M3_COMPILER_CLANG 1 +# elif defined(__INTEL_COMPILER) +# define M3_COMPILER_ICC 1 +# elif defined(__GNUC__) || defined(__GNUG__) +# define M3_COMPILER_GCC 1 +# elif defined(_MSC_VER) +# define M3_COMPILER_MSVC 1 +# else +# warning "Compiler not detected" +# endif + +# if defined(M3_COMPILER_CLANG) +# if defined(WIN32) +# define M3_COMPILER_VER __VERSION__ " for Windows" +# else +# define M3_COMPILER_VER __VERSION__ +# endif +# elif defined(M3_COMPILER_GCC) +# define M3_COMPILER_VER "GCC " __VERSION__ +# elif defined(M3_COMPILER_MSVC) +# define M3_COMPILER_VER "MSVC " M3_STR(_MSC_VER) +# else +# define M3_COMPILER_VER "unknown" +# endif + +# ifdef __has_feature +# define M3_COMPILER_HAS_FEATURE(x) __has_feature(x) +# else +# define M3_COMPILER_HAS_FEATURE(x) 0 +# endif + +# ifdef __has_builtin +# define M3_COMPILER_HAS_BUILTIN(x) __has_builtin(x) +# else +# define M3_COMPILER_HAS_BUILTIN(x) 0 +# endif + +/* + * Detect endianness + */ + +# if defined(M3_COMPILER_MSVC) +# define M3_LITTLE_ENDIAN //_byteswap_ushort, _byteswap_ulong, _byteswap_uint64 +# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define M3_LITTLE_ENDIAN +# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define M3_BIG_ENDIAN +# else +# error "Byte order not detected" +# endif + +/* + * Detect platform + */ + +# if defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_GCC) +# if defined(__wasm__) +# define M3_ARCH "wasm" + +# elif defined(__x86_64__) +# define M3_ARCH "x86_64" + +# elif defined(__i386__) +# define M3_ARCH "i386" + +# elif defined(__aarch64__) +# define M3_ARCH "arm64-v8a" + +# elif defined(__arm__) +# if defined(__ARM_ARCH_7A__) +# if defined(__ARM_NEON__) +# if defined(__ARM_PCS_VFP) +# define M3_ARCH "arm-v7a/NEON hard-float" +# else +# define M3_ARCH "arm-v7a/NEON" +# endif +# else +# if defined(__ARM_PCS_VFP) +# define M3_ARCH "arm-v7a hard-float" +# else +# define M3_ARCH "arm-v7a" +# endif +# endif +# else +# define M3_ARCH "arm" +# endif + +# elif defined(__riscv) +# if defined(__riscv_32e) +# define _M3_ARCH_RV "rv32e" +# elif __riscv_xlen == 128 +# define _M3_ARCH_RV "rv128i" +# elif __riscv_xlen == 64 +# define _M3_ARCH_RV "rv64i" +# elif __riscv_xlen == 32 +# define _M3_ARCH_RV "rv32i" +# endif +# if defined(__riscv_muldiv) +# define _M3_ARCH_RV_M _M3_ARCH_RV "m" +# else +# define _M3_ARCH_RV_M _M3_ARCH_RV +# endif +# if defined(__riscv_atomic) +# define _M3_ARCH_RV_A _M3_ARCH_RV_M "a" +# else +# define _M3_ARCH_RV_A _M3_ARCH_RV_M +# endif +# if defined(__riscv_flen) +# define _M3_ARCH_RV_F _M3_ARCH_RV_A "f" +# else +# define _M3_ARCH_RV_F _M3_ARCH_RV_A +# endif +# if defined(__riscv_flen) && __riscv_flen >= 64 +# define _M3_ARCH_RV_D _M3_ARCH_RV_F "d" +# else +# define _M3_ARCH_RV_D _M3_ARCH_RV_F +# endif +# if defined(__riscv_compressed) +# define _M3_ARCH_RV_C _M3_ARCH_RV_D "c" +# else +# define _M3_ARCH_RV_C _M3_ARCH_RV_D +# endif +# define M3_ARCH _M3_ARCH_RV_C + +# elif defined(__mips__) +# if defined(__MIPSEB__) && defined(__mips64) +# define M3_ARCH "mips64 " _MIPS_ARCH +# elif defined(__MIPSEL__) && defined(__mips64) +# define M3_ARCH "mips64el " _MIPS_ARCH +# elif defined(__MIPSEB__) +# define M3_ARCH "mips " _MIPS_ARCH +# elif defined(__MIPSEL__) +# define M3_ARCH "mipsel " _MIPS_ARCH +# endif + +# elif defined(__PPC__) +# if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) +# define M3_ARCH "ppc64le" +# elif defined(__PPC64__) +# define M3_ARCH "ppc64" +# else +# define M3_ARCH "ppc" +# endif + +# elif defined(__sparc__) +# if defined(__arch64__) +# define M3_ARCH "sparc64" +# else +# define M3_ARCH "sparc" +# endif + +# elif defined(__s390x__) +# define M3_ARCH "s390x" + +# elif defined(__alpha__) +# define M3_ARCH "alpha" + +# elif defined(__m68k__) +# define M3_ARCH "m68k" + +# elif defined(__xtensa__) +# define M3_ARCH "xtensa" + +# elif defined(__arc__) +# define M3_ARCH "arc32" + +# elif defined(__AVR__) +# define M3_ARCH "avr" +# endif +# endif + +# if defined(M3_COMPILER_MSVC) +# if defined(_M_X64) +# define M3_ARCH "x86_64" +# elif defined(_M_IX86) +# define M3_ARCH "i386" +# elif defined(_M_ARM64) +# define M3_ARCH "arm64" +# elif defined(_M_ARM) +# define M3_ARCH "arm" +# endif +# endif + +# if !defined(M3_ARCH) +# warning "Architecture not detected" +# define M3_ARCH "unknown" +# endif + +/* + * Byte swapping (for Big-Endian systems only) + */ + +# if defined(M3_COMPILER_MSVC) +# define m3_bswap16(x) _byteswap_ushort((x)) +# define m3_bswap32(x) _byteswap_ulong((x)) +# define m3_bswap64(x) _byteswap_uint64((x)) +# elif defined(M3_COMPILER_GCC) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) +// __builtin_bswap32/64 added in gcc 4.3, __builtin_bswap16 added in gcc 4.8 +# define m3_bswap16(x) __builtin_bswap16((x)) +# define m3_bswap32(x) __builtin_bswap32((x)) +# define m3_bswap64(x) __builtin_bswap64((x)) +# elif defined(M3_COMPILER_CLANG) && M3_COMPILER_HAS_BUILTIN(__builtin_bswap16) +# define m3_bswap16(x) __builtin_bswap16((x)) +# define m3_bswap32(x) __builtin_bswap32((x)) +# define m3_bswap64(x) __builtin_bswap64((x)) +# else +# include +# if defined(__bswap_16) +# define m3_bswap16(x) __bswap_16((x)) +# define m3_bswap32(x) __bswap_32((x)) +# define m3_bswap64(x) __bswap_64((x)) +# else +# warning "Using naive (probably slow) bswap operations" + static inline + uint16_t m3_bswap16(uint16_t x) { + return ((( x >> 8 ) & 0xffu ) | (( x & 0xffu ) << 8 )); + } + static inline + uint32_t m3_bswap32(uint32_t x) { + return ((( x & 0xff000000u ) >> 24 ) | + (( x & 0x00ff0000u ) >> 8 ) | + (( x & 0x0000ff00u ) << 8 ) | + (( x & 0x000000ffu ) << 24 )); + } + static inline + uint64_t m3_bswap64(uint64_t x) { + return ((( x & 0xff00000000000000ull ) >> 56 ) | + (( x & 0x00ff000000000000ull ) >> 40 ) | + (( x & 0x0000ff0000000000ull ) >> 24 ) | + (( x & 0x000000ff00000000ull ) >> 8 ) | + (( x & 0x00000000ff000000ull ) << 8 ) | + (( x & 0x0000000000ff0000ull ) << 24 ) | + (( x & 0x000000000000ff00ull ) << 40 ) | + (( x & 0x00000000000000ffull ) << 56 )); + } +# endif +# endif + +/* + * Other + */ + +# if defined(M3_COMPILER_GCC) || defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_ICC) +# define M3_UNLIKELY(x) __builtin_expect(!!(x), 0) +# define M3_LIKELY(x) __builtin_expect(!!(x), 1) +# else +# define M3_UNLIKELY(x) (x) +# define M3_LIKELY(x) (x) +# endif + +// TODO: remove +# if defined(M3_COMPILER_GCC) || defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_ICC) +# define UNLIKELY(x) __builtin_expect(!!(x), 0) +# define LIKELY(x) __builtin_expect(!!(x), 1) +# else +# define UNLIKELY(x) (x) +# define LIKELY(x) (x) +# endif + + +#endif // wasm3_defs_h diff --git a/wasm3-sys/wasm3/test/fuzz/corpus/fib.c.wasm b/wasm3-sys/wasm3/test/fuzz/corpus/fib.c.wasm new file mode 100644 index 0000000..8e0af19 Binary files /dev/null and b/wasm3-sys/wasm3/test/fuzz/corpus/fib.c.wasm differ diff --git a/wasm3-sys/wasm3/test/fuzz/corpus/fib32.wasm b/wasm3-sys/wasm3/test/fuzz/corpus/fib32.wasm new file mode 100644 index 0000000..b6d023a Binary files /dev/null and b/wasm3-sys/wasm3/test/fuzz/corpus/fib32.wasm differ diff --git a/wasm3-sys/wasm3/test/fuzz/corpus/fib32_tail.wasm b/wasm3-sys/wasm3/test/fuzz/corpus/fib32_tail.wasm new file mode 100644 index 0000000..d9cc474 Binary files /dev/null and b/wasm3-sys/wasm3/test/fuzz/corpus/fib32_tail.wasm differ diff --git a/wasm3-sys/wasm3/test/fuzz/corpus/fib64.wasm b/wasm3-sys/wasm3/test/fuzz/corpus/fib64.wasm new file mode 100644 index 0000000..dae916a Binary files /dev/null and b/wasm3-sys/wasm3/test/fuzz/corpus/fib64.wasm differ diff --git a/wasm3-sys/wasm3/test/fuzz/corpus/fib64_tail.wasm b/wasm3-sys/wasm3/test/fuzz/corpus/fib64_tail.wasm new file mode 100644 index 0000000..c37d96a Binary files /dev/null and b/wasm3-sys/wasm3/test/fuzz/corpus/fib64_tail.wasm differ diff --git a/wasm3-sys/wasm3/test/internal/m3_test.c b/wasm3-sys/wasm3/test/internal/m3_test.c new file mode 100644 index 0000000..9332d2d --- /dev/null +++ b/wasm3-sys/wasm3/test/internal/m3_test.c @@ -0,0 +1,262 @@ +// +// m3_test.c +// +// Created by Steven Massey on 2/27/20. +// Copyright © 2020 Steven Massey. All rights reserved. +// + +#include + +#include "wasm3_ext.h" +#include "m3_bind.h" + +#define Test(NAME) if (RunTest (argc, argv, #NAME) != 0) +#define DisabledTest(NAME) printf ("\ndisabled: %s\n", #NAME); if (false) +#define expect(TEST) if (not (TEST)) { printf ("failed: (%s) on line: %d\n", #TEST, __LINE__); } + + +bool RunTest (int i_argc, const char * i_argv [], cstr_t i_name) +{ + cstr_t option = (i_argc == 2) ? i_argv [1] : NULL; + + bool runningTest = option ? strcmp (option, i_name) == 0 : true; + + if (runningTest) + printf ("\n test: %s\n", i_name); + + return runningTest; +} + + +int main (int argc, const char * argv []) +{ + Test (signatures) + { + M3Result result; + + IM3FuncType ftype = NULL; + + result = SignatureToFuncType (& ftype, ""); expect (result == m3Err_malformedFunctionSignature) + m3_Free (ftype); + + // implicit void return + result = SignatureToFuncType (& ftype, "()"); expect (result == m3Err_none) + m3_Free (ftype); + + result = SignatureToFuncType (& ftype, " v () "); expect (result == m3Err_none) + expect (ftype->numRets == 0) + expect (ftype->numArgs == 0) + m3_Free (ftype); + + result = SignatureToFuncType (& ftype, "f(IiF)"); expect (result == m3Err_none) + expect (ftype->numRets == 1) + expect (ftype->types [0] == c_m3Type_f32) + expect (ftype->numArgs == 3) + expect (ftype->types [1] == c_m3Type_i64) + expect (ftype->types [2] == c_m3Type_i32) + expect (ftype->types [3] == c_m3Type_f64) + + IM3FuncType ftype2 = NULL; + result = SignatureToFuncType (& ftype2, "f(I i F)"); expect (result == m3Err_none); + expect (AreFuncTypesEqual (ftype, ftype2)); + m3_Free (ftype); + m3_Free (ftype2); + } + + + Test (codepages.simple) + { + M3Environment env = { 0 }; + M3Runtime runtime = { 0 }; + runtime.environment = & env; + + IM3CodePage page = AcquireCodePage (& runtime); expect (page); + expect (runtime.numCodePages == 1); + expect (runtime.numActiveCodePages == 1); + + IM3CodePage page2 = AcquireCodePage (& runtime); expect (page2); + expect (runtime.numCodePages == 2); + expect (runtime.numActiveCodePages == 2); + + ReleaseCodePage (& runtime, page); expect (runtime.numCodePages == 2); + expect (runtime.numActiveCodePages == 1); + + ReleaseCodePage (& runtime, page2); expect (runtime.numCodePages == 2); + expect (runtime.numActiveCodePages == 0); + + Runtime_Release (& runtime); expect (CountCodePages (env.pagesReleased) == 2); + Environment_Release (& env); expect (CountCodePages (env.pagesReleased) == 0); + } + + + Test (codepages.b) + { + const u32 c_numPages = 2000; + IM3CodePage pages [2000] = { NULL }; + + M3Environment env = { 0 }; + M3Runtime runtime = { 0 }; + runtime.environment = & env; + + u32 numActive = 0; + + for (u32 i = 0; i < 2000000; ++i) + { + u32 index = rand () % c_numPages; // printf ("%5u ", index); + + if (pages [index] == NULL) + { +// printf ("acq\n"); + pages [index] = AcquireCodePage (& runtime); + ++numActive; + } + else + { +// printf ("rel\n"); + ReleaseCodePage (& runtime, pages [index]); + pages [index] = NULL; + --numActive; + } + + expect (runtime.numActiveCodePages == numActive); + } + + printf ("num pages: %d\n", runtime.numCodePages); + + for (u32 i = 0; i < c_numPages; ++i) + { + if (pages [i]) + { + ReleaseCodePage (& runtime, pages [i]); + pages [i] = NULL; + --numActive; expect (runtime.numActiveCodePages == numActive); + } + } + + Runtime_Release (& runtime); + Environment_Release (& env); + } + + + Test (extensions) + { + M3Result result; + + IM3Environment env = m3_NewEnvironment (); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + + IM3Module module = m3_NewModule (env); + + + i32 functionIndex = -1; + + u8 wasm [5] = { 0x04, // size + 0x00, // num local defs + 0x41, 0x37, // i32.const= 55 + 0x0b // end block + }; + + // will partially fail (compilation) because module isn't attached to a runtime yet. + result = m3_InjectFunction (module, & functionIndex, "i()", wasm, true); expect (result != m3Err_none) + expect (functionIndex >= 0) + + result = m3_LoadModule (runtime, module); expect (result == m3Err_none) + + // try again + result = m3_InjectFunction (module, & functionIndex, "i()", wasm, true); expect (result == m3Err_none) + + IM3Function function = m3_GetFunctionByIndex (module, functionIndex); expect (function) + + if (function) + { + result = m3_CallV (function); expect (result == m3Err_none) + u32 ret = 0; + m3_GetResultsV (function, & ret); expect (ret == 55); + } + + m3_FreeRuntime (runtime); + } + + IM3Environment env = m3_NewEnvironment (); + + + Test (multireturn.a) + { + M3Result result; + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + +# if 0 + (module + (func (result i32 f32) + + i32.const 1234 + f32.const 5678.9 + ) + + (export "main" (func 0)) + ) +# endif + + u8 wasm [44] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x00, 0x02, 0x7f, 0x7d, 0x03, 0x02, 0x01, 0x00, 0x07, 0x08, 0x01, 0x04, + 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x0a, 0x0c, 0x01, 0x0a, 0x00, 0x41, 0xd2, 0x09, 0x43, 0x33, 0x77, 0xb1, 0x45, 0x0b + }; + + IM3Module module; + result = m3_ParseModule (env, & module, wasm, 44); expect (result == m3Err_none) + + result = m3_LoadModule (runtime, module); expect (result == m3Err_none) + + IM3Function function = NULL; + result = m3_FindFunction (& function, runtime, "main"); expect (result == m3Err_none) + expect (function) + printf ("\n%s\n", result); + + if (function) + { + result = m3_CallV (function); expect (result == m3Err_none) + + i32 ret0 = 0; + f32 ret1 = 0.; + m3_GetResultsV (function, & ret0, & ret1); + + printf ("%d %f\n", ret0, ret1); + } + } + + + Test (multireturn.branch) + { +# if 0 + (module + (func (param i32) (result i32 i32) + + i32.const 123 + i32.const 456 + i32.const 789 + + block (param i32 i32) (result i32 i32 i32) + + local.get 0 + local.get 0 + + local.get 0 + br_if 0 + + drop + + end + + drop + drop + ) + + (export "main" (func 0)) + ) +# endif + } + + return 0; +} diff --git a/wasm3-sys/wasm3/test/internal/tailcall/build.sh b/wasm3-sys/wasm3/test/internal/tailcall/build.sh new file mode 100755 index 0000000..cc9887c --- /dev/null +++ b/wasm3-sys/wasm3/test/internal/tailcall/build.sh @@ -0,0 +1,91 @@ +# Misc. helper commands: +#llc-9 --version +#llc-9 -march=wasm32 -mattr=help +#llc-9 -march=riscv32 -mattr=help +#echo | clang-9 -E - -march=native -### + +# MSVC +#cl /TP /c /Ox /Oy /FA /Fax64.msvc.S ops.c + +FLAGS="-Os -fverbose-asm" + +OPT="/media/vshymanskyy/Data" + +# x86 - clang and gcc + +clang-9 $FLAGS -m64 -S ops.c -o x64.clang.S +gcc $FLAGS -m64 -S ops.c -o x64.S + +clang-9 $FLAGS -m32 -S ops.c -o x86.clang.S +gcc $FLAGS -m32 -S ops.c -o x86.S + +# clang - risc-v + +clang-9 $FLAGS --target=riscv32 -march=rv32i -mabi=ilp32 -S ops.c -o riscv32i.clang.S +clang-9 $FLAGS --target=riscv64 -S ops.c -o riscv64.clang.S + +# clang - arm + +clang-9 $FLAGS --target=arm -mcpu=cortex-m4 -mthumb -S ops.c -o arm-m4.clang.S +clang-9 $FLAGS --target=arm -mcpu=cortex-m0 -mthumb -S ops.c -o arm-m0.clang.S +clang-9 $FLAGS --target=aarch64 -S ops.c -o arm.aarch64.clang.S + +# clang - other + +clang-9 $FLAGS --target=mipsel -S ops.c -o mipsel.clang.S +clang-9 $FLAGS --target=ppc32 -S ops.c -o ppc32.clang.S + +# enable tail-call for wasm +clang-9 $FLAGS --target=wasm32 -Xclang -target-feature -Xclang +tail-call -S ops.c -o wasm32.clang.S + + +clang-9 $FLAGS --target=wasm32 -Xclang -target-feature -Xclang +tail-call -nostdlib -Wl,--no-entry -Wl,--export-all -o wasm32.clang.wasm ops.c + +# clang - xtensa + +export PATH=$OPT/llvm_build_xtensa/bin:$PATH +clang -target xtensa -mcpu=esp32 -O3 -S ops.c -o esp32.clang.S +clang -target xtensa -mcpu=esp8266 -O3 -S ops.c -o esp8266.clang.S + +# gcc - xtensa + +export PATH=~/.platformio/packages/toolchain-xtensa/bin/:$PATH +xtensa-lx106-elf-gcc $FLAGS -S ops.c -o esp8266.S + +export PATH=~/.platformio/packages/toolchain-xtensa32/bin/:$PATH +xtensa-esp32-elf-gcc $FLAGS -S ops.c -o esp32.S + +# gcc - arm + +export PATH=/opt/gcc-arm-none-eabi-8-2018-q4/bin:$PATH +arm-none-eabi-gcc $FLAGS -mcpu=cortex-m4 -mthumb -mabi=aapcs -S ops.c -o arm-m4.S +arm-none-eabi-gcc $FLAGS -mcpu=cortex-m0 -mthumb -mabi=aapcs -S ops.c -o arm-m0.S + +# gcc - risc-v + +export PATH=~/.platformio/packages/toolchain-riscv/bin:$PATH +riscv64-unknown-elf-gcc $FLAGS -march=rv32i -mabi=ilp32 -S ops.c -o riscv32i.S +riscv64-unknown-elf-gcc $FLAGS -S ops.c -o riscv64.S + +# gcc - mips + +export STAGING_DIR=$OPT/openwrt-chaoscalmer/staging_dir +export PATH=$OPT/openwrt-chaoscalmer/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin:$PATH +mipsel-openwrt-linux-gcc $FLAGS -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -S ops.c -o mips24kc.S + +# gcc - arc + +export PATH=~/.platformio/packages/toolchain-intelarc32/bin:$PATH +arc-elf32-gcc $FLAGS -S ops.c -o arc32.S + +# ---------------------- +# Just for fun ;) + +export PATH=~/.platformio/packages/toolchain-atmelavr/bin:$PATH +avr-gcc $FLAGS -S ops.c -o avr.S + +export PATH=~/.platformio/packages/toolchain-timsp430/bin:$PATH +msp430-gcc $FLAGS -S ops.c -o msp430.S + +#clang-9 --target=avr -mmcu=atmega328p $FLAGS -S ops.c -o avr.clang.S +clang-9 --target=msp430 $FLAGS -S ops.c -o msp430.clang.S diff --git a/wasm3-sys/wasm3/test/internal/tailcall/ops.c b/wasm3-sys/wasm3/test/internal/tailcall/ops.c new file mode 100644 index 0000000..0d592ed --- /dev/null +++ b/wasm3-sys/wasm3/test/internal/tailcall/ops.c @@ -0,0 +1,111 @@ +#include + +#define NULL (0) + +typedef double f64; +typedef float f32; +typedef uint64_t u64; +typedef int64_t i64; +typedef uint32_t u32; +typedef int32_t i32; +typedef uint16_t u16; +typedef int16_t i16; +typedef uint8_t u8; +typedef int8_t i8; + + +typedef i64 m3reg_t; +typedef void /*const*/ * code_t; +typedef code_t const * /*__restrict__*/ pc_t; +typedef const void * m3ret_t; + +# define vectorcall + +# define d_m3OpSig pc_t _pc, u64 * _sp, u8 * _mem, m3reg_t _r0, f64 _fp0 +# define d_m3OpArgs _sp, _mem, _r0, _fp0 +# define d_m3OpAllArgs _pc, _sp, _mem, _r0, _fp0 +# define d_m3OpDefaultArgs 666, 666.0 + +typedef m3ret_t (vectorcall * IM3Operation) (d_m3OpSig); + +# define immediate(TYPE) * ((TYPE *) _pc++) +# define slot(TYPE) * (TYPE *) (_sp + immediate (i32)) + + +# define d_m3RetSig static inline m3ret_t vectorcall +# define d_m3Op(NAME) d_m3RetSig op_##NAME (d_m3OpSig) + + +# define nextOp() ((IM3Operation)(* _pc))(_pc + 1, d_m3OpArgs) + + +#define d_m3CommutativeOpMacro(RES, REG, TYPE, NAME, OP, ...) \ +d_m3Op(TYPE##_##NAME##_sr) \ +{ \ + TYPE * stack = (TYPE *) (_sp + immediate (i32)); \ + OP((RES), (* stack), ((TYPE) REG), ##__VA_ARGS__); \ + return nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_ss) \ +{ \ + TYPE * stackB = (TYPE *) (_sp + immediate (i32)); \ + TYPE * stackA = (TYPE *) (_sp + immediate (i32)); \ + OP((RES), (* stackA), (* stackB), ##__VA_ARGS__); \ + return nextOp (); \ +} + +#define d_m3OpMacro(RES, REG, TYPE, NAME, OP, ...) \ +d_m3Op(TYPE##_##NAME##_rs) \ +{ \ + TYPE * stack = (TYPE *) (_sp + immediate (i32)); \ + OP((RES), (* stack), ((TYPE) REG), ##__VA_ARGS__); \ + return nextOp (); \ +} \ +d_m3CommutativeOpMacro(RES, REG, TYPE,NAME, OP, ##__VA_ARGS__) + +// Accept macros +#define d_m3CommutativeOpMacro_i(TYPE, NAME, MACRO, ...) d_m3CommutativeOpMacro ( _r0, _r0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3OpMacro_i(TYPE, NAME, MACRO, ...) d_m3OpMacro ( _r0, _r0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3CommutativeOpMacro_f(TYPE, NAME, MACRO, ...) d_m3CommutativeOpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3OpMacro_f(TYPE, NAME, MACRO, ...) d_m3OpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) + +#define M3_FUNC(RES, A, B, OP) (RES) = OP((A), (B)) // Accept functions: res = OP(a,b) +#define M3_OPER(RES, A, B, OP) (RES) = ((A) OP (B)) // Accept operators: res = a OP b + +#define d_m3CommutativeOpFunc_i(TYPE, NAME, OP) d_m3CommutativeOpMacro_i (TYPE, NAME, M3_FUNC, OP) +#define d_m3OpFunc_i(TYPE, NAME, OP) d_m3OpMacro_i (TYPE, NAME, M3_FUNC, OP) +#define d_m3CommutativeOpFunc_f(TYPE, NAME, OP) d_m3CommutativeOpMacro_f (TYPE, NAME, M3_FUNC, OP) +#define d_m3OpFunc_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_FUNC, OP) + +#define d_m3CommutativeOp_i(TYPE, NAME, OP) d_m3CommutativeOpMacro_i (TYPE, NAME, M3_OPER, OP) +#define d_m3Op_i(TYPE, NAME, OP) d_m3OpMacro_i (TYPE, NAME, M3_OPER, OP) +#define d_m3CommutativeOp_f(TYPE, NAME, OP) d_m3CommutativeOpMacro_f (TYPE, NAME, M3_OPER, OP) +#define d_m3Op_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_OPER, OP) + + +d_m3CommutativeOp_i (i32, Equal, ==) +d_m3CommutativeOp_i (i64, Equal, ==) +d_m3Op_i (i32, NotEqual, !=) +d_m3Op_i (i64, NotEqual, !=) + + +typedef struct M3OpInfo +{ + IM3Operation operation_sr; // top operand in register + IM3Operation operation_rs; // top operand in stack + IM3Operation operation_ss; // both operands in stack +} +M3OpInfo; + +#define d_emptyOpList() NULL, NULL, NULL +#define d_unaryOpList(TYPE, NAME) op_##TYPE##_##NAME##_r, op_##TYPE##_##NAME##_s, NULL +#define d_binOpList(TYPE, NAME) op_##TYPE##_##NAME##_sr, op_##TYPE##_##NAME##_rs, op_##TYPE##_##NAME##_ss +#define d_commutativeBinOpList(TYPE, NAME) op_##TYPE##_##NAME##_sr, NULL, op_##TYPE##_##NAME##_ss + + +M3OpInfo c_operations[] = { + { d_commutativeBinOpList (i32, Equal) }, + { d_binOpList (i32, NotEqual) }, + { d_commutativeBinOpList (i64, Equal) }, + { d_binOpList (i64, NotEqual) }, +}; diff --git a/wasm3-sys/wasm3/test/lang/README.md b/wasm3-sys/wasm3/test/lang/README.md new file mode 100644 index 0000000..ba12029 --- /dev/null +++ b/wasm3-sys/wasm3/test/lang/README.md @@ -0,0 +1,31 @@ +# Performance + +```log +Function: fib(40) +----------------------------------------------------- + Device: Lenovo Ideapad 720s [i5-8250U @ 1.60GHz] +----------------------------------------------------- +Linux x64 gcc 7.4.0 4.63s +Linux x64 clang 9 5.32s +Win 10 x64 clang 9 5.35s +Win 10 x64 msvc 2019 6.10s +Win 10 x86 clang 9.43s - no TCO +Linux x86 gcc 11.34s +Linux x86 clang 15.37s - no TCO +``` + +## Running + +```sh +# WAC +time $(ENGINES_PATH)/wac/wac fib32.wasm fib 40 + +# WAMR +time $(ENGINES_PATH)/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm -f fib fib32.wasm 40 + +# Wasmer +time wasmer run --em-entrypoint fib fib32.wasm -- 40 + +# WAVM +time $(ENGINES_PATH)/wasm-jit-prototype/_build/bin/wavm run -f fib fib32.wasm 40 +``` diff --git a/wasm3-sys/wasm3/test/lang/fib.c b/wasm3-sys/wasm3/test/lang/fib.c new file mode 100644 index 0000000..aa75f9f --- /dev/null +++ b/wasm3-sys/wasm3/test/lang/fib.c @@ -0,0 +1,30 @@ +/* + * emcc -g0 -O3 -s SIDE_MODULE=1 -s STRICT=1 -s WASM=1 -s ONLY_MY_CODE=1 -o fib.c.wasm fib.c + * gcc -g0 -O3 fib.c -o fib.c.elf + */ + +#include +#define WASM_EXPORT __attribute__((used)) __attribute__((visibility ("default"))) + +WASM_EXPORT +uint32_t fib(uint32_t n) +{ + if(n < 2) { + return n; + } + return fib(n-1) + fib(n-2); +} + +int parseInt(char* str) { + int res = 0; + for (int i = 0; str[i] != '\0'; ++i) { + res = res * 10 + str[i] - '0'; + } + return res; +} + +WASM_EXPORT +int main(int args, char* argv[]) { + uint32_t n = parseInt(argv[1]); + return fib(n); +} diff --git a/wasm3-sys/wasm3/test/lang/fib.c.wasm b/wasm3-sys/wasm3/test/lang/fib.c.wasm new file mode 100644 index 0000000..8e0af19 Binary files /dev/null and b/wasm3-sys/wasm3/test/lang/fib.c.wasm differ diff --git a/wasm3-sys/wasm3/test/lang/fib.js b/wasm3-sys/wasm3/test/lang/fib.js new file mode 100755 index 0000000..a685186 --- /dev/null +++ b/wasm3-sys/wasm3/test/lang/fib.js @@ -0,0 +1,8 @@ +function fib(n) { + if(n < 2) { + return n; + } + return fib(n-1) + fib(n-2) +} + +console.log(fib(process.argv[2])) diff --git a/wasm3-sys/wasm3/test/lang/fib.lua b/wasm3-sys/wasm3/test/lang/fib.lua new file mode 100755 index 0000000..bc14e7a --- /dev/null +++ b/wasm3-sys/wasm3/test/lang/fib.lua @@ -0,0 +1,8 @@ +local function fib(n) + if n < 2 then + return n + end + return fib(n-1) + fib(n-2) +end + +print(fib(tonumber(arg[1]))) diff --git a/wasm3-sys/wasm3/test/lang/fib.min.js b/wasm3-sys/wasm3/test/lang/fib.min.js new file mode 100755 index 0000000..0903156 --- /dev/null +++ b/wasm3-sys/wasm3/test/lang/fib.min.js @@ -0,0 +1,3 @@ +function fib(f){if(f<2)return f +return fib(f-1)+fib(f-2)} +console.log(fib(32)); diff --git a/wasm3-sys/wasm3/test/lang/fib.py b/wasm3-sys/wasm3/test/lang/fib.py new file mode 100755 index 0000000..cb47c8f --- /dev/null +++ b/wasm3-sys/wasm3/test/lang/fib.py @@ -0,0 +1,7 @@ +import sys +def fib(n): + if n < 2: + return n + return fib(n-1) + fib(n-2) + +print(fib(int(sys.argv[1]))) diff --git a/wasm3-sys/wasm3/test/lang/fib.walt b/wasm3-sys/wasm3/test/lang/fib.walt new file mode 100644 index 0000000..45d02dd --- /dev/null +++ b/wasm3-sys/wasm3/test/lang/fib.walt @@ -0,0 +1,6 @@ +export function fib(n: i32): i32 { + if (n < 2) { + return n; + } + return fib(n-1) + fib(n-2); +} diff --git a/wasm3-sys/wasm3/test/lang/fib32.wasm b/wasm3-sys/wasm3/test/lang/fib32.wasm new file mode 100644 index 0000000..b6d023a Binary files /dev/null and b/wasm3-sys/wasm3/test/lang/fib32.wasm differ diff --git a/wasm3-sys/wasm3/test/lang/fib32.wat b/wasm3-sys/wasm3/test/lang/fib32.wat new file mode 100644 index 0000000..5316eb2 --- /dev/null +++ b/wasm3-sys/wasm3/test/lang/fib32.wat @@ -0,0 +1,30 @@ +(module + (export "fib" (func $fib)) + (func $fib (param $n i32) (result i32) + (if + (i32.lt_u + (get_local $n) + (i32.const 2) + ) + (return + (get_local $n) + ) + ) + (return + (i32.add + (call $fib + (i32.sub + (get_local $n) + (i32.const 2) + ) + ) + (call $fib + (i32.sub + (get_local $n) + (i32.const 1) + ) + ) + ) + ) + ) +) diff --git a/wasm3-sys/wasm3/test/lang/fib32_tail.wasm b/wasm3-sys/wasm3/test/lang/fib32_tail.wasm new file mode 100644 index 0000000..d9cc474 Binary files /dev/null and b/wasm3-sys/wasm3/test/lang/fib32_tail.wasm differ diff --git a/wasm3-sys/wasm3/test/lang/fib32_tail.wat b/wasm3-sys/wasm3/test/lang/fib32_tail.wat new file mode 100644 index 0000000..36d2614 --- /dev/null +++ b/wasm3-sys/wasm3/test/lang/fib32_tail.wat @@ -0,0 +1,17 @@ +(module + (func $fib2 (param $n i32) (param $a i32) (param $b i32) (result i32) + (if (result i32) + (i32.eqz (get_local $n)) + (then (get_local $a)) + (else (return_call $fib2 (i32.sub (get_local $n) + (i32.const 1)) + (get_local $b) + (i32.add (get_local $a) + (get_local $b)))))) + + (func $fib (param i32) (result i32) + (return_call $fib2 (get_local 0) + (i32.const 0) ;; seed value $a + (i32.const 1))) ;; seed value $b + + (export "fib" (func $fib))) diff --git a/wasm3-sys/wasm3/test/lang/fib64.wasm b/wasm3-sys/wasm3/test/lang/fib64.wasm new file mode 100644 index 0000000..dae916a Binary files /dev/null and b/wasm3-sys/wasm3/test/lang/fib64.wasm differ diff --git a/wasm3-sys/wasm3/test/lang/fib64.wat b/wasm3-sys/wasm3/test/lang/fib64.wat new file mode 100644 index 0000000..9a31ba3 --- /dev/null +++ b/wasm3-sys/wasm3/test/lang/fib64.wat @@ -0,0 +1,30 @@ +(module + (export "fib" (func $fib)) + (func $fib (param $n i64) (result i64) + (if + (i64.lt_u + (get_local $n) + (i64.const 2) + ) + (return + (get_local $n) + ) + ) + (return + (i64.add + (call $fib + (i64.sub + (get_local $n) + (i64.const 2) + ) + ) + (call $fib + (i64.sub + (get_local $n) + (i64.const 1) + ) + ) + ) + ) + ) +) diff --git a/wasm3-sys/wasm3/test/run-spec-test.py b/wasm3-sys/wasm3/test/run-spec-test.py new file mode 100755 index 0000000..fdd9e51 --- /dev/null +++ b/wasm3-sys/wasm3/test/run-spec-test.py @@ -0,0 +1,596 @@ +#!/usr/bin/env python3 + +# Author: Volodymyr Shymanskyy +# Usage: +# ./run-spec-test.py +# ./run-spec-test.py --spec=opam-1.1.1 +# ./run-spec-test.py .spec-v1.1/core/i32.json +# ./run-spec-test.py .spec-v1.1/core/float_exprs.json --line 2070 +# ./run-spec-test.py .spec-v1.1/proposals/tail-call/*.json +# ./run-spec-test.py --exec "../build-custom/wasm3 --repl" +# +# Running WASI version with different engines: +# cp ../build-wasi/wasm3.wasm ./ +# ./run-spec-test.py --exec "../build/wasm3 wasm3.wasm --repl" +# ./run-spec-test.py --exec "wasmtime --dir=. wasm3.wasm -- --repl" +# ./run-spec-test.py --exec "wasmer run --dir=. wasm3.wasm -- --repl" +# ./run-spec-test.py --exec "wasmer run --dir=. --backend=llvm wasm3.wasm -- --repl" +# ./run-spec-test.py --exec "wasmer-js run wasm3.wasm --dir=. -- --repl" +# ./run-spec-test.py --exec "wasirun wasm3.wasm --repl" +# ./run-spec-test.py --exec "wavm run --mount-root ./ wasm3.wasm -- --repl" +# ./run-spec-test.py --exec "iwasm --dir=. wasm3.wasm --repl" +# + +# TODO +# - Get more tests from: https://github.com/microsoft/ChakraCore/tree/master/test/WasmSpec +# - Fix "Empty Stack" check +# - Check Canonical NaN and Arithmetic NaN separately +# - Fix imports.wast + +import argparse +import os, sys, glob, time +import subprocess +import json +import re +import struct +import math +import pathlib + +scriptDir = os.path.dirname(os.path.abspath(sys.argv[0])) +sys.path.append(os.path.join(scriptDir, '..', 'extra')) + +from testutils import * +from pprint import pprint + + +# +# Args handling +# + +parser = argparse.ArgumentParser() +parser.add_argument("--exec", metavar="", default="../build/wasm3 --repl") +parser.add_argument("--spec", default="opam-1.1.1") +parser.add_argument("--timeout", type=int, default=30) +parser.add_argument("--line", metavar="", type=int) +parser.add_argument("--all", action="store_true") +parser.add_argument("--show-logs", action="store_true") +parser.add_argument("--format", choices=["raw", "hex", "fp"], default="fp") +parser.add_argument("-v", "--verbose", action="store_true") +parser.add_argument("-s", "--silent", action="store_true") +parser.add_argument("file", nargs='*') + +args = parser.parse_args() + +if args.line: + args.show_logs = True + +# +# Utilities +# + +log = open("spec-test.log","w+") +log.write("======================\n") + +def warning(msg, force=False): + log.write("Warning: " + msg + "\n") + log.flush() + if args.verbose or force: + print(f"{ansi.WARNING}Warning:{ansi.ENDC} {msg}") + +def fatal(msg): + log.write("Fatal: " + msg + "\n") + log.flush() + print(f"{ansi.FAIL}Fatal:{ansi.ENDC} {msg}") + sys.exit(1) + +def safe_fn(fn): + keepcharacters = (' ','.','_','-') + return "".join(c for c in fn if c.isalnum() or c in keepcharacters).strip() + +def binaryToFloat(num, t): + if t == "f32": + return struct.unpack('!f', struct.pack('!L', int(num)))[0] + elif t == "f64": + return struct.unpack('!d', struct.pack('!Q', int(num)))[0] + else: + fatal(f"Unknown type '{t}'") + +def escape_str(s): + if s == "": + return r'\x00' + + if all((ord(c) < 128 and c.isprintable() and c not in " \n\r\t\\") for c in s): + return s + + return '\\x' + '\\x'.join('{0:02x}'.format(x) for x in s.encode('utf-8')) + +# +# Value format options +# + +def formatValueRaw(num, t): + return str(num) + +def formatValueHex(num, t): + if t == "f32" or t == "i32": + return "{0:#0{1}x}".format(int(num), 8+2) + elif t == "f64" or t == "i64": + return "{0:#0{1}x}".format(int(num), 16+2) + else: + return str(num) + +def formatValueFloat(num, t): + if t == "f32": + s = 6 + elif t == "f64": + s = 10 + else: + return str(num) + + result = "{0:.{1}f}".format(binaryToFloat(num, t), s).rstrip('0') + if result.endswith('.'): + result = result + '0' + if len(result) > s*2: + result = "{0:.{1}e}".format(binaryToFloat(num, t), s) + return result + +formaters = { + 'raw': formatValueRaw, + 'hex': formatValueHex, + 'fp': formatValueFloat, +} +formatValue = formaters[args.format] + +if args.format == "fp": + print("When using fp display format, values are compared loosely (some tests may produce false positives)") + +# +# Spec tests preparation +# + +spec_dir = os.path.join(".", ".spec-" + safe_fn(args.spec)) + +if not (os.path.isdir(spec_dir)): + from io import BytesIO + from zipfile import ZipFile + from urllib.request import urlopen + + officialSpec = f"https://github.com/wasm3/wasm-core-testsuite/archive/{args.spec}.zip" + + print(f"Downloading {officialSpec}") + resp = urlopen(officialSpec) + with ZipFile(BytesIO(resp.read())) as zipFile: + for zipInfo in zipFile.infolist(): + if re.match(r".*-.*/.*/.*(\.wasm|\.json)", zipInfo.filename): + parts = pathlib.Path(zipInfo.filename).parts + newpath = str(pathlib.Path(*parts[1:-1])) + newfn = str(pathlib.Path(*parts[-1:])) + ensure_path(os.path.join(spec_dir, newpath)) + newpath = os.path.join(spec_dir, newpath, newfn) + zipInfo.filename = newpath + zipFile.extract(zipInfo) + +# +# Wasm3 REPL +# + +from subprocess import Popen, STDOUT, PIPE +from threading import Thread +from queue import Queue, Empty + +import shlex + +class Wasm3(): + def __init__(self, exe): + self.exe = exe + self.p = None + self.loaded = None + self.timeout = args.timeout + self.autorestart = True + + self.run() + + def run(self): + if self.p: + self.terminate() + + cmd = shlex.split(self.exe) + + #print(f"wasm3: Starting {' '.join(cmd)}") + + self.q = Queue() + self.p = Popen(cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=STDOUT) + + def _read_output(out, queue): + for data in iter(lambda: out.read(1024), b''): + queue.put(data) + queue.put(None) + + self.t = Thread(target=_read_output, args=(self.p.stdout, self.q)) + self.t.daemon = True + self.t.start() + + try: + self._read_until("wasm3> ") + except Exception as e: + print(f"wasm3: Could not start: {e}") + + def restart(self): + print(f"wasm3: Restarting") + for i in range(10): + try: + self.run() + try: + if self.loaded: + self.load(self.loaded) + except Exception as e: + pass + break + except Exception as e: + print(f"wasm3: {e} => retry") + time.sleep(0.1) + + def init(self): + return self._run_cmd(f":init\n") + + def version(self): + return self._run_cmd(f":version\n") + + def load(self, fn): + self.loaded = None + with open(fn,"rb") as f: + wasm = f.read() + res = self._run_cmd(f":load-hex {len(wasm)}\n{wasm.hex()}\n") + self.loaded = fn + return res + + def invoke(self, cmd): + return self._run_cmd(":invoke " + " ".join(map(str, cmd)) + "\n") + + def _run_cmd(self, cmd): + if self.autorestart and not self._is_running(): + self.restart() + self._flush_input() + + #print(f"wasm3: {cmd.strip()}") + self._write(cmd) + return self._read_until("wasm3> ") + + def _read_until(self, token): + buff = "" + tout = time.time() + self.timeout + error = None + + while time.time() < tout: + try: + data = self.q.get(timeout=0.1) + if data is None: + error = "Crashed" + break + buff = buff + data.decode("utf-8") + idx = buff.rfind(token) + if idx >= 0: + return buff[0:idx].strip() + except Empty: + pass + else: + error = "Timeout" + + self.terminate() + raise Exception(error) + + def _write(self, data): + self.p.stdin.write(data.encode("utf-8")) + self.p.stdin.flush() + + def _is_running(self): + return self.p and (self.p.poll() is None) + + def _flush_input(self): + while not self.q.empty(): + self.q.get() + + def terminate(self): + self.p.stdin.close() + self.p.terminate() + self.p.wait(timeout=1.0) + self.p = None + +# +# Multi-value result handling +# + +def parseResults(s): + values = s.split(", ") + values = [x.split(":") for x in values] + values = [{ "type": x[1], "value": int(x[0]) } for x in values] + + return normalizeResults(values) + +def normalizeResults(values): + for x in values: + t = x["type"] + v = x["value"] + if t == "f32" or t == "f64": + if v == "nan:canonical" or v == "nan:arithmetic" or math.isnan(binaryToFloat(v, t)): + x["value"] = "nan:any" + else: + x["value"] = formatValue(v, t) + else: + x["value"] = formatValue(v, t) + return values + +def combineResults(values): + values = [x["value"]+":"+x["type"] for x in values] + return ", ".join(values) + +# +# Actual test +# + +wasm3 = Wasm3(args.exec) + +wasm3_ver = wasm3.version() +print(wasm3_ver) + +blacklist = Blacklist([ + "float_exprs.wast:* f32.nonarithmetic_nan_bitpattern*", + "imports.wast:*", + "names.wast:* *.wasm \\x00*", # names that start with '\0' +]) + +if wasm3_ver in Blacklist(["* on i386* MSVC *", "* on i386* Clang * for Windows"]): + warning("Win32 x86 has i64->f32 conversion precision issues, skipping some tests", True) + # See: https://docs.microsoft.com/en-us/cpp/c-runtime-library/floating-point-support + blacklist.add([ + "conversions.wast:* f32.convert_i64_u(9007199791611905)", + "conversions.wast:* f32.convert_i64_u(9223371761976868863)", + "conversions.wast:* f32.convert_i64_u(9223372586610589697)", + ]) +elif wasm3_ver in Blacklist(["* on mips* GCC *"]): + warning("MIPS has NaN representation issues, skipping some tests", True) + blacklist.add([ + "float_exprs.wast:* *_nan_bitpattern(*", + "float_exprs.wast:* *no_fold_*", + ]) +elif wasm3_ver in Blacklist(["* on sparc* GCC *"]): + warning("SPARC has NaN representation issues, skipping some tests", True) + blacklist.add([ + "float_exprs.wast:* *.canonical_nan_bitpattern(0, 0)", + ]) + +stats = dotdict(total_run=0, skipped=0, failed=0, crashed=0, timeout=0, success=0, missing=0) + +# Convert some trap names from the original spec +trapmap = { + "unreachable": "unreachable executed" +} + +def runInvoke(test): + test.cmd = [test.action.field] + + displayArgs = [] + for arg in test.action.args: + test.cmd.append(arg['value']) + displayArgs.append(formatValue(arg['value'], arg['type'])) + + test_id = f"{test.source} {test.wasm} {test.cmd[0]}({', '.join(test.cmd[1:])})" + if test_id in blacklist and not args.all: + warning(f"Skipped {test_id} (blacklisted)") + stats.skipped += 1 + return + + if args.verbose: + print(f"Running {test_id}") + + stats.total_run += 1 + + output = "" + actual = None + actual_val = None + force_fail = False + + try: + output = wasm3.invoke(test.cmd) + except Exception as e: + actual = f"<{e}>" + force_fail = True + + # Parse the actual output + if not actual: + result = re.findall(r'Result: (.*?)$', "\n" + output + "\n", re.MULTILINE) + if len(result) > 0: + actual = "result " + result[-1] + actual_val = result[0] + if not actual: + result = re.findall(r'Error: \[trap\] (.*?) \(', "\n" + output + "\n", re.MULTILINE) + if len(result) > 0: + actual = "trap " + result[-1] + if not actual: + result = re.findall(r'Error: (.*?)$', "\n" + output + "\n", re.MULTILINE) + if len(result) > 0: + actual = "error " + result[-1] + if not actual: + actual = "" + force_fail = True + + if actual == "error no operation ()": + actual = "" + stats.missing += 1 + force_fail = True + elif actual == "": + stats.crashed += 1 + force_fail = True + elif actual == "": + stats.timeout += 1 + force_fail = True + + # Prepare the expected result + expect = None + if "expected" in test: + if len(test.expected) == 0: + expect = "result " + else: + if actual_val is not None: + actual = "result " + combineResults(parseResults(actual_val)) + expect = "result " + combineResults(normalizeResults(test.expected)) + + elif "expected_trap" in test: + if test.expected_trap in trapmap: + test.expected_trap = trapmap[test.expected_trap] + + expect = "trap " + str(test.expected_trap) + elif "expected_anything" in test: + expect = "" + else: + expect = "" + + def showTestResult(): + print(" ----------------------") + print(f"Test: {ansi.HEADER}{test_id}{ansi.ENDC}") + print(f"Args: {', '.join(displayArgs)}") + print(f"Expected: {ansi.OKGREEN}{expect}{ansi.ENDC}") + print(f"Actual: {ansi.WARNING}{actual}{ansi.ENDC}") + if args.show_logs and len(output): + print(f"Log:") + print(output) + + log.write(f"{test.source}\t|\t{test.wasm} {test.action.field}({', '.join(displayArgs)})\t=>\t\t") + if actual == expect or (expect == "" and not force_fail): + stats.success += 1 + log.write(f"OK: {actual}\n") + if args.line: + showTestResult() + else: + stats.failed += 1 + log.write(f"FAIL: {actual}, should be: {expect}\n") + if args.silent: + return + + showTestResult() + #sys.exit(1) + +if args.file: + jsonFiles = args.file +else: + jsonFiles = glob.glob(os.path.join(spec_dir, "core", "*.json")) + jsonFiles += glob.glob(os.path.join(spec_dir, "proposals", "sign-extension-ops", "*.json")) + jsonFiles += glob.glob(os.path.join(spec_dir, "proposals", "nontrapping-float-to-int-conversions", "*.json")) + +jsonFiles = list(map(lambda x: os.path.relpath(x, scriptDir), jsonFiles)) +jsonFiles.sort() + +for fn in jsonFiles: + with open(fn, encoding='utf-8') as f: + data = json.load(f) + + wast_source = filename(data["source_filename"]) + wasm_module = "" + + print(f"Running {fn}") + + wasm3.init() + + for cmd in data["commands"]: + test = dotdict() + test.line = int(cmd["line"]) + test.source = wast_source + ":" + str(test.line) + test.wasm = wasm_module + test.type = cmd["type"] + + if test.type == "module": + wasm_module = cmd["filename"] + + if args.verbose: + print(f"Loading {wasm_module}") + + try: + wasm_fn = os.path.join(pathname(fn), wasm_module) + res = wasm3.load(wasm_fn) + if res: + warning(res) + except Exception as e: + pass #fatal(str(e)) + + elif ( test.type == "action" or + test.type == "assert_return" or + test.type == "assert_trap" or + test.type == "assert_exhaustion" or + test.type == "assert_return_canonical_nan" or + test.type == "assert_return_arithmetic_nan"): + + if args.line and test.line != args.line: + continue + + if test.type == "action": + test.expected_anything = True + elif test.type == "assert_return": + test.expected = cmd["expected"] + elif test.type == "assert_return_canonical_nan": + test.expected = cmd["expected"] + test.expected[0]["value"] = "nan:canonical" + elif test.type == "assert_return_arithmetic_nan": + test.expected = cmd["expected"] + test.expected[0]["value"] = "nan:arithmetic" + elif test.type == "assert_trap": + test.expected_trap = cmd["text"] + elif test.type == "assert_exhaustion": + test.expected_trap = "stack overflow" + else: + stats.skipped += 1 + warning(f"Skipped {test.source} ({test.type} not implemented)") + continue + + test.action = dotdict(cmd["action"]) + if test.action.type == "invoke": + + # TODO: invoking in modules not implemented + if test.action.module: + stats.skipped += 1 + warning(f"Skipped {test.source} (invoke in module)") + continue + + test.action.field = escape_str(test.action.field) + + runInvoke(test) + else: + stats.skipped += 1 + warning(f"Skipped {test.source} (unknown action type '{test.action.type}')") + + + # These are irrelevant + elif (test.type == "assert_invalid" or + test.type == "assert_malformed" or + test.type == "assert_uninstantiable"): + pass + + # Others - report as skipped + else: + stats.skipped += 1 + warning(f"Skipped {test.source} ('{test.type}' not implemented)") + +if (stats.failed + stats.success) != stats.total_run: + warning("Statistics summary invalid", True) + +pprint(stats) + +if stats.failed > 0: + failed = (stats.failed*100)/stats.total_run + print(f"{ansi.FAIL}=======================") + print(f" FAILED: {failed:.2f}%") + if stats.crashed > 0: + print(f" Crashed: {stats.crashed}") + print(f"======================={ansi.ENDC}") + sys.exit(1) + +elif stats.success > 0: + print(f"{ansi.OKGREEN}=======================") + print(f" {stats.success}/{stats.total_run} tests OK") + if stats.skipped > 0: + print(f"{ansi.WARNING} ({stats.skipped} tests skipped){ansi.OKGREEN}") + print(f"======================={ansi.ENDC}") + +elif stats.total_run == 0: + print("Error: No tests run") + sys.exit(1) + diff --git a/wasm3-sys/wasm3/test/run-wasi-test.py b/wasm3-sys/wasm3/test/run-wasi-test.py new file mode 100755 index 0000000..9773b1e --- /dev/null +++ b/wasm3-sys/wasm3/test/run-wasi-test.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 + +# Author: Volodymyr Shymanskyy +# Usage: +# ./run-wasi-test.py +# ./run-wasi-test.py --exec ../custom_build/wasm3 --timeout 120 +# ./run-wasi-test.py --exec "wasmer run --mapdir=/:." --separate-args +# ./run-wasi-test.py --exec "wasmer run --mapdir=/:. wasm3.wasm --" --fast + +import argparse +import sys +import subprocess +import hashlib +import fnmatch + +sys.path.append('../extra') + +from testutils import * +from pprint import pprint + +# +# Args handling +# + +parser = argparse.ArgumentParser() +parser.add_argument("--exec", metavar="", default="../build/wasm3") +parser.add_argument("--separate-args", action='store_true') # use "--" separator for wasmer, wasmtime +parser.add_argument("--timeout", type=int, default=120) +parser.add_argument("--fast", action='store_true') + +args = parser.parse_args() + +stats = dotdict(total_run=0, failed=0, crashed=0, timeout=0) + +commands_full = [ + { + "name": "Simple WASI test", + "wasm": "./wasi/simple/test.wasm", + "args": ["cat", "/wasi/simple/0.txt"], + "expect_pattern": "Hello world*Constructor OK*Args: *; cat; /wasi/simple/0.txt;*fib(20) = 6765* ms*48 65 6c 6c 6f 20 77 6f 72 6c 64*=== done ===*" + }, { + "name": "Simple WASI test (wasm-opt -O3)", + "wasm": "./wasi/simple/test-opt.wasm", + "args": ["cat", "./wasi/simple/0.txt"], + "expect_pattern": "Hello world*Constructor OK*Args: *; cat; ./wasi/simple/0.txt;*fib(20) = 6765* ms*48 65 6c 6c 6f 20 77 6f 72 6c 64*=== done ===*" + }, { + "name": "mandelbrot", + "wasm": "./wasi/mandelbrot/mandel.wasm", + "args": ["128", "4e5"], + "expect_sha1": "37091e7ce96adeea88f079ad95d239a651308a56" + }, { + "name": "mandelbrot (doubledouble)", + "wasm": "./wasi/mandelbrot/mandel_dd.wasm", + "args": ["128", "4e5"], + "expect_sha1": "b3f904daf1c972b4f7d3f8996743cb5b5146b877" + }, { + "name": "C-Ray", + "stdin": "./wasi/c-ray/scene", + "wasm": "./wasi/c-ray/c-ray.wasm", + "args": ["-s", "128x128"], + "expect_sha1": "90f86845ae227466a06ea8db06e753af4838f2fa" + }, { + "name": "smallpt (explicit light sampling)", + "wasm": "./wasi/smallpt/smallpt-ex.wasm", + "args": ["16", "64"], + "expect_sha1": "d85df3561eb15f6f0e6f20d5640e8e1306222c6d" + }, { + "name": "smallpt (explicit light sampling, multi-value)", + "wasm": "./wasi/smallpt/smallpt-ex-mv.wasm", + "args": ["16", "64"], + "expect_sha1": "d85df3561eb15f6f0e6f20d5640e8e1306222c6d" + }, { + "name": "mal", + "wasm": "./wasi/mal/mal.wasm", + "args": ["./wasi/mal/test-fib.mal", "16"], + "expect_pattern": "987\n", + }, { + "name": "STREAM", + "wasm": "./wasi/stream/stream.wasm", + "expect_pattern": "----*Solution Validates:*on all three arrays*----*" + }, { + # TODO "if": { "file_exists": "./self-hosting/wasm3-fib.wasm" }, + "name": "Self-hosting", + "wasm": "./self-hosting/wasm3-fib.wasm", + "expect_pattern": "wasm3 on WASM*Result: 832040*Elapsed: * ms*" + }, { + "name": "Brotli", + "stdin": "./wasi/brotli/alice29.txt", + "wasm": "./wasi/brotli/brotli.wasm", + "args": ["-c", "-f"], + "expect_sha1": "8eacda4b80fc816cad185330caa7556e19643dff" + }, { + "name": "CoreMark", + "wasm": "./wasi/coremark/coremark.wasm", + "expect_pattern": "*Correct operation validated.*CoreMark 1.0 : * / Clang* / STATIC*" + } +] + +commands_fast = [ + { + "name": "Simple WASI test", + "wasm": "./wasi/simple/test.wasm", + "args": ["cat", "./wasi/simple/0.txt"], + "expect_pattern": "Hello world*Constructor OK*Args: *; cat; ./wasi/simple/0.txt;*fib(20) = 6765* ms*48 65 6c 6c 6f 20 77 6f 72 6c 64*=== done ===*" + }, { + "skip": True, # Backtraces not enabled by default + "name": "Simple WASI test", + "wasm": "./wasi/test.wasm", + "args": ["trap"], + "can_crash": True, + "expect_pattern": "Hello world*Constructor OK*Args: *; trap;* wasm backtrace:* 6: 0x*Error:* unreachable executed*" + }, { + "name": "mandelbrot", + "wasm": "./wasi/mandelbrot/mandel.wasm", + "args": ["32", "4e5"], + "expect_sha1": "1fdb7dea7ec0f2465054cc623dc5a7225a876361" + }, { + "name": "mandelbrot (doubledouble)", + "wasm": "./wasi/mandelbrot/mandel_dd.wasm", + "args": ["32", "4e5"], + "expect_sha1": "b6d3c158a5c0dff1f6e82a3556c071e4f8b9e3f0" + }, { + "name": "C-Ray", + "stdin": "./wasi/c-ray/scene", + "wasm": "./wasi/c-ray/c-ray.wasm", + "args": ["-s", "32x32"], + "expect_sha1": "05af9604bf352234276e4d64e84b8d666574316c" + }, { + "name": "smallpt (explicit light sampling)", + "wasm": "./wasi/smallpt/smallpt-ex.wasm", + "args": ["4", "32"], + "expect_sha1": "ea05d85998b2f453b588ef76a1256215bf9b851c" + }, { + "name": "smallpt (explicit light sampling, multi-value)", + "wasm": "./wasi/smallpt/smallpt-ex-mv.wasm", + "args": ["4", "32"], + "expect_sha1": "ea05d85998b2f453b588ef76a1256215bf9b851c" + }, { + "name": "mal", + "wasm": "./wasi/mal/mal.wasm", + "args": ["./wasi/mal/test-fib.mal", "16"], + "expect_pattern": "987\n", + }, { + "name": "Brotli", + "stdin": "./wasi/brotli/alice29_small.txt", + "wasm": "./wasi/brotli/brotli.wasm", + "args": ["-c", "-f"], + "expect_sha1": "0e8af02a7207c0c617d7d38eed92853c4a619987" + } +] + +def fail(msg): + print(f"{ansi.FAIL}FAIL:{ansi.ENDC} {msg}") + stats.failed += 1 + +commands = commands_fast if args.fast else commands_full + +for cmd in commands: + if "skip" in cmd: + continue + + command = args.exec.split(' ') + command.append(cmd['wasm']) + if "args" in cmd: + if args.separate_args: + command.append("--") + command.extend(cmd['args']) + + command = list(map(str, command)) + print(f"=== {cmd['name']} ===") + stats.total_run += 1 + try: + if "stdin" in cmd: + fn = cmd['stdin'] + f = open(fn, "rb") + print(f"cat {fn} | {' '.join(command)}") + output = subprocess.check_output(command, timeout=args.timeout, stdin=f) + elif "can_crash" in cmd: + print(f"{' '.join(command)}") + output = subprocess.run(command, timeout=args.timeout, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout + else: + print(f"{' '.join(command)}") + output = subprocess.check_output(command, timeout=args.timeout) + except subprocess.TimeoutExpired: + stats.timeout += 1 + fail("Timeout") + continue + except subprocess.CalledProcessError as e: + stats.crashed += 1 + fail(f"Exited with error code {e.returncode}") + continue + + if "expect_sha1" in cmd: + actual = hashlib.sha1(output).hexdigest() + if actual != cmd['expect_sha1']: + fail(f"Actual sha1: {actual}") + + if "expect_pattern" in cmd: + actual = output.decode("utf-8") + if not fnmatch.fnmatch(actual, cmd['expect_pattern']): + fail(f"Output does not match pattern:\n{actual}") + + print() + +pprint(stats) + +if stats.failed: + print(f"{ansi.FAIL}=======================") + print(f" FAILED: {stats.failed}/{stats.total_run}") + print(f"======================={ansi.ENDC}") + sys.exit(1) + +else: + print(f"{ansi.OKGREEN}=======================") + print(f" All {stats.total_run} tests OK") + print(f"======================={ansi.ENDC}") diff --git a/wasm3-sys/wasm3/test/self-hosting/wasm3-fib.wasm b/wasm3-sys/wasm3/test/self-hosting/wasm3-fib.wasm new file mode 100644 index 0000000..1c55fe2 Binary files /dev/null and b/wasm3-sys/wasm3/test/self-hosting/wasm3-fib.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/brotli/README.md b/wasm3-sys/wasm3/test/wasi/brotli/README.md new file mode 100644 index 0000000..ec8f6aa --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/brotli/README.md @@ -0,0 +1,47 @@ +# Brotli 1.0.7 + +https://github.com/google/brotli + +### Results + +```log +TODO +``` + +### Building + +```sh +export CC=wasicc +make +cd bin +wasm-opt -O3 brotli.wasm -o brotli.wasm +``` + +### Running + +```sh +export ENGINES_PATH=/opt/wasm_engines + +# Wasm3 +cat alice29.txt | ../../../build/wasm3 brotli.wasm -c > alice29.txt.comp + +# WAC +cat alice29.txt | $ENGINES_PATH/wac/wax brotli.wasm -c > alice29.txt.comp + +# wasm-micro-runtime +cat alice29.txt | $ENGINES_PATH/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm brotli.wasm -c > alice29.txt.comp + +# wasmtime +cat alice29.txt | wasmtime --optimize brotli.wasm -- -c > alice29.txt.comp + +# Wasmer +cat alice29.txt | wasmer run brotli.wasm -- -c > alice29.txt.comp + +# Wasmer-JS (V8) +cat alice29.txt | wasmer-js run brotli.wasm -- -c > alice29.txt.comp + +cat alice29.txt | node --wasm_interpret_all $(which wasmer-js) run brotli.wasm -- -c > alice29.txt.comp + +# WAVM +cat alice29.txt | $ENGINES_PATH/WAVM/Release/bin/wavm run brotli.wasm -c > alice29.txt.comp +``` diff --git a/wasm3-sys/wasm3/test/wasi/brotli/alice29.txt b/wasm3-sys/wasm3/test/wasi/brotli/alice29.txt new file mode 100644 index 0000000..7033655 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/brotli/alice29.txt @@ -0,0 +1,3609 @@ + + + + + ALICE'S ADVENTURES IN WONDERLAND + + Lewis Carroll + + THE MILLENNIUM FULCRUM EDITION 2.9 + + + + + CHAPTER I + + Down the Rabbit-Hole + + + Alice was beginning to get very tired of sitting by her sister +on the bank, and of having nothing to do: once or twice she had +peeped into the book her sister was reading, but it had no +pictures or conversations in it, `and what is the use of a book,' +thought Alice `without pictures or conversation?' + + So she was considering in her own mind (as well as she could, +for the hot day made her feel very sleepy and stupid), whether +the pleasure of making a daisy-chain would be worth the trouble +of getting up and picking the daisies, when suddenly a White +Rabbit with pink eyes ran close by her. + + There was nothing so VERY remarkable in that; nor did Alice +think it so VERY much out of the way to hear the Rabbit say to +itself, `Oh dear! Oh dear! I shall be late!' (when she thought +it over afterwards, it occurred to her that she ought to have +wondered at this, but at the time it all seemed quite natural); +but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT- +POCKET, and looked at it, and then hurried on, Alice started to +her feet, for it flashed across her mind that she had never +before seen a rabbit with either a waistcoat-pocket, or a watch to +take out of it, and burning with curiosity, she ran across the +field after it, and fortunately was just in time to see it pop +down a large rabbit-hole under the hedge. + + In another moment down went Alice after it, never once +considering how in the world she was to get out again. + + The rabbit-hole went straight on like a tunnel for some way, +and then dipped suddenly down, so suddenly that Alice had not a +moment to think about stopping herself before she found herself +falling down a very deep well. + + Either the well was very deep, or she fell very slowly, for she +had plenty of time as she went down to look about her and to +wonder what was going to happen next. First, she tried to look +down and make out what she was coming to, but it was too dark to +see anything; then she looked at the sides of the well, and +noticed that they were filled with cupboards and book-shelves; +here and there she saw maps and pictures hung upon pegs. She +took down a jar from one of the shelves as she passed; it was +labelled `ORANGE MARMALADE', but to her great disappointment it +was empty: she did not like to drop the jar for fear of killing +somebody, so managed to put it into one of the cupboards as she +fell past it. + + `Well!' thought Alice to herself, `after such a fall as this, I +shall think nothing of tumbling down stairs! How brave they'll +all think me at home! Why, I wouldn't say anything about it, +even if I fell off the top of the house!' (Which was very likely +true.) + + Down, down, down. Would the fall NEVER come to an end! `I +wonder how many miles I've fallen by this time?' she said aloud. +`I must be getting somewhere near the centre of the earth. Let +me see: that would be four thousand miles down, I think--' (for, +you see, Alice had learnt several things of this sort in her +lessons in the schoolroom, and though this was not a VERY good +opportunity for showing off her knowledge, as there was no one to +listen to her, still it was good practice to say it over) `--yes, +that's about the right distance--but then I wonder what Latitude +or Longitude I've got to?' (Alice had no idea what Latitude was, +or Longitude either, but thought they were nice grand words to +say.) + + Presently she began again. `I wonder if I shall fall right +THROUGH the earth! How funny it'll seem to come out among the +people that walk with their heads downward! The Antipathies, I +think--' (she was rather glad there WAS no one listening, this +time, as it didn't sound at all the right word) `--but I shall +have to ask them what the name of the country is, you know. +Please, Ma'am, is this New Zealand or Australia?' (and she tried +to curtsey as she spoke--fancy CURTSEYING as you're falling +through the air! Do you think you could manage it?) `And what +an ignorant little girl she'll think me for asking! No, it'll +never do to ask: perhaps I shall see it written up somewhere.' + + Down, down, down. There was nothing else to do, so Alice soon +began talking again. `Dinah'll miss me very much to-night, I +should think!' (Dinah was the cat.) `I hope they'll remember +her saucer of milk at tea-time. Dinah my dear! I wish you were +down here with me! There are no mice in the air, I'm afraid, but +you might catch a bat, and that's very like a mouse, you know. +But do cats eat bats, I wonder?' And here Alice began to get +rather sleepy, and went on saying to herself, in a dreamy sort of +way, `Do cats eat bats? Do cats eat bats?' and sometimes, `Do +bats eat cats?' for, you see, as she couldn't answer either +question, it didn't much matter which way she put it. She felt +that she was dozing off, and had just begun to dream that she +was walking hand in hand with Dinah, and saying to her very +earnestly, `Now, Dinah, tell me the truth: did you ever eat a +bat?' when suddenly, thump! thump! down she came upon a heap of +sticks and dry leaves, and the fall was over. + + Alice was not a bit hurt, and she jumped up on to her feet in a +moment: she looked up, but it was all dark overhead; before her +was another long passage, and the White Rabbit was still in +sight, hurrying down it. There was not a moment to be lost: +away went Alice like the wind, and was just in time to hear it +say, as it turned a corner, `Oh my ears and whiskers, how late +it's getting!' She was close behind it when she turned the +corner, but the Rabbit was no longer to be seen: she found +herself in a long, low hall, which was lit up by a row of lamps +hanging from the roof. + + There were doors all round the hall, but they were all locked; +and when Alice had been all the way down one side and up the +other, trying every door, she walked sadly down the middle, +wondering how she was ever to get out again. + + Suddenly she came upon a little three-legged table, all made of +solid glass; there was nothing on it except a tiny golden key, +and Alice's first thought was that it might belong to one of the +doors of the hall; but, alas! either the locks were too large, or +the key was too small, but at any rate it would not open any of +them. However, on the second time round, she came upon a low +curtain she had not noticed before, and behind it was a little +door about fifteen inches high: she tried the little golden key +in the lock, and to her great delight it fitted! + + Alice opened the door and found that it led into a small +passage, not much larger than a rat-hole: she knelt down and +looked along the passage into the loveliest garden you ever saw. +How she longed to get out of that dark hall, and wander about +among those beds of bright flowers and those cool fountains, but +she could not even get her head though the doorway; `and even if +my head would go through,' thought poor Alice, `it would be of +very little use without my shoulders. Oh, how I wish +I could shut up like a telescope! I think I could, if I only +know how to begin.' For, you see, so many out-of-the-way things +had happened lately, that Alice had begun to think that very few +things indeed were really impossible. + + There seemed to be no use in waiting by the little door, so she +went back to the table, half hoping she might find another key on +it, or at any rate a book of rules for shutting people up like +telescopes: this time she found a little bottle on it, (`which +certainly was not here before,' said Alice,) and round the neck +of the bottle was a paper label, with the words `DRINK ME' +beautifully printed on it in large letters. + + It was all very well to say `Drink me,' but the wise little +Alice was not going to do THAT in a hurry. `No, I'll look +first,' she said, `and see whether it's marked "poison" or not'; +for she had read several nice little histories about children who +had got burnt, and eaten up by wild beasts and other unpleasant +things, all because they WOULD not remember the simple rules +their friends had taught them: such as, that a red-hot poker +will burn you if you hold it too long; and that if you cut your +finger VERY deeply with a knife, it usually bleeds; and she had +never forgotten that, if you drink much from a bottle marked +`poison,' it is almost certain to disagree with you, sooner or +later. + + However, this bottle was NOT marked `poison,' so Alice ventured +to taste it, and finding it very nice, (it had, in fact, a sort +of mixed flavour of cherry-tart, custard, pine-apple, roast +turkey, toffee, and hot buttered toast,) she very soon finished +it off. + + * * * * * * * + + * * * * * * + + * * * * * * * + + `What a curious feeling!' said Alice; `I must be shutting up +like a telescope.' + + And so it was indeed: she was now only ten inches high, and +her face brightened up at the thought that she was now the right +size for going though the little door into that lovely garden. +First, however, she waited for a few minutes to see if she was +going to shrink any further: she felt a little nervous about +this; `for it might end, you know,' said Alice to herself, `in my +going out altogether, like a candle. I wonder what I should be +like then?' And she tried to fancy what the flame of a candle is +like after the candle is blown out, for she could not remember +ever having seen such a thing. + + After a while, finding that nothing more happened, she decided +on going into the garden at once; but, alas for poor Alice! when +she got to the door, she found he had forgotten the little golden +key, and when she went back to the table for it, she found she +could not possibly reach it: she could see it quite plainly +through the glass, and she tried her best to climb up one of the +legs of the table, but it was too slippery; and when she had +tired herself out with trying, the poor little thing sat down and +cried. + + `Come, there's no use in crying like that!' said Alice to +herself, rather sharply; `I advise you to leave off this minute!' +She generally gave herself very good advice, (though she very +seldom followed it), and sometimes she scolded herself so +severely as to bring tears into her eyes; and once she remembered +trying to box her own ears for having cheated herself in a game +of croquet she was playing against herself, for this curious +child was very fond of pretending to be two people. `But it's no +use now,' thought poor Alice, `to pretend to be two people! Why, +there's hardly enough of me left to make ONE respectable +person!' + + Soon her eye fell on a little glass box that was lying under +the table: she opened it, and found in it a very small cake, on +which the words `EAT ME' were beautifully marked in currants. +`Well, I'll eat it,' said Alice, `and if it makes me grow larger, +I can reach the key; and if it makes me grow smaller, I can creep +under the door; so either way I'll get into the garden, and I +don't care which happens!' + + She ate a little bit, and said anxiously to herself, `Which +way? Which way?', holding her hand on the top of her head to +feel which way it was growing, and she was quite surprised to +find that she remained the same size: to be sure, this generally +happens when one eats cake, but Alice had got so much into the +way of expecting nothing but out-of-the-way things to happen, +that it seemed quite dull and stupid for life to go on in the +common way. + + So she set to work, and very soon finished off the cake. + + * * * * * * * + + * * * * * * + + * * * * * * * + + + + + CHAPTER II + + The Pool of Tears + + + `Curiouser and curiouser!' cried Alice (she was so much +surprised, that for the moment she quite forgot how to speak good +English); `now I'm opening out like the largest telescope that +ever was! Good-bye, feet!' (for when she looked down at her +feet, they seemed to be almost out of sight, they were getting so +far off). `Oh, my poor little feet, I wonder who will put on +your shoes and stockings for you now, dears? I'm sure _I_ shan't +be able! I shall be a great deal too far off to trouble myself +about you: you must manage the best way you can; --but I must be +kind to them,' thought Alice, `or perhaps they won't walk the +way I want to go! Let me see: I'll give them a new pair of +boots every Christmas.' + + And she went on planning to herself how she would manage it. +`They must go by the carrier,' she thought; `and how funny it'll +seem, sending presents to one's own feet! And how odd the +directions will look! + + ALICE'S RIGHT FOOT, ESQ. + HEARTHRUG, + NEAR THE FENDER, + (WITH ALICE'S LOVE). + +Oh dear, what nonsense I'm talking!' + + Just then her head struck against the roof of the hall: in +fact she was now more than nine feet high, and she at once took +up the little golden key and hurried off to the garden door. + + Poor Alice! It was as much as she could do, lying down on one +side, to look through into the garden with one eye; but to get +through was more hopeless than ever: she sat down and began to +cry again. + + `You ought to be ashamed of yourself,' said Alice, `a great +girl like you,' (she might well say this), `to go on crying in +this way! Stop this moment, I tell you!' But she went on all +the same, shedding gallons of tears, until there was a large pool +all round her, about four inches deep and reaching half down the +hall. + + After a time she heard a little pattering of feet in the +distance, and she hastily dried her eyes to see what was coming. +It was the White Rabbit returning, splendidly dressed, with a +pair of white kid gloves in one hand and a large fan in the +other: he came trotting along in a great hurry, muttering to +himself as he came, `Oh! the Duchess, the Duchess! Oh! won't she +be savage if I've kept her waiting!' Alice felt so desperate +that she was ready to ask help of any one; so, when the Rabbit +came near her, she began, in a low, timid voice, `If you please, +sir--' The Rabbit started violently, dropped the white kid +gloves and the fan, and skurried away into the darkness as hard +as he could go. + + Alice took up the fan and gloves, and, as the hall was very +hot, she kept fanning herself all the time she went on talking: +`Dear, dear! How queer everything is to-day! And yesterday +things went on just as usual. I wonder if I've been changed in +the night? Let me think: was I the same when I got up this +morning? I almost think I can remember feeling a little +different. But if I'm not the same, the next question is, Who in +the world am I? Ah, THAT'S the great puzzle!' And she began +thinking over all the children she knew that were of the same age +as herself, to see if she could have been changed for any of +them. + + `I'm sure I'm not Ada,' she said, `for her hair goes in such +long ringlets, and mine doesn't go in ringlets at all; and I'm +sure I can't be Mabel, for I know all sorts of things, and she, +oh! she knows such a very little! Besides, SHE'S she, and I'm I, +and--oh dear, how puzzling it all is! I'll try if I know all the +things I used to know. Let me see: four times five is twelve, +and four times six is thirteen, and four times seven is--oh dear! +I shall never get to twenty at that rate! However, the +Multiplication Table doesn't signify: let's try Geography. +London is the capital of Paris, and Paris is the capital of Rome, +and Rome--no, THAT'S all wrong, I'm certain! I must have been +changed for Mabel! I'll try and say "How doth the little--"' +and she crossed her hands on her lap as if she were saying lessons, +and began to repeat it, but her voice sounded hoarse and +strange, and the words did not come the same as they used to do:-- + + `How doth the little crocodile + Improve his shining tail, + And pour the waters of the Nile + On every golden scale! + + `How cheerfully he seems to grin, + How neatly spread his claws, + And welcome little fishes in + With gently smiling jaws!' + + `I'm sure those are not the right words,' said poor Alice, and +her eyes filled with tears again as she went on, `I must be Mabel +after all, and I shall have to go and live in that poky little +house, and have next to no toys to play with, and oh! ever so +many lessons to learn! No, I've made up my mind about it; if I'm +Mabel, I'll stay down here! It'll be no use their putting their +heads down and saying "Come up again, dear!" I shall only look +up and say "Who am I then? Tell me that first, and then, if I +like being that person, I'll come up: if not, I'll stay down +here till I'm somebody else"--but, oh dear!' cried Alice, with a +sudden burst of tears, `I do wish they WOULD put their heads +down! I am so VERY tired of being all alone here!' + + As she said this she looked down at her hands, and was +surprised to see that she had put on one of the Rabbit's little +white kid gloves while she was talking. `How CAN I have done +that?' she thought. `I must be growing small again.' She got up +and went to the table to measure herself by it, and found that, +as nearly as she could guess, she was now about two feet high, +and was going on shrinking rapidly: she soon found out that the +cause of this was the fan she was holding, and she dropped it +hastily, just in time to avoid shrinking away altogether. + +`That WAS a narrow escape!' said Alice, a good deal frightened at +the sudden change, but very glad to find herself still in +existence; `and now for the garden!' and she ran with all speed +back to the little door: but, alas! the little door was shut +again, and the little golden key was lying on the glass table as +before, `and things are worse than ever,' thought the poor child, +`for I never was so small as this before, never! And I declare +it's too bad, that it is!' + + As she said these words her foot slipped, and in another +moment, splash! she was up to her chin in salt water. He first +idea was that she had somehow fallen into the sea, `and in that +case I can go back by railway,' she said to herself. (Alice had +been to the seaside once in her life, and had come to the general +conclusion, that wherever you go to on the English coast you find +a number of bathing machines in the sea, some children digging in +the sand with wooden spades, then a row of lodging houses, and +behind them a railway station.) However, she soon made out that +she was in the pool of tears which she had wept when she was nine +feet high. + + `I wish I hadn't cried so much!' said Alice, as she swam about, +trying to find her way out. `I shall be punished for it now, I +suppose, by being drowned in my own tears! That WILL be a queer +thing, to be sure! However, everything is queer to-day.' + + Just then she heard something splashing about in the pool a +little way off, and she swam nearer to make out what it was: at +first she thought it must be a walrus or hippopotamus, but then +she remembered how small she was now, and she soon made out that +it was only a mouse that had slipped in like herself. + + `Would it be of any use, now,' thought Alice, `to speak to this +mouse? Everything is so out-of-the-way down here, that I should +think very likely it can talk: at any rate, there's no harm in +trying.' So she began: `O Mouse, do you know the way out of +this pool? I am very tired of swimming about here, O Mouse!' +(Alice thought this must be the right way of speaking to a mouse: +she had never done such a thing before, but she remembered having +seen in her brother's Latin Grammar, `A mouse--of a mouse--to a +mouse--a mouse--O mouse!' The Mouse looked at her rather +inquisitively, and seemed to her to wink with one of its little +eyes, but it said nothing. + + `Perhaps it doesn't understand English,' thought Alice; `I +daresay it's a French mouse, come over with William the +Conqueror.' (For, with all her knowledge of history, Alice had +no very clear notion how long ago anything had happened.) So she +began again: `Ou est ma chatte?' which was the first sentence in +her French lesson-book. The Mouse gave a sudden leap out of the +water, and seemed to quiver all over with fright. `Oh, I beg +your pardon!' cried Alice hastily, afraid that she had hurt the +poor animal's feelings. `I quite forgot you didn't like cats.' + + `Not like cats!' cried the Mouse, in a shrill, passionate +voice. `Would YOU like cats if you were me?' + + `Well, perhaps not,' said Alice in a soothing tone: `don't be +angry about it. And yet I wish I could show you our cat Dinah: +I think you'd take a fancy to cats if you could only see her. +She is such a dear quiet thing,' Alice went on, half to herself, +as she swam lazily about in the pool, `and she sits purring so +nicely by the fire, licking her paws and washing her face--and +she is such a nice soft thing to nurse--and she's such a capital +one for catching mice--oh, I beg your pardon!' cried Alice again, +for this time the Mouse was bristling all over, and she felt +certain it must be really offended. `We won't talk about her any +more if you'd rather not.' + + `We indeed!' cried the Mouse, who was trembling down to the end +of his tail. `As if I would talk on such a subject! Our family +always HATED cats: nasty, low, vulgar things! Don't let me hear +the name again!' + + `I won't indeed!' said Alice, in a great hurry to change the +subject of conversation. `Are you--are you fond--of--of dogs?' +The Mouse did not answer, so Alice went on eagerly: `There is +such a nice little dog near our house I should like to show you! +A little bright-eyed terrier, you know, with oh, such long curly +brown hair! And it'll fetch things when you throw them, and +it'll sit up and beg for its dinner, and all sorts of things--I +can't remember half of them--and it belongs to a farmer, you +know, and he says it's so useful, it's worth a hundred pounds! +He says it kills all the rats and--oh dear!' cried Alice in a +sorrowful tone, `I'm afraid I've offended it again!' For the +Mouse was swimming away from her as hard as it could go, and +making quite a commotion in the pool as it went. + + So she called softly after it, `Mouse dear! Do come back +again, and we won't talk about cats or dogs either, if you don't +like them!' When the Mouse heard this, it turned round and swam +slowly back to her: its face was quite pale (with passion, Alice +thought), and it said in a low trembling voice, `Let us get to +the shore, and then I'll tell you my history, and you'll +understand why it is I hate cats and dogs.' + + It was high time to go, for the pool was getting quite crowded +with the birds and animals that had fallen into it: there were a +Duck and a Dodo, a Lory and an Eaglet, and several other curious +creatures. Alice led the way, and the whole party swam to the +shore. + + + + CHAPTER III + + A Caucus-Race and a Long Tale + + + They were indeed a queer-looking party that assembled on the +bank--the birds with draggled feathers, the animals with their +fur clinging close to them, and all dripping wet, cross, and +uncomfortable. + + The first question of course was, how to get dry again: they +had a consultation about this, and after a few minutes it seemed +quite natural to Alice to find herself talking familiarly with +them, as if she had known them all her life. Indeed, she had +quite a long argument with the Lory, who at last turned sulky, +and would only say, `I am older than you, and must know better'; +and this Alice would not allow without knowing how old it was, +and, as the Lory positively refused to tell its age, there was no +more to be said. + + At last the Mouse, who seemed to be a person of authority among +them, called out, `Sit down, all of you, and listen to me! I'LL +soon make you dry enough!' They all sat down at once, in a large +ring, with the Mouse in the middle. Alice kept her eyes +anxiously fixed on it, for she felt sure she would catch a bad +cold if she did not get dry very soon. + + `Ahem!' said the Mouse with an important air, `are you all ready? +This is the driest thing I know. Silence all round, if you please! +"William the Conqueror, whose cause was favoured by the pope, was +soon submitted to by the English, who wanted leaders, and had been +of late much accustomed to usurpation and conquest. Edwin and +Morcar, the earls of Mercia and Northumbria--"' + + `Ugh!' said the Lory, with a shiver. + + `I beg your pardon!' said the Mouse, frowning, but very +politely: `Did you speak?' + + `Not I!' said the Lory hastily. + + `I thought you did,' said the Mouse. `--I proceed. "Edwin and +Morcar, the earls of Mercia and Northumbria, declared for him: +and even Stigand, the patriotic archbishop of Canterbury, found +it advisable--"' + + `Found WHAT?' said the Duck. + + `Found IT,' the Mouse replied rather crossly: `of course you +know what "it" means.' + + `I know what "it" means well enough, when I find a thing,' said +the Duck: `it's generally a frog or a worm. The question is, +what did the archbishop find?' + + The Mouse did not notice this question, but hurriedly went on, +`"--found it advisable to go with Edgar Atheling to meet William +and offer him the crown. William's conduct at first was +moderate. But the insolence of his Normans--" How are you +getting on now, my dear?' it continued, turning to Alice as it +spoke. + + `As wet as ever,' said Alice in a melancholy tone: `it doesn't +seem to dry me at all.' + + `In that case,' said the Dodo solemnly, rising to its feet, `I +move that the meeting adjourn, for the immediate adoption of more +energetic remedies--' + + `Speak English!' said the Eaglet. `I don't know the meaning of +half those long words, and, what's more, I don't believe you do +either!' And the Eaglet bent down its head to hide a smile: +some of the other birds tittered audibly. + + `What I was going to say,' said the Dodo in an offended tone, +`was, that the best thing to get us dry would be a Caucus-race.' + + `What IS a Caucus-race?' said Alice; not that she wanted much +to know, but the Dodo had paused as if it thought that SOMEBODY +ought to speak, and no one else seemed inclined to say anything. + + `Why,' said the Dodo, `the best way to explain it is to do it.' +(And, as you might like to try the thing yourself, some winter +day, I will tell you how the Dodo managed it.) + + First it marked out a race-course, in a sort of circle, (`the +exact shape doesn't matter,' it said,) and then all the party +were placed along the course, here and there. There was no `One, +two, three, and away,' but they began running when they liked, +and left off when they liked, so that it was not easy to know +when the race was over. However, when they had been running half +an hour or so, and were quite dry again, the Dodo suddenly called +out `The race is over!' and they all crowded round it, panting, +and asking, `But who has won?' + + This question the Dodo could not answer without a great deal of +thought, and it sat for a long time with one finger pressed upon +its forehead (the position in which you usually see Shakespeare, +in the pictures of him), while the rest waited in silence. At +last the Dodo said, `EVERYBODY has won, and all must have +prizes.' + + `But who is to give the prizes?' quite a chorus of voices +asked. + + `Why, SHE, of course,' said the Dodo, pointing to Alice with +one finger; and the whole party at once crowded round her, +calling out in a confused way, `Prizes! Prizes!' + + Alice had no idea what to do, and in despair she put her hand +in her pocket, and pulled out a box of comfits, (luckily the salt +water had not got into it), and handed them round as prizes. +There was exactly one a-piece all round. + + `But she must have a prize herself, you know,' said the Mouse. + + `Of course,' the Dodo replied very gravely. `What else have +you got in your pocket?' he went on, turning to Alice. + + `Only a thimble,' said Alice sadly. + + `Hand it over here,' said the Dodo. + + Then they all crowded round her once more, while the Dodo +solemnly presented the thimble, saying `We beg your acceptance of +this elegant thimble'; and, when it had finished this short +speech, they all cheered. + + Alice thought the whole thing very absurd, but they all looked +so grave that she did not dare to laugh; and, as she could not +think of anything to say, she simply bowed, and took the thimble, +looking as solemn as she could. + + The next thing was to eat the comfits: this caused some noise +and confusion, as the large birds complained that they could not +taste theirs, and the small ones choked and had to be patted on +the back. However, it was over at last, and they sat down again +in a ring, and begged the Mouse to tell them something more. + + `You promised to tell me your history, you know,' said Alice, +`and why it is you hate--C and D,' she added in a whisper, half +afraid that it would be offended again. + + `Mine is a long and a sad tale!' said the Mouse, turning to +Alice, and sighing. + + `It IS a long tail, certainly,' said Alice, looking down with +wonder at the Mouse's tail; `but why do you call it sad?' And +she kept on puzzling about it while the Mouse was speaking, so +that her idea of the tale was something like this:-- + + `Fury said to a + mouse, That he + met in the + house, + "Let us + both go to + law: I will + prosecute + YOU. --Come, + I'll take no + denial; We + must have a + trial: For + really this + morning I've + nothing + to do." + Said the + mouse to the + cur, "Such + a trial, + dear Sir, + With + no jury + or judge, + would be + wasting + our + breath." + "I'll be + judge, I'll + be jury," + Said + cunning + old Fury: + "I'll + try the + whole + cause, + and + condemn + you + to + death."' + + + `You are not attending!' said the Mouse to Alice severely. +`What are you thinking of?' + + `I beg your pardon,' said Alice very humbly: `you had got to +the fifth bend, I think?' + + `I had NOT!' cried the Mouse, sharply and very angrily. + + `A knot!' said Alice, always ready to make herself useful, and +looking anxiously about her. `Oh, do let me help to undo it!' + + `I shall do nothing of the sort,' said the Mouse, getting up +and walking away. `You insult me by talking such nonsense!' + + `I didn't mean it!' pleaded poor Alice. `But you're so easily +offended, you know!' + + The Mouse only growled in reply. + + `Please come back and finish your story!' Alice called after +it; and the others all joined in chorus, `Yes, please do!' but +the Mouse only shook its head impatiently, and walked a little +quicker. + + `What a pity it wouldn't stay!' sighed the Lory, as soon as it +was quite out of sight; and an old Crab took the opportunity of +saying to her daughter `Ah, my dear! Let this be a lesson to you +never to lose YOUR temper!' `Hold your tongue, Ma!' said the +young Crab, a little snappishly. `You're enough to try the +patience of an oyster!' + + `I wish I had our Dinah here, I know I do!' said Alice aloud, +addressing nobody in particular. `She'd soon fetch it back!' + + `And who is Dinah, if I might venture to ask the question?' +said the Lory. + + Alice replied eagerly, for she was always ready to talk about +her pet: `Dinah's our cat. And she's such a capital one for +catching mice you can't think! And oh, I wish you could see her +after the birds! Why, she'll eat a little bird as soon as look +at it!' + + This speech caused a remarkable sensation among the party. +Some of the birds hurried off at once: one the old Magpie began +wrapping itself up very carefully, remarking, `I really must be +getting home; the night-air doesn't suit my throat!' and a Canary +called out in a trembling voice to its children, `Come away, my +dears! It's high time you were all in bed!' On various pretexts +they all moved off, and Alice was soon left alone. + + `I wish I hadn't mentioned Dinah!' she said to herself in a +melancholy tone. `Nobody seems to like her, down here, and I'm +sure she's the best cat in the world! Oh, my dear Dinah! I +wonder if I shall ever see you any more!' And here poor Alice +began to cry again, for she felt very lonely and low-spirited. +In a little while, however, she again heard a little pattering of +footsteps in the distance, and she looked up eagerly, half hoping +that the Mouse had changed his mind, and was coming back to +finish his story. + + + + CHAPTER IV + + The Rabbit Sends in a Little Bill + + + It was the White Rabbit, trotting slowly back again, and +looking anxiously about as it went, as if it had lost something; +and she heard it muttering to itself `The Duchess! The Duchess! +Oh my dear paws! Oh my fur and whiskers! She'll get me +executed, as sure as ferrets are ferrets! Where CAN I have +dropped them, I wonder?' Alice guessed in a moment that it was +looking for the fan and the pair of white kid gloves, and she +very good-naturedly began hunting about for them, but they were +nowhere to be seen--everything seemed to have changed since her +swim in the pool, and the great hall, with the glass table and +the little door, had vanished completely. + + Very soon the Rabbit noticed Alice, as she went hunting about, +and called out to her in an angry tone, `Why, Mary Ann, what ARE +you doing out here? Run home this moment, and fetch me a pair of +gloves and a fan! Quick, now!' And Alice was so much frightened +that she ran off at once in the direction it pointed to, without +trying to explain the mistake it had made. + + `He took me for his housemaid,' she said to herself as she ran. +`How surprised he'll be when he finds out who I am! But I'd +better take him his fan and gloves--that is, if I can find them.' +As she said this, she came upon a neat little house, on the door +of which was a bright brass plate with the name `W. RABBIT' +engraved upon it. She went in without knocking, and hurried +upstairs, in great fear lest she should meet the real Mary Ann, +and be turned out of the house before she had found the fan and +gloves. + + `How queer it seems,' Alice said to herself, `to be going +messages for a rabbit! I suppose Dinah'll be sending me on +messages next!' And she began fancying the sort of thing that +would happen: `"Miss Alice! Come here directly, and get ready +for your walk!" "Coming in a minute, nurse! But I've got to see +that the mouse doesn't get out." Only I don't think,' Alice went +on, `that they'd let Dinah stop in the house if it began ordering +people about like that!' + + By this time she had found her way into a tidy little room with +a table in the window, and on it (as she had hoped) a fan and two +or three pairs of tiny white kid gloves: she took up the fan and +a pair of the gloves, and was just going to leave the room, when +her eye fell upon a little bottle that stood near the looking- +glass. There was no label this time with the words `DRINK ME,' +but nevertheless she uncorked it and put it to her lips. `I know +SOMETHING interesting is sure to happen,' she said to herself, +`whenever I eat or drink anything; so I'll just see what this +bottle does. I do hope it'll make me grow large again, for +really I'm quite tired of being such a tiny little thing!' + + It did so indeed, and much sooner than she had expected: +before she had drunk half the bottle, she found her head pressing +against the ceiling, and had to stoop to save her neck from being +broken. She hastily put down the bottle, saying to herself +`That's quite enough--I hope I shan't grow any more--As it is, I +can't get out at the door--I do wish I hadn't drunk quite so +much!' + + Alas! it was too late to wish that! She went on growing, and +growing, and very soon had to kneel down on the floor: in +another minute there was not even room for this, and she tried +the effect of lying down with one elbow against the door, and the +other arm curled round her head. Still she went on growing, and, +as a last resource, she put one arm out of the window, and one +foot up the chimney, and said to herself `Now I can do no more, +whatever happens. What WILL become of me?' + + Luckily for Alice, the little magic bottle had now had its full +effect, and she grew no larger: still it was very uncomfortable, +and, as there seemed to be no sort of chance of her ever getting +out of the room again, no wonder she felt unhappy. + + `It was much pleasanter at home,' thought poor Alice, `when one +wasn't always growing larger and smaller, and being ordered about +by mice and rabbits. I almost wish I hadn't gone down that +rabbit-hole--and yet--and yet--it's rather curious, you know, +this sort of life! I do wonder what CAN have happened to me! +When I used to read fairy-tales, I fancied that kind of thing +never happened, and now here I am in the middle of one! There +ought to be a book written about me, that there ought! And when +I grow up, I'll write one--but I'm grown up now,' she added in a +sorrowful tone; `at least there's no room to grow up any more +HERE.' + + `But then,' thought Alice, `shall I NEVER get any older than I +am now? That'll be a comfort, one way--never to be an old woman- +-but then--always to have lessons to learn! Oh, I shouldn't like +THAT!' + + `Oh, you foolish Alice!' she answered herself. `How can you +learn lessons in here? Why, there's hardly room for YOU, and no +room at all for any lesson-books!' + + And so she went on, taking first one side and then the other, +and making quite a conversation of it altogether; but after a few +minutes she heard a voice outside, and stopped to listen. + + `Mary Ann! Mary Ann!' said the voice. `Fetch me my gloves +this moment!' Then came a little pattering of feet on the +stairs. Alice knew it was the Rabbit coming to look for her, and +she trembled till she shook the house, quite forgetting that she +was now about a thousand times as large as the Rabbit, and had no +reason to be afraid of it. + + Presently the Rabbit came up to the door, and tried to open it; +but, as the door opened inwards, and Alice's elbow was pressed +hard against it, that attempt proved a failure. Alice heard it +say to itself `Then I'll go round and get in at the window.' + + `THAT you won't' thought Alice, and, after waiting till she +fancied she heard the Rabbit just under the window, she suddenly +spread out her hand, and made a snatch in the air. She did not +get hold of anything, but she heard a little shriek and a fall, +and a crash of broken glass, from which she concluded that it was +just possible it had fallen into a cucumber-frame, or something +of the sort. + + Next came an angry voice--the Rabbit's--`Pat! Pat! Where are +you?' And then a voice she had never heard before, `Sure then +I'm here! Digging for apples, yer honour!' + + `Digging for apples, indeed!' said the Rabbit angrily. `Here! +Come and help me out of THIS!' (Sounds of more broken glass.) + + `Now tell me, Pat, what's that in the window?' + + `Sure, it's an arm, yer honour!' (He pronounced it `arrum.') + + `An arm, you goose! Who ever saw one that size? Why, it +fills the whole window!' + + `Sure, it does, yer honour: but it's an arm for all that.' + + `Well, it's got no business there, at any rate: go and take it +away!' + + There was a long silence after this, and Alice could only hear +whispers now and then; such as, `Sure, I don't like it, yer +honour, at all, at all!' `Do as I tell you, you coward!' and at +last she spread out her hand again, and made another snatch in +the air. This time there were TWO little shrieks, and more +sounds of broken glass. `What a number of cucumber-frames there +must be!' thought Alice. `I wonder what they'll do next! As for +pulling me out of the window, I only wish they COULD! I'm sure I +don't want to stay in here any longer!' + + She waited for some time without hearing anything more: at +last came a rumbling of little cartwheels, and the sound of a +good many voice all talking together: she made out the words: +`Where's the other ladder?--Why, I hadn't to bring but one; +Bill's got the other--Bill! fetch it here, lad!--Here, put 'em up +at this corner--No, tie 'em together first--they don't reach half +high enough yet--Oh! they'll do well enough; don't be particular- +-Here, Bill! catch hold of this rope--Will the roof bear?--Mind +that loose slate--Oh, it's coming down! Heads below!' (a loud +crash)--`Now, who did that?--It was Bill, I fancy--Who's to go +down the chimney?--Nay, I shan't! YOU do it!--That I won't, +then!--Bill's to go down--Here, Bill! the master says you're to +go down the chimney!' + + `Oh! So Bill's got to come down the chimney, has he?' said +Alice to herself. `Shy, they seem to put everything upon Bill! +I wouldn't be in Bill's place for a good deal: this fireplace is +narrow, to be sure; but I THINK I can kick a little!' + + She drew her foot as far down the chimney as she could, and +waited till she heard a little animal (she couldn't guess of what +sort it was) scratching and scrambling about in the chimney close +above her: then, saying to herself `This is Bill,' she gave one +sharp kick, and waited to see what would happen next. + + The first thing she heard was a general chorus of `There goes +Bill!' then the Rabbit's voice along--`Catch him, you by the +hedge!' then silence, and then another confusion of voices--`Hold +up his head--Brandy now--Don't choke him--How was it, old fellow? +What happened to you? Tell us all about it!' + + Last came a little feeble, squeaking voice, (`That's Bill,' +thought Alice,) `Well, I hardly know--No more, thank ye; I'm +better now--but I'm a deal too flustered to tell you--all I know +is, something comes at me like a Jack-in-the-box, and up I goes +like a sky-rocket!' + + `So you did, old fellow!' said the others. + + `We must burn the house down!' said the Rabbit's voice; and +Alice called out as loud as she could, `If you do. I'll set +Dinah at you!' + + There was a dead silence instantly, and Alice thought to +herself, `I wonder what they WILL do next! If they had any +sense, they'd take the roof off.' After a minute or two, they +began moving about again, and Alice heard the Rabbit say, `A +barrowful will do, to begin with.' + + `A barrowful of WHAT?' thought Alice; but she had not long to +doubt, for the next moment a shower of little pebbles came +rattling in at the window, and some of them hit her in the face. +`I'll put a stop to this,' she said to herself, and shouted out, +`You'd better not do that again!' which produced another dead +silence. + + Alice noticed with some surprise that the pebbles were all +turning into little cakes as they lay on the floor, and a bright +idea came into her head. `If I eat one of these cakes,' she +thought, `it's sure to make SOME change in my size; and as it +can't possibly make me larger, it must make me smaller, I +suppose.' + + So she swallowed one of the cakes, and was delighted to find +that she began shrinking directly. As soon as she was small +enough to get through the door, she ran out of the house, and +found quite a crowd of little animals and birds waiting outside. +The poor little Lizard, Bill, was in the middle, being held up by +two guinea-pigs, who were giving it something out of a bottle. +They all made a rush at Alice the moment she appeared; but she +ran off as hard as she could, and soon found herself safe in a +thick wood. + + `The first thing I've got to do,' said Alice to herself, as she +wandered about in the wood, `is to grow to my right size again; +and the second thing is to find my way into that lovely garden. +I think that will be the best plan.' + + It sounded an excellent plan, no doubt, and very neatly and +simply arranged; the only difficulty was, that she had not the +smallest idea how to set about it; and while she was peering +about anxiously among the trees, a little sharp bark just over +her head made her look up in a great hurry. + + An enormous puppy was looking down at her with large round +eyes, and feebly stretching out one paw, trying to touch her. +`Poor little thing!' said Alice, in a coaxing tone, and she tried +hard to whistle to it; but she was terribly frightened all the +time at the thought that it might be hungry, in which case it +would be very likely to eat her up in spite of all her coaxing. + + Hardly knowing what she did, she picked up a little bit of +stick, and held it out to the puppy; whereupon the puppy jumped +into the air off all its feet at once, with a yelp of delight, +and rushed at the stick, and made believe to worry it; then Alice +dodged behind a great thistle, to keep herself from being run +over; and the moment she appeared on the other side, the puppy +made another rush at the stick, and tumbled head over heels in +its hurry to get hold of it; then Alice, thinking it was very +like having a game of play with a cart-horse, and expecting every +moment to be trampled under its feet, ran round the thistle +again; then the puppy began a series of short charges at the +stick, running a very little way forwards each time and a long +way back, and barking hoarsely all the while, till at last it sat +down a good way off, panting, with its tongue hanging out of its +mouth, and its great eyes half shut. + + This seemed to Alice a good opportunity for making her escape; +so she set off at once, and ran till she was quite tired and out +of breath, and till the puppy's bark sounded quite faint in the +distance. + + `And yet what a dear little puppy it was!' said Alice, as she +leant against a buttercup to rest herself, and fanned herself +with one of the leaves: `I should have liked teaching it tricks +very much, if--if I'd only been the right size to do it! Oh +dear! I'd nearly forgotten that I've got to grow up again! Let +me see--how IS it to be managed? I suppose I ought to eat or +drink something or other; but the great question is, what?' + + The great question certainly was, what? Alice looked all round +her at the flowers and the blades of grass, but she did not see +anything that looked like the right thing to eat or drink under +the circumstances. There was a large mushroom growing near her, +about the same height as herself; and when she had looked under +it, and on both sides of it, and behind it, it occurred to her +that she might as well look and see what was on the top of it. + + She stretched herself up on tiptoe, and peeped over the edge of +the mushroom, and her eyes immediately met those of a large +caterpillar, that was sitting on the top with its arms folded, +quietly smoking a long hookah, and taking not the smallest notice +of her or of anything else. + + + + CHAPTER V + + Advice from a Caterpillar + + + The Caterpillar and Alice looked at each other for some time in +silence: at last the Caterpillar took the hookah out of its +mouth, and addressed her in a languid, sleepy voice. + + `Who are YOU?' said the Caterpillar. + + This was not an encouraging opening for a conversation. Alice +replied, rather shyly, `I--I hardly know, sir, just at present-- +at least I know who I WAS when I got up this morning, but I think +I must have been changed several times since then.' + + `What do you mean by that?' said the Caterpillar sternly. +`Explain yourself!' + + `I can't explain MYSELF, I'm afraid, sir' said Alice, `because +I'm not myself, you see.' + + `I don't see,' said the Caterpillar. + + `I'm afraid I can't put it more clearly,' Alice replied very +politely, `for I can't understand it myself to begin with; and +being so many different sizes in a day is very confusing.' + + `It isn't,' said the Caterpillar. + + `Well, perhaps you haven't found it so yet,' said Alice; `but +when you have to turn into a chrysalis--you will some day, you +know--and then after that into a butterfly, I should think you'll +feel it a little queer, won't you?' + + `Not a bit,' said the Caterpillar. + + `Well, perhaps your feelings may be different,' said Alice; +`all I know is, it would feel very queer to ME.' + + `You!' said the Caterpillar contemptuously. `Who are YOU?' + + Which brought them back again to the beginning of the +conversation. Alice felt a little irritated at the Caterpillar's +making such VERY short remarks, and she drew herself up and said, +very gravely, `I think, you ought to tell me who YOU are, first.' + + `Why?' said the Caterpillar. + + Here was another puzzling question; and as Alice could not +think of any good reason, and as the Caterpillar seemed to be in +a VERY unpleasant state of mind, she turned away. + + `Come back!' the Caterpillar called after her. `I've something +important to say!' + + This sounded promising, certainly: Alice turned and came back +again. + + `Keep your temper,' said the Caterpillar. + + `Is that all?' said Alice, swallowing down her anger as well as +she could. + + `No,' said the Caterpillar. + + Alice thought she might as well wait, as she had nothing else +to do, and perhaps after all it might tell her something worth +hearing. For some minutes it puffed away without speaking, but +at last it unfolded its arms, took the hookah out of its mouth +again, and said, `So you think you're changed, do you?' + + `I'm afraid I am, sir,' said Alice; `I can't remember things as +I used--and I don't keep the same size for ten minutes together!' + + `Can't remember WHAT things?' said the Caterpillar. + + `Well, I've tried to say "HOW DOTH THE LITTLE BUSY BEE," but it +all came different!' Alice replied in a very melancholy voice. + + `Repeat, "YOU ARE OLD, FATHER WILLIAM,"' said the Caterpillar. + + Alice folded her hands, and began:-- + + `You are old, Father William,' the young man said, + `And your hair has become very white; + And yet you incessantly stand on your head-- + Do you think, at your age, it is right?' + + `In my youth,' Father William replied to his son, + `I feared it might injure the brain; + But, now that I'm perfectly sure I have none, + Why, I do it again and again.' + + `You are old,' said the youth, `as I mentioned before, + And have grown most uncommonly fat; + Yet you turned a back-somersault in at the door-- + Pray, what is the reason of that?' + + `In my youth,' said the sage, as he shook his grey locks, + `I kept all my limbs very supple + By the use of this ointment--one shilling the box-- + Allow me to sell you a couple?' + + `You are old,' said the youth, `and your jaws are too weak + For anything tougher than suet; + Yet you finished the goose, with the bones and the beak-- + Pray how did you manage to do it?' + + `In my youth,' said his father, `I took to the law, + And argued each case with my wife; + And the muscular strength, which it gave to my jaw, + Has lasted the rest of my life.' + + `You are old,' said the youth, `one would hardly suppose + That your eye was as steady as ever; + Yet you balanced an eel on the end of your nose-- + What made you so awfully clever?' + + `I have answered three questions, and that is enough,' + Said his father; `don't give yourself airs! + Do you think I can listen all day to such stuff? + Be off, or I'll kick you down stairs!' + + + `That is not said right,' said the Caterpillar. + + `Not QUITE right, I'm afraid,' said Alice, timidly; `some of the +words have got altered.' + + `It is wrong from beginning to end,' said the Caterpillar +decidedly, and there was silence for some minutes. + + The Caterpillar was the first to speak. + + `What size do you want to be?' it asked. + + `Oh, I'm not particular as to size,' Alice hastily replied; +`only one doesn't like changing so often, you know.' + + `I DON'T know,' said the Caterpillar. + + Alice said nothing: she had never been so much contradicted in +her life before, and she felt that she was losing her temper. + + `Are you content now?' said the Caterpillar. + + `Well, I should like to be a LITTLE larger, sir, if you +wouldn't mind,' said Alice: `three inches is such a wretched +height to be.' + + `It is a very good height indeed!' said the Caterpillar +angrily, rearing itself upright as it spoke (it was exactly three +inches high). + + `But I'm not used to it!' pleaded poor Alice in a piteous tone. +And she thought of herself, `I wish the creatures wouldn't be so +easily offended!' + + `You'll get used to it in time,' said the Caterpillar; and it +put the hookah into its mouth and began smoking again. + + This time Alice waited patiently until it chose to speak again. +In a minute or two the Caterpillar took the hookah out of its +mouth and yawned once or twice, and shook itself. Then it got +down off the mushroom, and crawled away in the grass, merely +remarking as it went, `One side will make you grow taller, and +the other side will make you grow shorter.' + + `One side of WHAT? The other side of WHAT?' thought Alice to +herself. + + `Of the mushroom,' said the Caterpillar, just as if she had +asked it aloud; and in another moment it was out of sight. + + Alice remained looking thoughtfully at the mushroom for a +minute, trying to make out which were the two sides of it; and as +it was perfectly round, she found this a very difficult question. +However, at last she stretched her arms round it as far as they +would go, and broke off a bit of the edge with each hand. + + `And now which is which?' she said to herself, and nibbled a +little of the right-hand bit to try the effect: the next moment +she felt a violent blow underneath her chin: it had struck her +foot! + + She was a good deal frightened by this very sudden change, but +she felt that there was no time to be lost, as she was shrinking +rapidly; so she set to work at once to eat some of the other bit. +Her chin was pressed so closely against her foot, that there was +hardly room to open her mouth; but she did it at last, and +managed to swallow a morsel of the lefthand bit. + + + * * * * * * * + + * * * * * * + + * * * * * * * + + `Come, my head's free at last!' said Alice in a tone of +delight, which changed into alarm in another moment, when she +found that her shoulders were nowhere to be found: all she could +see, when she looked down, was an immense length of neck, which +seemed to rise like a stalk out of a sea of green leaves that lay +far below her. + + `What CAN all that green stuff be?' said Alice. `And where +HAVE my shoulders got to? And oh, my poor hands, how is it I +can't see you?' She was moving them about as she spoke, but no +result seemed to follow, except a little shaking among the +distant green leaves. + + As there seemed to be no chance of getting her hands up to her +head, she tried to get her head down to them, and was delighted +to find that her neck would bend about easily in any direction, +like a serpent. She had just succeeded in curving it down into a +graceful zigzag, and was going to dive in among the leaves, which +she found to be nothing but the tops of the trees under which she +had been wandering, when a sharp hiss made her draw back in a +hurry: a large pigeon had flown into her face, and was beating +her violently with its wings. + + `Serpent!' screamed the Pigeon. + + `I'm NOT a serpent!' said Alice indignantly. `Let me alone!' + + `Serpent, I say again!' repeated the Pigeon, but in a more +subdued tone, and added with a kind of sob, `I've tried every +way, and nothing seems to suit them!' + + `I haven't the least idea what you're talking about,' said +Alice. + + `I've tried the roots of trees, and I've tried banks, and I've +tried hedges,' the Pigeon went on, without attending to her; `but +those serpents! There's no pleasing them!' + + Alice was more and more puzzled, but she thought there was no +use in saying anything more till the Pigeon had finished. + + `As if it wasn't trouble enough hatching the eggs,' said the +Pigeon; `but I must be on the look-out for serpents night and +day! Why, I haven't had a wink of sleep these three weeks!' + + `I'm very sorry you've been annoyed,' said Alice, who was +beginning to see its meaning. + + `And just as I'd taken the highest tree in the wood,' continued +the Pigeon, raising its voice to a shriek, `and just as I was +thinking I should be free of them at last, they must needs come +wriggling down from the sky! Ugh, Serpent!' + + `But I'm NOT a serpent, I tell you!' said Alice. `I'm a--I'm +a--' + + `Well! WHAT are you?' said the Pigeon. `I can see you're +trying to invent something!' + + `I--I'm a little girl,' said Alice, rather doubtfully, as she +remembered the number of changes she had gone through that day. + + `A likely story indeed!' said the Pigeon in a tone of the +deepest contempt. `I've seen a good many little girls in my +time, but never ONE with such a neck as that! No, no! You're a +serpent; and there's no use denying it. I suppose you'll be +telling me next that you never tasted an egg!' + + `I HAVE tasted eggs, certainly,' said Alice, who was a very +truthful child; `but little girls eat eggs quite as much as +serpents do, you know.' + + `I don't believe it,' said the Pigeon; `but if they do, why +then they're a kind of serpent, that's all I can say.' + + This was such a new idea to Alice, that she was quite silent +for a minute or two, which gave the Pigeon the opportunity of +adding, `You're looking for eggs, I know THAT well enough; and +what does it matter to me whether you're a little girl or a +serpent?' + + `It matters a good deal to ME,' said Alice hastily; `but I'm +not looking for eggs, as it happens; and if I was, I shouldn't +want YOURS: I don't like them raw.' + + `Well, be off, then!' said the Pigeon in a sulky tone, as it +settled down again into its nest. Alice crouched down among the +trees as well as she could, for her neck kept getting entangled +among the branches, and every now and then she had to stop and +untwist it. After a while she remembered that she still held the +pieces of mushroom in her hands, and she set to work very +carefully, nibbling first at one and then at the other, and +growing sometimes taller and sometimes shorter, until she had +succeeded in bringing herself down to her usual height. + + It was so long since she had been anything near the right size, +that it felt quite strange at first; but she got used to it in a +few minutes, and began talking to herself, as usual. `Come, +there's half my plan done now! How puzzling all these changes +are! I'm never sure what I'm going to be, from one minute to +another! However, I've got back to my right size: the next +thing is, to get into that beautiful garden--how IS that to be +done, I wonder?' As she said this, she came suddenly upon an +open place, with a little house in it about four feet high. +`Whoever lives there,' thought Alice, `it'll never do to come +upon them THIS size: why, I should frighten them out of their +wits!' So she began nibbling at the righthand bit again, and did +not venture to go near the house till she had brought herself +down to nine inches high. + + + + CHAPTER VI + + Pig and Pepper + + + For a minute or two she stood looking at the house, and +wondering what to do next, when suddenly a footman in livery came +running out of the wood--(she considered him to be a footman +because he was in livery: otherwise, judging by his face only, +she would have called him a fish)--and rapped loudly at the door +with his knuckles. It was opened by another footman in livery, +with a round face, and large eyes like a frog; and both footmen, +Alice noticed, had powdered hair that curled all over their +heads. She felt very curious to know what it was all about, and +crept a little way out of the wood to listen. + + The Fish-Footman began by producing from under his arm a great +letter, nearly as large as himself, and this he handed over to +the other, saying, in a solemn tone, `For the Duchess. An +invitation from the Queen to play croquet.' The Frog-Footman +repeated, in the same solemn tone, only changing the order of the +words a little, `From the Queen. An invitation for the Duchess +to play croquet.' + + Then they both bowed low, and their curls got entangled +together. + + Alice laughed so much at this, that she had to run back into +the wood for fear of their hearing her; and when she next peeped +out the Fish-Footman was gone, and the other was sitting on the +ground near the door, staring stupidly up into the sky. + + Alice went timidly up to the door, and knocked. + + `There's no sort of use in knocking,' said the Footman, `and +that for two reasons. First, because I'm on the same side of the +door as you are; secondly, because they're making such a noise +inside, no one could possibly hear you.' And certainly there was +a most extraordinary noise going on within--a constant howling +and sneezing, and every now and then a great crash, as if a dish +or kettle had been broken to pieces. + + `Please, then,' said Alice, `how am I to get in?' + + `There might be some sense in your knocking,' the Footman went +on without attending to her, `if we had the door between us. For +instance, if you were INSIDE, you might knock, and I could let +you out, you know.' He was looking up into the sky all the time +he was speaking, and this Alice thought decidedly uncivil. `But +perhaps he can't help it,' she said to herself; `his eyes are so +VERY nearly at the top of his head. But at any rate he might +answer questions.--How am I to get in?' she repeated, aloud. + + `I shall sit here,' the Footman remarked, `till tomorrow--' + + At this moment the door of the house opened, and a large plate +came skimming out, straight at the Footman's head: it just +grazed his nose, and broke to pieces against one of the trees +behind him. + + `--or next day, maybe,' the Footman continued in the same tone, +exactly as if nothing had happened. + + `How am I to get in?' asked Alice again, in a louder tone. + + `ARE you to get in at all?' said the Footman. `That's the +first question, you know.' + + It was, no doubt: only Alice did not like to be told so. +`It's really dreadful,' she muttered to herself, `the way all the +creatures argue. It's enough to drive one crazy!' + + The Footman seemed to think this a good opportunity for +repeating his remark, with variations. `I shall sit here,' he +said, `on and off, for days and days.' + + `But what am I to do?' said Alice. + + `Anything you like,' said the Footman, and began whistling. + + `Oh, there's no use in talking to him,' said Alice desperately: +`he's perfectly idiotic!' And she opened the door and went in. + + The door led right into a large kitchen, which was full of +smoke from one end to the other: the Duchess was sitting on a +three-legged stool in the middle, nursing a baby; the cook was +leaning over the fire, stirring a large cauldron which seemed to +be full of soup. + + `There's certainly too much pepper in that soup!' Alice said to +herself, as well as she could for sneezing. + + There was certainly too much of it in the air. Even the +Duchess sneezed occasionally; and as for the baby, it was +sneezing and howling alternately without a moment's pause. The +only things in the kitchen that did not sneeze, were the cook, +and a large cat which was sitting on the hearth and grinning from +ear to ear. + + `Please would you tell me,' said Alice, a little timidly, for +she was not quite sure whether it was good manners for her to +speak first, `why your cat grins like that?' + + `It's a Cheshire cat,' said the Duchess, `and that's why. +Pig!' + + She said the last word with such sudden violence that Alice +quite jumped; but she saw in another moment that it was addressed +to the baby, and not to her, so she took courage, and went on +again:-- + + `I didn't know that Cheshire cats always grinned; in fact, I +didn't know that cats COULD grin.' + + `They all can,' said the Duchess; `and most of 'em do.' + + `I don't know of any that do,' Alice said very politely, +feeling quite pleased to have got into a conversation. + + `You don't know much,' said the Duchess; `and that's a fact.' + + Alice did not at all like the tone of this remark, and thought +it would be as well to introduce some other subject of +conversation. While she was trying to fix on one, the cook took +the cauldron of soup off the fire, and at once set to work +throwing everything within her reach at the Duchess and the baby +--the fire-irons came first; then followed a shower of saucepans, +plates, and dishes. The Duchess took no notice of them even when +they hit her; and the baby was howling so much already, that it +was quite impossible to say whether the blows hurt it or not. + + `Oh, PLEASE mind what you're doing!' cried Alice, jumping up +and down in an agony of terror. `Oh, there goes his PRECIOUS +nose'; as an unusually large saucepan flew close by it, and very +nearly carried it off. + + `If everybody minded their own business,' the Duchess said in a +hoarse growl, `the world would go round a deal faster than it +does.' + + `Which would NOT be an advantage,' said Alice, who felt very +glad to get an opportunity of showing off a little of her +knowledge. `Just think of what work it would make with the day +and night! You see the earth takes twenty-four hours to turn +round on its axis--' + + `Talking of axes,' said the Duchess, `chop off her head!' + + Alice glanced rather anxiously at the cook, to see if she meant +to take the hint; but the cook was busily stirring the soup, and +seemed not to be listening, so she went on again: `Twenty-four +hours, I THINK; or is it twelve? I--' + + `Oh, don't bother ME,' said the Duchess; `I never could abide +figures!' And with that she began nursing her child again, +singing a sort of lullaby to it as she did so, and giving it a +violent shake at the end of every line: + + `Speak roughly to your little boy, + And beat him when he sneezes: + He only does it to annoy, + Because he knows it teases.' + + CHORUS. + + (In which the cook and the baby joined):-- + + `Wow! wow! wow!' + + While the Duchess sang the second verse of the song, she kept +tossing the baby violently up and down, and the poor little thing +howled so, that Alice could hardly hear the words:-- + + `I speak severely to my boy, + I beat him when he sneezes; + For he can thoroughly enjoy + The pepper when he pleases!' + + CHORUS. + + `Wow! wow! wow!' + + `Here! you may nurse it a bit, if you like!' the Duchess said +to Alice, flinging the baby at her as she spoke. `I must go and +get ready to play croquet with the Queen,' and she hurried out of +the room. The cook threw a frying-pan after her as she went out, +but it just missed her. + + Alice caught the baby with some difficulty, as it was a queer- +shaped little creature, and held out its arms and legs in all +directions, `just like a star-fish,' thought Alice. The poor +little thing was snorting like a steam-engine when she caught it, +and kept doubling itself up and straightening itself out again, +so that altogether, for the first minute or two, it was as much +as she could do to hold it. + + As soon as she had made out the proper way of nursing it, +(which was to twist it up into a sort of knot, and then keep +tight hold of its right ear and left foot, so as to prevent its +undoing itself,) she carried it out into the open air. `IF I +don't take this child away with me,' thought Alice, `they're sure +to kill it in a day or two: wouldn't it be murder to leave it +behind?' She said the last words out loud, and the little thing +grunted in reply (it had left off sneezing by this time). `Don't +grunt,' said Alice; `that's not at all a proper way of expressing +yourself.' + + The baby grunted again, and Alice looked very anxiously into +its face to see what was the matter with it. There could be no +doubt that it had a VERY turn-up nose, much more like a snout +than a real nose; also its eyes were getting extremely small for +a baby: altogether Alice did not like the look of the thing at +all. `But perhaps it was only sobbing,' she thought, and looked +into its eyes again, to see if there were any tears. + + No, there were no tears. `If you're going to turn into a pig, +my dear,' said Alice, seriously, `I'll have nothing more to do +with you. Mind now!' The poor little thing sobbed again (or +grunted, it was impossible to say which), and they went on for +some while in silence. + + Alice was just beginning to think to herself, `Now, what am I +to do with this creature when I get it home?' when it grunted +again, so violently, that she looked down into its face in some +alarm. This time there could be NO mistake about it: it was +neither more nor less than a pig, and she felt that it would be +quite absurd for her to carry it further. + + So she set the little creature down, and felt quite relieved to +see it trot away quietly into the wood. `If it had grown up,' +she said to herself, `it would have made a dreadfully ugly child: +but it makes rather a handsome pig, I think.' And she began +thinking over other children she knew, who might do very well as +pigs, and was just saying to herself, `if one only knew the right +way to change them--' when she was a little startled by seeing +the Cheshire Cat sitting on a bough of a tree a few yards off. + + The Cat only grinned when it saw Alice. It looked good- +natured, she thought: still it had VERY long claws and a great +many teeth, so she felt that it ought to be treated with respect. + + `Cheshire Puss,' she began, rather timidly, as she did not at +all know whether it would like the name: however, it only +grinned a little wider. `Come, it's pleased so far,' thought +Alice, and she went on. `Would you tell me, please, which way I +ought to go from here?' + + `That depends a good deal on where you want to get to,' said +the Cat. + + `I don't much care where--' said Alice. + + `Then it doesn't matter which way you go,' said the Cat. + + `--so long as I get SOMEWHERE,' Alice added as an explanation. + + `Oh, you're sure to do that,' said the Cat, `if you only walk +long enough.' + + Alice felt that this could not be denied, so she tried another +question. `What sort of people live about here?' + + `In THAT direction,' the Cat said, waving its right paw round, +`lives a Hatter: and in THAT direction,' waving the other paw, +`lives a March Hare. Visit either you like: they're both mad.' + + `But I don't want to go among mad people,' Alice remarked. + + `Oh, you can't help that,' said the Cat: `we're all mad here. +I'm mad. You're mad.' + + `How do you know I'm mad?' said Alice. + + `You must be,' said the Cat, `or you wouldn't have come here.' + + Alice didn't think that proved it at all; however, she went on +`And how do you know that you're mad?' + + `To begin with,' said the Cat, `a dog's not mad. You grant +that?' + + `I suppose so,' said Alice. + + `Well, then,' the Cat went on, `you see, a dog growls when it's +angry, and wags its tail when it's pleased. Now I growl when I'm +pleased, and wag my tail when I'm angry. Therefore I'm mad.' + + `I call it purring, not growling,' said Alice. + + `Call it what you like,' said the Cat. `Do you play croquet +with the Queen to-day?' + + `I should like it very much,' said Alice, `but I haven't been +invited yet.' + + `You'll see me there,' said the Cat, and vanished. + + Alice was not much surprised at this, she was getting so used +to queer things happening. While she was looking at the place +where it had been, it suddenly appeared again. + + `By-the-bye, what became of the baby?' said the Cat. `I'd +nearly forgotten to ask.' + + `It turned into a pig,' Alice quietly said, just as if it had +come back in a natural way. + + `I thought it would,' said the Cat, and vanished again. + + Alice waited a little, half expecting to see it again, but it +did not appear, and after a minute or two she walked on in the +direction in which the March Hare was said to live. `I've seen +hatters before,' she said to herself; `the March Hare will be +much the most interesting, and perhaps as this is May it won't be +raving mad--at least not so mad as it was in March.' As she said +this, she looked up, and there was the Cat again, sitting on a +branch of a tree. + + `Did you say pig, or fig?' said the Cat. + + `I said pig,' replied Alice; `and I wish you wouldn't keep +appearing and vanishing so suddenly: you make one quite giddy.' + + `All right,' said the Cat; and this time it vanished quite +slowly, beginning with the end of the tail, and ending with the +grin, which remained some time after the rest of it had gone. + + `Well! I've often seen a cat without a grin,' thought Alice; +`but a grin without a cat! It's the most curious thing I ever +say in my life!' + + She had not gone much farther before she came in sight of the +house of the March Hare: she thought it must be the right house, +because the chimneys were shaped like ears and the roof was +thatched with fur. It was so large a house, that she did not +like to go nearer till she had nibbled some more of the lefthand +bit of mushroom, and raised herself to about two feet high: even +then she walked up towards it rather timidly, saying to herself +`Suppose it should be raving mad after all! I almost wish I'd +gone to see the Hatter instead!' + + + + CHAPTER VII + + A Mad Tea-Party + + + There was a table set out under a tree in front of the house, +and the March Hare and the Hatter were having tea at it: a +Dormouse was sitting between them, fast asleep, and the other two +were using it as a cushion, resting their elbows on it, and the +talking over its head. `Very uncomfortable for the Dormouse,' +thought Alice; `only, as it's asleep, I suppose it doesn't mind.' + + The table was a large one, but the three were all crowded +together at one corner of it: `No room! No room!' they cried +out when they saw Alice coming. `There's PLENTY of room!' said +Alice indignantly, and she sat down in a large arm-chair at one +end of the table. + + `Have some wine,' the March Hare said in an encouraging tone. + + Alice looked all round the table, but there was nothing on it +but tea. `I don't see any wine,' she remarked. + + `There isn't any,' said the March Hare. + + `Then it wasn't very civil of you to offer it,' said Alice +angrily. + + `It wasn't very civil of you to sit down without being +invited,' said the March Hare. + + `I didn't know it was YOUR table,' said Alice; `it's laid for a +great many more than three.' + + `Your hair wants cutting,' said the Hatter. He had been +looking at Alice for some time with great curiosity, and this was +his first speech. + + `You should learn not to make personal remarks,' Alice said +with some severity; `it's very rude.' + + The Hatter opened his eyes very wide on hearing this; but all +he SAID was, `Why is a raven like a writing-desk?' + + `Come, we shall have some fun now!' thought Alice. `I'm glad +they've begun asking riddles.--I believe I can guess that,' she +added aloud. + + `Do you mean that you think you can find out the answer to it?' +said the March Hare. + + `Exactly so,' said Alice. + + `Then you should say what you mean,' the March Hare went on. + + `I do,' Alice hastily replied; `at least--at least I mean what +I say--that's the same thing, you know.' + + `Not the same thing a bit!' said the Hatter. `You might just +as well say that "I see what I eat" is the same thing as "I eat +what I see"!' + + `You might just as well say,' added the March Hare, `that "I +like what I get" is the same thing as "I get what I like"!' + + `You might just as well say,' added the Dormouse, who seemed to +be talking in his sleep, `that "I breathe when I sleep" is the +same thing as "I sleep when I breathe"!' + + `It IS the same thing with you,' said the Hatter, and here the +conversation dropped, and the party sat silent for a minute, +while Alice thought over all she could remember about ravens and +writing-desks, which wasn't much. + + The Hatter was the first to break the silence. `What day of +the month is it?' he said, turning to Alice: he had taken his +watch out of his pocket, and was looking at it uneasily, shaking +it every now and then, and holding it to his ear. + + Alice considered a little, and then said `The fourth.' + + `Two days wrong!' sighed the Hatter. `I told you butter +wouldn't suit the works!' he added looking angrily at the March +Hare. + + `It was the BEST butter,' the March Hare meekly replied. + + `Yes, but some crumbs must have got in as well,' the Hatter +grumbled: `you shouldn't have put it in with the bread-knife.' + + The March Hare took the watch and looked at it gloomily: then +he dipped it into his cup of tea, and looked at it again: but he +could think of nothing better to say than his first remark, `It +was the BEST butter, you know.' + + Alice had been looking over his shoulder with some curiosity. +`What a funny watch!' she remarked. `It tells the day of the +month, and doesn't tell what o'clock it is!' + + `Why should it?' muttered the Hatter. `Does YOUR watch tell +you what year it is?' + + `Of course not,' Alice replied very readily: `but that's +because it stays the same year for such a long time together.' + + `Which is just the case with MINE,' said the Hatter. + + Alice felt dreadfully puzzled. The Hatter's remark seemed to +have no sort of meaning in it, and yet it was certainly English. +`I don't quite understand you,' she said, as politely as she +could. + + `The Dormouse is asleep again,' said the Hatter, and he poured +a little hot tea upon its nose. + + The Dormouse shook its head impatiently, and said, without +opening its eyes, `Of course, of course; just what I was going to +remark myself.' + + `Have you guessed the riddle yet?' the Hatter said, turning to +Alice again. + + `No, I give it up,' Alice replied: `what's the answer?' + + `I haven't the slightest idea,' said the Hatter. + + `Nor I,' said the March Hare. + + Alice sighed wearily. `I think you might do something better +with the time,' she said, `than waste it in asking riddles that +have no answers.' + + `If you knew Time as well as I do,' said the Hatter, `you +wouldn't talk about wasting IT. It's HIM.' + + `I don't know what you mean,' said Alice. + + `Of course you don't!' the Hatter said, tossing his head +contemptuously. `I dare say you never even spoke to Time!' + + `Perhaps not,' Alice cautiously replied: `but I know I have to +beat time when I learn music.' + + `Ah! that accounts for it,' said the Hatter. `He won't stand +beating. Now, if you only kept on good terms with him, he'd do +almost anything you liked with the clock. For instance, suppose +it were nine o'clock in the morning, just time to begin lessons: +you'd only have to whisper a hint to Time, and round goes the +clock in a twinkling! Half-past one, time for dinner!' + + (`I only wish it was,' the March Hare said to itself in a +whisper.) + + `That would be grand, certainly,' said Alice thoughtfully: +`but then--I shouldn't be hungry for it, you know.' + + `Not at first, perhaps,' said the Hatter: `but you could keep +it to half-past one as long as you liked.' + + `Is that the way YOU manage?' Alice asked. + + The Hatter shook his head mournfully. `Not I!' he replied. +`We quarrelled last March--just before HE went mad, you know--' +(pointing with his tea spoon at the March Hare,) `--it was at the +great concert given by the Queen of Hearts, and I had to sing + + "Twinkle, twinkle, little bat! + How I wonder what you're at!" + +You know the song, perhaps?' + + `I've heard something like it,' said Alice. + + `It goes on, you know,' the Hatter continued, `in this way:-- + + "Up above the world you fly, + Like a tea-tray in the sky. + Twinkle, twinkle--"' + +Here the Dormouse shook itself, and began singing in its sleep +`Twinkle, twinkle, twinkle, twinkle--' and went on so long that +they had to pinch it to make it stop. + + `Well, I'd hardly finished the first verse,' said the Hatter, +`when the Queen jumped up and bawled out, "He's murdering the +time! Off with his head!"' + + `How dreadfully savage!' exclaimed Alice. + + `And ever since that,' the Hatter went on in a mournful tone, +`he won't do a thing I ask! It's always six o'clock now.' + + A bright idea came into Alice's head. `Is that the reason so +many tea-things are put out here?' she asked. + + `Yes, that's it,' said the Hatter with a sigh: `it's always +tea-time, and we've no time to wash the things between whiles.' + + `Then you keep moving round, I suppose?' said Alice. + + `Exactly so,' said the Hatter: `as the things get used up.' + + `But what happens when you come to the beginning again?' Alice +ventured to ask. + + `Suppose we change the subject,' the March Hare interrupted, +yawning. `I'm getting tired of this. I vote the young lady +tells us a story.' + + `I'm afraid I don't know one,' said Alice, rather alarmed at +the proposal. + + `Then the Dormouse shall!' they both cried. `Wake up, +Dormouse!' And they pinched it on both sides at once. + + The Dormouse slowly opened his eyes. `I wasn't asleep,' he +said in a hoarse, feeble voice: `I heard every word you fellows +were saying.' + + `Tell us a story!' said the March Hare. + + `Yes, please do!' pleaded Alice. + + `And be quick about it,' added the Hatter, `or you'll be asleep +again before it's done.' + + `Once upon a time there were three little sisters,' the +Dormouse began in a great hurry; `and their names were Elsie, +Lacie, and Tillie; and they lived at the bottom of a well--' + + `What did they live on?' said Alice, who always took a great +interest in questions of eating and drinking. + + `They lived on treacle,' said the Dormouse, after thinking a +minute or two. + + `They couldn't have done that, you know,' Alice gently +remarked; `they'd have been ill.' + + `So they were,' said the Dormouse; `VERY ill.' + + Alice tried to fancy to herself what such an extraordinary ways +of living would be like, but it puzzled her too much, so she went +on: `But why did they live at the bottom of a well?' + + `Take some more tea,' the March Hare said to Alice, very +earnestly. + + `I've had nothing yet,' Alice replied in an offended tone, `so +I can't take more.' + + `You mean you can't take LESS,' said the Hatter: `it's very +easy to take MORE than nothing.' + + `Nobody asked YOUR opinion,' said Alice. + + `Who's making personal remarks now?' the Hatter asked +triumphantly. + + Alice did not quite know what to say to this: so she helped +herself to some tea and bread-and-butter, and then turned to the +Dormouse, and repeated her question. `Why did they live at the +bottom of a well?' + + The Dormouse again took a minute or two to think about it, and +then said, `It was a treacle-well.' + + `There's no such thing!' Alice was beginning very angrily, but +the Hatter and the March Hare went `Sh! sh!' and the Dormouse +sulkily remarked, `If you can't be civil, you'd better finish the +story for yourself.' + + `No, please go on!' Alice said very humbly; `I won't interrupt +again. I dare say there may be ONE.' + + `One, indeed!' said the Dormouse indignantly. However, he +consented to go on. `And so these three little sisters--they +were learning to draw, you know--' + + `What did they draw?' said Alice, quite forgetting her promise. + + `Treacle,' said the Dormouse, without considering at all this +time. + + `I want a clean cup,' interrupted the Hatter: `let's all move +one place on.' + + He moved on as he spoke, and the Dormouse followed him: the +March Hare moved into the Dormouse's place, and Alice rather +unwillingly took the place of the March Hare. The Hatter was the +only one who got any advantage from the change: and Alice was a +good deal worse off than before, as the March Hare had just upset +the milk-jug into his plate. + + Alice did not wish to offend the Dormouse again, so she began +very cautiously: `But I don't understand. Where did they draw +the treacle from?' + + `You can draw water out of a water-well,' said the Hatter; `so +I should think you could draw treacle out of a treacle-well--eh, +stupid?' + + `But they were IN the well,' Alice said to the Dormouse, not +choosing to notice this last remark. + + `Of course they were', said the Dormouse; `--well in.' + + This answer so confused poor Alice, that she let the Dormouse +go on for some time without interrupting it. + + `They were learning to draw,' the Dormouse went on, yawning and +rubbing its eyes, for it was getting very sleepy; `and they drew +all manner of things--everything that begins with an M--' + + `Why with an M?' said Alice. + + `Why not?' said the March Hare. + + Alice was silent. + + The Dormouse had closed its eyes by this time, and was going +off into a doze; but, on being pinched by the Hatter, it woke up +again with a little shriek, and went on: `--that begins with an +M, such as mouse-traps, and the moon, and memory, and muchness-- +you know you say things are "much of a muchness"--did you ever +see such a thing as a drawing of a muchness?' + + `Really, now you ask me,' said Alice, very much confused, `I +don't think--' + + `Then you shouldn't talk,' said the Hatter. + + This piece of rudeness was more than Alice could bear: she got +up in great disgust, and walked off; the Dormouse fell asleep +instantly, and neither of the others took the least notice of her +going, though she looked back once or twice, half hoping that +they would call after her: the last time she saw them, they were +trying to put the Dormouse into the teapot. + + `At any rate I'll never go THERE again!' said Alice as she +picked her way through the wood. `It's the stupidest tea-party I +ever was at in all my life!' + + Just as she said this, she noticed that one of the trees had a +door leading right into it. `That's very curious!' she thought. +`But everything's curious today. I think I may as well go in at +once.' And in she went. + + Once more she found herself in the long hall, and close to the +little glass table. `Now, I'll manage better this time,' she +said to herself, and began by taking the little golden key, and +unlocking the door that led into the garden. Then she went to +work nibbling at the mushroom (she had kept a piece of it in her +pocked) till she was about a foot high: then she walked down the +little passage: and THEN--she found herself at last in the +beautiful garden, among the bright flower-beds and the cool +fountains. + + + + CHAPTER VIII + + The Queen's Croquet-Ground + + + A large rose-tree stood near the entrance of the garden: the +roses growing on it were white, but there were three gardeners at +it, busily painting them red. Alice thought this a very curious +thing, and she went nearer to watch them, and just as she came up +to them she heard one of them say, `Look out now, Five! Don't go +splashing paint over me like that!' + + `I couldn't help it,' said Five, in a sulky tone; `Seven jogged +my elbow.' + + On which Seven looked up and said, `That's right, Five! Always +lay the blame on others!' + + `YOU'D better not talk!' said Five. `I heard the Queen say only +yesterday you deserved to be beheaded!' + + `What for?' said the one who had spoken first. + + `That's none of YOUR business, Two!' said Seven. + + `Yes, it IS his business!' said Five, `and I'll tell him--it +was for bringing the cook tulip-roots instead of onions.' + + Seven flung down his brush, and had just begun `Well, of all +the unjust things--' when his eye chanced to fall upon Alice, as +she stood watching them, and he checked himself suddenly: the +others looked round also, and all of them bowed low. + + `Would you tell me,' said Alice, a little timidly, `why you are +painting those roses?' + + Five and Seven said nothing, but looked at Two. Two began in a +low voice, `Why the fact is, you see, Miss, this here ought to +have been a RED rose-tree, and we put a white one in by mistake; +and if the Queen was to find it out, we should all have our heads +cut off, you know. So you see, Miss, we're doing our best, afore +she comes, to--' At this moment Five, who had been anxiously +looking across the garden, called out `The Queen! The Queen!' +and the three gardeners instantly threw themselves flat upon +their faces. There was a sound of many footsteps, and Alice +looked round, eager to see the Queen. + + First came ten soldiers carrying clubs; these were all shaped +like the three gardeners, oblong and flat, with their hands and +feet at the corners: next the ten courtiers; these were +ornamented all over with diamonds, and walked two and two, as the +soldiers did. After these came the royal children; there were +ten of them, and the little dears came jumping merrily along hand +in hand, in couples: they were all ornamented with hearts. Next +came the guests, mostly Kings and Queens, and among them Alice +recognised the White Rabbit: it was talking in a hurried nervous +manner, smiling at everything that was said, and went by without +noticing her. Then followed the Knave of Hearts, carrying the +King's crown on a crimson velvet cushion; and, last of all this +grand procession, came THE KING AND QUEEN OF HEARTS. + + Alice was rather doubtful whether she ought not to lie down on +her face like the three gardeners, but she could not remember +every having heard of such a rule at processions; `and besides, +what would be the use of a procession,' thought she, `if people +had all to lie down upon their faces, so that they couldn't see +it?' So she stood still where she was, and waited. + + When the procession came opposite to Alice, they all stopped +and looked at her, and the Queen said severely `Who is this?' +She said it to the Knave of Hearts, who only bowed and smiled in +reply. + + `Idiot!' said the Queen, tossing her head impatiently; and, +turning to Alice, she went on, `What's your name, child?' + + `My name is Alice, so please your Majesty,' said Alice very +politely; but she added, to herself, `Why, they're only a pack of +cards, after all. I needn't be afraid of them!' + + `And who are THESE?' said the Queen, pointing to the three +gardeners who were lying round the rosetree; for, you see, as +they were lying on their faces, and the pattern on their backs +was the same as the rest of the pack, she could not tell whether +they were gardeners, or soldiers, or courtiers, or three of her +own children. + + `How should I know?' said Alice, surprised at her own courage. +`It's no business of MINE.' + + The Queen turned crimson with fury, and, after glaring at her +for a moment like a wild beast, screamed `Off with her head! +Off--' + + `Nonsense!' said Alice, very loudly and decidedly, and the +Queen was silent. + + The King laid his hand upon her arm, and timidly said +`Consider, my dear: she is only a child!' + + The Queen turned angrily away from him, and said to the Knave +`Turn them over!' + + The Knave did so, very carefully, with one foot. + + `Get up!' said the Queen, in a shrill, loud voice, and the +three gardeners instantly jumped up, and began bowing to the +King, the Queen, the royal children, and everybody else. + + `Leave off that!' screamed the Queen. `You make me giddy.' +And then, turning to the rose-tree, she went on, `What HAVE you +been doing here?' + + `May it please your Majesty,' said Two, in a very humble tone, +going down on one knee as he spoke, `we were trying--' + + `I see!' said the Queen, who had meanwhile been examining the +roses. `Off with their heads!' and the procession moved on, +three of the soldiers remaining behind to execute the unfortunate +gardeners, who ran to Alice for protection. + + `You shan't be beheaded!' said Alice, and she put them into a +large flower-pot that stood near. The three soldiers wandered +about for a minute or two, looking for them, and then quietly +marched off after the others. + + `Are their heads off?' shouted the Queen. + + `Their heads are gone, if it please your Majesty!' the soldiers +shouted in reply. + + `That's right!' shouted the Queen. `Can you play croquet?' + + The soldiers were silent, and looked at Alice, as the question +was evidently meant for her. + + `Yes!' shouted Alice. + + `Come on, then!' roared the Queen, and Alice joined the +procession, wondering very much what would happen next. + + `It's--it's a very fine day!' said a timid voice at her side. +She was walking by the White Rabbit, who was peeping anxiously +into her face. + + `Very,' said Alice: `--where's the Duchess?' + + `Hush! Hush!' said the Rabbit in a low, hurried tone. He +looked anxiously over his shoulder as he spoke, and then raised +himself upon tiptoe, put his mouth close to her ear, and +whispered `She's under sentence of execution.' + + `What for?' said Alice. + + `Did you say "What a pity!"?' the Rabbit asked. + + `No, I didn't,' said Alice: `I don't think it's at all a pity. +I said "What for?"' + + `She boxed the Queen's ears--' the Rabbit began. Alice gave a +little scream of laughter. `Oh, hush!' the Rabbit whispered in a +frightened tone. `The Queen will hear you! You see, she came +rather late, and the Queen said--' + + `Get to your places!' shouted the Queen in a voice of thunder, +and people began running about in all directions, tumbling up +against each other; however, they got settled down in a minute or +two, and the game began. Alice thought she had never seen such a +curious croquet-ground in her life; it was all ridges and +furrows; the balls were live hedgehogs, the mallets live +flamingoes, and the soldiers had to double themselves up and to +stand on their hands and feet, to make the arches. + + The chief difficulty Alice found at first was in managing her +flamingo: she succeeded in getting its body tucked away, +comfortably enough, under her arm, with its legs hanging down, +but generally, just as she had got its neck nicely straightened +out, and was going to give the hedgehog a blow with its head, it +WOULD twist itself round and look up in her face, with such a +puzzled expression that she could not help bursting out laughing: +and when she had got its head down, and was going to begin again, +it was very provoking to find that the hedgehog had unrolled +itself, and was in the act of crawling away: besides all this, +there was generally a ridge or furrow in the way wherever she +wanted to send the hedgehog to, and, as the doubled-up soldiers +were always getting up and walking off to other parts of the +ground, Alice soon came to the conclusion that it was a very +difficult game indeed. + + The players all played at once without waiting for turns, +quarrelling all the while, and fighting for the hedgehogs; and in +a very short time the Queen was in a furious passion, and went +stamping about, and shouting `Off with his head!' or `Off with +her head!' about once in a minute. + + Alice began to feel very uneasy: to be sure, she had not as +yet had any dispute with the Queen, but she knew that it might +happen any minute, `and then,' thought she, `what would become of +me? They're dreadfully fond of beheading people here; the great +wonder is, that there's any one left alive!' + + She was looking about for some way of escape, and wondering +whether she could get away without being seen, when she noticed a +curious appearance in the air: it puzzled her very much at +first, but, after watching it a minute or two, she made it out to +be a grin, and she said to herself `It's the Cheshire Cat: now I +shall have somebody to talk to.' + + `How are you getting on?' said the Cat, as soon as there was +mouth enough for it to speak with. + + Alice waited till the eyes appeared, and then nodded. `It's no +use speaking to it,' she thought, `till its ears have come, or at +least one of them.' In another minute the whole head appeared, +and then Alice put down her flamingo, and began an account of the +game, feeling very glad she had someone to listen to her. The +Cat seemed to think that there was enough of it now in sight, and +no more of it appeared. + + `I don't think they play at all fairly,' Alice began, in rather +a complaining tone, `and they all quarrel so dreadfully one can't +hear oneself speak--and they don't seem to have any rules in +particular; at least, if there are, nobody attends to them--and +you've no idea how confusing it is all the things being alive; +for instance, there's the arch I've got to go through next +walking about at the other end of the ground--and I should have +croqueted the Queen's hedgehog just now, only it ran away when it +saw mine coming!' + + `How do you like the Queen?' said the Cat in a low voice. + + `Not at all,' said Alice: `she's so extremely--' Just then +she noticed that the Queen was close behind her, listening: so +she went on, `--likely to win, that it's hardly worth while +finishing the game.' + + The Queen smiled and passed on. + + `Who ARE you talking to?' said the King, going up to Alice, and +looking at the Cat's head with great curiosity. + + `It's a friend of mine--a Cheshire Cat,' said Alice: `allow me +to introduce it.' + + `I don't like the look of it at all,' said the King: `however, +it may kiss my hand if it likes.' + + `I'd rather not,' the Cat remarked. + + `Don't be impertinent,' said the King, `and don't look at me +like that!' He got behind Alice as he spoke. + + `A cat may look at a king,' said Alice. `I've read that in +some book, but I don't remember where.' + + `Well, it must be removed,' said the King very decidedly, and +he called the Queen, who was passing at the moment, `My dear! I +wish you would have this cat removed!' + + The Queen had only one way of settling all difficulties, great +or small. `Off with his head!' she said, without even looking +round. + + `I'll fetch the executioner myself,' said the King eagerly, and +he hurried off. + + Alice thought she might as well go back, and see how the game +was going on, as she heard the Queen's voice in the distance, +screaming with passion. She had already heard her sentence three +of the players to be executed for having missed their turns, and +she did not like the look of things at all, as the game was in +such confusion that she never knew whether it was her turn or +not. So she went in search of her hedgehog. + + The hedgehog was engaged in a fight with another hedgehog, +which seemed to Alice an excellent opportunity for croqueting one +of them with the other: the only difficulty was, that her +flamingo was gone across to the other side of the garden, where +Alice could see it trying in a helpless sort of way to fly up +into a tree. + + By the time she had caught the flamingo and brought it back, +the fight was over, and both the hedgehogs were out of sight: +`but it doesn't matter much,' thought Alice, `as all the arches +are gone from this side of the ground.' So she tucked it away +under her arm, that it might not escape again, and went back for +a little more conversation with her friend. + + When she got back to the Cheshire Cat, she was surprised to +find quite a large crowd collected round it: there was a dispute +going on between the executioner, the King, and the Queen, who +were all talking at once, while all the rest were quite silent, +and looked very uncomfortable. + + The moment Alice appeared, she was appealed to by all three to +settle the question, and they repeated their arguments to her, +though, as they all spoke at once, she found it very hard indeed +to make out exactly what they said. + + The executioner's argument was, that you couldn't cut off a +head unless there was a body to cut it off from: that he had +never had to do such a thing before, and he wasn't going to begin +at HIS time of life. + + The King's argument was, that anything that had a head could be +beheaded, and that you weren't to talk nonsense. + + The Queen's argument was, that if something wasn't done about +it in less than no time she'd have everybody executed, all round. +(It was this last remark that had made the whole party look so +grave and anxious.) + + Alice could think of nothing else to say but `It belongs to the +Duchess: you'd better ask HER about it.' + + `She's in prison,' the Queen said to the executioner: `fetch +her here.' And the executioner went off like an arrow. + + The Cat's head began fading away the moment he was gone, and, +by the time he had come back with the Dutchess, it had entirely +disappeared; so the King and the executioner ran wildly up and +down looking for it, while the rest of the party went back to the game. + + + + CHAPTER IX + + The Mock Turtle's Story + + + `You can't think how glad I am to see you again, you dear old +thing!' said the Duchess, as she tucked her arm affectionately +into Alice's, and they walked off together. + + Alice was very glad to find her in such a pleasant temper, and +thought to herself that perhaps it was only the pepper that had +made her so savage when they met in the kitchen. + + `When I'M a Duchess,' she said to herself, (not in a very +hopeful tone though), `I won't have any pepper in my kitchen AT +ALL. Soup does very well without--Maybe it's always pepper that +makes people hot-tempered,' she went on, very much pleased at +having found out a new kind of rule, `and vinegar that makes them +sour--and camomile that makes them bitter--and--and barley-sugar +and such things that make children sweet-tempered. I only wish +people knew that: then they wouldn't be so stingy about it, you +know--' + + She had quite forgotten the Duchess by this time, and was a +little startled when she heard her voice close to her ear. +`You're thinking about something, my dear, and that makes you +forget to talk. I can't tell you just now what the moral of that +is, but I shall remember it in a bit.' + + `Perhaps it hasn't one,' Alice ventured to remark. + + `Tut, tut, child!' said the Duchess. `Everything's got a +moral, if only you can find it.' And she squeezed herself up +closer to Alice's side as she spoke. + + Alice did not much like keeping so close to her: first, +because the Duchess was VERY ugly; and secondly, because she was +exactly the right height to rest her chin upon Alice's shoulder, +and it was an uncomfortably sharp chin. However, she did not +like to be rude, so she bore it as well as she could. + + `The game's going on rather better now,' she said, by way of +keeping up the conversation a little. + + `'Tis so,' said the Duchess: `and the moral of that is--"Oh, +'tis love, 'tis love, that makes the world go round!"' + + `Somebody said,' Alice whispered, `that it's done by everybody +minding their own business!' + + `Ah, well! It means much the same thing,' said the Duchess, +digging her sharp little chin into Alice's shoulder as she added, +`and the moral of THAT is--"Take care of the sense, and the +sounds will take care of themselves."' + + `How fond she is of finding morals in things!' Alice thought to +herself. + + `I dare say you're wondering why I don't put my arm round your +waist,' the Duchess said after a pause: `the reason is, that I'm +doubtful about the temper of your flamingo. Shall I try the +experiment?' + + `HE might bite,' Alice cautiously replied, not feeling at all +anxious to have the experiment tried. + + `Very true,' said the Duchess: `flamingoes and mustard both +bite. And the moral of that is--"Birds of a feather flock +together."' + + `Only mustard isn't a bird,' Alice remarked. + + `Right, as usual,' said the Duchess: `what a clear way you +have of putting things!' + + `It's a mineral, I THINK,' said Alice. + + `Of course it is,' said the Duchess, who seemed ready to agree +to everything that Alice said; `there's a large mustard-mine near +here. And the moral of that is--"The more there is of mine, the +less there is of yours."' + + `Oh, I know!' exclaimed Alice, who had not attended to this +last remark, `it's a vegetable. It doesn't look like one, but it +is.' + + `I quite agree with you,' said the Duchess; `and the moral of +that is--"Be what you would seem to be"--or if you'd like it put +more simply--"Never imagine yourself not to be otherwise than +what it might appear to others that what you were or might have +been was not otherwise than what you had been would have appeared +to them to be otherwise."' + + `I think I should understand that better,' Alice said very +politely, `if I had it written down: but I can't quite follow it +as you say it.' + + `That's nothing to what I could say if I chose,' the Duchess +replied, in a pleased tone. + + `Pray don't trouble yourself to say it any longer than that,' +said Alice. + + `Oh, don't talk about trouble!' said the Duchess. `I make you +a present of everything I've said as yet.' + + `A cheap sort of present!' thought Alice. `I'm glad they don't +give birthday presents like that!' But she did not venture to +say it out loud. + + `Thinking again?' the Duchess asked, with another dig of her +sharp little chin. + + `I've a right to think,' said Alice sharply, for she was +beginning to feel a little worried. + + `Just about as much right,' said the Duchess, `as pigs have to +fly; and the m--' + + But here, to Alice's great surprise, the Duchess's voice died +away, even in the middle of her favourite word `moral,' and the +arm that was linked into hers began to tremble. Alice looked up, +and there stood the Queen in front of them, with her arms folded, +frowning like a thunderstorm. + + `A fine day, your Majesty!' the Duchess began in a low, weak +voice. + + `Now, I give you fair warning,' shouted the Queen, stamping on +the ground as she spoke; `either you or your head must be off, +and that in about half no time! Take your choice!' + + The Duchess took her choice, and was gone in a moment. + + `Let's go on with the game,' the Queen said to Alice; and Alice +was too much frightened to say a word, but slowly followed her +back to the croquet-ground. + + The other guests had taken advantage of the Queen's absence, +and were resting in the shade: however, the moment they saw her, +they hurried back to the game, the Queen merely remarking that a +moment's delay would cost them their lives. + + All the time they were playing the Queen never left off +quarrelling with the other players, and shouting `Off with his +head!' or `Off with her head!' Those whom she sentenced were +taken into custody by the soldiers, who of course had to leave +off being arches to do this, so that by the end of half an hour +or so there were no arches left, and all the players, except the +King, the Queen, and Alice, were in custody and under sentence of +execution. + + Then the Queen left off, quite out of breath, and said to +Alice, `Have you seen the Mock Turtle yet?' + + `No,' said Alice. `I don't even know what a Mock Turtle is.' + + `It's the thing Mock Turtle Soup is made from,' said the Queen. + + `I never saw one, or heard of one,' said Alice. + + `Come on, then,' said the Queen, `and he shall tell you his +history,' + + As they walked off together, Alice heard the King say in a low +voice, to the company generally, `You are all pardoned.' `Come, +THAT'S a good thing!' she said to herself, for she had felt quite +unhappy at the number of executions the Queen had ordered. + + They very soon came upon a Gryphon, lying fast asleep in the +sun. (IF you don't know what a Gryphon is, look at the picture.) +`Up, lazy thing!' said the Queen, `and take this young lady to +see the Mock Turtle, and to hear his history. I must go back and +see after some executions I have ordered'; and she walked off, +leaving Alice alone with the Gryphon. Alice did not quite like +the look of the creature, but on the whole she thought it would +be quite as safe to stay with it as to go after that savage +Queen: so she waited. + + The Gryphon sat up and rubbed its eyes: then it watched the +Queen till she was out of sight: then it chuckled. `What fun!' +said the Gryphon, half to itself, half to Alice. + + `What IS the fun?' said Alice. + + `Why, SHE,' said the Gryphon. `It's all her fancy, that: they +never executes nobody, you know. Come on!' + + `Everybody says "come on!" here,' thought Alice, as she went +slowly after it: `I never was so ordered about in all my life, +never!' + + They had not gone far before they saw the Mock Turtle in the +distance, sitting sad and lonely on a little ledge of rock, and, +as they came nearer, Alice could hear him sighing as if his heart +would break. She pitied him deeply. `What is his sorrow?' she +asked the Gryphon, and the Gryphon answered, very nearly in the +same words as before, `It's all his fancy, that: he hasn't got +no sorrow, you know. Come on!' + + So they went up to the Mock Turtle, who looked at them with +large eyes full of tears, but said nothing. + + `This here young lady,' said the Gryphon, `she wants for to +know your history, she do.' + + `I'll tell it her,' said the Mock Turtle in a deep, hollow +tone: `sit down, both of you, and don't speak a word till I've +finished.' + + So they sat down, and nobody spoke for some minutes. Alice +thought to herself, `I don't see how he can EVEN finish, if he +doesn't begin.' But she waited patiently. + + `Once,' said the Mock Turtle at last, with a deep sigh, `I was +a real Turtle.' + + These words were followed by a very long silence, broken only +by an occasional exclamation of `Hjckrrh!' from the Gryphon, and +the constant heavy sobbing of the Mock Turtle. Alice was very +nearly getting up and saying, `Thank you, sir, for your +interesting story,' but she could not help thinking there MUST be +more to come, so she sat still and said nothing. + + `When we were little,' the Mock Turtle went on at last, more +calmly, though still sobbing a little now and then, `we went to +school in the sea. The master was an old Turtle--we used to call +him Tortoise--' + + `Why did you call him Tortoise, if he wasn't one?' Alice asked. + + `We called him Tortoise because he taught us,' said the Mock +Turtle angrily: `really you are very dull!' + + `You ought to be ashamed of yourself for asking such a simple +question,' added the Gryphon; and then they both sat silent and +looked at poor Alice, who felt ready to sink into the earth. At +last the Gryphon said to the Mock Turtle, `Drive on, old fellow! +Don't be all day about it!' and he went on in these words: + + `Yes, we went to school in the sea, though you mayn't believe +it--' + + `I never said I didn't!' interrupted Alice. + + `You did,' said the Mock Turtle. + + `Hold your tongue!' added the Gryphon, before Alice could speak +again. The Mock Turtle went on. + + `We had the best of educations--in fact, we went to school +every day--' + + `I'VE been to a day-school, too,' said Alice; `you needn't be +so proud as all that.' + + `With extras?' asked the Mock Turtle a little anxiously. + + `Yes,' said Alice, `we learned French and music.' + + `And washing?' said the Mock Turtle. + + `Certainly not!' said Alice indignantly. + + `Ah! then yours wasn't a really good school,' said the Mock +Turtle in a tone of great relief. `Now at OURS they had at the +end of the bill, "French, music, AND WASHING--extra."' + + `You couldn't have wanted it much,' said Alice; `living at the +bottom of the sea.' + + `I couldn't afford to learn it.' said the Mock Turtle with a +sigh. `I only took the regular course.' + + `What was that?' inquired Alice. + + `Reeling and Writhing, of course, to begin with,' the Mock +Turtle replied; `and then the different branches of Arithmetic-- +Ambition, Distraction, Uglification, and Derision.' + + `I never heard of "Uglification,"' Alice ventured to say. `What +is it?' + + The Gryphon lifted up both its paws in surprise. `What! Never +heard of uglifying!' it exclaimed. `You know what to beautify +is, I suppose?' + + `Yes,' said Alice doubtfully: `it means--to--make--anything-- +prettier.' + + `Well, then,' the Gryphon went on, `if you don't know what to +uglify is, you ARE a simpleton.' + + Alice did not feel encouraged to ask any more questions about +it, so she turned to the Mock Turtle, and said `What else had you +to learn?' + + `Well, there was Mystery,' the Mock Turtle replied, counting +off the subjects on his flappers, `--Mystery, ancient and modern, +with Seaography: then Drawling--the Drawling-master was an old +conger-eel, that used to come once a week: HE taught us +Drawling, Stretching, and Fainting in Coils.' + + `What was THAT like?' said Alice. + + `Well, I can't show it you myself,' the Mock Turtle said: `I'm +too stiff. And the Gryphon never learnt it.' + + `Hadn't time,' said the Gryphon: `I went to the Classics +master, though. He was an old crab, HE was.' + + `I never went to him,' the Mock Turtle said with a sigh: `he +taught Laughing and Grief, they used to say.' + + `So he did, so he did,' said the Gryphon, sighing in his turn; +and both creatures hid their faces in their paws. + + `And how many hours a day did you do lessons?' said Alice, in a +hurry to change the subject. + + `Ten hours the first day,' said the Mock Turtle: `nine the +next, and so on.' + + `What a curious plan!' exclaimed Alice. + + `That's the reason they're called lessons,' the Gryphon +remarked: `because they lessen from day to day.' + + This was quite a new idea to Alice, and she thought it over a +little before she made her next remark. `Then the eleventh day +must have been a holiday?' + + `Of course it was,' said the Mock Turtle. + + `And how did you manage on the twelfth?' Alice went on eagerly. + + `That's enough about lessons,' the Gryphon interrupted in a +very decided tone: `tell her something about the games now.' + + + + CHAPTER X + + The Lobster Quadrille + + + The Mock Turtle sighed deeply, and drew the back of one flapper +across his eyes. He looked at Alice, and tried to speak, but for +a minute or two sobs choked his voice. `Same as if he had a bone +in his throat,' said the Gryphon: and it set to work shaking him +and punching him in the back. At last the Mock Turtle recovered +his voice, and, with tears running down his cheeks, he went on +again:-- + + `You may not have lived much under the sea--' (`I haven't,' +said Alice)--`and perhaps you were never even introduced to a lobster--' +(Alice began to say `I once tasted--' but checked herself hastily, +and said `No, never') `--so you can have no idea what a delightful +thing a Lobster Quadrille is!' + + `No, indeed,' said Alice. `What sort of a dance is it?' + + `Why,' said the Gryphon, `you first form into a line along the +sea-shore--' + + `Two lines!' cried the Mock Turtle. `Seals, turtles, salmon, +and so on; then, when you've cleared all the jelly-fish out of +the way--' + + `THAT generally takes some time,' interrupted the Gryphon. + + `--you advance twice--' + + `Each with a lobster as a partner!' cried the Gryphon. + + `Of course,' the Mock Turtle said: `advance twice, set to +partners--' + + `--change lobsters, and retire in same order,' continued the +Gryphon. + + `Then, you know,' the Mock Turtle went on, `you throw the--' + + `The lobsters!' shouted the Gryphon, with a bound into the air. + + `--as far out to sea as you can--' + + `Swim after them!' screamed the Gryphon. + + `Turn a somersault in the sea!' cried the Mock Turtle, +capering wildly about. + + `Back to land again, and that's all the first figure,' said the +Mock Turtle, suddenly dropping his voice; and the two creatures, +who had been jumping about like mad things all this time, sat +down again very sadly and quietly, and looked at Alice. + + `It must be a very pretty dance,' said Alice timidly. + + `Would you like to see a little of it?' said the Mock Turtle. + + `Very much indeed,' said Alice. + + `Come, let's try the first figure!' said the Mock Turtle to the +Gryphon. `We can do without lobsters, you know. Which shall +sing?' + + `Oh, YOU sing,' said the Gryphon. `I've forgotten the words.' + + So they began solemnly dancing round and round Alice, every now +and then treading on her toes when they passed too close, and +waving their forepaws to mark the time, while the Mock Turtle +sang this, very slowly and sadly:-- + + +`"Will you walk a little faster?" said a whiting to a snail. +"There's a porpoise close behind us, and he's treading on my + tail. +See how eagerly the lobsters and the turtles all advance! +They are waiting on the shingle--will you come and join the +dance? + +Will you, won't you, will you, won't you, will you join the +dance? +Will you, won't you, will you, won't you, won't you join the +dance? + + +"You can really have no notion how delightful it will be +When they take us up and throw us, with the lobsters, out to + sea!" +But the snail replied "Too far, too far!" and gave a look + askance-- +Said he thanked the whiting kindly, but he would not join the + dance. + Would not, could not, would not, could not, would not join + the dance. + Would not, could not, would not, could not, could not join + the dance. + +`"What matters it how far we go?" his scaly friend replied. +"There is another shore, you know, upon the other side. +The further off from England the nearer is to France-- +Then turn not pale, beloved snail, but come and join the dance. + + Will you, won't you, will you, won't you, will you join the + dance? + Will you, won't you, will you, won't you, won't you join the + dance?"' + + + + `Thank you, it's a very interesting dance to watch,' said +Alice, feeling very glad that it was over at last: `and I do so +like that curious song about the whiting!' + + `Oh, as to the whiting,' said the Mock Turtle, `they--you've +seen them, of course?' + + `Yes,' said Alice, `I've often seen them at dinn--' she +checked herself hastily. + + `I don't know where Dinn may be,' said the Mock Turtle, `but +if you've seen them so often, of course you know what they're +like.' + + `I believe so,' Alice replied thoughtfully. `They have their +tails in their mouths--and they're all over crumbs.' + + `You're wrong about the crumbs,' said the Mock Turtle: +`crumbs would all wash off in the sea. But they HAVE their tails +in their mouths; and the reason is--' here the Mock Turtle +yawned and shut his eyes.--`Tell her about the reason and all +that,' he said to the Gryphon. + + `The reason is,' said the Gryphon, `that they WOULD go with +the lobsters to the dance. So they got thrown out to sea. So +they had to fall a long way. So they got their tails fast in +their mouths. So they couldn't get them out again. That's all.' + + `Thank you,' said Alice, `it's very interesting. I never knew +so much about a whiting before.' + + `I can tell you more than that, if you like,' said the +Gryphon. `Do you know why it's called a whiting?' + + `I never thought about it,' said Alice. `Why?' + + `IT DOES THE BOOTS AND SHOES.' the Gryphon replied very +solemnly. + + Alice was thoroughly puzzled. `Does the boots and shoes!' she +repeated in a wondering tone. + + `Why, what are YOUR shoes done with?' said the Gryphon. `I +mean, what makes them so shiny?' + + Alice looked down at them, and considered a little before she +gave her answer. `They're done with blacking, I believe.' + + `Boots and shoes under the sea,' the Gryphon went on in a deep +voice, `are done with a whiting. Now you know.' + + `And what are they made of?' Alice asked in a tone of great +curiosity. + + `Soles and eels, of course,' the Gryphon replied rather +impatiently: `any shrimp could have told you that.' + + `If I'd been the whiting,' said Alice, whose thoughts were +still running on the song, `I'd have said to the porpoise, "Keep +back, please: we don't want YOU with us!"' + + `They were obliged to have him with them,' the Mock Turtle +said: `no wise fish would go anywhere without a porpoise.' + + `Wouldn't it really?' said Alice in a tone of great surprise. + + `Of course not,' said the Mock Turtle: `why, if a fish came +to ME, and told me he was going a journey, I should say "With +what porpoise?"' + + `Don't you mean "purpose"?' said Alice. + + `I mean what I say,' the Mock Turtle replied in an offended +tone. And the Gryphon added `Come, let's hear some of YOUR +adventures.' + + `I could tell you my adventures--beginning from this morning,' +said Alice a little timidly: `but it's no use going back to +yesterday, because I was a different person then.' + + `Explain all that,' said the Mock Turtle. + + `No, no! The adventures first,' said the Gryphon in an +impatient tone: `explanations take such a dreadful time.' + + So Alice began telling them her adventures from the time when +she first saw the White Rabbit. She was a little nervous about +it just at first, the two creatures got so close to her, one on +each side, and opened their eyes and mouths so VERY wide, but she +gained courage as she went on. Her listeners were perfectly +quiet till she got to the part about her repeating `YOU ARE OLD, +FATHER WILLIAM,' to the Caterpillar, and the words all coming +different, and then the Mock Turtle drew a long breath, and said +`That's very curious.' + + `It's all about as curious as it can be,' said the Gryphon. + + `It all came different!' the Mock Turtle repeated +thoughtfully. `I should like to hear her try and repeat +something now. Tell her to begin.' He looked at the Gryphon as +if he thought it had some kind of authority over Alice. + + `Stand up and repeat "'TIS THE VOICE OF THE SLUGGARD,"' said +the Gryphon. + + `How the creatures order one about, and make one repeat +lessons!' thought Alice; `I might as well be at school at once.' +However, she got up, and began to repeat it, but her head was so +full of the Lobster Quadrille, that she hardly knew what she was +saying, and the words came very queer indeed:-- + + `'Tis the voice of the Lobster; I heard him declare, + "You have baked me too brown, I must sugar my hair." + As a duck with its eyelids, so he with his nose + Trims his belt and his buttons, and turns out his toes.' + + [later editions continued as follows + When the sands are all dry, he is gay as a lark, + And will talk in contemptuous tones of the Shark, + But, when the tide rises and sharks are around, + His voice has a timid and tremulous sound.] + + `That's different from what I used to say when I was a child,' +said the Gryphon. + + `Well, I never heard it before,' said the Mock Turtle; `but it +sounds uncommon nonsense.' + + Alice said nothing; she had sat down with her face in her +hands, wondering if anything would EVER happen in a natural way +again. + + `I should like to have it explained,' said the Mock Turtle. + + `She can't explain it,' said the Gryphon hastily. `Go on with +the next verse.' + + `But about his toes?' the Mock Turtle persisted. `How COULD +he turn them out with his nose, you know?' + + `It's the first position in dancing.' Alice said; but was +dreadfully puzzled by the whole thing, and longed to change the +subject. + + `Go on with the next verse,' the Gryphon repeated impatiently: +`it begins "I passed by his garden."' + + Alice did not dare to disobey, though she felt sure it would +all come wrong, and she went on in a trembling voice:-- + + `I passed by his garden, and marked, with one eye, + How the Owl and the Panther were sharing a pie--' + + [later editions continued as follows + The Panther took pie-crust, and gravy, and meat, + While the Owl had the dish as its share of the treat. + When the pie was all finished, the Owl, as a boon, + Was kindly permitted to pocket the spoon: + While the Panther received knife and fork with a growl, + And concluded the banquet--] + + `What IS the use of repeating all that stuff,' the Mock Turtle +interrupted, `if you don't explain it as you go on? It's by far +the most confusing thing I ever heard!' + + `Yes, I think you'd better leave off,' said the Gryphon: and +Alice was only too glad to do so. + + `Shall we try another figure of the Lobster Quadrille?' the +Gryphon went on. `Or would you like the Mock Turtle to sing you +a song?' + + `Oh, a song, please, if the Mock Turtle would be so kind,' +Alice replied, so eagerly that the Gryphon said, in a rather +offended tone, `Hm! No accounting for tastes! Sing her "Turtle +Soup," will you, old fellow?' + + The Mock Turtle sighed deeply, and began, in a voice sometimes +choked with sobs, to sing this:-- + + + `Beautiful Soup, so rich and green, + Waiting in a hot tureen! + Who for such dainties would not stoop? + Soup of the evening, beautiful Soup! + Soup of the evening, beautiful Soup! + Beau--ootiful Soo--oop! + Beau--ootiful Soo--oop! + Soo--oop of the e--e--evening, + Beautiful, beautiful Soup! + + `Beautiful Soup! Who cares for fish, + Game, or any other dish? + Who would not give all else for two p + ennyworth only of beautiful Soup? + Pennyworth only of beautiful Soup? + Beau--ootiful Soo--oop! + Beau--ootiful Soo--oop! + Soo--oop of the e--e--evening, + Beautiful, beauti--FUL SOUP!' + + `Chorus again!' cried the Gryphon, and the Mock Turtle had +just begun to repeat it, when a cry of `The trial's beginning!' +was heard in the distance. + + `Come on!' cried the Gryphon, and, taking Alice by the hand, +it hurried off, without waiting for the end of the song. + + `What trial is it?' Alice panted as she ran; but the Gryphon +only answered `Come on!' and ran the faster, while more and more +faintly came, carried on the breeze that followed them, the +melancholy words:-- + + `Soo--oop of the e--e--evening, + Beautiful, beautiful Soup!' + + + + CHAPTER XI + + Who Stole the Tarts? + + + The King and Queen of Hearts were seated on their throne when +they arrived, with a great crowd assembled about them--all sorts +of little birds and beasts, as well as the whole pack of cards: +the Knave was standing before them, in chains, with a soldier on +each side to guard him; and near the King was the White Rabbit, +with a trumpet in one hand, and a scroll of parchment in the +other. In the very middle of the court was a table, with a large +dish of tarts upon it: they looked so good, that it made Alice +quite hungry to look at them--`I wish they'd get the trial done,' +she thought, `and hand round the refreshments!' But there seemed +to be no chance of this, so she began looking at everything about +her, to pass away the time. + + Alice had never been in a court of justice before, but she had +read about them in books, and she was quite pleased to find that +she knew the name of nearly everything there. `That's the +judge,' she said to herself, `because of his great wig.' + + The judge, by the way, was the King; and as he wore his crown +over the wig, (look at the frontispiece if you want to see how he +did it,) he did not look at all comfortable, and it was certainly +not becoming. + + `And that's the jury-box,' thought Alice, `and those twelve +creatures,' (she was obliged to say `creatures,' you see, because +some of them were animals, and some were birds,) `I suppose they +are the jurors.' She said this last word two or three times over +to herself, being rather proud of it: for she thought, and +rightly too, that very few little girls of her age knew the +meaning of it at all. However, `jury-men' would have done just +as well. + + The twelve jurors were all writing very busily on slates. +`What are they doing?' Alice whispered to the Gryphon. `They +can't have anything to put down yet, before the trial's begun.' + + `They're putting down their names,' the Gryphon whispered in +reply, `for fear they should forget them before the end of the +trial.' + + `Stupid things!' Alice began in a loud, indignant voice, but +she stopped hastily, for the White Rabbit cried out, `Silence in +the court!' and the King put on his spectacles and looked +anxiously round, to make out who was talking. + + Alice could see, as well as if she were looking over their +shoulders, that all the jurors were writing down `stupid things!' +on their slates, and she could even make out that one of them +didn't know how to spell `stupid,' and that he had to ask his +neighbour to tell him. `A nice muddle their slates'll be in +before the trial's over!' thought Alice. + + One of the jurors had a pencil that squeaked. This of course, +Alice could not stand, and she went round the court and got +behind him, and very soon found an opportunity of taking it +away. She did it so quickly that the poor little juror (it was +Bill, the Lizard) could not make out at all what had become of +it; so, after hunting all about for it, he was obliged to write +with one finger for the rest of the day; and this was of very +little use, as it left no mark on the slate. + + `Herald, read the accusation!' said the King. + + On this the White Rabbit blew three blasts on the trumpet, and +then unrolled the parchment scroll, and read as follows:-- + + `The Queen of Hearts, she made some tarts, + All on a summer day: + The Knave of Hearts, he stole those tarts, + And took them quite away!' + + `Consider your verdict,' the King said to the jury. + + `Not yet, not yet!' the Rabbit hastily interrupted. `There's +a great deal to come before that!' + + `Call the first witness,' said the King; and the White Rabbit +blew three blasts on the trumpet, and called out, `First +witness!' + + The first witness was the Hatter. He came in with a teacup in +one hand and a piece of bread-and-butter in the other. `I beg +pardon, your Majesty,' he began, `for bringing these in: but I +hadn't quite finished my tea when I was sent for.' + + `You ought to have finished,' said the King. `When did you +begin?' + + The Hatter looked at the March Hare, who had followed him into +the court, arm-in-arm with the Dormouse. `Fourteenth of March, I +think it was,' he said. + + `Fifteenth,' said the March Hare. + + `Sixteenth,' added the Dormouse. + + `Write that down,' the King said to the jury, and the jury +eagerly wrote down all three dates on their slates, and then +added them up, and reduced the answer to shillings and pence. + + `Take off your hat,' the King said to the Hatter. + + `It isn't mine,' said the Hatter. + + `Stolen!' the King exclaimed, turning to the jury, who +instantly made a memorandum of the fact. + + `I keep them to sell,' the Hatter added as an explanation; +`I've none of my own. I'm a hatter.' + + Here the Queen put on her spectacles, and began staring at the +Hatter, who turned pale and fidgeted. + + `Give your evidence,' said the King; `and don't be nervous, or +I'll have you executed on the spot.' + + This did not seem to encourage the witness at all: he kept +shifting from one foot to the other, looking uneasily at the +Queen, and in his confusion he bit a large piece out of his +teacup instead of the bread-and-butter. + + Just at this moment Alice felt a very curious sensation, which +puzzled her a good deal until she made out what it was: she was +beginning to grow larger again, and she thought at first she +would get up and leave the court; but on second thoughts she +decided to remain where she was as long as there was room for +her. + + `I wish you wouldn't squeeze so.' said the Dormouse, who was +sitting next to her. `I can hardly breathe.' + + `I can't help it,' said Alice very meekly: `I'm growing.' + + `You've no right to grow here,' said the Dormouse. + + `Don't talk nonsense,' said Alice more boldly: `you know +you're growing too.' + + `Yes, but I grow at a reasonable pace,' said the Dormouse: +`not in that ridiculous fashion.' And he got up very sulkily +and crossed over to the other side of the court. + + All this time the Queen had never left off staring at the +Hatter, and, just as the Dormouse crossed the court, she said to +one of the officers of the court, `Bring me the list of the +singers in the last concert!' on which the wretched Hatter +trembled so, that he shook both his shoes off. + + `Give your evidence,' the King repeated angrily, `or I'll have +you executed, whether you're nervous or not.' + + `I'm a poor man, your Majesty,' the Hatter began, in a +trembling voice, `--and I hadn't begun my tea--not above a week +or so--and what with the bread-and-butter getting so thin--and +the twinkling of the tea--' + + `The twinkling of the what?' said the King. + + `It began with the tea,' the Hatter replied. + + `Of course twinkling begins with a T!' said the King sharply. +`Do you take me for a dunce? Go on!' + + `I'm a poor man,' the Hatter went on, `and most things +twinkled after that--only the March Hare said--' + + `I didn't!' the March Hare interrupted in a great hurry. + + `You did!' said the Hatter. + + `I deny it!' said the March Hare. + + `He denies it,' said the King: `leave out that part.' + + `Well, at any rate, the Dormouse said--' the Hatter went on, +looking anxiously round to see if he would deny it too: but the +Dormouse denied nothing, being fast asleep. + + `After that,' continued the Hatter, `I cut some more bread- +and-butter--' + + `But what did the Dormouse say?' one of the jury asked. + + `That I can't remember,' said the Hatter. + + `You MUST remember,' remarked the King, `or I'll have you +executed.' + + The miserable Hatter dropped his teacup and bread-and-butter, +and went down on one knee. `I'm a poor man, your Majesty,' he +began. + + `You're a very poor speaker,' said the King. + + Here one of the guinea-pigs cheered, and was immediately +suppressed by the officers of the court. (As that is rather a +hard word, I will just explain to you how it was done. They had +a large canvas bag, which tied up at the mouth with strings: +into this they slipped the guinea-pig, head first, and then sat +upon it.) + + `I'm glad I've seen that done,' thought Alice. `I've so often +read in the newspapers, at the end of trials, "There was some +attempts at applause, which was immediately suppressed by the +officers of the court," and I never understood what it meant +till now.' + + `If that's all you know about it, you may stand down,' +continued the King. + + `I can't go no lower,' said the Hatter: `I'm on the floor, as +it is.' + + `Then you may SIT down,' the King replied. + + Here the other guinea-pig cheered, and was suppressed. + + `Come, that finished the guinea-pigs!' thought Alice. `Now we +shall get on better.' + + `I'd rather finish my tea,' said the Hatter, with an anxious +look at the Queen, who was reading the list of singers. + + `You may go,' said the King, and the Hatter hurriedly left the +court, without even waiting to put his shoes on. + + `--and just take his head off outside,' the Queen added to one +of the officers: but the Hatter was out of sight before the +officer could get to the door. + + `Call the next witness!' said the King. + + The next witness was the Duchess's cook. She carried the +pepper-box in her hand, and Alice guessed who it was, even before +she got into the court, by the way the people near the door began +sneezing all at once. + + `Give your evidence,' said the King. + + `Shan't,' said the cook. + + The King looked anxiously at the White Rabbit, who said in a +low voice, `Your Majesty must cross-examine THIS witness.' + + `Well, if I must, I must,' the King said, with a melancholy +air, and, after folding his arms and frowning at the cook till +his eyes were nearly out of sight, he said in a deep voice, `What +are tarts made of?' + + `Pepper, mostly,' said the cook. + + `Treacle,' said a sleepy voice behind her. + + `Collar that Dormouse,' the Queen shrieked out. `Behead that +Dormouse! Turn that Dormouse out of court! Suppress him! Pinch +him! Off with his whiskers!' + + For some minutes the whole court was in confusion, getting the +Dormouse turned out, and, by the time they had settled down +again, the cook had disappeared. + + `Never mind!' said the King, with an air of great relief. +`Call the next witness.' And he added in an undertone to the +Queen, `Really, my dear, YOU must cross-examine the next witness. +It quite makes my forehead ache!' + + Alice watched the White Rabbit as he fumbled over the list, +feeling very curious to see what the next witness would be like, +`--for they haven't got much evidence YET,' she said to herself. +Imagine her surprise, when the White Rabbit read out, at the top +of his shrill little voice, the name `Alice!' + + + + CHAPTER XII + + Alice's Evidence + + + `Here!' cried Alice, quite forgetting in the flurry of the +moment how large she had grown in the last few minutes, and she +jumped up in such a hurry that she tipped over the jury-box with +the edge of her skirt, upsetting all the jurymen on to the heads +of the crowd below, and there they lay sprawling about, reminding +her very much of a globe of goldfish she had accidentally upset +the week before. + + `Oh, I BEG your pardon!' she exclaimed in a tone of great +dismay, and began picking them up again as quickly as she could, +for the accident of the goldfish kept running in her head, and +she had a vague sort of idea that they must be collected at once +and put back into the jury-box, or they would die. + + `The trial cannot proceed,' said the King in a very grave +voice, `until all the jurymen are back in their proper places-- +ALL,' he repeated with great emphasis, looking hard at Alice as +he said do. + + Alice looked at the jury-box, and saw that, in her haste, she +had put the Lizard in head downwards, and the poor little thing +was waving its tail about in a melancholy way, being quite unable +to move. She soon got it out again, and put it right; `not that +it signifies much,' she said to herself; `I should think it +would be QUITE as much use in the trial one way up as the other.' + + As soon as the jury had a little recovered from the shock of +being upset, and their slates and pencils had been found and +handed back to them, they set to work very diligently to write +out a history of the accident, all except the Lizard, who seemed +too much overcome to do anything but sit with its mouth open, +gazing up into the roof of the court. + + `What do you know about this business?' the King said to +Alice. + + `Nothing,' said Alice. + + `Nothing WHATEVER?' persisted the King. + + `Nothing whatever,' said Alice. + + `That's very important,' the King said, turning to the jury. +They were just beginning to write this down on their slates, when +the White Rabbit interrupted: `UNimportant, your Majesty means, +of course,' he said in a very respectful tone, but frowning and +making faces at him as he spoke. + + `UNimportant, of course, I meant,' the King hastily said, and +went on to himself in an undertone, `important--unimportant-- +unimportant--important--' as if he were trying which word +sounded best. + + Some of the jury wrote it down `important,' and some +`unimportant.' Alice could see this, as she was near enough to +look over their slates; `but it doesn't matter a bit,' she +thought to herself. + + At this moment the King, who had been for some time busily +writing in his note-book, cackled out `Silence!' and read out +from his book, `Rule Forty-two. ALL PERSONS MORE THAN A MILE +HIGH TO LEAVE THE COURT.' + + Everybody looked at Alice. + + `I'M not a mile high,' said Alice. + + `You are,' said the King. + + `Nearly two miles high,' added the Queen. + + `Well, I shan't go, at any rate,' said Alice: `besides, +that's not a regular rule: you invented it just now.' + + `It's the oldest rule in the book,' said the King. + + `Then it ought to be Number One,' said Alice. + + The King turned pale, and shut his note-book hastily. +`Consider your verdict,' he said to the jury, in a low, trembling +voice. + + `There's more evidence to come yet, please your Majesty,' said +the White Rabbit, jumping up in a great hurry; `this paper has +just been picked up.' + + `What's in it?' said the Queen. + + `I haven't opened it yet,' said the White Rabbit, `but it seems +to be a letter, written by the prisoner to--to somebody.' + + `It must have been that,' said the King, `unless it was +written to nobody, which isn't usual, you know.' + + `Who is it directed to?' said one of the jurymen. + + `It isn't directed at all,' said the White Rabbit; `in fact, +there's nothing written on the OUTSIDE.' He unfolded the paper +as he spoke, and added `It isn't a letter, after all: it's a set +of verses.' + + `Are they in the prisoner's handwriting?' asked another of +they jurymen. + + `No, they're not,' said the White Rabbit, `and that's the +queerest thing about it.' (The jury all looked puzzled.) + + `He must have imitated somebody else's hand,' said the King. +(The jury all brightened up again.) + + `Please your Majesty,' said the Knave, `I didn't write it, and +they can't prove I did: there's no name signed at the end.' + + `If you didn't sign it,' said the King, `that only makes the +matter worse. You MUST have meant some mischief, or else you'd +have signed your name like an honest man.' + + There was a general clapping of hands at this: it was the +first really clever thing the King had said that day. + + `That PROVES his guilt,' said the Queen. + + `It proves nothing of the sort!' said Alice. `Why, you don't +even know what they're about!' + + `Read them,' said the King. + + The White Rabbit put on his spectacles. `Where shall I begin, +please your Majesty?' he asked. + + `Begin at the beginning,' the King said gravely, `and go on +till you come to the end: then stop.' + + These were the verses the White Rabbit read:-- + + `They told me you had been to her, + And mentioned me to him: + She gave me a good character, + But said I could not swim. + + He sent them word I had not gone + (We know it to be true): + If she should push the matter on, + What would become of you? + + I gave her one, they gave him two, + You gave us three or more; + They all returned from him to you, + Though they were mine before. + + If I or she should chance to be + Involved in this affair, + He trusts to you to set them free, + Exactly as we were. + + My notion was that you had been + (Before she had this fit) + An obstacle that came between + Him, and ourselves, and it. + + Don't let him know she liked them best, + For this must ever be + A secret, kept from all the rest, + Between yourself and me.' + + `That's the most important piece of evidence we've heard yet,' +said the King, rubbing his hands; `so now let the jury--' + + `If any one of them can explain it,' said Alice, (she had +grown so large in the last few minutes that she wasn't a bit +afraid of interrupting him,) `I'll give him sixpence. _I_ don't +believe there's an atom of meaning in it.' + + The jury all wrote down on their slates, `SHE doesn't believe +there's an atom of meaning in it,' but none of them attempted to +explain the paper. + + `If there's no meaning in it,' said the King, `that saves a +world of trouble, you know, as we needn't try to find any. And +yet I don't know,' he went on, spreading out the verses on his +knee, and looking at them with one eye; `I seem to see some +meaning in them, after all. "--SAID I COULD NOT SWIM--" you +can't swim, can you?' he added, turning to the Knave. + + The Knave shook his head sadly. `Do I look like it?' he said. +(Which he certainly did NOT, being made entirely of cardboard.) + + `All right, so far,' said the King, and he went on muttering +over the verses to himself: `"WE KNOW IT TO BE TRUE--" that's +the jury, of course-- "I GAVE HER ONE, THEY GAVE HIM TWO--" why, +that must be what he did with the tarts, you know--' + + `But, it goes on "THEY ALL RETURNED FROM HIM TO YOU,"' said +Alice. + + `Why, there they are!' said the King triumphantly, pointing to +the tarts on the table. `Nothing can be clearer than THAT. +Then again--"BEFORE SHE HAD THIS FIT--" you never had fits, my +dear, I think?' he said to the Queen. + + `Never!' said the Queen furiously, throwing an inkstand at the +Lizard as she spoke. (The unfortunate little Bill had left off +writing on his slate with one finger, as he found it made no +mark; but he now hastily began again, using the ink, that was +trickling down his face, as long as it lasted.) + + `Then the words don't FIT you,' said the King, looking round +the court with a smile. There was a dead silence. + + `It's a pun!' the King added in an offended tone, and +everybody laughed, `Let the jury consider their verdict,' the +King said, for about the twentieth time that day. + + `No, no!' said the Queen. `Sentence first--verdict afterwards.' + + `Stuff and nonsense!' said Alice loudly. `The idea of having +the sentence first!' + + `Hold your tongue!' said the Queen, turning purple. + + `I won't!' said Alice. + + `Off with her head!' the Queen shouted at the top of her voice. +Nobody moved. + + `Who cares for you?' said Alice, (she had grown to her full +size by this time.) `You're nothing but a pack of cards!' + + At this the whole pack rose up into the air, and came flying +down upon her: she gave a little scream, half of fright and half +of anger, and tried to beat them off, and found herself lying on +the bank, with her head in the lap of her sister, who was gently +brushing away some dead leaves that had fluttered down from the +trees upon her face. + + `Wake up, Alice dear!' said her sister; `Why, what a long +sleep you've had!' + + `Oh, I've had such a curious dream!' said Alice, and she told +her sister, as well as she could remember them, all these strange +Adventures of hers that you have just been reading about; and +when she had finished, her sister kissed her, and said, `It WAS a +curious dream, dear, certainly: but now run in to your tea; it's +getting late.' So Alice got up and ran off, thinking while she +ran, as well she might, what a wonderful dream it had been. + + But her sister sat still just as she left her, leaning her +head on her hand, watching the setting sun, and thinking of +little Alice and all her wonderful Adventures, till she too began +dreaming after a fashion, and this was her dream:-- + + First, she dreamed of little Alice herself, and once again the +tiny hands were clasped upon her knee, and the bright eager eyes +were looking up into hers--she could hear the very tones of her +voice, and see that queer little toss of her head to keep back +the wandering hair that WOULD always get into her eyes--and +still as she listened, or seemed to listen, the whole place +around her became alive the strange creatures of her little +sister's dream. + + The long grass rustled at her feet as the White Rabbit hurried +by--the frightened Mouse splashed his way through the +neighbouring pool--she could hear the rattle of the teacups as +the March Hare and his friends shared their never-ending meal, +and the shrill voice of the Queen ordering off her unfortunate +guests to execution--once more the pig-baby was sneezing on the +Duchess's knee, while plates and dishes crashed around it--once +more the shriek of the Gryphon, the squeaking of the Lizard's +slate-pencil, and the choking of the suppressed guinea-pigs, +filled the air, mixed up with the distant sobs of the miserable +Mock Turtle. + + So she sat on, with closed eyes, and half believed herself in +Wonderland, though she knew she had but to open them again, and +all would change to dull reality--the grass would be only +rustling in the wind, and the pool rippling to the waving of the +reeds--the rattling teacups would change to tinkling sheep- +bells, and the Queen's shrill cries to the voice of the shepherd +boy--and the sneeze of the baby, the shriek of the Gryphon, and +all thy other queer noises, would change (she knew) to the +confused clamour of the busy farm-yard--while the lowing of the +cattle in the distance would take the place of the Mock Turtle's +heavy sobs. + + Lastly, she pictured to herself how this same little sister of +hers would, in the after-time, be herself a grown woman; and how +she would keep, through all her riper years, the simple and +loving heart of her childhood: and how she would gather about +her other little children, and make THEIR eyes bright and eager +with many a strange tale, perhaps even with the dream of +Wonderland of long ago: and how she would feel with all their +simple sorrows, and find a pleasure in all their simple joys, +remembering her own child-life, and the happy summer days. + + THE END + \ No newline at end of file diff --git a/wasm3-sys/wasm3/test/wasi/brotli/alice29.txt.compressed b/wasm3-sys/wasm3/test/wasi/brotli/alice29.txt.compressed new file mode 100644 index 0000000..253d6ff Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/brotli/alice29.txt.compressed differ diff --git a/wasm3-sys/wasm3/test/wasi/brotli/alice29_small.txt b/wasm3-sys/wasm3/test/wasi/brotli/alice29_small.txt new file mode 100644 index 0000000..06bea8f --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/brotli/alice29_small.txt @@ -0,0 +1,245 @@ + + + + + ALICE'S ADVENTURES IN WONDERLAND + + Lewis Carroll + + THE MILLENNIUM FULCRUM EDITION 2.9 + + + + + CHAPTER I + + Down the Rabbit-Hole + + + Alice was beginning to get very tired of sitting by her sister +on the bank, and of having nothing to do: once or twice she had +peeped into the book her sister was reading, but it had no +pictures or conversations in it, `and what is the use of a book,' +thought Alice `without pictures or conversation?' + + So she was considering in her own mind (as well as she could, +for the hot day made her feel very sleepy and stupid), whether +the pleasure of making a daisy-chain would be worth the trouble +of getting up and picking the daisies, when suddenly a White +Rabbit with pink eyes ran close by her. + + There was nothing so VERY remarkable in that; nor did Alice +think it so VERY much out of the way to hear the Rabbit say to +itself, `Oh dear! Oh dear! I shall be late!' (when she thought +it over afterwards, it occurred to her that she ought to have +wondered at this, but at the time it all seemed quite natural); +but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT- +POCKET, and looked at it, and then hurried on, Alice started to +her feet, for it flashed across her mind that she had never +before seen a rabbit with either a waistcoat-pocket, or a watch to +take out of it, and burning with curiosity, she ran across the +field after it, and fortunately was just in time to see it pop +down a large rabbit-hole under the hedge. + + In another moment down went Alice after it, never once +considering how in the world she was to get out again. + + The rabbit-hole went straight on like a tunnel for some way, +and then dipped suddenly down, so suddenly that Alice had not a +moment to think about stopping herself before she found herself +falling down a very deep well. + + Either the well was very deep, or she fell very slowly, for she +had plenty of time as she went down to look about her and to +wonder what was going to happen next. First, she tried to look +down and make out what she was coming to, but it was too dark to +see anything; then she looked at the sides of the well, and +noticed that they were filled with cupboards and book-shelves; +here and there she saw maps and pictures hung upon pegs. She +took down a jar from one of the shelves as she passed; it was +labelled `ORANGE MARMALADE', but to her great disappointment it +was empty: she did not like to drop the jar for fear of killing +somebody, so managed to put it into one of the cupboards as she +fell past it. + + `Well!' thought Alice to herself, `after such a fall as this, I +shall think nothing of tumbling down stairs! How brave they'll +all think me at home! Why, I wouldn't say anything about it, +even if I fell off the top of the house!' (Which was very likely +true.) + + Down, down, down. Would the fall NEVER come to an end! `I +wonder how many miles I've fallen by this time?' she said aloud. +`I must be getting somewhere near the centre of the earth. Let +me see: that would be four thousand miles down, I think--' (for, +you see, Alice had learnt several things of this sort in her +lessons in the schoolroom, and though this was not a VERY good +opportunity for showing off her knowledge, as there was no one to +listen to her, still it was good practice to say it over) `--yes, +that's about the right distance--but then I wonder what Latitude +or Longitude I've got to?' (Alice had no idea what Latitude was, +or Longitude either, but thought they were nice grand words to +say.) + + Presently she began again. `I wonder if I shall fall right +THROUGH the earth! How funny it'll seem to come out among the +people that walk with their heads downward! The Antipathies, I +think--' (she was rather glad there WAS no one listening, this +time, as it didn't sound at all the right word) `--but I shall +have to ask them what the name of the country is, you know. +Please, Ma'am, is this New Zealand or Australia?' (and she tried +to curtsey as she spoke--fancy CURTSEYING as you're falling +through the air! Do you think you could manage it?) `And what +an ignorant little girl she'll think me for asking! No, it'll +never do to ask: perhaps I shall see it written up somewhere.' + + Down, down, down. There was nothing else to do, so Alice soon +began talking again. `Dinah'll miss me very much to-night, I +should think!' (Dinah was the cat.) `I hope they'll remember +her saucer of milk at tea-time. Dinah my dear! I wish you were +down here with me! There are no mice in the air, I'm afraid, but +you might catch a bat, and that's very like a mouse, you know. +But do cats eat bats, I wonder?' And here Alice began to get +rather sleepy, and went on saying to herself, in a dreamy sort of +way, `Do cats eat bats? Do cats eat bats?' and sometimes, `Do +bats eat cats?' for, you see, as she couldn't answer either +question, it didn't much matter which way she put it. She felt +that she was dozing off, and had just begun to dream that she +was walking hand in hand with Dinah, and saying to her very +earnestly, `Now, Dinah, tell me the truth: did you ever eat a +bat?' when suddenly, thump! thump! down she came upon a heap of +sticks and dry leaves, and the fall was over. + + Alice was not a bit hurt, and she jumped up on to her feet in a +moment: she looked up, but it was all dark overhead; before her +was another long passage, and the White Rabbit was still in +sight, hurrying down it. There was not a moment to be lost: +away went Alice like the wind, and was just in time to hear it +say, as it turned a corner, `Oh my ears and whiskers, how late +it's getting!' She was close behind it when she turned the +corner, but the Rabbit was no longer to be seen: she found +herself in a long, low hall, which was lit up by a row of lamps +hanging from the roof. + + There were doors all round the hall, but they were all locked; +and when Alice had been all the way down one side and up the +other, trying every door, she walked sadly down the middle, +wondering how she was ever to get out again. + + Suddenly she came upon a little three-legged table, all made of +solid glass; there was nothing on it except a tiny golden key, +and Alice's first thought was that it might belong to one of the +doors of the hall; but, alas! either the locks were too large, or +the key was too small, but at any rate it would not open any of +them. However, on the second time round, she came upon a low +curtain she had not noticed before, and behind it was a little +door about fifteen inches high: she tried the little golden key +in the lock, and to her great delight it fitted! + + Alice opened the door and found that it led into a small +passage, not much larger than a rat-hole: she knelt down and +looked along the passage into the loveliest garden you ever saw. +How she longed to get out of that dark hall, and wander about +among those beds of bright flowers and those cool fountains, but +she could not even get her head though the doorway; `and even if +my head would go through,' thought poor Alice, `it would be of +very little use without my shoulders. Oh, how I wish +I could shut up like a telescope! I think I could, if I only +know how to begin.' For, you see, so many out-of-the-way things +had happened lately, that Alice had begun to think that very few +things indeed were really impossible. + + There seemed to be no use in waiting by the little door, so she +went back to the table, half hoping she might find another key on +it, or at any rate a book of rules for shutting people up like +telescopes: this time she found a little bottle on it, (`which +certainly was not here before,' said Alice,) and round the neck +of the bottle was a paper label, with the words `DRINK ME' +beautifully printed on it in large letters. + + It was all very well to say `Drink me,' but the wise little +Alice was not going to do THAT in a hurry. `No, I'll look +first,' she said, `and see whether it's marked "poison" or not'; +for she had read several nice little histories about children who +had got burnt, and eaten up by wild beasts and other unpleasant +things, all because they WOULD not remember the simple rules +their friends had taught them: such as, that a red-hot poker +will burn you if you hold it too long; and that if you cut your +finger VERY deeply with a knife, it usually bleeds; and she had +never forgotten that, if you drink much from a bottle marked +`poison,' it is almost certain to disagree with you, sooner or +later. + + However, this bottle was NOT marked `poison,' so Alice ventured +to taste it, and finding it very nice, (it had, in fact, a sort +of mixed flavour of cherry-tart, custard, pine-apple, roast +turkey, toffee, and hot buttered toast,) she very soon finished +it off. + + * * * * * * * + + * * * * * * + + * * * * * * * + + `What a curious feeling!' said Alice; `I must be shutting up +like a telescope.' + + And so it was indeed: she was now only ten inches high, and +her face brightened up at the thought that she was now the right +size for going though the little door into that lovely garden. +First, however, she waited for a few minutes to see if she was +going to shrink any further: she felt a little nervous about +this; `for it might end, you know,' said Alice to herself, `in my +going out altogether, like a candle. I wonder what I should be +like then?' And she tried to fancy what the flame of a candle is +like after the candle is blown out, for she could not remember +ever having seen such a thing. + + After a while, finding that nothing more happened, she decided +on going into the garden at once; but, alas for poor Alice! when +she got to the door, she found he had forgotten the little golden +key, and when she went back to the table for it, she found she +could not possibly reach it: she could see it quite plainly +through the glass, and she tried her best to climb up one of the +legs of the table, but it was too slippery; and when she had +tired herself out with trying, the poor little thing sat down and +cried. + + `Come, there's no use in crying like that!' said Alice to +herself, rather sharply; `I advise you to leave off this minute!' +She generally gave herself very good advice, (though she very +seldom followed it), and sometimes she scolded herself so +severely as to bring tears into her eyes; and once she remembered +trying to box her own ears for having cheated herself in a game +of croquet she was playing against herself, for this curious +child was very fond of pretending to be two people. `But it's no +use now,' thought poor Alice, `to pretend to be two people! Why, +there's hardly enough of me left to make ONE respectable +person!' + + Soon her eye fell on a little glass box that was lying under +the table: she opened it, and found in it a very small cake, on +which the words `EAT ME' were beautifully marked in currants. +`Well, I'll eat it,' said Alice, `and if it makes me grow larger, +I can reach the key; and if it makes me grow smaller, I can creep +under the door; so either way I'll get into the garden, and I +don't care which happens!' + + She ate a little bit, and said anxiously to herself, `Which +way? Which way?', holding her hand on the top of her head to +feel which way it was growing, and she was quite surprised to +find that she remained the same size: to be sure, this generally +happens when one eats cake, but Alice had got so much into the +way of expecting nothing but out-of-the-way things to happen, +that it seemed quite dull and stupid for life to go on in the +common way. + + So she set to work, and very soon finished off the cake. + + * * * * * * * + + * * * * * * + + * * * * * * * + diff --git a/wasm3-sys/wasm3/test/wasi/brotli/brotli.wasm b/wasm3-sys/wasm3/test/wasi/brotli/brotli.wasm new file mode 100644 index 0000000..093c02e Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/brotli/brotli.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/c-ray/README.md b/wasm3-sys/wasm3/test/wasi/c-ray/README.md new file mode 100644 index 0000000..1a0dfbc --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/c-ray/README.md @@ -0,0 +1,54 @@ +# C-Ray 1.1 + +

+ +### Results + +```log + time(ms) +Node v13.0.1 (interpreter) 181527 +wasm-micro-runtime 78499 +wac (wax) - +wasm3 - +Wasmer 0.11.0 singlepass 1447 +wasmtime 0.7.0 (--optimize) 576 +Wasmer 0.11.0 cranelift 565 +wasmer-js (Node v13.0.1) 336 +Wasmer 0.11.0 llvm crash +WAVM 299 +Native (GCC 7.4.0, 32-bit) 249 +``` + +### Building + +```sh +wasicc -g0 -O3 c-ray-f.c -Dunix -o c-ray.wasm +``` + +### Running + +```sh +export ENGINES_PATH=/opt/wasm_engines + +# Wasm3 +cat scene | ../../../build/wasm3 c-ray.wasm -s 1024x768 > foo.ppm + +# wasm-micro-runtime +cat scene | $ENGINES_PATH/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm c-ray.wasm -s 1024x768 > foo.ppm + +# wasmtime +cat scene | wasmtime --optimize c-ray.wasm -- -s 1024x768 > foo.ppm + +# Wasmer +cat scene | wasmer run c-ray.wasm -- -s 1024x768 > foo.ppm +cat scene | wasmer run --backend singlepass c-ray.wasm -- -s 1024x768 > foo.ppm +cat scene | wasmer run --backend llvm c-ray.wasm -- -s 1024x768 > foo.ppm + +# Wasmer-JS (V8) +cat scene | wasmer-js run c-ray.wasm -s 1024x768 > foo.ppm + +cat scene | node --wasm_interpret_all $(which wasmer-js) run c-ray.wasm -s 1024x768 > foo.ppm + +# WAVM +cat scene | $ENGINES_PATH/WAVM/Release/bin/wavm run c-ray.wasm -s 1024x768 > foo.ppm +``` diff --git a/wasm3-sys/wasm3/test/wasi/c-ray/c-ray-f.c b/wasm3-sys/wasm3/test/wasi/c-ray/c-ray-f.c new file mode 100644 index 0000000..9613245 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/c-ray/c-ray-f.c @@ -0,0 +1,583 @@ +/* c-ray-f - a simple raytracing filter. + * Copyright (C) 2006 John Tsiombikas + * + * You are free to use, modify and redistribute this program under the + * terms of the GNU General Public License v2 or (at your option) later. + * see "http://www.gnu.org/licenses/gpl.txt" for details. + * --------------------------------------------------------------------- + * Usage: + * compile: cc -o c-ray-f c-ray-f.c -lm + * run: cat scene | ./c-ray-f >foo.ppm + * enjoy: display foo.ppm (with imagemagick) + * or: imgview foo.ppm (on IRIX) + * --------------------------------------------------------------------- + * Scene file format: + * # sphere (many) + * s x y z rad r g b shininess reflectivity + * # light (many) + * l x y z + * # camera (one) + * c x y z fov tx ty tz + * --------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include + +/* find the appropriate way to define explicitly sized types */ +#if (__STDC_VERSION__ >= 199900) || defined(__GLIBC__) /* C99 or GNU libc */ +#include +#elif defined(__unix__) || defined(unix) +#include +#elif defined(_MSC_VER) /* the nameless one */ +typedef unsigned __int8 uint8_t; +typedef unsigned __int32 uint32_t; +#endif + +struct vec3 { + double x, y, z; +}; + +struct ray { + struct vec3 orig, dir; +}; + +struct material { + struct vec3 col; /* color */ + double spow; /* specular power */ + double refl; /* reflection intensity */ +}; + +struct sphere { + struct vec3 pos; + double rad; + struct material mat; + struct sphere *next; +}; + +struct spoint { + struct vec3 pos, normal, vref; /* position, normal and view reflection */ + double dist; /* parametric distance of intersection along the ray */ +}; + +struct camera { + struct vec3 pos, targ; + double fov; +}; + +void render(int xsz, int ysz, uint32_t *fb, int samples); +struct vec3 trace(struct ray ray, int depth); +struct vec3 shade(struct sphere *obj, struct spoint *sp, int depth); +struct vec3 reflect(struct vec3 v, struct vec3 n); +struct vec3 cross_product(struct vec3 v1, struct vec3 v2); +struct ray get_primary_ray(int x, int y, int sample); +struct vec3 get_sample_pos(int x, int y, int sample); +struct vec3 jitter(int x, int y, int s); +int ray_sphere(const struct sphere *sph, struct ray ray, struct spoint *sp); +void load_scene(FILE *fp); +unsigned long get_msec(void); + +#define MAX_LIGHTS 16 /* maximum number of lights */ +#define RAY_MAG 1000.0 /* trace rays of this magnitude */ +#define MAX_RAY_DEPTH 5 /* raytrace recursion limit */ +#define FOV 0.78539816 /* field of view in rads (pi/4) */ +#define HALF_FOV (FOV * 0.5) +#define ERR_MARGIN 1e-6 /* an arbitrary error margin to avoid surface acne */ + +/* bit-shift amount for packing each color into a 32bit uint */ +#ifdef LITTLE_ENDIAN +#define RSHIFT 16 +#define BSHIFT 0 +#else /* big endian */ +#define RSHIFT 0 +#define BSHIFT 16 +#endif /* endianness */ +#define GSHIFT 8 /* this is the same in both byte orders */ + +/* some helpful macros... */ +#define SQ(x) ((x) * (x)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define DOT(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z) +#define NORMALIZE(a) do {\ + double len = sqrt(DOT(a, a));\ + (a).x /= len; (a).y /= len; (a).z /= len;\ +} while(0); + +/* global state */ +int xres = 800; +int yres = 600; +double aspect = 1.333333; +struct sphere *obj_list; +struct vec3 lights[MAX_LIGHTS]; +int lnum = 0; +struct camera cam; + +#define NRAN 1024 +#define MASK (NRAN - 1) +struct vec3 urand[NRAN]; +int irand[NRAN]; + +const char *usage = { + "Usage: c-ray-f [options]\n" + " Reads a scene file from stdin, writes the image to stdout, and stats to stderr.\n\n" + "Options:\n" + " -s WxH where W is the width and H the height of the image\n" + " -r shoot rays per pixel (antialiasing)\n" + " -i read from instead of stdin\n" + " -o write to instead of stdout\n" + " -h this help screen\n\n" +}; + + + +int main(int argc, char **argv) { + int i; + unsigned long rend_time, start_time; + uint32_t *pixels; + int rays_per_pixel = 1; + FILE *infile = stdin, *outfile = stdout; + + for(i=1; i> RSHIFT) & 0xff, outfile); + fputc((pixels[i] >> GSHIFT) & 0xff, outfile); + fputc((pixels[i] >> BSHIFT) & 0xff, outfile); + } + fflush(outfile); + + if(infile != stdin) fclose(infile); + if(outfile != stdout) fclose(outfile); + return 0; +} + +/* render a frame of xsz/ysz dimensions into the provided framebuffer */ +void render(int xsz, int ysz, uint32_t *fb, int samples) { + int i, j, s; + double rcp_samples = 1.0 / (double)samples; + + /* for each subpixel, trace a ray through the scene, accumulate the + * colors of the subpixels of each pixel, then pack the color and + * put it into the framebuffer. + * XXX: assumes contiguous scanlines with NO padding, and 32bit pixels. + */ + for(j=0; jnext; + + /* if we reached the recursion limit, bail out */ + if(depth >= MAX_RAY_DEPTH) { + col.x = col.y = col.z = 0.0; + return col; + } + + /* find the nearest intersection ... */ + while(iter) { + if(ray_sphere(iter, ray, &sp)) { + if(!nearest_obj || sp.dist < nearest_sp.dist) { + nearest_obj = iter; + nearest_sp = sp; + } + } + iter = iter->next; + } + + /* and perform shading calculations as needed by calling shade() */ + if(nearest_obj) { + col = shade(nearest_obj, &nearest_sp, depth); + } else { + col.x = col.y = col.z = 0.0; + } + + return col; +} + +/* Calculates direct illumination with the phong reflectance model. + * Also handles reflections by calling trace again, if necessary. + */ +struct vec3 shade(struct sphere *obj, struct spoint *sp, int depth) { + int i; + struct vec3 col = {0, 0, 0}; + + /* for all lights ... */ + for(i=0; inext; + int in_shadow = 0; + + ldir.x = lights[i].x - sp->pos.x; + ldir.y = lights[i].y - sp->pos.y; + ldir.z = lights[i].z - sp->pos.z; + + shadow_ray.orig = sp->pos; + shadow_ray.dir = ldir; + + /* shoot shadow rays to determine if we have a line of sight with the light */ + while(iter) { + if(ray_sphere(iter, shadow_ray, 0)) { + in_shadow = 1; + break; + } + iter = iter->next; + } + + /* and if we're not in shadow, calculate direct illumination with the phong model. */ + if(!in_shadow) { + NORMALIZE(ldir); + + idiff = MAX(DOT(sp->normal, ldir), 0.0); + ispec = obj->mat.spow > 0.0 ? pow(MAX(DOT(sp->vref, ldir), 0.0), obj->mat.spow) : 0.0; + + col.x += idiff * obj->mat.col.x + ispec; + col.y += idiff * obj->mat.col.y + ispec; + col.z += idiff * obj->mat.col.z + ispec; + } + } + + /* Also, if the object is reflective, spawn a reflection ray, and call trace() + * to calculate the light arriving from the mirror direction. + */ + if(obj->mat.refl > 0.0) { + struct ray ray; + struct vec3 rcol; + + ray.orig = sp->pos; + ray.dir = sp->vref; + ray.dir.x *= RAY_MAG; + ray.dir.y *= RAY_MAG; + ray.dir.z *= RAY_MAG; + + rcol = trace(ray, depth + 1); + col.x += rcol.x * obj->mat.refl; + col.y += rcol.y * obj->mat.refl; + col.z += rcol.z * obj->mat.refl; + } + + return col; +} + +/* calculate reflection vector */ +struct vec3 reflect(struct vec3 v, struct vec3 n) { + struct vec3 res; + double dot = v.x * n.x + v.y * n.y + v.z * n.z; + res.x = -(2.0 * dot * n.x - v.x); + res.y = -(2.0 * dot * n.y - v.y); + res.z = -(2.0 * dot * n.z - v.z); + return res; +} + +struct vec3 cross_product(struct vec3 v1, struct vec3 v2) { + struct vec3 res; + res.x = v1.y * v2.z - v1.z * v2.y; + res.y = v1.z * v2.x - v1.x * v2.z; + res.z = v1.x * v2.y - v1.y * v2.x; + return res; +} + +/* determine the primary ray corresponding to the specified pixel (x, y) */ +struct ray get_primary_ray(int x, int y, int sample) { + struct ray ray; + float m[3][3]; + struct vec3 i, j = {0, 1, 0}, k, dir, orig, foo; + + k.x = cam.targ.x - cam.pos.x; + k.y = cam.targ.y - cam.pos.y; + k.z = cam.targ.z - cam.pos.z; + NORMALIZE(k); + + i = cross_product(j, k); + j = cross_product(k, i); + m[0][0] = i.x; m[0][1] = j.x; m[0][2] = k.x; + m[1][0] = i.y; m[1][1] = j.y; m[1][2] = k.y; + m[2][0] = i.z; m[2][1] = j.z; m[2][2] = k.z; + + ray.orig.x = ray.orig.y = ray.orig.z = 0.0; + ray.dir = get_sample_pos(x, y, sample); + ray.dir.z = 1.0 / HALF_FOV; + ray.dir.x *= RAY_MAG; + ray.dir.y *= RAY_MAG; + ray.dir.z *= RAY_MAG; + + dir.x = ray.dir.x + ray.orig.x; + dir.y = ray.dir.y + ray.orig.y; + dir.z = ray.dir.z + ray.orig.z; + foo.x = dir.x * m[0][0] + dir.y * m[0][1] + dir.z * m[0][2]; + foo.y = dir.x * m[1][0] + dir.y * m[1][1] + dir.z * m[1][2]; + foo.z = dir.x * m[2][0] + dir.y * m[2][1] + dir.z * m[2][2]; + + orig.x = ray.orig.x * m[0][0] + ray.orig.y * m[0][1] + ray.orig.z * m[0][2] + cam.pos.x; + orig.y = ray.orig.x * m[1][0] + ray.orig.y * m[1][1] + ray.orig.z * m[1][2] + cam.pos.y; + orig.z = ray.orig.x * m[2][0] + ray.orig.y * m[2][1] + ray.orig.z * m[2][2] + cam.pos.z; + + ray.orig = orig; + ray.dir.x = foo.x + orig.x; + ray.dir.y = foo.y + orig.y; + ray.dir.z = foo.z + orig.z; + + return ray; +} + + +struct vec3 get_sample_pos(int x, int y, int sample) { + struct vec3 pt; + double xsz = 2.0, ysz = xres / aspect; + static double sf = 0.0; + + if(sf == 0.0) { + sf = 2.0 / (double)xres; + } + + pt.x = ((double)x / (double)xres) - 0.5; + pt.y = -(((double)y / (double)yres) - 0.65) / aspect; + + if(sample) { + struct vec3 jt = jitter(x, y, sample); + pt.x += jt.x * sf; + pt.y += jt.y * sf / aspect; + } + return pt; +} + +/* jitter function taken from Graphics Gems I. */ +struct vec3 jitter(int x, int y, int s) { + struct vec3 pt; + pt.x = urand[(x + (y << 2) + irand[(x + s) & MASK]) & MASK].x; + pt.y = urand[(y + (x << 2) + irand[(y + s) & MASK]) & MASK].y; + return pt; +} + +/* Calculate ray-sphere intersection, and return {1, 0} to signify hit or no hit. + * Also the surface point parameters like position, normal, etc are returned through + * the sp pointer if it is not NULL. + */ +int ray_sphere(const struct sphere *sph, struct ray ray, struct spoint *sp) { + double a, b, c, d, sqrt_d, t1, t2; + + a = SQ(ray.dir.x) + SQ(ray.dir.y) + SQ(ray.dir.z); + b = 2.0 * ray.dir.x * (ray.orig.x - sph->pos.x) + + 2.0 * ray.dir.y * (ray.orig.y - sph->pos.y) + + 2.0 * ray.dir.z * (ray.orig.z - sph->pos.z); + c = SQ(sph->pos.x) + SQ(sph->pos.y) + SQ(sph->pos.z) + + SQ(ray.orig.x) + SQ(ray.orig.y) + SQ(ray.orig.z) + + 2.0 * (-sph->pos.x * ray.orig.x - sph->pos.y * ray.orig.y - sph->pos.z * ray.orig.z) - SQ(sph->rad); + + if((d = SQ(b) - 4.0 * a * c) < 0.0) return 0; + + sqrt_d = sqrt(d); + t1 = (-b + sqrt_d) / (2.0 * a); + t2 = (-b - sqrt_d) / (2.0 * a); + + if((t1 < ERR_MARGIN && t2 < ERR_MARGIN) || (t1 > 1.0 && t2 > 1.0)) return 0; + + if(sp) { + if(t1 < ERR_MARGIN) t1 = t2; + if(t2 < ERR_MARGIN) t2 = t1; + sp->dist = t1 < t2 ? t1 : t2; + + sp->pos.x = ray.orig.x + ray.dir.x * sp->dist; + sp->pos.y = ray.orig.y + ray.dir.y * sp->dist; + sp->pos.z = ray.orig.z + ray.dir.z * sp->dist; + + sp->normal.x = (sp->pos.x - sph->pos.x) / sph->rad; + sp->normal.y = (sp->pos.y - sph->pos.y) / sph->rad; + sp->normal.z = (sp->pos.z - sph->pos.z) / sph->rad; + + sp->vref = reflect(ray.dir, sp->normal); + NORMALIZE(sp->vref); + } + return 1; +} + +/* Load the scene from an extremely simple scene description file */ +#define DELIM " \t\n" +void load_scene(FILE *fp) { + char line[256], *ptr, type; + + obj_list = malloc(sizeof(struct sphere)); + obj_list->next = 0; + + while((ptr = fgets(line, 256, fp))) { + int i; + struct vec3 pos, col; + double rad, spow, refl; + + while(*ptr == ' ' || *ptr == '\t') ptr++; + if(*ptr == '#' || *ptr == '\n') continue; + + if(!(ptr = strtok(line, DELIM))) continue; + type = *ptr; + + for(i=0; i<3; i++) { + if(!(ptr = strtok(0, DELIM))) break; + *((double*)&pos.x + i) = atof(ptr); + } + + if(type == 'l') { + lights[lnum++] = pos; + continue; + } + + if(!(ptr = strtok(0, DELIM))) continue; + rad = atof(ptr); + + for(i=0; i<3; i++) { + if(!(ptr = strtok(0, DELIM))) break; + *((double*)&col.x + i) = atof(ptr); + } + + if(type == 'c') { + cam.pos = pos; + cam.targ = col; + cam.fov = rad; + continue; + } + + if(!(ptr = strtok(0, DELIM))) continue; + spow = atof(ptr); + + if(!(ptr = strtok(0, DELIM))) continue; + refl = atof(ptr); + + if(type == 's') { + struct sphere *sph = malloc(sizeof *sph); + sph->next = obj_list->next; + obj_list->next = sph; + + sph->pos = pos; + sph->rad = rad; + sph->mat.col = col; + sph->mat.spow = spow; + sph->mat.refl = refl; + } else { + fprintf(stderr, "unknown type: %c\n", type); + } + } +} + + +/* provide a millisecond-resolution timer for each system */ +#if defined(__unix__) || defined(unix) +#include +#include +unsigned long get_msec(void) { + static struct timeval timeval, first_timeval; + + gettimeofday(&timeval, 0); + if(first_timeval.tv_sec == 0) { + first_timeval = timeval; + return 0; + } + return (timeval.tv_sec - first_timeval.tv_sec) * 1000 + (timeval.tv_usec - first_timeval.tv_usec) / 1000; +} +#elif defined(__WIN32__) || defined(WIN32) +#include +unsigned long get_msec(void) { + return GetTickCount(); +} +#else +#error "I don't know how to measure time on your platform" +#endif diff --git a/wasm3-sys/wasm3/test/wasi/c-ray/c-ray.wasm b/wasm3-sys/wasm3/test/wasi/c-ray/c-ray.wasm new file mode 100755 index 0000000..b2d62ba Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/c-ray/c-ray.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/c-ray/scene b/wasm3-sys/wasm3/test/wasi/c-ray/scene new file mode 100644 index 0000000..082ef11 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/c-ray/scene @@ -0,0 +1,18 @@ +# spheres +# position radius color shininess reflectivity +s -1.5 -0.3 -1 0.7 1.0 0.2 0.05 50.0 0.3 +s 1.5 -0.4 0 0.6 0.1 0.85 1.0 50.0 0.4 + +# walls +s 0 -1000 2 999 0.1 0.2 0.6 80.0 0.8 + +# bouncing ball +s 0 0 2 1 1.0 0.5 0.1 60.0 0.7 + +# lights... +l -50 100 -50 +l 40 40 150 + +# camera (there can be only one!) +# position FOV target +c 0 6 -17 45 0 -1 0 diff --git a/wasm3-sys/wasm3/test/wasi/c-ray/scene.jpg b/wasm3-sys/wasm3/test/wasi/c-ray/scene.jpg new file mode 100644 index 0000000..1b93960 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/c-ray/scene.jpg differ diff --git a/wasm3-sys/wasm3/test/wasi/c-ray/sphfract b/wasm3-sys/wasm3/test/wasi/c-ray/sphfract new file mode 100644 index 0000000..72da260 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/c-ray/sphfract @@ -0,0 +1,192 @@ +s 0 0 0 1.0 0.25 0.25 0.25 50.0 0.65 +s 1.4 0 0 0.4 0.25 0.25 0.25 50.0 0.65 +s 1.96 0 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 2.184 0 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.96 0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.96 -0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.96 0 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.96 0 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 1.624 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.176 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 1.624 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.176 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0 0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 1.624 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.176 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0 0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 1.624 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.176 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0 0 0.4 0.25 0.25 0.25 50.0 0.65 +s -1.96 0 0 0.16 0.25 0.25 0.25 50.0 0.65 +s -2.184 0 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.96 0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.96 -0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.96 0 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.96 0 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 +s -1.176 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.624 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 +s -1.176 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.624 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0 0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s -1.176 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.624 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0 0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s -1.176 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.624 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.4 0 0.4 0.25 0.25 0.25 50.0 0.65 +s 0.56 1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.784 1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 +s -0.784 1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.96 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 2.184 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.96 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.96 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.4 0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.624 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.176 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.4 0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.4 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.624 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.176 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.4 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.4 0 0.4 0.25 0.25 0.25 50.0 0.65 +s 0.56 -1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.784 -1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 +s -0.784 -1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.96 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 -1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 -1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -2.184 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.96 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.96 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.4 0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 -1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 -1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.176 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.624 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.4 0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.4 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 -1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 -1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.176 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.624 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.4 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 1.4 0.4 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.784 0 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s -0.784 0 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.784 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 -0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 -0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.784 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 1.96 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 0 1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 0 1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.224 1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.224 1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 2.184 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 -1.4 0.4 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.784 0 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s -0.784 0 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.784 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 -0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 -0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.784 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 -1.96 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 0 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 0 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.224 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.224 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 -2.184 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -10002.25 0 10000 0.2 0.35 0.5 80.0 0.4 +s 0 10100.00 0 10000 0.5 0.2 0.1 40.0 0.0 +l -50 68 -50 +l 40 40 150 +c -7 6 -12 45 0 -0.65 0 diff --git a/wasm3-sys/wasm3/test/wasi/c-ray/sphfract.jpg b/wasm3-sys/wasm3/test/wasi/c-ray/sphfract.jpg new file mode 100644 index 0000000..859f327 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/c-ray/sphfract.jpg differ diff --git a/wasm3-sys/wasm3/test/wasi/coremark/README.md b/wasm3-sys/wasm3/test/wasi/coremark/README.md new file mode 100644 index 0000000..40cafde --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/coremark/README.md @@ -0,0 +1,3 @@ +# CoreMark 1.0 + +See https://github.com/wasm3/wasm3-coremark diff --git a/wasm3-sys/wasm3/test/wasi/coremark/coremark-minimal.wasm b/wasm3-sys/wasm3/test/wasi/coremark/coremark-minimal.wasm new file mode 100755 index 0000000..c5d6b87 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/coremark/coremark-minimal.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/coremark/coremark.wasm b/wasm3-sys/wasm3/test/wasi/coremark/coremark.wasm new file mode 100755 index 0000000..b661d74 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/coremark/coremark.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/mal/.gitattributes b/wasm3-sys/wasm3/test/wasi/mal/.gitattributes new file mode 100644 index 0000000..f1a8064 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/mal/.gitattributes @@ -0,0 +1 @@ +*.mal binary diff --git a/wasm3-sys/wasm3/test/wasi/mal/README.md b/wasm3-sys/wasm3/test/wasi/mal/README.md new file mode 100644 index 0000000..6fe5a49 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/mal/README.md @@ -0,0 +1,21 @@ +# mal (Make a Lisp) + +[mal](https://github.com/kanaka/mal) is a Lisp interpreter. + +### Running + +```sh +# REPL: +../../../build/wasm3 mal.wasm + +# Self-hosted REPL: +../../../build/wasm3 mal.wasm ./mal.mal + +# Fibonacci test: +../../../build/wasm3 mal.wasm ./test-fib.mal 16 +987 + +# Self-hosted Fibonacci test (takes ~10 seconds): +../../../build/wasm3 mal.wasm ./mal.mal ./test-fib.mal 10 +55 +``` diff --git a/wasm3-sys/wasm3/test/wasi/mal/core.mal b/wasm3-sys/wasm3/test/wasi/mal/core.mal new file mode 100644 index 0000000..11af471 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/mal/core.mal @@ -0,0 +1,72 @@ +(def! _macro? (fn* [x] + (if (map? x) + (contains? x :__MAL_MACRO__) + false))) + +(def! core_ns + [['= =] + ['throw throw] + ['nil? nil?] + ['true? true?] + ['false? false?] + ['number? number?] + ['string? string?] + ['symbol symbol] + ['symbol? symbol?] + ['keyword keyword] + ['keyword? keyword?] + ['fn? fn?] + ['macro? _macro?] + + ['pr-str pr-str] + ['str str] + ['prn prn] + ['println println] + ['readline readline] + ['read-string read-string] + ['slurp slurp] + ['< <] + ['<= <=] + ['> >] + ['>= >=] + ['+ +] + ['- -] + ['* *] + ['/ /] + ['time-ms time-ms] + + ['list list] + ['list? list?] + ['vector vector] + ['vector? vector?] + ['hash-map hash-map] + ['map? map?] + ['assoc assoc] + ['dissoc dissoc] + ['get get] + ['contains? contains?] + ['keys keys] + ['vals vals] + + ['sequential? sequential?] + ['cons cons] + ['concat concat] + ['vec vec] + ['nth nth] + ['first first] + ['rest rest] + ['empty? empty?] + ['count count] + ['apply apply] + ['map map] + + ['conj conj] + ['seq seq] + + ['with-meta with-meta] + ['meta meta] + ['atom atom] + ['atom? atom?] + ['deref deref] + ['reset! reset!] + ['swap! swap!]]) diff --git a/wasm3-sys/wasm3/test/wasi/mal/env.mal b/wasm3-sys/wasm3/test/wasi/mal/env.mal new file mode 100644 index 0000000..590110e --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/mal/env.mal @@ -0,0 +1,34 @@ +(def! bind-env (fn* [env b e] + (if (empty? b) + env + (let* [b0 (first b)] + (if (= '& b0) + (assoc env (str (nth b 1)) e) + (bind-env (assoc env (str b0) (first e)) (rest b) (rest e))))))) + +(def! new-env (fn* [& args] + (if (<= (count args) 1) + (atom {:outer (first args)}) + (atom (apply bind-env {:outer (first args)} (rest args)))))) + +(def! env-find (fn* [env k] + (env-find-str env (str k)))) + +(def! env-find-str (fn* [env ks] + (if env + (let* [data @env] + (if (contains? data ks) + env + (env-find-str (get data :outer) ks)))))) + +(def! env-get (fn* [env k] + (let* [ks (str k) + e (env-find-str env ks)] + (if e + (get @e ks) + (throw (str "'" ks "' not found")))))) + +(def! env-set (fn* [env k v] + (do + (swap! env assoc (str k) v) + v))) diff --git a/wasm3-sys/wasm3/test/wasi/mal/mal.mal b/wasm3-sys/wasm3/test/wasi/mal/mal.mal new file mode 100644 index 0000000..82dc147 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/mal/mal.mal @@ -0,0 +1,152 @@ +(load-file "./env.mal") +(load-file "./core.mal") + +;; read +(def! READ read-string) + + +;; eval + +(def! qq-loop (fn* [elt acc] + (if (if (list? elt) (= (first elt) 'splice-unquote)) ; 2nd 'if' means 'and' + (list 'concat (nth elt 1) acc) + (list 'cons (QUASIQUOTE elt) acc)))) +(def! qq-foldr (fn* [xs] + (if (empty? xs) + (list) + (qq-loop (first xs) (qq-foldr (rest xs)))))) +(def! QUASIQUOTE (fn* [ast] + (cond + (vector? ast) (list 'vec (qq-foldr ast)) + (map? ast) (list 'quote ast) + (symbol? ast) (list 'quote ast) + (not (list? ast)) ast + (= (first ast) 'unquote) (nth ast 1) + "else" (qq-foldr ast)))) + +(def! MACROEXPAND (fn* [ast env] + (let* [a0 (if (list? ast) (first ast)) + e (if (symbol? a0) (env-find env a0)) + m (if e (env-get e a0))] + (if (_macro? m) + (MACROEXPAND (apply (get m :__MAL_MACRO__) (rest ast)) env) + ast)))) + +(def! eval-ast (fn* [ast env] + ;; (do (prn "eval-ast" ast "/" (keys env)) ) + (cond + (symbol? ast) (env-get env ast) + + (list? ast) (map (fn* [exp] (EVAL exp env)) ast) + + (vector? ast) (vec (map (fn* [exp] (EVAL exp env)) ast)) + + (map? ast) (apply hash-map + (apply concat + (map (fn* [k] [k (EVAL (get ast k) env)]) + (keys ast)))) + + "else" ast))) + +(def! LET (fn* [env binds form] + (if (empty? binds) + (EVAL form env) + (do + (env-set env (first binds) (EVAL (nth binds 1) env)) + (LET env (rest (rest binds)) form))))) + +(def! EVAL (fn* [ast env] + ;; (do (prn "EVAL" ast "/" (keys @env)) ) + (let* [ast (MACROEXPAND ast env)] + (if (not (list? ast)) + (eval-ast ast env) + + ;; apply list + (let* [a0 (first ast)] + (cond + (empty? ast) + ast + + (= 'def! a0) + (env-set env (nth ast 1) (EVAL (nth ast 2) env)) + + (= 'let* a0) + (LET (new-env env) (nth ast 1) (nth ast 2)) + + (= 'quote a0) + (nth ast 1) + + (= 'quasiquoteexpand a0) + (QUASIQUOTE (nth ast 1)) + + (= 'quasiquote a0) + (EVAL (QUASIQUOTE (nth ast 1)) env) + + (= 'defmacro! a0) + (env-set env (nth ast 1) (hash-map :__MAL_MACRO__ + (EVAL (nth ast 2) env))) + + (= 'macroexpand a0) + (MACROEXPAND (nth ast 1) env) + + (= 'try* a0) + (if (< (count ast) 3) + (EVAL (nth ast 1) env) + (try* + (EVAL (nth ast 1) env) + (catch* exc + (let* [a2 (nth ast 2)] + (EVAL (nth a2 2) (new-env env [(nth a2 1)] [exc])))))) + + (= 'do a0) + (let* [el (eval-ast (rest ast) env)] + (nth el (- (count el) 1))) + + (= 'if a0) + (if (EVAL (nth ast 1) env) + (EVAL (nth ast 2) env) + (if (> (count ast) 3) + (EVAL (nth ast 3) env))) + + (= 'fn* a0) + (fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args))) + + "else" + (let* [el (eval-ast ast env)] + (apply (first el) (rest el))))))))) + + +;; print +(def! PRINT pr-str) + +;; repl +(def! repl-env (new-env)) +(def! rep (fn* [strng] + (PRINT (EVAL (READ strng) repl-env)))) + +;; core.mal: defined directly using mal +(map (fn* [data] (apply env-set repl-env data)) core_ns) +(env-set repl-env 'eval (fn* [ast] (EVAL ast repl-env))) +(env-set repl-env '*ARGV* (rest *ARGV*)) + +;; core.mal: defined using the new language itself +(rep (str "(def! *host-language* \"" *host-language* "-mal\")")) +(rep "(def! not (fn* [a] (if a false true)))") +(rep "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))") +(rep "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))") + +;; repl loop +(def! repl-loop (fn* [line] + (if line + (do + (if (not (= "" line)) + (try* + (println (rep line)) + (catch* exc + (println "Uncaught exception:" exc)))) + (repl-loop (readline "mal-user> ")))))) + +;; main +(if (empty? *ARGV*) + (repl-loop "(println (str \"Mal [\" *host-language* \"]\"))") + (rep (str "(load-file \"" (first *ARGV*) "\")"))) diff --git a/wasm3-sys/wasm3/test/wasi/mal/mal.wasm b/wasm3-sys/wasm3/test/wasi/mal/mal.wasm new file mode 100644 index 0000000..a0ea44f Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/mal/mal.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/mal/test-fib.mal b/wasm3-sys/wasm3/test/wasi/mal/test-fib.mal new file mode 100644 index 0000000..d348652 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/mal/test-fib.mal @@ -0,0 +1,8 @@ +;; Compute a Fibonacci number with two recursions. +(def! fib + (fn* [n] ; non-negative number + (if (<= n 1) + n + (+ (fib (- n 1)) (fib (- n 2)))))) + +(println (fib (read-string (first *ARGV*)))) diff --git a/wasm3-sys/wasm3/test/wasi/mandelbrot/README.md b/wasm3-sys/wasm3/test/wasi/mandelbrot/README.md new file mode 100644 index 0000000..b236e18 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/mandelbrot/README.md @@ -0,0 +1,49 @@ +# mandelbrot + +Based on https://github.com/josch/mandelbrot + +

+ +### Results + +```log +TODO +``` + +### Building + +```sh +wasicc -g0 -O3 mandel_dd.c -o mandel_dd.wasm +wasicc -g0 -O3 mandel.c -o mandel.wasm +``` + +### Running + +```sh +export ENGINES_PATH=/opt/wasm_engines + +# Wasm3 +../../../build/wasm3 mandel_dd.wasm > image.ppm + +# WAC +$ENGINES_PATH/wac/wax mandel_dd.wasm > image.ppm + +# wasm-micro-runtime +$ENGINES_PATH/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm mandel_dd.wasm > image.ppm + +# wasmtime +wasmtime --optimize mandel_dd.wasm > image.ppm + +# Wasmer +wasmer run mandel_dd.wasm > image.ppm +wasmer run --backend singlepass mandel_dd.wasm > image.ppm +wasmer run --backend llvm mandel_dd.wasm > image.ppm + +# Wasmer-JS (V8) +wasmer-js run mandel_dd.wasm > image.ppm + +node --wasm_interpret_all $(which wasmer-js) run mandel_dd.wasm > image.ppm + +# WAVM +$ENGINES_PATH/WAVM/Release/bin/wavm run mandel_dd.wasm > image.ppm +``` diff --git a/wasm3-sys/wasm3/test/wasi/mandelbrot/colors.h b/wasm3-sys/wasm3/test/wasi/mandelbrot/colors.h new file mode 100644 index 0000000..cd44393 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/mandelbrot/colors.h @@ -0,0 +1,836 @@ +#define GRADIENTLENGTH 4990 + +const unsigned char colors[GRADIENTLENGTH][3] = { + {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, + {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x53}, {0x0e, 0x0b, 0x53}, + {0x0e, 0x0b, 0x53}, {0x0e, 0x0b, 0x53}, {0x0e, 0x0b, 0x53}, {0x0e, 0x0b, 0x53}, {0x0e, 0x0b, 0x53}, {0x0e, 0x0c, 0x53}, + {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, + {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x54}, + {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, + {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, + {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, + {0x0e, 0x0c, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, + {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, + {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, + {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, + {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, + {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0e, 0x56}, {0x0e, 0x0e, 0x56}, {0x0e, 0x0e, 0x56}, + {0x0e, 0x0e, 0x56}, {0x0e, 0x0e, 0x56}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, + {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, + {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, + {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, + {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0f, 0x58}, + {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, + {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, + {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, + {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, + {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x5a}, + {0x0e, 0x0f, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, + {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, + {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, + {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, + {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, + {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x11, 0x5b}, {0x0e, 0x11, 0x5b}, + {0x0e, 0x11, 0x5b}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, + {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, + {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, + {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, + {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, + {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, + {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, + {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, + {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, + {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5f}, {0x0e, 0x12, 0x5f}, + {0x0e, 0x12, 0x5f}, {0x0e, 0x12, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, + {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, + {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x60}, + {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, + {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, + {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x14, 0x60}, {0x0e, 0x14, 0x60}, + {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, + {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, + {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, + {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, + {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, + {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, + {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, + {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, + {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, + {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x64}, {0x0e, 0x15, 0x64}, {0x0e, 0x15, 0x64}, + {0x0e, 0x15, 0x64}, {0x0e, 0x15, 0x64}, {0x0e, 0x15, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, + {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, + {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, + {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, + {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, + {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x17, 0x66}, + {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, + {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, + {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, + {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, + {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, + {0x0e, 0x17, 0x67}, {0x0e, 0x18, 0x67}, {0x0e, 0x18, 0x67}, {0x0e, 0x18, 0x67}, {0x0e, 0x18, 0x67}, {0x0e, 0x18, 0x67}, + {0x0e, 0x18, 0x67}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, + {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, + {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, + {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x69}, {0x0e, 0x18, 0x69}, {0x0e, 0x18, 0x69}, {0x0e, 0x18, 0x69}, + {0x0e, 0x18, 0x69}, {0x0e, 0x18, 0x69}, {0x0e, 0x18, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, + {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, + {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, + {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, + {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, + {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6b}, {0x0e, 0x1a, 0x6b}, + {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, + {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, + {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6c}, + {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, + {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, + {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1b, 0x6c}, {0x0e, 0x1b, 0x6c}, {0x0e, 0x1b, 0x6c}, {0x0e, 0x1b, 0x6c}, + {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, + {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, + {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, + {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, + {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, + {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, + {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, + {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, + {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, + {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x70}, {0x0e, 0x1c, 0x70}, {0x0e, 0x1c, 0x70}, + {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, + {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, + {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, + {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, + {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, + {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1e, 0x71}, {0x0e, 0x1e, 0x71}, {0x0e, 0x1e, 0x71}, {0x0e, 0x1e, 0x72}, + {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, + {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, + {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, + {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, + {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, + {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, + {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, + {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, + {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, + {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x75}, {0x0e, 0x1f, 0x75}, {0x0e, 0x1f, 0x75}, {0x0e, 0x1f, 0x75}, + {0x0e, 0x1f, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, + {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, + {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, + {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, + {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, + {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x21, 0x76}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, + {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, + {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, + {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x78}, + {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, + {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x22, 0x78}, + {0x0e, 0x22, 0x78}, {0x0e, 0x22, 0x78}, {0x0e, 0x22, 0x78}, {0x0e, 0x22, 0x78}, {0x0e, 0x22, 0x78}, {0x0e, 0x22, 0x78}, + {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, + {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, + {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, + {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x7a}, {0x0e, 0x22, 0x7a}, {0x0e, 0x22, 0x7a}, {0x0e, 0x22, 0x7a}, {0x0e, 0x22, 0x7a}, + {0x0e, 0x22, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, + {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, + {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, + {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, + {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, + {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, + {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, + {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, + {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, + {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, + {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, + {0x0e, 0x25, 0x7d}, {0x0e, 0x25, 0x7d}, {0x0e, 0x25, 0x7d}, {0x0e, 0x25, 0x7d}, {0x0e, 0x25, 0x7d}, {0x0e, 0x25, 0x7e}, + {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, + {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, + {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, + {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, + {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, + {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, + {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, + {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, + {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, + {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x81}, {0x0e, 0x26, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, + {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, + {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, + {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, + {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, + {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, + {0x0e, 0x28, 0x82}, {0x0e, 0x28, 0x82}, {0x0e, 0x28, 0x82}, {0x0e, 0x28, 0x82}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, + {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, + {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, + {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x84}, + {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, + {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, + {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, + {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, + {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, + {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, + {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x86}, {0x0e, 0x29, 0x86}, {0x0e, 0x29, 0x86}, {0x0e, 0x29, 0x86}, {0x0e, 0x2a, 0x86}, + {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, + {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, + {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, + {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, + {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, + {0x0e, 0x2a, 0x87}, {0x0e, 0x2b, 0x87}, {0x0e, 0x2b, 0x87}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, + {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, + {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, + {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, + {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, + {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, + {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x8a}, + {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, + {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, + {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, + {0x0e, 0x2c, 0x8b}, {0x0e, 0x2c, 0x8b}, {0x0e, 0x2c, 0x8b}, {0x0e, 0x2c, 0x8b}, {0x0e, 0x2c, 0x8b}, {0x0e, 0x2d, 0x8b}, + {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, + {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, + {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, + {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, + {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, + {0x0e, 0x2d, 0x8c}, {0x0e, 0x2e, 0x8c}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, + {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, + {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, + {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, + {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, + {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8e}, + {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, + {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, + {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, + {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x90}, + {0x0e, 0x2f, 0x90}, {0x0e, 0x2f, 0x90}, {0x0e, 0x2f, 0x90}, {0x0e, 0x2f, 0x90}, {0x0e, 0x2f, 0x90}, {0x0e, 0x2f, 0x90}, + {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, + {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, + {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, + {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, + {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, + {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, + {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, + {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, + {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, + {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, + {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x32, 0x93}, {0x0e, 0x32, 0x93}, + {0x0e, 0x32, 0x93}, {0x0e, 0x32, 0x93}, {0x0e, 0x32, 0x93}, {0x0e, 0x32, 0x93}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, + {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, + {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, + {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x95}, + {0x0e, 0x32, 0x95}, {0x0e, 0x32, 0x95}, {0x0e, 0x32, 0x95}, {0x0e, 0x32, 0x95}, {0x0e, 0x32, 0x95}, {0x0e, 0x32, 0x95}, + {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, + {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, + {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, + {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, + {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, + {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, + {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, + {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, + {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, + {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, + {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x35, 0x98}, + {0x0e, 0x35, 0x98}, {0x0e, 0x35, 0x98}, {0x0e, 0x35, 0x98}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, + {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, + {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, + {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, + {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, + {0x0e, 0x35, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, + {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9b}, + {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, + {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, + {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, + {0x0e, 0x36, 0x9c}, {0x0e, 0x36, 0x9c}, {0x0e, 0x36, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, + {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, + {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, + {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, + {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, + {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x38, 0x9d}, + {0x0e, 0x38, 0x9d}, {0x0e, 0x38, 0x9d}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, + {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, + {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, + {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, + {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, + {0x0e, 0x38, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, + {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, + {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, + {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, + {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa1}, + {0x0e, 0x39, 0xa1}, {0x0e, 0x39, 0xa1}, {0x0e, 0x39, 0xa1}, {0x0e, 0x39, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, + {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, + {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, + {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, + {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, + {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, + {0x0e, 0x3b, 0xa2}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, + {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, + {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, + {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, + {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, + {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa4}, + {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, + {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, + {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3d, 0xa5}, {0x0f, 0x3d, 0xa5}, + {0x0f, 0x3d, 0xa6}, {0x0f, 0x3d, 0xa6}, {0x0f, 0x3d, 0xa6}, {0x0f, 0x3d, 0xa6}, {0x0f, 0x3d, 0xa6}, {0x0f, 0x3e, 0xa6}, + {0x0f, 0x3e, 0xa6}, {0x0f, 0x3e, 0xa6}, {0x0f, 0x3e, 0xa6}, {0x10, 0x3e, 0xa6}, {0x10, 0x3e, 0xa6}, {0x10, 0x3e, 0xa6}, + {0x10, 0x3f, 0xa7}, {0x10, 0x3f, 0xa7}, {0x10, 0x3f, 0xa7}, {0x10, 0x3f, 0xa7}, {0x10, 0x3f, 0xa7}, {0x10, 0x3f, 0xa7}, + {0x10, 0x40, 0xa7}, {0x10, 0x40, 0xa7}, {0x11, 0x40, 0xa7}, {0x11, 0x40, 0xa7}, {0x11, 0x40, 0xa7}, {0x11, 0x40, 0xa7}, + {0x11, 0x40, 0xa8}, {0x11, 0x41, 0xa8}, {0x11, 0x41, 0xa8}, {0x11, 0x41, 0xa8}, {0x11, 0x41, 0xa8}, {0x11, 0x41, 0xa8}, + {0x12, 0x41, 0xa8}, {0x12, 0x41, 0xa8}, {0x12, 0x42, 0xa8}, {0x12, 0x42, 0xa8}, {0x12, 0x42, 0xa8}, {0x12, 0x42, 0xa8}, + {0x12, 0x42, 0xa9}, {0x12, 0x42, 0xa9}, {0x12, 0x42, 0xa9}, {0x12, 0x43, 0xa9}, {0x13, 0x43, 0xa9}, {0x13, 0x43, 0xa9}, + {0x13, 0x43, 0xa9}, {0x13, 0x43, 0xa9}, {0x13, 0x43, 0xa9}, {0x13, 0x43, 0xa9}, {0x13, 0x44, 0xa9}, {0x13, 0x44, 0xa9}, + {0x13, 0x44, 0xaa}, {0x13, 0x44, 0xaa}, {0x14, 0x44, 0xaa}, {0x14, 0x44, 0xaa}, {0x14, 0x44, 0xaa}, {0x14, 0x45, 0xaa}, + {0x14, 0x45, 0xaa}, {0x14, 0x45, 0xaa}, {0x14, 0x45, 0xaa}, {0x14, 0x45, 0xaa}, {0x14, 0x45, 0xaa}, {0x14, 0x45, 0xaa}, + {0x14, 0x46, 0xab}, {0x15, 0x46, 0xab}, {0x15, 0x46, 0xab}, {0x15, 0x46, 0xab}, {0x15, 0x46, 0xab}, {0x15, 0x46, 0xab}, + {0x15, 0x46, 0xab}, {0x15, 0x47, 0xab}, {0x15, 0x47, 0xab}, {0x15, 0x47, 0xab}, {0x15, 0x47, 0xab}, {0x16, 0x47, 0xac}, + {0x16, 0x47, 0xac}, {0x16, 0x47, 0xac}, {0x16, 0x48, 0xac}, {0x16, 0x48, 0xac}, {0x16, 0x48, 0xac}, {0x16, 0x48, 0xac}, + {0x16, 0x48, 0xac}, {0x16, 0x48, 0xac}, {0x16, 0x48, 0xac}, {0x17, 0x49, 0xac}, {0x17, 0x49, 0xac}, {0x17, 0x49, 0xad}, + {0x17, 0x49, 0xad}, {0x17, 0x49, 0xad}, {0x17, 0x49, 0xad}, {0x17, 0x49, 0xad}, {0x17, 0x4a, 0xad}, {0x17, 0x4a, 0xad}, + {0x17, 0x4a, 0xad}, {0x18, 0x4a, 0xad}, {0x18, 0x4a, 0xad}, {0x18, 0x4a, 0xad}, {0x18, 0x4a, 0xad}, {0x18, 0x4b, 0xae}, + {0x18, 0x4b, 0xae}, {0x18, 0x4b, 0xae}, {0x18, 0x4b, 0xae}, {0x18, 0x4b, 0xae}, {0x18, 0x4b, 0xae}, {0x19, 0x4b, 0xae}, + {0x19, 0x4c, 0xae}, {0x19, 0x4c, 0xae}, {0x19, 0x4c, 0xae}, {0x19, 0x4c, 0xae}, {0x19, 0x4c, 0xae}, {0x19, 0x4c, 0xaf}, + {0x19, 0x4c, 0xaf}, {0x19, 0x4d, 0xaf}, {0x19, 0x4d, 0xaf}, {0x19, 0x4d, 0xaf}, {0x1a, 0x4d, 0xaf}, {0x1a, 0x4d, 0xaf}, + {0x1a, 0x4d, 0xaf}, {0x1a, 0x4d, 0xaf}, {0x1a, 0x4e, 0xaf}, {0x1a, 0x4e, 0xaf}, {0x1a, 0x4e, 0xaf}, {0x1a, 0x4e, 0xb0}, + {0x1a, 0x4e, 0xb0}, {0x1a, 0x4e, 0xb0}, {0x1b, 0x4e, 0xb0}, {0x1b, 0x4f, 0xb0}, {0x1b, 0x4f, 0xb0}, {0x1b, 0x4f, 0xb0}, + {0x1b, 0x4f, 0xb0}, {0x1b, 0x4f, 0xb0}, {0x1b, 0x4f, 0xb0}, {0x1b, 0x4f, 0xb0}, {0x1b, 0x50, 0xb0}, {0x1b, 0x50, 0xb1}, + {0x1c, 0x50, 0xb1}, {0x1c, 0x50, 0xb1}, {0x1c, 0x50, 0xb1}, {0x1c, 0x50, 0xb1}, {0x1c, 0x50, 0xb1}, {0x1c, 0x51, 0xb1}, + {0x1c, 0x51, 0xb1}, {0x1c, 0x51, 0xb1}, {0x1c, 0x51, 0xb1}, {0x1c, 0x51, 0xb1}, {0x1d, 0x51, 0xb1}, {0x1d, 0x51, 0xb2}, + {0x1d, 0x52, 0xb2}, {0x1d, 0x52, 0xb2}, {0x1d, 0x52, 0xb2}, {0x1d, 0x52, 0xb2}, {0x1d, 0x52, 0xb2}, {0x1d, 0x52, 0xb2}, + {0x1d, 0x52, 0xb2}, {0x1d, 0x53, 0xb2}, {0x1e, 0x53, 0xb2}, {0x1e, 0x53, 0xb2}, {0x1e, 0x53, 0xb2}, {0x1e, 0x53, 0xb3}, + {0x1e, 0x53, 0xb3}, {0x1e, 0x53, 0xb3}, {0x1e, 0x54, 0xb3}, {0x1e, 0x54, 0xb3}, {0x1e, 0x54, 0xb3}, {0x1e, 0x54, 0xb3}, + {0x1e, 0x54, 0xb3}, {0x1f, 0x54, 0xb3}, {0x1f, 0x55, 0xb3}, {0x1f, 0x55, 0xb3}, {0x1f, 0x55, 0xb4}, {0x1f, 0x55, 0xb4}, + {0x1f, 0x55, 0xb4}, {0x1f, 0x55, 0xb4}, {0x1f, 0x55, 0xb4}, {0x1f, 0x56, 0xb4}, {0x1f, 0x56, 0xb4}, {0x20, 0x56, 0xb4}, + {0x20, 0x56, 0xb4}, {0x20, 0x56, 0xb4}, {0x20, 0x56, 0xb4}, {0x20, 0x56, 0xb4}, {0x20, 0x57, 0xb5}, {0x20, 0x57, 0xb5}, + {0x20, 0x57, 0xb5}, {0x20, 0x57, 0xb5}, {0x20, 0x57, 0xb5}, {0x21, 0x57, 0xb5}, {0x21, 0x57, 0xb5}, {0x21, 0x58, 0xb5}, + {0x21, 0x58, 0xb5}, {0x21, 0x58, 0xb5}, {0x21, 0x58, 0xb5}, {0x21, 0x58, 0xb5}, {0x21, 0x58, 0xb6}, {0x21, 0x58, 0xb6}, + {0x21, 0x59, 0xb6}, {0x22, 0x59, 0xb6}, {0x22, 0x59, 0xb6}, {0x22, 0x59, 0xb6}, {0x22, 0x59, 0xb6}, {0x22, 0x59, 0xb6}, + {0x22, 0x59, 0xb6}, {0x22, 0x5a, 0xb6}, {0x22, 0x5a, 0xb6}, {0x22, 0x5a, 0xb6}, {0x22, 0x5a, 0xb7}, {0x23, 0x5a, 0xb7}, + {0x23, 0x5a, 0xb7}, {0x23, 0x5a, 0xb7}, {0x23, 0x5b, 0xb7}, {0x23, 0x5b, 0xb7}, {0x23, 0x5b, 0xb7}, {0x23, 0x5b, 0xb7}, + {0x23, 0x5b, 0xb7}, {0x23, 0x5b, 0xb7}, {0x23, 0x5b, 0xb7}, {0x23, 0x5c, 0xb7}, {0x24, 0x5c, 0xb8}, {0x24, 0x5c, 0xb8}, + {0x24, 0x5c, 0xb8}, {0x24, 0x5c, 0xb8}, {0x24, 0x5c, 0xb8}, {0x24, 0x5c, 0xb8}, {0x24, 0x5d, 0xb8}, {0x24, 0x5d, 0xb8}, + {0x24, 0x5d, 0xb8}, {0x24, 0x5d, 0xb8}, {0x25, 0x5d, 0xb8}, {0x25, 0x5d, 0xb8}, {0x25, 0x5d, 0xb9}, {0x25, 0x5e, 0xb9}, + {0x25, 0x5e, 0xb9}, {0x25, 0x5e, 0xb9}, {0x25, 0x5e, 0xb9}, {0x25, 0x5e, 0xb9}, {0x25, 0x5e, 0xb9}, {0x25, 0x5e, 0xb9}, + {0x26, 0x5f, 0xb9}, {0x26, 0x5f, 0xb9}, {0x26, 0x5f, 0xb9}, {0x26, 0x5f, 0xb9}, {0x26, 0x5f, 0xba}, {0x26, 0x5f, 0xba}, + {0x26, 0x5f, 0xba}, {0x26, 0x60, 0xba}, {0x26, 0x60, 0xba}, {0x26, 0x60, 0xba}, {0x27, 0x60, 0xba}, {0x27, 0x60, 0xba}, + {0x27, 0x60, 0xba}, {0x27, 0x60, 0xba}, {0x27, 0x61, 0xba}, {0x27, 0x61, 0xba}, {0x27, 0x61, 0xbb}, {0x27, 0x61, 0xbb}, + {0x27, 0x61, 0xbb}, {0x27, 0x61, 0xbb}, {0x27, 0x61, 0xbb}, {0x28, 0x62, 0xbb}, {0x28, 0x62, 0xbb}, {0x28, 0x62, 0xbb}, + {0x28, 0x62, 0xbb}, {0x28, 0x62, 0xbb}, {0x28, 0x62, 0xbb}, {0x28, 0x62, 0xbc}, {0x28, 0x63, 0xbc}, {0x28, 0x63, 0xbc}, + {0x28, 0x63, 0xbc}, {0x29, 0x63, 0xbc}, {0x29, 0x63, 0xbc}, {0x29, 0x63, 0xbc}, {0x29, 0x63, 0xbc}, {0x29, 0x64, 0xbc}, + {0x29, 0x64, 0xbc}, {0x29, 0x64, 0xbc}, {0x29, 0x64, 0xbc}, {0x29, 0x64, 0xbd}, {0x29, 0x64, 0xbd}, {0x2a, 0x64, 0xbd}, + {0x2a, 0x65, 0xbd}, {0x2a, 0x65, 0xbd}, {0x2a, 0x65, 0xbd}, {0x2a, 0x65, 0xbd}, {0x2a, 0x65, 0xbd}, {0x2a, 0x65, 0xbd}, + {0x2a, 0x65, 0xbd}, {0x2a, 0x66, 0xbd}, {0x2a, 0x66, 0xbd}, {0x2b, 0x66, 0xbe}, {0x2b, 0x66, 0xbe}, {0x2b, 0x66, 0xbe}, + {0x2b, 0x66, 0xbe}, {0x2b, 0x66, 0xbe}, {0x2b, 0x67, 0xbe}, {0x2b, 0x67, 0xbe}, {0x2b, 0x67, 0xbe}, {0x2b, 0x67, 0xbe}, + {0x2b, 0x67, 0xbe}, {0x2c, 0x67, 0xbe}, {0x2c, 0x67, 0xbe}, {0x2c, 0x68, 0xbf}, {0x2c, 0x68, 0xbf}, {0x2c, 0x68, 0xbf}, + {0x2c, 0x68, 0xbf}, {0x2c, 0x68, 0xbf}, {0x2c, 0x68, 0xbf}, {0x2c, 0x68, 0xbf}, {0x2c, 0x69, 0xbf}, {0x2c, 0x69, 0xbf}, + {0x2d, 0x69, 0xbf}, {0x2d, 0x69, 0xbf}, {0x2d, 0x69, 0xbf}, {0x2d, 0x69, 0xc0}, {0x2d, 0x6a, 0xc0}, {0x2d, 0x6a, 0xc0}, + {0x2d, 0x6a, 0xc0}, {0x2d, 0x6a, 0xc0}, {0x2d, 0x6a, 0xc0}, {0x2d, 0x6a, 0xc0}, {0x2e, 0x6a, 0xc0}, {0x2e, 0x6b, 0xc0}, + {0x2e, 0x6b, 0xc0}, {0x2e, 0x6b, 0xc0}, {0x2e, 0x6b, 0xc0}, {0x2e, 0x6b, 0xc1}, {0x2e, 0x6b, 0xc1}, {0x2e, 0x6b, 0xc1}, + {0x2e, 0x6c, 0xc1}, {0x2e, 0x6c, 0xc1}, {0x2f, 0x6c, 0xc1}, {0x2f, 0x6c, 0xc1}, {0x2f, 0x6c, 0xc1}, {0x2f, 0x6c, 0xc1}, + {0x2f, 0x6c, 0xc1}, {0x2f, 0x6d, 0xc1}, {0x2f, 0x6d, 0xc1}, {0x2f, 0x6d, 0xc2}, {0x2f, 0x6d, 0xc2}, {0x2f, 0x6d, 0xc2}, + {0x30, 0x6d, 0xc2}, {0x30, 0x6d, 0xc2}, {0x30, 0x6e, 0xc2}, {0x30, 0x6e, 0xc2}, {0x30, 0x6e, 0xc2}, {0x30, 0x6e, 0xc2}, + {0x30, 0x6e, 0xc2}, {0x30, 0x6e, 0xc2}, {0x30, 0x6e, 0xc2}, {0x30, 0x6f, 0xc3}, {0x31, 0x6f, 0xc3}, {0x31, 0x6f, 0xc3}, + {0x31, 0x6f, 0xc3}, {0x31, 0x6f, 0xc3}, {0x31, 0x6f, 0xc3}, {0x31, 0x6f, 0xc3}, {0x31, 0x70, 0xc3}, {0x31, 0x70, 0xc3}, + {0x31, 0x70, 0xc3}, {0x31, 0x70, 0xc3}, {0x31, 0x70, 0xc3}, {0x32, 0x70, 0xc4}, {0x32, 0x70, 0xc4}, {0x32, 0x71, 0xc4}, + {0x32, 0x71, 0xc4}, {0x32, 0x71, 0xc4}, {0x32, 0x71, 0xc4}, {0x32, 0x71, 0xc4}, {0x32, 0x71, 0xc4}, {0x32, 0x71, 0xc4}, + {0x32, 0x72, 0xc4}, {0x33, 0x72, 0xc4}, {0x33, 0x72, 0xc5}, {0x33, 0x72, 0xc5}, {0x33, 0x72, 0xc5}, {0x33, 0x72, 0xc5}, + {0x33, 0x72, 0xc5}, {0x33, 0x73, 0xc5}, {0x33, 0x73, 0xc5}, {0x33, 0x73, 0xc5}, {0x33, 0x73, 0xc5}, {0x34, 0x73, 0xc5}, + {0x34, 0x73, 0xc5}, {0x34, 0x73, 0xc5}, {0x34, 0x74, 0xc6}, {0x34, 0x74, 0xc6}, {0x34, 0x74, 0xc6}, {0x34, 0x74, 0xc6}, + {0x34, 0x74, 0xc6}, {0x34, 0x74, 0xc6}, {0x34, 0x74, 0xc6}, {0x35, 0x75, 0xc6}, {0x35, 0x75, 0xc6}, {0x35, 0x75, 0xc6}, + {0x35, 0x75, 0xc6}, {0x35, 0x75, 0xc6}, {0x35, 0x75, 0xc7}, {0x35, 0x75, 0xc7}, {0x35, 0x76, 0xc7}, {0x35, 0x76, 0xc7}, + {0x35, 0x76, 0xc7}, {0x36, 0x76, 0xc7}, {0x36, 0x76, 0xc7}, {0x36, 0x76, 0xc7}, {0x36, 0x76, 0xc7}, {0x36, 0x77, 0xc7}, + {0x36, 0x77, 0xc7}, {0x36, 0x77, 0xc7}, {0x36, 0x77, 0xc8}, {0x36, 0x77, 0xc8}, {0x36, 0x77, 0xc8}, {0x36, 0x77, 0xc8}, + {0x37, 0x78, 0xc8}, {0x37, 0x78, 0xc8}, {0x37, 0x78, 0xc8}, {0x37, 0x78, 0xc8}, {0x37, 0x78, 0xc8}, {0x37, 0x78, 0xc8}, + {0x37, 0x78, 0xc8}, {0x37, 0x79, 0xc8}, {0x37, 0x79, 0xc9}, {0x37, 0x79, 0xc9}, {0x38, 0x79, 0xc9}, {0x38, 0x79, 0xc9}, + {0x38, 0x79, 0xc9}, {0x38, 0x79, 0xc9}, {0x38, 0x7a, 0xc9}, {0x38, 0x7a, 0xc9}, {0x38, 0x7a, 0xc9}, {0x38, 0x7a, 0xc9}, + {0x38, 0x7a, 0xc9}, {0x38, 0x7a, 0xc9}, {0x39, 0x7a, 0xca}, {0x39, 0x7b, 0xca}, {0x39, 0x7b, 0xca}, {0x39, 0x7b, 0xca}, + {0x39, 0x7b, 0xca}, {0x39, 0x7b, 0xca}, {0x39, 0x7b, 0xca}, {0x39, 0x7b, 0xca}, {0x39, 0x7c, 0xca}, {0x39, 0x7c, 0xca}, + {0x3a, 0x7c, 0xca}, {0x3a, 0x7c, 0xca}, {0x3a, 0x7c, 0xcb}, {0x3a, 0x7c, 0xcb}, {0x3a, 0x7c, 0xcb}, {0x3a, 0x7d, 0xcb}, + {0x3a, 0x7d, 0xcb}, {0x3a, 0x7d, 0xcb}, {0x3a, 0x7d, 0xcb}, {0x3a, 0x7d, 0xcb}, {0x3a, 0x7d, 0xcb}, {0x3b, 0x7d, 0xcb}, + {0x3b, 0x7e, 0xcb}, {0x3b, 0x7e, 0xcb}, {0x3b, 0x7e, 0xcc}, {0x3b, 0x7e, 0xcc}, {0x3b, 0x7e, 0xcc}, {0x3b, 0x7e, 0xcc}, + {0x3b, 0x7f, 0xcc}, {0x3b, 0x7f, 0xcc}, {0x3b, 0x7f, 0xcc}, {0x3c, 0x7f, 0xcc}, {0x3c, 0x7f, 0xcc}, {0x3c, 0x7f, 0xcc}, + {0x3c, 0x7f, 0xcc}, {0x3c, 0x80, 0xcd}, {0x3c, 0x80, 0xcd}, {0x3c, 0x80, 0xcd}, {0x3c, 0x80, 0xcd}, {0x3c, 0x80, 0xcd}, + {0x3c, 0x80, 0xcd}, {0x3d, 0x80, 0xcd}, {0x3d, 0x81, 0xcd}, {0x3d, 0x81, 0xcd}, {0x3d, 0x81, 0xcd}, {0x3d, 0x81, 0xcd}, + {0x3d, 0x81, 0xcd}, {0x3d, 0x81, 0xce}, {0x3d, 0x81, 0xce}, {0x3d, 0x82, 0xce}, {0x3d, 0x82, 0xce}, {0x3e, 0x82, 0xce}, + {0x3e, 0x82, 0xce}, {0x3e, 0x82, 0xce}, {0x3e, 0x82, 0xce}, {0x3e, 0x82, 0xce}, {0x3e, 0x83, 0xce}, {0x3e, 0x83, 0xce}, + {0x3e, 0x83, 0xce}, {0x3e, 0x83, 0xcf}, {0x3e, 0x83, 0xcf}, {0x3f, 0x83, 0xcf}, {0x3f, 0x83, 0xcf}, {0x3f, 0x84, 0xcf}, + {0x3f, 0x84, 0xcf}, {0x3f, 0x84, 0xcf}, {0x3f, 0x84, 0xcf}, {0x3f, 0x84, 0xcf}, {0x3f, 0x84, 0xcf}, {0x3f, 0x84, 0xcf}, + {0x3f, 0x85, 0xcf}, {0x3f, 0x85, 0xd0}, {0x40, 0x85, 0xd0}, {0x40, 0x85, 0xd0}, {0x40, 0x85, 0xd0}, {0x40, 0x85, 0xd0}, + {0x40, 0x85, 0xd0}, {0x40, 0x86, 0xd0}, {0x40, 0x86, 0xd0}, {0x40, 0x86, 0xd0}, {0x40, 0x86, 0xd0}, {0x40, 0x86, 0xd0}, + {0x41, 0x86, 0xd0}, {0x41, 0x86, 0xd1}, {0x41, 0x87, 0xd1}, {0x41, 0x87, 0xd1}, {0x41, 0x87, 0xd1}, {0x41, 0x87, 0xd1}, + {0x41, 0x87, 0xd1}, {0x41, 0x87, 0xd1}, {0x41, 0x87, 0xd1}, {0x41, 0x88, 0xd1}, {0x42, 0x88, 0xd1}, {0x42, 0x88, 0xd1}, + {0x42, 0x88, 0xd1}, {0x42, 0x88, 0xd2}, {0x42, 0x88, 0xd2}, {0x42, 0x88, 0xd2}, {0x42, 0x89, 0xd2}, {0x42, 0x89, 0xd2}, + {0x42, 0x89, 0xd2}, {0x42, 0x89, 0xd2}, {0x43, 0x89, 0xd2}, {0x43, 0x89, 0xd2}, {0x43, 0x89, 0xd2}, {0x43, 0x8a, 0xd2}, + {0x43, 0x8a, 0xd2}, {0x43, 0x8a, 0xd3}, {0x43, 0x8a, 0xd3}, {0x43, 0x8a, 0xd3}, {0x43, 0x8a, 0xd3}, {0x43, 0x8a, 0xd3}, + {0x44, 0x8b, 0xd3}, {0x44, 0x8b, 0xd3}, {0x44, 0x8b, 0xd3}, {0x44, 0x8b, 0xd3}, {0x44, 0x8b, 0xd3}, {0x44, 0x8b, 0xd3}, + {0x44, 0x8b, 0xd3}, {0x44, 0x8c, 0xd4}, {0x44, 0x8c, 0xd4}, {0x44, 0x8c, 0xd4}, {0x44, 0x8c, 0xd4}, {0x45, 0x8c, 0xd4}, + {0x45, 0x8c, 0xd4}, {0x45, 0x8c, 0xd4}, {0x45, 0x8d, 0xd4}, {0x45, 0x8d, 0xd4}, {0x45, 0x8d, 0xd4}, {0x45, 0x8d, 0xd4}, + {0x45, 0x8d, 0xd4}, {0x45, 0x8d, 0xd5}, {0x45, 0x8d, 0xd5}, {0x46, 0x8e, 0xd5}, {0x46, 0x8e, 0xd5}, {0x46, 0x8e, 0xd5}, + {0x46, 0x8e, 0xd5}, {0x46, 0x8e, 0xd5}, {0x46, 0x8e, 0xd5}, {0x46, 0x8e, 0xd5}, {0x46, 0x8f, 0xd5}, {0x46, 0x8f, 0xd5}, + {0x46, 0x8f, 0xd6}, {0x47, 0x8f, 0xd6}, {0x47, 0x8f, 0xd6}, {0x47, 0x8f, 0xd6}, {0x47, 0x8f, 0xd6}, {0x47, 0x90, 0xd6}, + {0x47, 0x90, 0xd6}, {0x47, 0x90, 0xd6}, {0x47, 0x90, 0xd6}, {0x47, 0x90, 0xd6}, {0x47, 0x90, 0xd6}, {0x48, 0x90, 0xd6}, + {0x48, 0x91, 0xd7}, {0x48, 0x91, 0xd7}, {0x48, 0x91, 0xd7}, {0x48, 0x91, 0xd7}, {0x48, 0x91, 0xd7}, {0x48, 0x91, 0xd7}, + {0x48, 0x91, 0xd7}, {0x48, 0x92, 0xd7}, {0x48, 0x92, 0xd7}, {0x49, 0x92, 0xd7}, {0x49, 0x92, 0xd7}, {0x49, 0x92, 0xd7}, + {0x49, 0x92, 0xd8}, {0x49, 0x92, 0xd8}, {0x49, 0x93, 0xd8}, {0x49, 0x93, 0xd8}, {0x49, 0x93, 0xd8}, {0x49, 0x93, 0xd8}, + {0x49, 0x93, 0xd8}, {0x49, 0x93, 0xd8}, {0x4a, 0x94, 0xd8}, {0x4a, 0x94, 0xd8}, {0x4a, 0x94, 0xd8}, {0x4a, 0x94, 0xd8}, + {0x4a, 0x94, 0xd9}, {0x4a, 0x94, 0xd9}, {0x4a, 0x94, 0xd9}, {0x4a, 0x95, 0xd9}, {0x4a, 0x95, 0xd9}, {0x4a, 0x95, 0xd9}, + {0x4b, 0x95, 0xd9}, {0x4b, 0x95, 0xd9}, {0x4b, 0x95, 0xd9}, {0x4b, 0x95, 0xd9}, {0x4b, 0x96, 0xd9}, {0x4b, 0x96, 0xd9}, + {0x4b, 0x96, 0xda}, {0x4b, 0x96, 0xda}, {0x4b, 0x96, 0xda}, {0x4b, 0x96, 0xda}, {0x4c, 0x96, 0xda}, {0x4c, 0x97, 0xda}, + {0x4c, 0x97, 0xda}, {0x4c, 0x97, 0xda}, {0x4c, 0x97, 0xda}, {0x4c, 0x97, 0xda}, {0x4c, 0x97, 0xda}, {0x4c, 0x97, 0xda}, + {0x4c, 0x98, 0xdb}, {0x4c, 0x98, 0xdb}, {0x4d, 0x98, 0xdb}, {0x4d, 0x98, 0xdb}, {0x4d, 0x98, 0xdb}, {0x4d, 0x98, 0xdb}, + {0x4d, 0x98, 0xdb}, {0x4d, 0x99, 0xdb}, {0x4d, 0x99, 0xdb}, {0x4d, 0x99, 0xdb}, {0x4d, 0x99, 0xdb}, {0x4d, 0x99, 0xdb}, + {0x4d, 0x99, 0xdc}, {0x4e, 0x99, 0xdc}, {0x4e, 0x9a, 0xdc}, {0x4e, 0x9a, 0xdc}, {0x4e, 0x9a, 0xdc}, {0x4e, 0x9a, 0xdc}, + {0x4e, 0x9a, 0xdc}, {0x4e, 0x9a, 0xdc}, {0x4f, 0x9a, 0xdc}, {0x4f, 0x9b, 0xdc}, {0x4f, 0x9b, 0xdc}, {0x4f, 0x9b, 0xdc}, + {0x4f, 0x9b, 0xdc}, {0x50, 0x9b, 0xdd}, {0x50, 0x9b, 0xdd}, {0x50, 0x9b, 0xdd}, {0x50, 0x9c, 0xdd}, {0x50, 0x9c, 0xdd}, + {0x51, 0x9c, 0xdd}, {0x51, 0x9c, 0xdd}, {0x51, 0x9c, 0xdd}, {0x51, 0x9c, 0xdd}, {0x51, 0x9d, 0xdd}, {0x51, 0x9d, 0xdd}, + {0x52, 0x9d, 0xdd}, {0x52, 0x9d, 0xdd}, {0x52, 0x9d, 0xdd}, {0x52, 0x9d, 0xde}, {0x52, 0x9d, 0xde}, {0x53, 0x9e, 0xde}, + {0x53, 0x9e, 0xde}, {0x53, 0x9e, 0xde}, {0x53, 0x9e, 0xde}, {0x53, 0x9e, 0xde}, {0x54, 0x9e, 0xde}, {0x54, 0x9e, 0xde}, + {0x54, 0x9f, 0xde}, {0x54, 0x9f, 0xde}, {0x54, 0x9f, 0xde}, {0x55, 0x9f, 0xde}, {0x55, 0x9f, 0xde}, {0x55, 0x9f, 0xdf}, + {0x55, 0xa0, 0xdf}, {0x55, 0xa0, 0xdf}, {0x56, 0xa0, 0xdf}, {0x56, 0xa0, 0xdf}, {0x56, 0xa0, 0xdf}, {0x56, 0xa0, 0xdf}, + {0x56, 0xa0, 0xdf}, {0x57, 0xa1, 0xdf}, {0x57, 0xa1, 0xdf}, {0x57, 0xa1, 0xdf}, {0x57, 0xa1, 0xdf}, {0x57, 0xa1, 0xdf}, + {0x58, 0xa1, 0xdf}, {0x58, 0xa1, 0xdf}, {0x58, 0xa2, 0xe0}, {0x58, 0xa2, 0xe0}, {0x58, 0xa2, 0xe0}, {0x59, 0xa2, 0xe0}, + {0x59, 0xa2, 0xe0}, {0x59, 0xa2, 0xe0}, {0x59, 0xa3, 0xe0}, {0x59, 0xa3, 0xe0}, {0x5a, 0xa3, 0xe0}, {0x5a, 0xa3, 0xe0}, + {0x5a, 0xa3, 0xe0}, {0x5a, 0xa3, 0xe0}, {0x5a, 0xa3, 0xe0}, {0x5a, 0xa4, 0xe0}, {0x5b, 0xa4, 0xe1}, {0x5b, 0xa4, 0xe1}, + {0x5b, 0xa4, 0xe1}, {0x5b, 0xa4, 0xe1}, {0x5b, 0xa4, 0xe1}, {0x5c, 0xa4, 0xe1}, {0x5c, 0xa5, 0xe1}, {0x5c, 0xa5, 0xe1}, + {0x5c, 0xa5, 0xe1}, {0x5c, 0xa5, 0xe1}, {0x5d, 0xa5, 0xe1}, {0x5d, 0xa5, 0xe1}, {0x5d, 0xa5, 0xe1}, {0x5d, 0xa6, 0xe1}, + {0x5d, 0xa6, 0xe2}, {0x5e, 0xa6, 0xe2}, {0x5e, 0xa6, 0xe2}, {0x5e, 0xa6, 0xe2}, {0x5e, 0xa6, 0xe2}, {0x5e, 0xa7, 0xe2}, + {0x5f, 0xa7, 0xe2}, {0x5f, 0xa7, 0xe2}, {0x5f, 0xa7, 0xe2}, {0x5f, 0xa7, 0xe2}, {0x5f, 0xa7, 0xe2}, {0x60, 0xa7, 0xe2}, + {0x60, 0xa8, 0xe2}, {0x60, 0xa8, 0xe2}, {0x60, 0xa8, 0xe2}, {0x60, 0xa8, 0xe3}, {0x61, 0xa8, 0xe3}, {0x61, 0xa8, 0xe3}, + {0x61, 0xa8, 0xe3}, {0x61, 0xa9, 0xe3}, {0x61, 0xa9, 0xe3}, {0x62, 0xa9, 0xe3}, {0x62, 0xa9, 0xe3}, {0x62, 0xa9, 0xe3}, + {0x62, 0xa9, 0xe3}, {0x62, 0xaa, 0xe3}, {0x62, 0xaa, 0xe3}, {0x63, 0xaa, 0xe3}, {0x63, 0xaa, 0xe3}, {0x63, 0xaa, 0xe4}, + {0x63, 0xaa, 0xe4}, {0x63, 0xaa, 0xe4}, {0x64, 0xab, 0xe4}, {0x64, 0xab, 0xe4}, {0x64, 0xab, 0xe4}, {0x64, 0xab, 0xe4}, + {0x64, 0xab, 0xe4}, {0x65, 0xab, 0xe4}, {0x65, 0xab, 0xe4}, {0x65, 0xac, 0xe4}, {0x65, 0xac, 0xe4}, {0x65, 0xac, 0xe4}, + {0x66, 0xac, 0xe4}, {0x66, 0xac, 0xe5}, {0x66, 0xac, 0xe5}, {0x66, 0xad, 0xe5}, {0x66, 0xad, 0xe5}, {0x67, 0xad, 0xe5}, + {0x67, 0xad, 0xe5}, {0x67, 0xad, 0xe5}, {0x67, 0xad, 0xe5}, {0x67, 0xad, 0xe5}, {0x68, 0xae, 0xe5}, {0x68, 0xae, 0xe5}, + {0x68, 0xae, 0xe5}, {0x68, 0xae, 0xe5}, {0x68, 0xae, 0xe5}, {0x69, 0xae, 0xe5}, {0x69, 0xae, 0xe6}, {0x69, 0xaf, 0xe6}, + {0x69, 0xaf, 0xe6}, {0x69, 0xaf, 0xe6}, {0x6a, 0xaf, 0xe6}, {0x6a, 0xaf, 0xe6}, {0x6a, 0xaf, 0xe6}, {0x6a, 0xb0, 0xe6}, + {0x6a, 0xb0, 0xe6}, {0x6b, 0xb0, 0xe6}, {0x6b, 0xb0, 0xe6}, {0x6b, 0xb0, 0xe6}, {0x6b, 0xb0, 0xe6}, {0x6b, 0xb0, 0xe6}, + {0x6b, 0xb1, 0xe7}, {0x6c, 0xb1, 0xe7}, {0x6c, 0xb1, 0xe7}, {0x6c, 0xb1, 0xe7}, {0x6c, 0xb1, 0xe7}, {0x6c, 0xb1, 0xe7}, + {0x6d, 0xb1, 0xe7}, {0x6d, 0xb2, 0xe7}, {0x6d, 0xb2, 0xe7}, {0x6d, 0xb2, 0xe7}, {0x6d, 0xb2, 0xe7}, {0x6e, 0xb2, 0xe7}, + {0x6e, 0xb2, 0xe7}, {0x6e, 0xb3, 0xe7}, {0x6e, 0xb3, 0xe8}, {0x6e, 0xb3, 0xe8}, {0x6f, 0xb3, 0xe8}, {0x6f, 0xb3, 0xe8}, + {0x6f, 0xb3, 0xe8}, {0x6f, 0xb3, 0xe8}, {0x6f, 0xb4, 0xe8}, {0x70, 0xb4, 0xe8}, {0x70, 0xb4, 0xe8}, {0x70, 0xb4, 0xe8}, + {0x70, 0xb4, 0xe8}, {0x70, 0xb4, 0xe8}, {0x71, 0xb4, 0xe8}, {0x71, 0xb5, 0xe8}, {0x71, 0xb5, 0xe8}, {0x71, 0xb5, 0xe9}, + {0x71, 0xb5, 0xe9}, {0x72, 0xb5, 0xe9}, {0x72, 0xb5, 0xe9}, {0x72, 0xb5, 0xe9}, {0x72, 0xb6, 0xe9}, {0x72, 0xb6, 0xe9}, + {0x73, 0xb6, 0xe9}, {0x73, 0xb6, 0xe9}, {0x73, 0xb6, 0xe9}, {0x73, 0xb6, 0xe9}, {0x73, 0xb7, 0xe9}, {0x73, 0xb7, 0xe9}, + {0x74, 0xb7, 0xe9}, {0x74, 0xb7, 0xea}, {0x74, 0xb7, 0xea}, {0x74, 0xb7, 0xea}, {0x74, 0xb7, 0xea}, {0x75, 0xb8, 0xea}, + {0x75, 0xb8, 0xea}, {0x75, 0xb8, 0xea}, {0x75, 0xb8, 0xea}, {0x75, 0xb8, 0xea}, {0x76, 0xb8, 0xea}, {0x76, 0xb8, 0xea}, + {0x76, 0xb9, 0xea}, {0x76, 0xb9, 0xea}, {0x76, 0xb9, 0xea}, {0x77, 0xb9, 0xeb}, {0x77, 0xb9, 0xeb}, {0x77, 0xb9, 0xeb}, + {0x77, 0xba, 0xeb}, {0x77, 0xba, 0xeb}, {0x78, 0xba, 0xeb}, {0x78, 0xba, 0xeb}, {0x78, 0xba, 0xeb}, {0x78, 0xba, 0xeb}, + {0x78, 0xba, 0xeb}, {0x79, 0xbb, 0xeb}, {0x79, 0xbb, 0xeb}, {0x79, 0xbb, 0xeb}, {0x79, 0xbb, 0xeb}, {0x79, 0xbb, 0xeb}, + {0x7a, 0xbb, 0xec}, {0x7a, 0xbb, 0xec}, {0x7a, 0xbc, 0xec}, {0x7a, 0xbc, 0xec}, {0x7a, 0xbc, 0xec}, {0x7b, 0xbc, 0xec}, + {0x7b, 0xbc, 0xec}, {0x7b, 0xbc, 0xec}, {0x7b, 0xbd, 0xec}, {0x7b, 0xbd, 0xec}, {0x7c, 0xbd, 0xec}, {0x7c, 0xbd, 0xec}, + {0x7c, 0xbd, 0xec}, {0x7c, 0xbd, 0xec}, {0x7c, 0xbd, 0xed}, {0x7c, 0xbe, 0xed}, {0x7d, 0xbe, 0xed}, {0x7d, 0xbe, 0xed}, + {0x7d, 0xbe, 0xed}, {0x7d, 0xbe, 0xed}, {0x7d, 0xbe, 0xed}, {0x7e, 0xbe, 0xed}, {0x7e, 0xbf, 0xed}, {0x7e, 0xbf, 0xed}, + {0x7e, 0xbf, 0xed}, {0x7e, 0xbf, 0xed}, {0x7f, 0xbf, 0xed}, {0x7f, 0xbf, 0xed}, {0x7f, 0xc0, 0xee}, {0x7f, 0xc0, 0xee}, + {0x7f, 0xc0, 0xee}, {0x80, 0xc0, 0xee}, {0x80, 0xc0, 0xee}, {0x80, 0xc0, 0xee}, {0x80, 0xc0, 0xee}, {0x80, 0xc1, 0xee}, + {0x81, 0xc1, 0xee}, {0x81, 0xc1, 0xee}, {0x81, 0xc1, 0xee}, {0x81, 0xc1, 0xee}, {0x81, 0xc1, 0xee}, {0x82, 0xc1, 0xee}, + {0x82, 0xc2, 0xee}, {0x82, 0xc2, 0xef}, {0x82, 0xc2, 0xef}, {0x82, 0xc2, 0xef}, {0x83, 0xc2, 0xef}, {0x83, 0xc2, 0xef}, + {0x83, 0xc3, 0xef}, {0x83, 0xc3, 0xef}, {0x83, 0xc3, 0xef}, {0x84, 0xc3, 0xef}, {0x84, 0xc3, 0xef}, {0x84, 0xc3, 0xef}, + {0x84, 0xc3, 0xef}, {0x84, 0xc4, 0xef}, {0x84, 0xc4, 0xef}, {0x85, 0xc4, 0xf0}, {0x85, 0xc4, 0xf0}, {0x85, 0xc4, 0xf0}, + {0x85, 0xc4, 0xf0}, {0x85, 0xc4, 0xf0}, {0x86, 0xc5, 0xf0}, {0x86, 0xc5, 0xf0}, {0x86, 0xc5, 0xf0}, {0x86, 0xc5, 0xf0}, + {0x86, 0xc5, 0xf0}, {0x87, 0xc5, 0xf0}, {0x87, 0xc6, 0xf0}, {0x87, 0xc6, 0xf0}, {0x87, 0xc6, 0xf0}, {0x87, 0xc6, 0xf1}, + {0x88, 0xc6, 0xf1}, {0x88, 0xc6, 0xf1}, {0x88, 0xc6, 0xf1}, {0x88, 0xc7, 0xf1}, {0x88, 0xc7, 0xf1}, {0x89, 0xc7, 0xf1}, + {0x89, 0xc7, 0xf1}, {0x89, 0xc7, 0xf1}, {0x89, 0xc7, 0xf1}, {0x89, 0xc7, 0xf1}, {0x8a, 0xc8, 0xf1}, {0x8a, 0xc8, 0xf1}, + {0x8a, 0xc8, 0xf1}, {0x8a, 0xc8, 0xf1}, {0x8a, 0xc8, 0xf2}, {0x8b, 0xc8, 0xf2}, {0x8b, 0xc8, 0xf2}, {0x8b, 0xc9, 0xf2}, + {0x8b, 0xc9, 0xf2}, {0x8b, 0xc9, 0xf2}, {0x8c, 0xc9, 0xf2}, {0x8c, 0xc9, 0xf2}, {0x8c, 0xc9, 0xf2}, {0x8c, 0xca, 0xf2}, + {0x8c, 0xca, 0xf2}, {0x8d, 0xca, 0xf2}, {0x8d, 0xca, 0xf2}, {0x8d, 0xca, 0xf2}, {0x8d, 0xca, 0xf3}, {0x8d, 0xca, 0xf3}, + {0x8d, 0xcb, 0xf3}, {0x8e, 0xcb, 0xf3}, {0x8e, 0xcb, 0xf3}, {0x8e, 0xcb, 0xf3}, {0x8e, 0xcb, 0xf3}, {0x8e, 0xcb, 0xf3}, + {0x8f, 0xcb, 0xf3}, {0x8f, 0xcc, 0xf3}, {0x8f, 0xcc, 0xf3}, {0x8f, 0xcc, 0xf3}, {0x8f, 0xcc, 0xf3}, {0x90, 0xcc, 0xf3}, + {0x90, 0xcc, 0xf4}, {0x90, 0xcd, 0xf4}, {0x90, 0xcd, 0xf4}, {0x90, 0xcd, 0xf4}, {0x91, 0xcd, 0xf4}, {0x91, 0xcd, 0xf4}, + {0x91, 0xcd, 0xf4}, {0x91, 0xcd, 0xf4}, {0x91, 0xce, 0xf4}, {0x92, 0xce, 0xf4}, {0x92, 0xce, 0xf4}, {0x92, 0xce, 0xf4}, + {0x92, 0xce, 0xf4}, {0x92, 0xce, 0xf4}, {0x93, 0xce, 0xf4}, {0x93, 0xcf, 0xf5}, {0x93, 0xcf, 0xf5}, {0x93, 0xcf, 0xf5}, + {0x93, 0xcf, 0xf5}, {0x94, 0xcf, 0xf5}, {0x94, 0xcf, 0xf5}, {0x94, 0xd0, 0xf5}, {0x94, 0xd0, 0xf5}, {0x94, 0xd0, 0xf5}, + {0x95, 0xd0, 0xf5}, {0x95, 0xd0, 0xf5}, {0x95, 0xd0, 0xf5}, {0x95, 0xd0, 0xf5}, {0x95, 0xd1, 0xf5}, {0x96, 0xd1, 0xf6}, + {0x96, 0xd1, 0xf6}, {0x96, 0xd1, 0xf6}, {0x96, 0xd1, 0xf6}, {0x96, 0xd1, 0xf6}, {0x96, 0xd1, 0xf6}, {0x97, 0xd2, 0xf6}, + {0x97, 0xd2, 0xf6}, {0x97, 0xd2, 0xf6}, {0x97, 0xd2, 0xf6}, {0x97, 0xd2, 0xf6}, {0x98, 0xd2, 0xf6}, {0x98, 0xd3, 0xf6}, + {0x98, 0xd3, 0xf6}, {0x98, 0xd3, 0xf7}, {0x98, 0xd3, 0xf7}, {0x99, 0xd3, 0xf7}, {0x99, 0xd3, 0xf7}, {0x99, 0xd3, 0xf7}, + {0x99, 0xd4, 0xf7}, {0x99, 0xd4, 0xf7}, {0x9a, 0xd4, 0xf7}, {0x9a, 0xd4, 0xf7}, {0x9a, 0xd4, 0xf7}, {0x9a, 0xd4, 0xf7}, + {0x9a, 0xd4, 0xf7}, {0x9b, 0xd5, 0xf7}, {0x9b, 0xd5, 0xf7}, {0x9b, 0xd5, 0xf7}, {0x9b, 0xd5, 0xf8}, {0x9b, 0xd5, 0xf8}, + {0x9c, 0xd5, 0xf8}, {0x9c, 0xd6, 0xf8}, {0x9c, 0xd6, 0xf8}, {0x9c, 0xd6, 0xf8}, {0x9c, 0xd6, 0xf8}, {0x9d, 0xd6, 0xf8}, + {0x9d, 0xd6, 0xf8}, {0x9d, 0xd6, 0xf8}, {0x9d, 0xd7, 0xf8}, {0x9d, 0xd7, 0xf8}, {0x9e, 0xd7, 0xf8}, {0x9e, 0xd7, 0xf8}, + {0x9e, 0xd7, 0xf9}, {0x9e, 0xd7, 0xf9}, {0x9e, 0xd7, 0xf9}, {0x9e, 0xd8, 0xf9}, {0x9f, 0xd8, 0xf9}, {0x9f, 0xd8, 0xf9}, + {0x9f, 0xd8, 0xf9}, {0x9f, 0xd8, 0xf9}, {0x9f, 0xd8, 0xf9}, {0xa0, 0xd8, 0xf9}, {0xa0, 0xd9, 0xf9}, {0xa0, 0xd9, 0xf9}, + {0xa0, 0xd9, 0xf9}, {0xa0, 0xd9, 0xf9}, {0xa1, 0xd9, 0xfa}, {0xa1, 0xd9, 0xfa}, {0xa1, 0xda, 0xfa}, {0xa1, 0xda, 0xfa}, + {0xa1, 0xda, 0xfa}, {0xa2, 0xda, 0xfa}, {0xa2, 0xda, 0xfa}, {0xa2, 0xda, 0xfa}, {0xa2, 0xda, 0xfa}, {0xa2, 0xdb, 0xfa}, + {0xa3, 0xdb, 0xfa}, {0xa3, 0xdb, 0xfa}, {0xa3, 0xdb, 0xfa}, {0xa3, 0xdb, 0xfa}, {0xa3, 0xdb, 0xfa}, {0xa4, 0xdb, 0xfb}, + {0xa4, 0xdc, 0xfb}, {0xa4, 0xdc, 0xfb}, {0xa4, 0xdc, 0xfb}, {0xa4, 0xdc, 0xfb}, {0xa5, 0xdc, 0xfb}, {0xa5, 0xdc, 0xfb}, + {0xa5, 0xdd, 0xfb}, {0xa5, 0xdd, 0xfb}, {0xa5, 0xdd, 0xfb}, {0xa6, 0xdd, 0xfb}, {0xa6, 0xdd, 0xfb}, {0xa6, 0xdd, 0xfb}, + {0xa6, 0xdd, 0xfb}, {0xa6, 0xde, 0xfc}, {0xa7, 0xde, 0xfc}, {0xa7, 0xde, 0xfc}, {0xa7, 0xde, 0xfc}, {0xa7, 0xde, 0xfc}, + {0xa7, 0xde, 0xfc}, {0xa7, 0xde, 0xfc}, {0xa8, 0xdf, 0xfc}, {0xa8, 0xdf, 0xfc}, {0xa8, 0xdf, 0xfc}, {0xa8, 0xdf, 0xfc}, + {0xa8, 0xdf, 0xfc}, {0xa9, 0xdf, 0xfc}, {0xa9, 0xe0, 0xfc}, {0xa9, 0xe0, 0xfd}, {0xa9, 0xe0, 0xfd}, {0xa9, 0xe0, 0xfd}, + {0xaa, 0xe0, 0xfd}, {0xaa, 0xe0, 0xfd}, {0xaa, 0xe0, 0xfd}, {0xaa, 0xe1, 0xfd}, {0xaa, 0xe1, 0xfd}, {0xab, 0xe1, 0xfd}, + {0xab, 0xe1, 0xfd}, {0xab, 0xe1, 0xfd}, {0xab, 0xe1, 0xfd}, {0xab, 0xe1, 0xfd}, {0xac, 0xe2, 0xfd}, {0xac, 0xe2, 0xfd}, + {0xac, 0xe2, 0xfe}, {0xac, 0xe2, 0xfe}, {0xac, 0xe2, 0xfe}, {0xad, 0xe2, 0xfe}, {0xad, 0xe3, 0xfe}, {0xad, 0xe3, 0xfe}, + {0xad, 0xe3, 0xfe}, {0xad, 0xe3, 0xfe}, {0xae, 0xe3, 0xfe}, {0xae, 0xe3, 0xfe}, {0xae, 0xe3, 0xfe}, {0xae, 0xe4, 0xfe}, + {0xae, 0xe4, 0xfe}, {0xaf, 0xe4, 0xfe}, {0xaf, 0xe4, 0xff}, {0xaf, 0xe4, 0xff}, {0xaf, 0xe4, 0xff}, {0xaf, 0xe4, 0xff}, + {0xaf, 0xe5, 0xff}, {0xb0, 0xe5, 0xff}, {0xb0, 0xe5, 0xff}, {0xb0, 0xe5, 0xff}, {0xb0, 0xe5, 0xff}, {0xb0, 0xe5, 0xff}, + {0xb1, 0xe5, 0xff}, {0xb1, 0xe5, 0xff}, {0xb1, 0xe5, 0xff}, {0xb1, 0xe5, 0xff}, {0xb1, 0xe5, 0xff}, {0xb1, 0xe5, 0xff}, + {0xb2, 0xe6, 0xff}, {0xb2, 0xe6, 0xff}, {0xb2, 0xe6, 0xff}, {0xb2, 0xe6, 0xff}, {0xb2, 0xe6, 0xfe}, {0xb2, 0xe6, 0xfe}, + {0xb3, 0xe6, 0xfe}, {0xb3, 0xe6, 0xfe}, {0xb3, 0xe6, 0xfe}, {0xb3, 0xe6, 0xfe}, {0xb3, 0xe6, 0xfe}, {0xb4, 0xe6, 0xfe}, + {0xb4, 0xe6, 0xfe}, {0xb4, 0xe6, 0xfe}, {0xb4, 0xe6, 0xfe}, {0xb4, 0xe6, 0xfe}, {0xb4, 0xe6, 0xfe}, {0xb5, 0xe6, 0xfe}, + {0xb5, 0xe7, 0xfe}, {0xb5, 0xe7, 0xfe}, {0xb5, 0xe7, 0xfe}, {0xb5, 0xe7, 0xfe}, {0xb5, 0xe7, 0xfe}, {0xb6, 0xe7, 0xfe}, + {0xb6, 0xe7, 0xfe}, {0xb6, 0xe7, 0xfe}, {0xb6, 0xe7, 0xfe}, {0xb6, 0xe7, 0xfe}, {0xb6, 0xe7, 0xfe}, {0xb7, 0xe7, 0xfe}, + {0xb7, 0xe7, 0xfe}, {0xb7, 0xe7, 0xfd}, {0xb7, 0xe7, 0xfd}, {0xb7, 0xe7, 0xfd}, {0xb7, 0xe7, 0xfd}, {0xb8, 0xe8, 0xfd}, + {0xb8, 0xe8, 0xfd}, {0xb8, 0xe8, 0xfd}, {0xb8, 0xe8, 0xfd}, {0xb8, 0xe8, 0xfd}, {0xb9, 0xe8, 0xfd}, {0xb9, 0xe8, 0xfd}, + {0xb9, 0xe8, 0xfd}, {0xb9, 0xe8, 0xfd}, {0xb9, 0xe8, 0xfd}, {0xb9, 0xe8, 0xfd}, {0xba, 0xe8, 0xfd}, {0xba, 0xe8, 0xfd}, + {0xba, 0xe8, 0xfd}, {0xba, 0xe8, 0xfd}, {0xba, 0xe8, 0xfd}, {0xba, 0xe8, 0xfd}, {0xbb, 0xe8, 0xfd}, {0xbb, 0xe9, 0xfd}, + {0xbb, 0xe9, 0xfd}, {0xbb, 0xe9, 0xfd}, {0xbb, 0xe9, 0xfd}, {0xbb, 0xe9, 0xfc}, {0xbc, 0xe9, 0xfc}, {0xbc, 0xe9, 0xfc}, + {0xbc, 0xe9, 0xfc}, {0xbc, 0xe9, 0xfc}, {0xbc, 0xe9, 0xfc}, {0xbd, 0xe9, 0xfc}, {0xbd, 0xe9, 0xfc}, {0xbd, 0xe9, 0xfc}, + {0xbd, 0xe9, 0xfc}, {0xbd, 0xe9, 0xfc}, {0xbd, 0xe9, 0xfc}, {0xbe, 0xe9, 0xfc}, {0xbe, 0xea, 0xfc}, {0xbe, 0xea, 0xfc}, + {0xbe, 0xea, 0xfc}, {0xbe, 0xea, 0xfc}, {0xbe, 0xea, 0xfc}, {0xbf, 0xea, 0xfc}, {0xbf, 0xea, 0xfc}, {0xbf, 0xea, 0xfc}, + {0xbf, 0xea, 0xfc}, {0xbf, 0xea, 0xfc}, {0xbf, 0xea, 0xfc}, {0xc0, 0xea, 0xfc}, {0xc0, 0xea, 0xfc}, {0xc0, 0xea, 0xfc}, + {0xc0, 0xea, 0xfb}, {0xc0, 0xea, 0xfb}, {0xc0, 0xea, 0xfb}, {0xc1, 0xea, 0xfb}, {0xc1, 0xeb, 0xfb}, {0xc1, 0xeb, 0xfb}, + {0xc1, 0xeb, 0xfb}, {0xc1, 0xeb, 0xfb}, {0xc2, 0xeb, 0xfb}, {0xc2, 0xeb, 0xfb}, {0xc2, 0xeb, 0xfb}, {0xc2, 0xeb, 0xfb}, + {0xc2, 0xeb, 0xfb}, {0xc2, 0xeb, 0xfb}, {0xc3, 0xeb, 0xfb}, {0xc3, 0xeb, 0xfb}, {0xc3, 0xeb, 0xfb}, {0xc3, 0xeb, 0xfb}, + {0xc3, 0xeb, 0xfb}, {0xc3, 0xeb, 0xfb}, {0xc4, 0xeb, 0xfb}, {0xc4, 0xeb, 0xfb}, {0xc4, 0xec, 0xfb}, {0xc4, 0xec, 0xfb}, + {0xc4, 0xec, 0xfb}, {0xc4, 0xec, 0xfb}, {0xc5, 0xec, 0xfa}, {0xc5, 0xec, 0xfa}, {0xc5, 0xec, 0xfa}, {0xc5, 0xec, 0xfa}, + {0xc5, 0xec, 0xfa}, {0xc5, 0xec, 0xfa}, {0xc6, 0xec, 0xfa}, {0xc6, 0xec, 0xfa}, {0xc6, 0xec, 0xfa}, {0xc6, 0xec, 0xfa}, + {0xc6, 0xec, 0xfa}, {0xc7, 0xec, 0xfa}, {0xc7, 0xec, 0xfa}, {0xc7, 0xed, 0xfa}, {0xc7, 0xed, 0xfa}, {0xc7, 0xed, 0xfa}, + {0xc7, 0xed, 0xfa}, {0xc8, 0xed, 0xfa}, {0xc8, 0xed, 0xfa}, {0xc8, 0xed, 0xfa}, {0xc8, 0xed, 0xfa}, {0xc8, 0xed, 0xfa}, + {0xc8, 0xed, 0xfa}, {0xc9, 0xed, 0xfa}, {0xc9, 0xed, 0xfa}, {0xc9, 0xed, 0xfa}, {0xc9, 0xed, 0xf9}, {0xc9, 0xed, 0xf9}, + {0xc9, 0xed, 0xf9}, {0xca, 0xed, 0xf9}, {0xca, 0xed, 0xf9}, {0xca, 0xee, 0xf9}, {0xca, 0xee, 0xf9}, {0xca, 0xee, 0xf9}, + {0xca, 0xee, 0xf9}, {0xcb, 0xee, 0xf9}, {0xcb, 0xee, 0xf9}, {0xcb, 0xee, 0xf9}, {0xcb, 0xee, 0xf9}, {0xcb, 0xee, 0xf9}, + {0xcc, 0xee, 0xf9}, {0xcc, 0xee, 0xf9}, {0xcc, 0xee, 0xf9}, {0xcc, 0xee, 0xf9}, {0xcc, 0xee, 0xf9}, {0xcc, 0xee, 0xf9}, + {0xcd, 0xee, 0xf9}, {0xcd, 0xee, 0xf9}, {0xcd, 0xef, 0xf9}, {0xcd, 0xef, 0xf9}, {0xcd, 0xef, 0xf9}, {0xcd, 0xef, 0xf9}, + {0xce, 0xef, 0xf9}, {0xce, 0xef, 0xf8}, {0xce, 0xef, 0xf8}, {0xce, 0xef, 0xf8}, {0xce, 0xef, 0xf8}, {0xce, 0xef, 0xf8}, + {0xcf, 0xef, 0xf8}, {0xcf, 0xef, 0xf8}, {0xcf, 0xef, 0xf8}, {0xcf, 0xef, 0xf8}, {0xcf, 0xef, 0xf8}, {0xd0, 0xef, 0xf8}, + {0xd0, 0xef, 0xf8}, {0xd0, 0xef, 0xf8}, {0xd0, 0xf0, 0xf8}, {0xd0, 0xf0, 0xf8}, {0xd0, 0xf0, 0xf8}, {0xd1, 0xf0, 0xf8}, + {0xd1, 0xf0, 0xf8}, {0xd1, 0xf0, 0xf8}, {0xd1, 0xf0, 0xf8}, {0xd1, 0xf0, 0xf8}, {0xd1, 0xf0, 0xf8}, {0xd2, 0xf0, 0xf8}, + {0xd2, 0xf0, 0xf8}, {0xd2, 0xf0, 0xf8}, {0xd2, 0xf0, 0xf8}, {0xd2, 0xf0, 0xf7}, {0xd2, 0xf0, 0xf7}, {0xd3, 0xf0, 0xf7}, + {0xd3, 0xf0, 0xf7}, {0xd3, 0xf0, 0xf7}, {0xd3, 0xf1, 0xf7}, {0xd3, 0xf1, 0xf7}, {0xd3, 0xf1, 0xf7}, {0xd4, 0xf1, 0xf7}, + {0xd4, 0xf1, 0xf7}, {0xd4, 0xf1, 0xf7}, {0xd4, 0xf1, 0xf7}, {0xd4, 0xf1, 0xf7}, {0xd5, 0xf1, 0xf7}, {0xd5, 0xf1, 0xf7}, + {0xd5, 0xf1, 0xf7}, {0xd5, 0xf1, 0xf7}, {0xd5, 0xf1, 0xf7}, {0xd5, 0xf1, 0xf7}, {0xd6, 0xf1, 0xf7}, {0xd6, 0xf1, 0xf7}, + {0xd6, 0xf1, 0xf7}, {0xd6, 0xf2, 0xf7}, {0xd6, 0xf2, 0xf7}, {0xd6, 0xf2, 0xf7}, {0xd7, 0xf2, 0xf7}, {0xd7, 0xf2, 0xf7}, + {0xd7, 0xf2, 0xf6}, {0xd7, 0xf2, 0xf6}, {0xd7, 0xf2, 0xf6}, {0xd7, 0xf2, 0xf6}, {0xd8, 0xf2, 0xf6}, {0xd8, 0xf2, 0xf6}, + {0xd8, 0xf2, 0xf6}, {0xd8, 0xf2, 0xf6}, {0xd8, 0xf2, 0xf6}, {0xd8, 0xf2, 0xf6}, {0xd9, 0xf2, 0xf6}, {0xd9, 0xf2, 0xf6}, + {0xd9, 0xf2, 0xf6}, {0xd9, 0xf3, 0xf6}, {0xd9, 0xf3, 0xf6}, {0xda, 0xf3, 0xf6}, {0xda, 0xf3, 0xf6}, {0xda, 0xf3, 0xf6}, + {0xda, 0xf3, 0xf6}, {0xda, 0xf3, 0xf6}, {0xda, 0xf3, 0xf6}, {0xdb, 0xf3, 0xf6}, {0xdb, 0xf3, 0xf6}, {0xdb, 0xf3, 0xf6}, + {0xdb, 0xf3, 0xf6}, {0xdb, 0xf3, 0xf6}, {0xdb, 0xf3, 0xf5}, {0xdc, 0xf3, 0xf5}, {0xdc, 0xf3, 0xf5}, {0xdc, 0xf3, 0xf5}, + {0xdc, 0xf4, 0xf5}, {0xdc, 0xf4, 0xf5}, {0xdc, 0xf4, 0xf5}, {0xdd, 0xf4, 0xf5}, {0xdd, 0xf4, 0xf5}, {0xdd, 0xf4, 0xf5}, + {0xdd, 0xf4, 0xf5}, {0xdd, 0xf4, 0xf5}, {0xdd, 0xf4, 0xf5}, {0xde, 0xf4, 0xf5}, {0xde, 0xf4, 0xf5}, {0xde, 0xf4, 0xf5}, + {0xde, 0xf4, 0xf5}, {0xde, 0xf4, 0xf5}, {0xdf, 0xf4, 0xf5}, {0xdf, 0xf4, 0xf5}, {0xdf, 0xf4, 0xf5}, {0xdf, 0xf4, 0xf5}, + {0xdf, 0xf5, 0xf5}, {0xdf, 0xf5, 0xf5}, {0xe0, 0xf5, 0xf5}, {0xe0, 0xf5, 0xf5}, {0xe0, 0xf5, 0xf5}, {0xe0, 0xf5, 0xf4}, + {0xe0, 0xf5, 0xf4}, {0xe0, 0xf5, 0xf4}, {0xe1, 0xf5, 0xf4}, {0xe1, 0xf5, 0xf4}, {0xe1, 0xf5, 0xf4}, {0xe1, 0xf5, 0xf4}, + {0xe1, 0xf5, 0xf4}, {0xe1, 0xf5, 0xf4}, {0xe2, 0xf5, 0xf4}, {0xe2, 0xf5, 0xf4}, {0xe2, 0xf5, 0xf4}, {0xe2, 0xf5, 0xf4}, + {0xe2, 0xf6, 0xf4}, {0xe2, 0xf6, 0xf4}, {0xe3, 0xf6, 0xf4}, {0xe3, 0xf6, 0xf4}, {0xe3, 0xf6, 0xf4}, {0xe3, 0xf6, 0xf4}, + {0xe3, 0xf6, 0xf4}, {0xe4, 0xf6, 0xf4}, {0xe4, 0xf6, 0xf4}, {0xe4, 0xf6, 0xf4}, {0xe4, 0xf6, 0xf4}, {0xe4, 0xf6, 0xf4}, + {0xe4, 0xf6, 0xf4}, {0xe5, 0xf6, 0xf3}, {0xe5, 0xf6, 0xf3}, {0xe5, 0xf6, 0xf3}, {0xe5, 0xf6, 0xf3}, {0xe5, 0xf7, 0xf3}, + {0xe5, 0xf7, 0xf3}, {0xe6, 0xf7, 0xf3}, {0xe6, 0xf7, 0xf3}, {0xe6, 0xf7, 0xf3}, {0xe6, 0xf7, 0xf3}, {0xe6, 0xf7, 0xf3}, + {0xe6, 0xf7, 0xf3}, {0xe7, 0xf7, 0xf3}, {0xe7, 0xf7, 0xf3}, {0xe7, 0xf7, 0xf3}, {0xe7, 0xf7, 0xf3}, {0xe7, 0xf7, 0xf3}, + {0xe8, 0xf7, 0xf3}, {0xe8, 0xf7, 0xf3}, {0xe8, 0xf7, 0xf3}, {0xe8, 0xf7, 0xf3}, {0xe8, 0xf7, 0xf3}, {0xe8, 0xf8, 0xf3}, + {0xe9, 0xf8, 0xf3}, {0xe9, 0xf8, 0xf3}, {0xe9, 0xf8, 0xf3}, {0xe9, 0xf8, 0xf2}, {0xe9, 0xf8, 0xf2}, {0xe9, 0xf8, 0xf2}, + {0xea, 0xf8, 0xf2}, {0xea, 0xf8, 0xf2}, {0xea, 0xf8, 0xf2}, {0xea, 0xf8, 0xf2}, {0xea, 0xf8, 0xf2}, {0xea, 0xf8, 0xf2}, + {0xeb, 0xf8, 0xf2}, {0xeb, 0xf8, 0xf2}, {0xeb, 0xf8, 0xf2}, {0xeb, 0xf8, 0xf2}, {0xeb, 0xf8, 0xf2}, {0xeb, 0xf9, 0xf2}, + {0xec, 0xf9, 0xf2}, {0xec, 0xf9, 0xf2}, {0xec, 0xf9, 0xf2}, {0xec, 0xf9, 0xf2}, {0xec, 0xf9, 0xf2}, {0xed, 0xf9, 0xf2}, + {0xed, 0xf9, 0xf2}, {0xed, 0xf9, 0xf2}, {0xed, 0xf9, 0xf2}, {0xed, 0xf9, 0xf2}, {0xed, 0xf9, 0xf2}, {0xee, 0xf9, 0xf2}, + {0xee, 0xf9, 0xf1}, {0xee, 0xf9, 0xf1}, {0xee, 0xf9, 0xf1}, {0xee, 0xf9, 0xf1}, {0xee, 0xfa, 0xf1}, {0xef, 0xfa, 0xf1}, + {0xef, 0xfa, 0xf1}, {0xef, 0xfa, 0xf1}, {0xef, 0xfa, 0xf1}, {0xef, 0xfa, 0xf1}, {0xef, 0xfa, 0xf1}, {0xf0, 0xfa, 0xf1}, + {0xf0, 0xfa, 0xf1}, {0xf0, 0xfa, 0xf1}, {0xf0, 0xfa, 0xf1}, {0xf0, 0xfa, 0xf1}, {0xf0, 0xfa, 0xf1}, {0xf1, 0xfa, 0xf1}, + {0xf1, 0xfa, 0xf1}, {0xf1, 0xfa, 0xf1}, {0xf1, 0xfa, 0xf1}, {0xf1, 0xfa, 0xf1}, {0xf2, 0xfb, 0xf1}, {0xf2, 0xfb, 0xf1}, + {0xf2, 0xfb, 0xf1}, {0xf2, 0xfb, 0xf1}, {0xf2, 0xfb, 0xf0}, {0xf2, 0xfb, 0xf0}, {0xf3, 0xfb, 0xf0}, {0xf3, 0xfb, 0xf0}, + {0xf3, 0xfb, 0xf0}, {0xf3, 0xfb, 0xf0}, {0xf3, 0xfb, 0xf0}, {0xf3, 0xfb, 0xf0}, {0xf4, 0xfb, 0xf0}, {0xf4, 0xfb, 0xf0}, + {0xf4, 0xfb, 0xf0}, {0xf4, 0xfb, 0xf0}, {0xf4, 0xfb, 0xf0}, {0xf4, 0xfc, 0xf0}, {0xf5, 0xfc, 0xf0}, {0xf5, 0xfc, 0xf0}, + {0xf5, 0xfc, 0xf0}, {0xf5, 0xfc, 0xf0}, {0xf5, 0xfc, 0xf0}, {0xf5, 0xfc, 0xf0}, {0xf6, 0xfc, 0xf0}, {0xf6, 0xfc, 0xf0}, + {0xf6, 0xfc, 0xf0}, {0xf6, 0xfc, 0xf0}, {0xf6, 0xfc, 0xf0}, {0xf7, 0xfc, 0xf0}, {0xf7, 0xfc, 0xf0}, {0xf7, 0xfc, 0xef}, + {0xf7, 0xfc, 0xef}, {0xf7, 0xfc, 0xef}, {0xf7, 0xfc, 0xef}, {0xf8, 0xfd, 0xef}, {0xf8, 0xfd, 0xef}, {0xf8, 0xfd, 0xef}, + {0xf8, 0xfd, 0xef}, {0xf8, 0xfd, 0xef}, {0xf8, 0xfd, 0xef}, {0xf9, 0xfd, 0xef}, {0xf9, 0xfd, 0xef}, {0xf9, 0xfd, 0xef}, + {0xf9, 0xfd, 0xef}, {0xf9, 0xfd, 0xee}, {0xf9, 0xfd, 0xee}, {0xf9, 0xfd, 0xee}, {0xf9, 0xfd, 0xed}, {0xf9, 0xfd, 0xed}, + {0xf9, 0xfd, 0xec}, {0xf9, 0xfd, 0xec}, {0xf9, 0xfc, 0xec}, {0xf9, 0xfc, 0xeb}, {0xf9, 0xfc, 0xeb}, {0xf9, 0xfc, 0xeb}, + {0xf9, 0xfc, 0xea}, {0xf9, 0xfc, 0xea}, {0xf9, 0xfc, 0xe9}, {0xf9, 0xfc, 0xe9}, {0xf9, 0xfc, 0xe9}, {0xf9, 0xfc, 0xe8}, + {0xf9, 0xfc, 0xe8}, {0xf9, 0xfc, 0xe7}, {0xf9, 0xfc, 0xe7}, {0xf9, 0xfc, 0xe7}, {0xf9, 0xfc, 0xe6}, {0xf9, 0xfb, 0xe6}, + {0xf9, 0xfb, 0xe6}, {0xf9, 0xfb, 0xe5}, {0xf9, 0xfb, 0xe5}, {0xf9, 0xfb, 0xe4}, {0xf9, 0xfb, 0xe4}, {0xf9, 0xfb, 0xe4}, + {0xf9, 0xfb, 0xe3}, {0xf9, 0xfb, 0xe3}, {0xf9, 0xfb, 0xe2}, {0xf9, 0xfb, 0xe2}, {0xf9, 0xfb, 0xe2}, {0xf9, 0xfb, 0xe1}, + {0xf9, 0xfb, 0xe1}, {0xf9, 0xfb, 0xe1}, {0xf9, 0xfb, 0xe0}, {0xf9, 0xfa, 0xe0}, {0xf9, 0xfa, 0xdf}, {0xf9, 0xfa, 0xdf}, + {0xf9, 0xfa, 0xdf}, {0xf9, 0xfa, 0xde}, {0xf9, 0xfa, 0xde}, {0xf9, 0xfa, 0xdd}, {0xf9, 0xfa, 0xdd}, {0xf9, 0xfa, 0xdd}, + {0xf9, 0xfa, 0xdc}, {0xf9, 0xfa, 0xdc}, {0xf9, 0xfa, 0xdc}, {0xf9, 0xfa, 0xdb}, {0xf9, 0xfa, 0xdb}, {0xf9, 0xfa, 0xda}, + {0xf9, 0xf9, 0xda}, {0xf9, 0xf9, 0xda}, {0xf9, 0xf9, 0xd9}, {0xf9, 0xf9, 0xd9}, {0xf9, 0xf9, 0xd8}, {0xf9, 0xf9, 0xd8}, + {0xf9, 0xf9, 0xd8}, {0xf9, 0xf9, 0xd7}, {0xf9, 0xf9, 0xd7}, {0xf9, 0xf9, 0xd7}, {0xf9, 0xf9, 0xd6}, {0xf9, 0xf9, 0xd6}, + {0xf9, 0xf9, 0xd5}, {0xf9, 0xf9, 0xd5}, {0xf9, 0xf9, 0xd5}, {0xf9, 0xf9, 0xd4}, {0xf9, 0xf8, 0xd4}, {0xf9, 0xf8, 0xd3}, + {0xf9, 0xf8, 0xd3}, {0xf9, 0xf8, 0xd3}, {0xf9, 0xf8, 0xd2}, {0xf9, 0xf8, 0xd2}, {0xf9, 0xf8, 0xd2}, {0xf9, 0xf8, 0xd1}, + {0xf9, 0xf8, 0xd1}, {0xf9, 0xf8, 0xd0}, {0xf9, 0xf8, 0xd0}, {0xf9, 0xf8, 0xd0}, {0xf9, 0xf8, 0xcf}, {0xf9, 0xf8, 0xcf}, + {0xf9, 0xf8, 0xce}, {0xf9, 0xf7, 0xce}, {0xf9, 0xf7, 0xce}, {0xf9, 0xf7, 0xcd}, {0xf9, 0xf7, 0xcd}, {0xf9, 0xf7, 0xcd}, + {0xf9, 0xf7, 0xcc}, {0xf9, 0xf7, 0xcc}, {0xf9, 0xf7, 0xcb}, {0xf9, 0xf7, 0xcb}, {0xf9, 0xf7, 0xcb}, {0xf9, 0xf7, 0xca}, + {0xf9, 0xf7, 0xca}, {0xf9, 0xf7, 0xc9}, {0xf9, 0xf7, 0xc9}, {0xf9, 0xf7, 0xc9}, {0xf9, 0xf7, 0xc8}, {0xf9, 0xf6, 0xc8}, + {0xf9, 0xf6, 0xc8}, {0xf9, 0xf6, 0xc7}, {0xf9, 0xf6, 0xc7}, {0xf9, 0xf6, 0xc6}, {0xf9, 0xf6, 0xc6}, {0xf9, 0xf6, 0xc6}, + {0xf9, 0xf6, 0xc5}, {0xf9, 0xf6, 0xc5}, {0xf9, 0xf6, 0xc5}, {0xf9, 0xf6, 0xc4}, {0xf9, 0xf6, 0xc4}, {0xf9, 0xf6, 0xc3}, + {0xf9, 0xf6, 0xc3}, {0xf9, 0xf6, 0xc3}, {0xf9, 0xf5, 0xc2}, {0xf9, 0xf5, 0xc2}, {0xf9, 0xf5, 0xc1}, {0xf9, 0xf5, 0xc1}, + {0xf9, 0xf5, 0xc1}, {0xf9, 0xf5, 0xc0}, {0xf9, 0xf5, 0xc0}, {0xf9, 0xf5, 0xc0}, {0xf9, 0xf5, 0xbf}, {0xf9, 0xf5, 0xbf}, + {0xf9, 0xf5, 0xbe}, {0xf9, 0xf5, 0xbe}, {0xf9, 0xf5, 0xbe}, {0xf9, 0xf5, 0xbd}, {0xf9, 0xf5, 0xbd}, {0xf9, 0xf5, 0xbc}, + {0xf9, 0xf4, 0xbc}, {0xf9, 0xf4, 0xbc}, {0xf9, 0xf4, 0xbb}, {0xf9, 0xf4, 0xbb}, {0xf9, 0xf4, 0xbb}, {0xf9, 0xf4, 0xba}, + {0xf9, 0xf4, 0xba}, {0xf9, 0xf4, 0xb9}, {0xf9, 0xf4, 0xb9}, {0xf9, 0xf4, 0xb9}, {0xf9, 0xf4, 0xb8}, {0xf9, 0xf4, 0xb8}, + {0xf9, 0xf4, 0xb7}, {0xf9, 0xf4, 0xb7}, {0xf9, 0xf4, 0xb7}, {0xf9, 0xf3, 0xb6}, {0xf9, 0xf3, 0xb6}, {0xf9, 0xf3, 0xb6}, + {0xf9, 0xf3, 0xb5}, {0xf9, 0xf3, 0xb5}, {0xf9, 0xf3, 0xb4}, {0xf9, 0xf3, 0xb4}, {0xf9, 0xf3, 0xb4}, {0xf9, 0xf3, 0xb3}, + {0xf9, 0xf3, 0xb3}, {0xf9, 0xf3, 0xb2}, {0xf9, 0xf3, 0xb2}, {0xf9, 0xf3, 0xb2}, {0xf9, 0xf3, 0xb1}, {0xf9, 0xf3, 0xb1}, + {0xf9, 0xf3, 0xb1}, {0xf9, 0xf2, 0xb0}, {0xf9, 0xf2, 0xb0}, {0xf9, 0xf2, 0xaf}, {0xf9, 0xf2, 0xaf}, {0xf9, 0xf2, 0xaf}, + {0xf9, 0xf2, 0xae}, {0xf9, 0xf2, 0xae}, {0xf9, 0xf2, 0xad}, {0xf9, 0xf2, 0xad}, {0xf9, 0xf2, 0xad}, {0xf9, 0xf2, 0xac}, + {0xf9, 0xf2, 0xac}, {0xf9, 0xf2, 0xac}, {0xf9, 0xf2, 0xab}, {0xf9, 0xf2, 0xab}, {0xf9, 0xf1, 0xaa}, {0xf9, 0xf1, 0xaa}, + {0xf9, 0xf1, 0xaa}, {0xf9, 0xf1, 0xa9}, {0xf9, 0xf1, 0xa9}, {0xf9, 0xf1, 0xa8}, {0xf9, 0xf1, 0xa8}, {0xf9, 0xf1, 0xa8}, + {0xf9, 0xf1, 0xa7}, {0xf9, 0xf1, 0xa7}, {0xf9, 0xf1, 0xa7}, {0xf9, 0xf1, 0xa6}, {0xf9, 0xf1, 0xa6}, {0xf9, 0xf1, 0xa5}, + {0xf9, 0xf1, 0xa5}, {0xf9, 0xf1, 0xa5}, {0xf9, 0xf0, 0xa4}, {0xf9, 0xf0, 0xa4}, {0xf9, 0xf0, 0xa3}, {0xf9, 0xf0, 0xa3}, + {0xf9, 0xf0, 0xa3}, {0xf9, 0xf0, 0xa2}, {0xf9, 0xf0, 0xa2}, {0xf9, 0xf0, 0xa2}, {0xf9, 0xf0, 0xa1}, {0xf9, 0xf0, 0xa1}, + {0xf9, 0xf0, 0xa0}, {0xf9, 0xf0, 0xa0}, {0xf9, 0xf0, 0xa0}, {0xf9, 0xf0, 0x9f}, {0xf9, 0xf0, 0x9f}, {0xf9, 0xef, 0x9e}, + {0xf9, 0xef, 0x9e}, {0xf9, 0xef, 0x9e}, {0xf9, 0xef, 0x9d}, {0xf9, 0xef, 0x9d}, {0xf9, 0xef, 0x9d}, {0xf9, 0xef, 0x9c}, + {0xf9, 0xef, 0x9c}, {0xf9, 0xef, 0x9b}, {0xf9, 0xef, 0x9b}, {0xf9, 0xef, 0x9b}, {0xf9, 0xef, 0x9a}, {0xf9, 0xef, 0x9a}, + {0xf9, 0xef, 0x9a}, {0xf9, 0xef, 0x99}, {0xf9, 0xef, 0x99}, {0xf9, 0xee, 0x98}, {0xf9, 0xee, 0x98}, {0xf9, 0xee, 0x98}, + {0xf9, 0xee, 0x97}, {0xf9, 0xee, 0x97}, {0xf9, 0xee, 0x96}, {0xf9, 0xee, 0x96}, {0xf9, 0xee, 0x96}, {0xf9, 0xee, 0x95}, + {0xf9, 0xee, 0x95}, {0xf9, 0xee, 0x95}, {0xf9, 0xee, 0x94}, {0xf9, 0xee, 0x94}, {0xf9, 0xee, 0x93}, {0xf9, 0xee, 0x93}, + {0xf9, 0xed, 0x93}, {0xf9, 0xed, 0x92}, {0xf9, 0xed, 0x92}, {0xf9, 0xed, 0x91}, {0xf9, 0xed, 0x91}, {0xf9, 0xed, 0x91}, + {0xf9, 0xed, 0x90}, {0xf9, 0xed, 0x90}, {0xf9, 0xed, 0x90}, {0xf9, 0xed, 0x8f}, {0xf9, 0xed, 0x8f}, {0xf9, 0xed, 0x8e}, + {0xf9, 0xed, 0x8e}, {0xf9, 0xed, 0x8e}, {0xf9, 0xed, 0x8d}, {0xf9, 0xed, 0x8d}, {0xf9, 0xec, 0x8c}, {0xf9, 0xec, 0x8c}, + {0xf9, 0xec, 0x8c}, {0xf9, 0xec, 0x8b}, {0xf9, 0xec, 0x8b}, {0xf9, 0xec, 0x8b}, {0xf9, 0xec, 0x8a}, {0xf9, 0xec, 0x8a}, + {0xf9, 0xec, 0x89}, {0xf9, 0xec, 0x89}, {0xf9, 0xec, 0x89}, {0xf9, 0xec, 0x88}, {0xf9, 0xec, 0x88}, {0xf9, 0xec, 0x87}, + {0xf9, 0xec, 0x87}, {0xf9, 0xeb, 0x87}, {0xf9, 0xeb, 0x86}, {0xf9, 0xeb, 0x86}, {0xf9, 0xeb, 0x86}, {0xf9, 0xeb, 0x85}, + {0xf9, 0xeb, 0x85}, {0xf9, 0xeb, 0x84}, {0xf9, 0xeb, 0x84}, {0xf9, 0xeb, 0x84}, {0xf9, 0xeb, 0x83}, {0xf9, 0xeb, 0x83}, + {0xf9, 0xeb, 0x82}, {0xf9, 0xeb, 0x82}, {0xf9, 0xeb, 0x82}, {0xf9, 0xeb, 0x81}, {0xf9, 0xeb, 0x81}, {0xf9, 0xea, 0x81}, + {0xf9, 0xea, 0x80}, {0xf9, 0xea, 0x80}, {0xf9, 0xea, 0x7f}, {0xf9, 0xea, 0x7f}, {0xf9, 0xea, 0x7f}, {0xf9, 0xea, 0x7e}, + {0xf9, 0xea, 0x7e}, {0xf9, 0xea, 0x7d}, {0xf9, 0xea, 0x7d}, {0xf9, 0xea, 0x7d}, {0xf9, 0xea, 0x7c}, {0xf9, 0xea, 0x7c}, + {0xf9, 0xea, 0x7c}, {0xf9, 0xea, 0x7b}, {0xf9, 0xe9, 0x7b}, {0xf9, 0xe9, 0x7a}, {0xf9, 0xe9, 0x7a}, {0xf9, 0xe9, 0x7a}, + {0xf9, 0xe9, 0x79}, {0xf9, 0xe9, 0x79}, {0xf9, 0xe9, 0x78}, {0xf9, 0xe9, 0x78}, {0xf9, 0xe9, 0x78}, {0xf9, 0xe9, 0x77}, + {0xf9, 0xe9, 0x77}, {0xf9, 0xe9, 0x77}, {0xf9, 0xe9, 0x76}, {0xf9, 0xe9, 0x76}, {0xf9, 0xe9, 0x75}, {0xf9, 0xe9, 0x75}, + {0xf9, 0xe8, 0x75}, {0xf9, 0xe8, 0x74}, {0xf9, 0xe8, 0x74}, {0xf9, 0xe8, 0x73}, {0xf9, 0xe8, 0x73}, {0xf9, 0xe8, 0x73}, + {0xf9, 0xe8, 0x72}, {0xf9, 0xe8, 0x72}, {0xf9, 0xe8, 0x72}, {0xf9, 0xe8, 0x71}, {0xf9, 0xe8, 0x71}, {0xf9, 0xe8, 0x70}, + {0xf9, 0xe8, 0x70}, {0xf9, 0xe8, 0x70}, {0xf9, 0xe8, 0x6f}, {0xf9, 0xe7, 0x6f}, {0xf9, 0xe7, 0x6e}, {0xf9, 0xe7, 0x6e}, + {0xf9, 0xe7, 0x6e}, {0xf9, 0xe7, 0x6d}, {0xf9, 0xe7, 0x6d}, {0xf9, 0xe7, 0x6d}, {0xf9, 0xe7, 0x6c}, {0xf9, 0xe7, 0x6c}, + {0xf9, 0xe7, 0x6b}, {0xf9, 0xe7, 0x6b}, {0xf9, 0xe7, 0x6b}, {0xf9, 0xe7, 0x6a}, {0xf9, 0xe7, 0x6a}, {0xf9, 0xe7, 0x6a}, + {0xf9, 0xe7, 0x69}, {0xf9, 0xe6, 0x69}, {0xf9, 0xe6, 0x68}, {0xf9, 0xe6, 0x68}, {0xf9, 0xe6, 0x68}, {0xf9, 0xe6, 0x67}, + {0xf9, 0xe6, 0x67}, {0xf9, 0xe6, 0x66}, {0xf9, 0xe6, 0x66}, {0xf9, 0xe6, 0x66}, {0xf9, 0xe6, 0x65}, {0xf9, 0xe6, 0x65}, + {0xf9, 0xe6, 0x65}, {0xf9, 0xe6, 0x64}, {0xf9, 0xe6, 0x64}, {0xf9, 0xe6, 0x63}, {0xf9, 0xe5, 0x63}, {0xf9, 0xe5, 0x63}, + {0xf9, 0xe5, 0x62}, {0xf9, 0xe5, 0x62}, {0xf9, 0xe5, 0x61}, {0xf9, 0xe5, 0x61}, {0xf9, 0xe5, 0x61}, {0xf9, 0xe5, 0x60}, + {0xf9, 0xe5, 0x60}, {0xf9, 0xe5, 0x60}, {0xf9, 0xe5, 0x5f}, {0xf9, 0xe5, 0x5f}, {0xf9, 0xe4, 0x5f}, {0xf9, 0xe4, 0x5f}, + {0xf9, 0xe4, 0x5e}, {0xf9, 0xe4, 0x5e}, {0xf9, 0xe4, 0x5e}, {0xf9, 0xe4, 0x5e}, {0xf9, 0xe4, 0x5e}, {0xf9, 0xe3, 0x5d}, + {0xf9, 0xe3, 0x5d}, {0xf9, 0xe3, 0x5d}, {0xf9, 0xe3, 0x5d}, {0xf9, 0xe3, 0x5c}, {0xf9, 0xe3, 0x5c}, {0xf9, 0xe3, 0x5c}, + {0xf9, 0xe2, 0x5c}, {0xf9, 0xe2, 0x5b}, {0xf9, 0xe2, 0x5b}, {0xf9, 0xe2, 0x5b}, {0xf9, 0xe2, 0x5b}, {0xf9, 0xe2, 0x5a}, + {0xf9, 0xe2, 0x5a}, {0xf9, 0xe1, 0x5a}, {0xf9, 0xe1, 0x5a}, {0xf9, 0xe1, 0x59}, {0xf9, 0xe1, 0x59}, {0xf9, 0xe1, 0x59}, + {0xf9, 0xe1, 0x59}, {0xf9, 0xe1, 0x58}, {0xf9, 0xe0, 0x58}, {0xf9, 0xe0, 0x58}, {0xf9, 0xe0, 0x58}, {0xf9, 0xe0, 0x58}, + {0xf9, 0xe0, 0x57}, {0xf9, 0xe0, 0x57}, {0xf9, 0xe0, 0x57}, {0xf9, 0xdf, 0x57}, {0xf9, 0xdf, 0x56}, {0xf9, 0xdf, 0x56}, + {0xf9, 0xdf, 0x56}, {0xf9, 0xdf, 0x56}, {0xf9, 0xdf, 0x55}, {0xf9, 0xdf, 0x55}, {0xf9, 0xde, 0x55}, {0xf9, 0xde, 0x55}, + {0xf9, 0xde, 0x54}, {0xf9, 0xde, 0x54}, {0xf9, 0xde, 0x54}, {0xf9, 0xde, 0x54}, {0xf9, 0xde, 0x53}, {0xf9, 0xdd, 0x53}, + {0xf9, 0xdd, 0x53}, {0xf9, 0xdd, 0x53}, {0xf9, 0xdd, 0x52}, {0xf9, 0xdd, 0x52}, {0xf9, 0xdd, 0x52}, {0xf9, 0xdd, 0x52}, + {0xf9, 0xdc, 0x52}, {0xf9, 0xdc, 0x51}, {0xf9, 0xdc, 0x51}, {0xf9, 0xdc, 0x51}, {0xf9, 0xdc, 0x51}, {0xf9, 0xdc, 0x50}, + {0xf9, 0xdc, 0x50}, {0xf9, 0xdb, 0x50}, {0xf9, 0xdb, 0x50}, {0xf9, 0xdb, 0x4f}, {0xf9, 0xdb, 0x4f}, {0xf9, 0xdb, 0x4f}, + {0xf9, 0xdb, 0x4f}, {0xf9, 0xdb, 0x4e}, {0xf9, 0xda, 0x4e}, {0xf9, 0xda, 0x4e}, {0xf9, 0xda, 0x4e}, {0xf9, 0xda, 0x4d}, + {0xf9, 0xda, 0x4d}, {0xf9, 0xda, 0x4d}, {0xf9, 0xda, 0x4d}, {0xf9, 0xd9, 0x4c}, {0xf9, 0xd9, 0x4c}, {0xf9, 0xd9, 0x4c}, + {0xf9, 0xd9, 0x4c}, {0xf9, 0xd9, 0x4b}, {0xf9, 0xd9, 0x4b}, {0xf9, 0xd9, 0x4b}, {0xf9, 0xd8, 0x4b}, {0xf9, 0xd8, 0x4b}, + {0xf9, 0xd8, 0x4a}, {0xf9, 0xd8, 0x4a}, {0xf9, 0xd8, 0x4a}, {0xf9, 0xd8, 0x4a}, {0xf9, 0xd8, 0x49}, {0xf9, 0xd7, 0x49}, + {0xf9, 0xd7, 0x49}, {0xf9, 0xd7, 0x49}, {0xf9, 0xd7, 0x48}, {0xf9, 0xd7, 0x48}, {0xf9, 0xd7, 0x48}, {0xf9, 0xd7, 0x48}, + {0xf9, 0xd6, 0x47}, {0xf9, 0xd6, 0x47}, {0xf9, 0xd6, 0x47}, {0xf9, 0xd6, 0x47}, {0xf9, 0xd6, 0x46}, {0xf9, 0xd6, 0x46}, + {0xf9, 0xd6, 0x46}, {0xf9, 0xd5, 0x46}, {0xf9, 0xd5, 0x45}, {0xf9, 0xd5, 0x45}, {0xf9, 0xd5, 0x45}, {0xf9, 0xd5, 0x45}, + {0xf9, 0xd5, 0x45}, {0xf9, 0xd5, 0x44}, {0xf9, 0xd4, 0x44}, {0xf9, 0xd4, 0x44}, {0xf9, 0xd4, 0x44}, {0xf9, 0xd4, 0x43}, + {0xf9, 0xd4, 0x43}, {0xf9, 0xd4, 0x43}, {0xf9, 0xd4, 0x43}, {0xf9, 0xd3, 0x42}, {0xf9, 0xd3, 0x42}, {0xf9, 0xd3, 0x42}, + {0xf9, 0xd3, 0x42}, {0xf9, 0xd3, 0x41}, {0xf9, 0xd3, 0x41}, {0xf9, 0xd3, 0x41}, {0xf9, 0xd2, 0x41}, {0xf9, 0xd2, 0x40}, + {0xf9, 0xd2, 0x40}, {0xf9, 0xd2, 0x40}, {0xf9, 0xd2, 0x40}, {0xf9, 0xd2, 0x3f}, {0xf9, 0xd2, 0x3f}, {0xf9, 0xd1, 0x3f}, + {0xf9, 0xd1, 0x3f}, {0xf9, 0xd1, 0x3f}, {0xf9, 0xd1, 0x3e}, {0xf9, 0xd1, 0x3e}, {0xf9, 0xd1, 0x3e}, {0xf9, 0xd1, 0x3e}, + {0xf9, 0xd0, 0x3d}, {0xf9, 0xd0, 0x3d}, {0xf9, 0xd0, 0x3d}, {0xf9, 0xd0, 0x3d}, {0xf9, 0xd0, 0x3c}, {0xf9, 0xd0, 0x3c}, + {0xf9, 0xd0, 0x3c}, {0xf9, 0xcf, 0x3c}, {0xf9, 0xcf, 0x3b}, {0xf9, 0xcf, 0x3b}, {0xf9, 0xcf, 0x3b}, {0xf9, 0xcf, 0x3b}, + {0xf9, 0xcf, 0x3a}, {0xf9, 0xcf, 0x3a}, {0xf9, 0xce, 0x3a}, {0xf9, 0xce, 0x3a}, {0xf9, 0xce, 0x39}, {0xf9, 0xce, 0x39}, + {0xf9, 0xce, 0x39}, {0xf9, 0xce, 0x39}, {0xf9, 0xce, 0x38}, {0xf9, 0xcd, 0x38}, {0xf9, 0xcd, 0x38}, {0xf9, 0xcd, 0x38}, + {0xf9, 0xcd, 0x38}, {0xf9, 0xcd, 0x37}, {0xf9, 0xcd, 0x37}, {0xf9, 0xcd, 0x37}, {0xf9, 0xcc, 0x37}, {0xf9, 0xcc, 0x36}, + {0xf9, 0xcc, 0x36}, {0xf9, 0xcc, 0x36}, {0xf9, 0xcc, 0x36}, {0xf9, 0xcc, 0x35}, {0xf9, 0xcc, 0x35}, {0xf9, 0xcb, 0x35}, + {0xf9, 0xcb, 0x35}, {0xf9, 0xcb, 0x34}, {0xf9, 0xcb, 0x34}, {0xf9, 0xcb, 0x34}, {0xf9, 0xcb, 0x34}, {0xf9, 0xcb, 0x33}, + {0xf9, 0xca, 0x33}, {0xf9, 0xca, 0x33}, {0xf9, 0xca, 0x33}, {0xf9, 0xca, 0x32}, {0xf9, 0xca, 0x32}, {0xf9, 0xca, 0x32}, + {0xf9, 0xca, 0x32}, {0xf9, 0xc9, 0x32}, {0xf9, 0xc9, 0x31}, {0xf9, 0xc9, 0x31}, {0xf9, 0xc9, 0x31}, {0xf9, 0xc9, 0x31}, + {0xf9, 0xc9, 0x30}, {0xf9, 0xc9, 0x30}, {0xf9, 0xc8, 0x30}, {0xf9, 0xc8, 0x30}, {0xf9, 0xc8, 0x2f}, {0xf9, 0xc8, 0x2f}, + {0xf9, 0xc8, 0x2f}, {0xf9, 0xc8, 0x2f}, {0xf9, 0xc8, 0x2e}, {0xf9, 0xc7, 0x2e}, {0xf9, 0xc7, 0x2e}, {0xf9, 0xc7, 0x2e}, + {0xf9, 0xc7, 0x2d}, {0xf9, 0xc7, 0x2d}, {0xf9, 0xc7, 0x2d}, {0xf9, 0xc7, 0x2d}, {0xf9, 0xc6, 0x2c}, {0xf9, 0xc6, 0x2c}, + {0xf9, 0xc6, 0x2c}, {0xf9, 0xc6, 0x2c}, {0xf9, 0xc6, 0x2b}, {0xf9, 0xc6, 0x2b}, {0xf9, 0xc6, 0x2b}, {0xf9, 0xc5, 0x2b}, + {0xf9, 0xc5, 0x2b}, {0xf9, 0xc5, 0x2a}, {0xf9, 0xc5, 0x2a}, {0xf9, 0xc5, 0x2a}, {0xf9, 0xc5, 0x2a}, {0xf9, 0xc5, 0x29}, + {0xf9, 0xc4, 0x29}, {0xf9, 0xc4, 0x29}, {0xf9, 0xc4, 0x29}, {0xf9, 0xc4, 0x28}, {0xf9, 0xc4, 0x28}, {0xf9, 0xc4, 0x28}, + {0xf9, 0xc4, 0x28}, {0xf9, 0xc3, 0x27}, {0xf9, 0xc3, 0x27}, {0xf9, 0xc3, 0x27}, {0xf9, 0xc3, 0x27}, {0xf9, 0xc3, 0x26}, + {0xf9, 0xc3, 0x26}, {0xf9, 0xc3, 0x26}, {0xf9, 0xc2, 0x26}, {0xf9, 0xc2, 0x25}, {0xf9, 0xc2, 0x25}, {0xf9, 0xc2, 0x25}, + {0xf9, 0xc2, 0x25}, {0xf9, 0xc2, 0x25}, {0xf9, 0xc2, 0x24}, {0xf9, 0xc1, 0x24}, {0xf9, 0xc1, 0x24}, {0xf9, 0xc1, 0x24}, + {0xf9, 0xc1, 0x23}, {0xf9, 0xc1, 0x23}, {0xf9, 0xc1, 0x23}, {0xf9, 0xc1, 0x23}, {0xf9, 0xc0, 0x22}, {0xf9, 0xc0, 0x22}, + {0xf9, 0xc0, 0x22}, {0xf9, 0xc0, 0x22}, {0xf9, 0xc0, 0x21}, {0xf9, 0xc0, 0x21}, {0xf9, 0xc0, 0x21}, {0xf9, 0xbf, 0x21}, + {0xf9, 0xbf, 0x20}, {0xf9, 0xbf, 0x20}, {0xf9, 0xbf, 0x20}, {0xf9, 0xbf, 0x20}, {0xf9, 0xbf, 0x1f}, {0xf9, 0xbf, 0x1f}, + {0xf9, 0xbe, 0x1f}, {0xf9, 0xbe, 0x1f}, {0xf9, 0xbe, 0x1f}, {0xf9, 0xbe, 0x1e}, {0xf9, 0xbe, 0x1e}, {0xf9, 0xbe, 0x1e}, + {0xf9, 0xbe, 0x1e}, {0xf9, 0xbd, 0x1d}, {0xf9, 0xbd, 0x1d}, {0xf9, 0xbd, 0x1d}, {0xf9, 0xbd, 0x1d}, {0xf9, 0xbd, 0x1c}, + {0xf9, 0xbd, 0x1c}, {0xf9, 0xbd, 0x1c}, {0xf9, 0xbc, 0x1c}, {0xf9, 0xbc, 0x1b}, {0xf9, 0xbc, 0x1b}, {0xf9, 0xbc, 0x1b}, + {0xf9, 0xbc, 0x1b}, {0xf9, 0xbc, 0x1a}, {0xf9, 0xbc, 0x1a}, {0xf9, 0xbb, 0x1a}, {0xf9, 0xbb, 0x1a}, {0xf9, 0xbb, 0x19}, + {0xf9, 0xbb, 0x19}, {0xf9, 0xbb, 0x19}, {0xf9, 0xbb, 0x19}, {0xf9, 0xbb, 0x18}, {0xf9, 0xba, 0x18}, {0xf9, 0xba, 0x18}, + {0xf9, 0xba, 0x18}, {0xf9, 0xba, 0x18}, {0xf9, 0xba, 0x17}, {0xf9, 0xba, 0x17}, {0xf9, 0xba, 0x17}, {0xf9, 0xb9, 0x17}, + {0xf9, 0xb9, 0x16}, {0xf9, 0xb9, 0x16}, {0xf9, 0xb9, 0x16}, {0xf9, 0xb9, 0x16}, {0xf9, 0xb9, 0x15}, {0xf9, 0xb9, 0x15}, + {0xf9, 0xb8, 0x15}, {0xf9, 0xb8, 0x15}, {0xf9, 0xb8, 0x14}, {0xf9, 0xb8, 0x14}, {0xf9, 0xb8, 0x14}, {0xf9, 0xb8, 0x14}, + {0xf9, 0xb8, 0x13}, {0xf9, 0xb7, 0x13}, {0xf9, 0xb7, 0x13}, {0xf9, 0xb7, 0x13}, {0xf9, 0xb7, 0x12}, {0xf9, 0xb7, 0x12}, + {0xf9, 0xb7, 0x12}, {0xf9, 0xb7, 0x12}, {0xf9, 0xb6, 0x12}, {0xf9, 0xb6, 0x11}, {0xf9, 0xb6, 0x11}, {0xf9, 0xb6, 0x11}, + {0xf9, 0xb6, 0x11}, {0xf9, 0xb6, 0x10}, {0xf9, 0xb6, 0x10}, {0xf9, 0xb5, 0x10}, {0xf9, 0xb5, 0x10}, {0xf9, 0xb5, 0x0f}, + {0xf9, 0xb5, 0x0f}, {0xf9, 0xb5, 0x0f}, {0xf9, 0xb5, 0x0f}, {0xf9, 0xb4, 0x0f}, {0xf9, 0xb4, 0x0f}, {0xf9, 0xb4, 0x0f}, + {0xf8, 0xb4, 0x0f}, {0xf8, 0xb3, 0x0f}, {0xf8, 0xb3, 0x0f}, {0xf8, 0xb3, 0x0f}, {0xf8, 0xb3, 0x0f}, {0xf8, 0xb3, 0x0f}, + {0xf8, 0xb2, 0x0f}, {0xf8, 0xb2, 0x0f}, {0xf8, 0xb2, 0x0e}, {0xf7, 0xb2, 0x0e}, {0xf7, 0xb1, 0x0e}, {0xf7, 0xb1, 0x0e}, + {0xf7, 0xb1, 0x0e}, {0xf7, 0xb1, 0x0e}, {0xf7, 0xb0, 0x0e}, {0xf7, 0xb0, 0x0e}, {0xf7, 0xb0, 0x0e}, {0xf7, 0xb0, 0x0e}, + {0xf7, 0xaf, 0x0e}, {0xf6, 0xaf, 0x0e}, {0xf6, 0xaf, 0x0e}, {0xf6, 0xaf, 0x0e}, {0xf6, 0xaf, 0x0e}, {0xf6, 0xae, 0x0e}, + {0xf6, 0xae, 0x0e}, {0xf6, 0xae, 0x0e}, {0xf6, 0xae, 0x0e}, {0xf6, 0xad, 0x0e}, {0xf6, 0xad, 0x0e}, {0xf5, 0xad, 0x0e}, + {0xf5, 0xad, 0x0e}, {0xf5, 0xac, 0x0e}, {0xf5, 0xac, 0x0e}, {0xf5, 0xac, 0x0e}, {0xf5, 0xac, 0x0d}, {0xf5, 0xab, 0x0d}, + {0xf5, 0xab, 0x0d}, {0xf5, 0xab, 0x0d}, {0xf5, 0xab, 0x0d}, {0xf4, 0xaa, 0x0d}, {0xf4, 0xaa, 0x0d}, {0xf4, 0xaa, 0x0d}, + {0xf4, 0xaa, 0x0d}, {0xf4, 0xaa, 0x0d}, {0xf4, 0xa9, 0x0d}, {0xf4, 0xa9, 0x0d}, {0xf4, 0xa9, 0x0d}, {0xf4, 0xa9, 0x0d}, + {0xf3, 0xa8, 0x0d}, {0xf3, 0xa8, 0x0d}, {0xf3, 0xa8, 0x0d}, {0xf3, 0xa8, 0x0d}, {0xf3, 0xa7, 0x0d}, {0xf3, 0xa7, 0x0d}, + {0xf3, 0xa7, 0x0d}, {0xf3, 0xa7, 0x0d}, {0xf3, 0xa6, 0x0d}, {0xf3, 0xa6, 0x0d}, {0xf2, 0xa6, 0x0d}, {0xf2, 0xa6, 0x0c}, + {0xf2, 0xa6, 0x0c}, {0xf2, 0xa5, 0x0c}, {0xf2, 0xa5, 0x0c}, {0xf2, 0xa5, 0x0c}, {0xf2, 0xa5, 0x0c}, {0xf2, 0xa4, 0x0c}, + {0xf2, 0xa4, 0x0c}, {0xf2, 0xa4, 0x0c}, {0xf1, 0xa4, 0x0c}, {0xf1, 0xa3, 0x0c}, {0xf1, 0xa3, 0x0c}, {0xf1, 0xa3, 0x0c}, + {0xf1, 0xa3, 0x0c}, {0xf1, 0xa2, 0x0c}, {0xf1, 0xa2, 0x0c}, {0xf1, 0xa2, 0x0c}, {0xf1, 0xa2, 0x0c}, {0xf0, 0xa2, 0x0c}, + {0xf0, 0xa1, 0x0c}, {0xf0, 0xa1, 0x0c}, {0xf0, 0xa1, 0x0c}, {0xf0, 0xa1, 0x0c}, {0xf0, 0xa0, 0x0c}, {0xf0, 0xa0, 0x0c}, + {0xf0, 0xa0, 0x0c}, {0xf0, 0xa0, 0x0b}, {0xf0, 0x9f, 0x0b}, {0xef, 0x9f, 0x0b}, {0xef, 0x9f, 0x0b}, {0xef, 0x9f, 0x0b}, + {0xef, 0x9e, 0x0b}, {0xef, 0x9e, 0x0b}, {0xef, 0x9e, 0x0b}, {0xef, 0x9e, 0x0b}, {0xef, 0x9e, 0x0b}, {0xef, 0x9d, 0x0b}, + {0xef, 0x9d, 0x0b}, {0xee, 0x9d, 0x0b}, {0xee, 0x9d, 0x0b}, {0xee, 0x9c, 0x0b}, {0xee, 0x9c, 0x0b}, {0xee, 0x9c, 0x0b}, + {0xee, 0x9c, 0x0b}, {0xee, 0x9b, 0x0b}, {0xee, 0x9b, 0x0b}, {0xee, 0x9b, 0x0b}, {0xed, 0x9b, 0x0b}, {0xed, 0x9a, 0x0b}, + {0xed, 0x9a, 0x0b}, {0xed, 0x9a, 0x0b}, {0xed, 0x9a, 0x0b}, {0xed, 0x9a, 0x0a}, {0xed, 0x99, 0x0a}, {0xed, 0x99, 0x0a}, + {0xed, 0x99, 0x0a}, {0xed, 0x99, 0x0a}, {0xec, 0x98, 0x0a}, {0xec, 0x98, 0x0a}, {0xec, 0x98, 0x0a}, {0xec, 0x98, 0x0a}, + {0xec, 0x97, 0x0a}, {0xec, 0x97, 0x0a}, {0xec, 0x97, 0x0a}, {0xec, 0x97, 0x0a}, {0xec, 0x96, 0x0a}, {0xec, 0x96, 0x0a}, + {0xeb, 0x96, 0x0a}, {0xeb, 0x96, 0x0a}, {0xeb, 0x96, 0x0a}, {0xeb, 0x95, 0x0a}, {0xeb, 0x95, 0x0a}, {0xeb, 0x95, 0x0a}, + {0xeb, 0x95, 0x0a}, {0xeb, 0x94, 0x0a}, {0xeb, 0x94, 0x0a}, {0xea, 0x94, 0x0a}, {0xea, 0x94, 0x0a}, {0xea, 0x93, 0x09}, + {0xea, 0x93, 0x09}, {0xea, 0x93, 0x09}, {0xea, 0x93, 0x09}, {0xea, 0x92, 0x09}, {0xea, 0x92, 0x09}, {0xea, 0x92, 0x09}, + {0xea, 0x92, 0x09}, {0xe9, 0x92, 0x09}, {0xe9, 0x91, 0x09}, {0xe9, 0x91, 0x09}, {0xe9, 0x91, 0x09}, {0xe9, 0x91, 0x09}, + {0xe9, 0x90, 0x09}, {0xe9, 0x90, 0x09}, {0xe9, 0x90, 0x09}, {0xe9, 0x90, 0x09}, {0xe9, 0x8f, 0x09}, {0xe8, 0x8f, 0x09}, + {0xe8, 0x8f, 0x09}, {0xe8, 0x8f, 0x09}, {0xe8, 0x8e, 0x09}, {0xe8, 0x8e, 0x09}, {0xe8, 0x8e, 0x09}, {0xe8, 0x8e, 0x09}, + {0xe8, 0x8e, 0x09}, {0xe8, 0x8d, 0x08}, {0xe7, 0x8d, 0x08}, {0xe7, 0x8d, 0x08}, {0xe7, 0x8d, 0x08}, {0xe7, 0x8c, 0x08}, + {0xe7, 0x8c, 0x08}, {0xe7, 0x8c, 0x08}, {0xe7, 0x8c, 0x08}, {0xe7, 0x8b, 0x08}, {0xe7, 0x8b, 0x08}, {0xe7, 0x8b, 0x08}, + {0xe6, 0x8b, 0x08}, {0xe6, 0x8a, 0x08}, {0xe6, 0x8a, 0x08}, {0xe6, 0x8a, 0x08}, {0xe6, 0x8a, 0x08}, {0xe6, 0x89, 0x08}, + {0xe6, 0x89, 0x08}, {0xe6, 0x89, 0x08}, {0xe6, 0x89, 0x08}, {0xe6, 0x89, 0x08}, {0xe5, 0x88, 0x08}, {0xe5, 0x88, 0x08}, + {0xe5, 0x88, 0x08}, {0xe5, 0x88, 0x08}, {0xe5, 0x87, 0x07}, {0xe5, 0x87, 0x07}, {0xe5, 0x87, 0x07}, {0xe5, 0x87, 0x07}, + {0xe5, 0x86, 0x07}, {0xe4, 0x86, 0x07}, {0xe4, 0x86, 0x07}, {0xe4, 0x86, 0x07}, {0xe4, 0x85, 0x07}, {0xe4, 0x85, 0x07}, + {0xe4, 0x85, 0x07}, {0xe4, 0x85, 0x07}, {0xe4, 0x85, 0x07}, {0xe4, 0x84, 0x07}, {0xe4, 0x84, 0x07}, {0xe3, 0x84, 0x07}, + {0xe3, 0x84, 0x07}, {0xe3, 0x83, 0x07}, {0xe3, 0x83, 0x07}, {0xe3, 0x83, 0x07}, {0xe3, 0x83, 0x07}, {0xe3, 0x82, 0x07}, + {0xe3, 0x82, 0x07}, {0xe3, 0x82, 0x07}, {0xe3, 0x82, 0x07}, {0xe2, 0x81, 0x07}, {0xe2, 0x81, 0x06}, {0xe2, 0x81, 0x06}, + {0xe2, 0x81, 0x06}, {0xe2, 0x81, 0x06}, {0xe2, 0x80, 0x06}, {0xe2, 0x80, 0x06}, {0xe2, 0x80, 0x06}, {0xe2, 0x80, 0x06}, + {0xe1, 0x7f, 0x06}, {0xe1, 0x7f, 0x06}, {0xe1, 0x7f, 0x06}, {0xe1, 0x7f, 0x06}, {0xe1, 0x7e, 0x06}, {0xe1, 0x7e, 0x06}, + {0xe1, 0x7e, 0x06}, {0xe1, 0x7e, 0x06}, {0xe1, 0x7d, 0x06}, {0xe1, 0x7d, 0x06}, {0xe0, 0x7d, 0x06}, {0xe0, 0x7d, 0x06}, + {0xe0, 0x7d, 0x06}, {0xe0, 0x7c, 0x06}, {0xe0, 0x7c, 0x06}, {0xe0, 0x7c, 0x06}, {0xe0, 0x7c, 0x06}, {0xe0, 0x7b, 0x06}, + {0xe0, 0x7b, 0x05}, {0xe0, 0x7b, 0x05}, {0xdf, 0x7b, 0x05}, {0xdf, 0x7a, 0x05}, {0xdf, 0x7a, 0x05}, {0xdf, 0x7a, 0x05}, + {0xdf, 0x7a, 0x05}, {0xdf, 0x79, 0x05}, {0xdf, 0x79, 0x05}, {0xdf, 0x79, 0x05}, {0xdf, 0x79, 0x05}, {0xde, 0x79, 0x05}, + {0xde, 0x78, 0x05}, {0xde, 0x78, 0x05}, {0xde, 0x78, 0x05}, {0xde, 0x78, 0x05}, {0xde, 0x77, 0x05}, {0xde, 0x77, 0x05}, + {0xde, 0x77, 0x05}, {0xde, 0x77, 0x05}, {0xde, 0x76, 0x05}, {0xdd, 0x76, 0x05}, {0xdd, 0x76, 0x05}, {0xdd, 0x76, 0x05}, + {0xdd, 0x75, 0x05}, {0xdd, 0x75, 0x05}, {0xdd, 0x75, 0x04}, {0xdd, 0x75, 0x04}, {0xdd, 0x75, 0x04}, {0xdd, 0x74, 0x04}, + {0xdd, 0x74, 0x04}, {0xdc, 0x74, 0x04}, {0xdc, 0x74, 0x04}, {0xdc, 0x73, 0x04}, {0xdc, 0x73, 0x04}, {0xdc, 0x73, 0x04}, + {0xdc, 0x73, 0x04}, {0xdc, 0x72, 0x04}, {0xdc, 0x72, 0x04}, {0xdc, 0x72, 0x04}, {0xdb, 0x72, 0x04}, {0xdb, 0x71, 0x04}, + {0xdb, 0x71, 0x04}, {0xdb, 0x71, 0x04}, {0xdb, 0x71, 0x04}, {0xdb, 0x71, 0x04}, {0xdb, 0x70, 0x04}, {0xdb, 0x70, 0x04}, + {0xdb, 0x70, 0x04}, {0xdb, 0x70, 0x04}, {0xda, 0x6f, 0x04}, {0xda, 0x6f, 0x04}, {0xda, 0x6f, 0x03}, {0xda, 0x6f, 0x03}, + {0xda, 0x6e, 0x03}, {0xda, 0x6e, 0x03}, {0xda, 0x6e, 0x03}, {0xda, 0x6e, 0x03}, {0xda, 0x6d, 0x03}, {0xda, 0x6d, 0x03}, + {0xd9, 0x6d, 0x03}, {0xd9, 0x6d, 0x03}, {0xd9, 0x6c, 0x03}, {0xd9, 0x6c, 0x03}, {0xd9, 0x6c, 0x03}, {0xd9, 0x6c, 0x03}, + {0xd8, 0x6b, 0x03}, {0xd8, 0x6b, 0x03}, {0xd8, 0x6b, 0x03}, {0xd8, 0x6b, 0x03}, {0xd7, 0x6a, 0x03}, {0xd7, 0x6a, 0x03}, + {0xd7, 0x6a, 0x03}, {0xd6, 0x6a, 0x03}, {0xd6, 0x69, 0x03}, {0xd6, 0x69, 0x03}, {0xd6, 0x69, 0x03}, {0xd5, 0x69, 0x03}, + {0xd5, 0x68, 0x03}, {0xd5, 0x68, 0x04}, {0xd4, 0x68, 0x04}, {0xd4, 0x68, 0x04}, {0xd4, 0x67, 0x04}, {0xd4, 0x67, 0x04}, + {0xd3, 0x67, 0x04}, {0xd3, 0x66, 0x04}, {0xd3, 0x66, 0x04}, {0xd2, 0x66, 0x04}, {0xd2, 0x66, 0x04}, {0xd2, 0x65, 0x04}, + {0xd2, 0x65, 0x04}, {0xd1, 0x65, 0x04}, {0xd1, 0x65, 0x04}, {0xd1, 0x64, 0x04}, {0xd0, 0x64, 0x04}, {0xd0, 0x64, 0x04}, + {0xd0, 0x64, 0x04}, {0xd0, 0x63, 0x04}, {0xcf, 0x63, 0x04}, {0xcf, 0x63, 0x04}, {0xcf, 0x63, 0x04}, {0xce, 0x62, 0x04}, + {0xce, 0x62, 0x04}, {0xce, 0x62, 0x04}, {0xce, 0x61, 0x04}, {0xcd, 0x61, 0x04}, {0xcd, 0x61, 0x04}, {0xcd, 0x61, 0x04}, + {0xcc, 0x60, 0x05}, {0xcc, 0x60, 0x05}, {0xcc, 0x60, 0x05}, {0xcb, 0x60, 0x05}, {0xcb, 0x5f, 0x05}, {0xcb, 0x5f, 0x05}, + {0xcb, 0x5f, 0x05}, {0xca, 0x5f, 0x05}, {0xca, 0x5e, 0x05}, {0xca, 0x5e, 0x05}, {0xc9, 0x5e, 0x05}, {0xc9, 0x5e, 0x05}, + {0xc9, 0x5d, 0x05}, {0xc9, 0x5d, 0x05}, {0xc8, 0x5d, 0x05}, {0xc8, 0x5c, 0x05}, {0xc8, 0x5c, 0x05}, {0xc7, 0x5c, 0x05}, + {0xc7, 0x5c, 0x05}, {0xc7, 0x5b, 0x05}, {0xc7, 0x5b, 0x05}, {0xc6, 0x5b, 0x05}, {0xc6, 0x5b, 0x05}, {0xc6, 0x5a, 0x05}, + {0xc5, 0x5a, 0x05}, {0xc5, 0x5a, 0x05}, {0xc5, 0x5a, 0x05}, {0xc5, 0x59, 0x05}, {0xc4, 0x59, 0x05}, {0xc4, 0x59, 0x06}, + {0xc4, 0x59, 0x06}, {0xc3, 0x58, 0x06}, {0xc3, 0x58, 0x06}, {0xc3, 0x58, 0x06}, {0xc3, 0x57, 0x06}, {0xc2, 0x57, 0x06}, + {0xc2, 0x57, 0x06}, {0xc2, 0x57, 0x06}, {0xc1, 0x56, 0x06}, {0xc1, 0x56, 0x06}, {0xc1, 0x56, 0x06}, {0xc1, 0x56, 0x06}, + {0xc0, 0x55, 0x06}, {0xc0, 0x55, 0x06}, {0xc0, 0x55, 0x06}, {0xbf, 0x55, 0x06}, {0xbf, 0x54, 0x06}, {0xbf, 0x54, 0x06}, + {0xbf, 0x54, 0x06}, {0xbe, 0x54, 0x06}, {0xbe, 0x53, 0x06}, {0xbe, 0x53, 0x06}, {0xbd, 0x53, 0x06}, {0xbd, 0x52, 0x06}, + {0xbd, 0x52, 0x06}, {0xbd, 0x52, 0x06}, {0xbc, 0x52, 0x06}, {0xbc, 0x51, 0x07}, {0xbc, 0x51, 0x07}, {0xbb, 0x51, 0x07}, + {0xbb, 0x51, 0x07}, {0xbb, 0x50, 0x07}, {0xbb, 0x50, 0x07}, {0xba, 0x50, 0x07}, {0xba, 0x50, 0x07}, {0xba, 0x4f, 0x07}, + {0xb9, 0x4f, 0x07}, {0xb9, 0x4f, 0x07}, {0xb9, 0x4e, 0x07}, {0xb8, 0x4e, 0x07}, {0xb8, 0x4e, 0x07}, {0xb8, 0x4e, 0x07}, + {0xb8, 0x4d, 0x07}, {0xb7, 0x4d, 0x07}, {0xb7, 0x4d, 0x07}, {0xb7, 0x4d, 0x07}, {0xb6, 0x4c, 0x07}, {0xb6, 0x4c, 0x07}, + {0xb6, 0x4c, 0x07}, {0xb6, 0x4c, 0x07}, {0xb5, 0x4b, 0x07}, {0xb5, 0x4b, 0x07}, {0xb5, 0x4b, 0x07}, {0xb4, 0x4b, 0x07}, + {0xb4, 0x4a, 0x07}, {0xb4, 0x4a, 0x07}, {0xb4, 0x4a, 0x08}, {0xb3, 0x49, 0x08}, {0xb3, 0x49, 0x08}, {0xb3, 0x49, 0x08}, + {0xb2, 0x49, 0x08}, {0xb2, 0x48, 0x08}, {0xb2, 0x48, 0x08}, {0xb2, 0x48, 0x08}, {0xb1, 0x48, 0x08}, {0xb1, 0x47, 0x08}, + {0xb1, 0x47, 0x08}, {0xb0, 0x47, 0x08}, {0xb0, 0x47, 0x08}, {0xb0, 0x46, 0x08}, {0xb0, 0x46, 0x08}, {0xaf, 0x46, 0x08}, + {0xaf, 0x46, 0x08}, {0xaf, 0x45, 0x08}, {0xae, 0x45, 0x08}, {0xae, 0x45, 0x08}, {0xae, 0x44, 0x08}, {0xae, 0x44, 0x08}, + {0xad, 0x44, 0x08}, {0xad, 0x44, 0x08}, {0xad, 0x43, 0x08}, {0xac, 0x43, 0x08}, {0xac, 0x43, 0x08}, {0xac, 0x43, 0x08}, + {0xac, 0x42, 0x08}, {0xab, 0x42, 0x09}, {0xab, 0x42, 0x09}, {0xab, 0x42, 0x09}, {0xaa, 0x41, 0x09}, {0xaa, 0x41, 0x09}, + {0xaa, 0x41, 0x09}, {0xaa, 0x41, 0x09}, {0xa9, 0x40, 0x09}, {0xa9, 0x40, 0x09}, {0xa9, 0x40, 0x09}, {0xa8, 0x3f, 0x09}, + {0xa8, 0x3f, 0x09}, {0xa8, 0x3f, 0x09}, {0xa7, 0x3f, 0x09}, {0xa7, 0x3e, 0x09}, {0xa7, 0x3e, 0x09}, {0xa7, 0x3e, 0x09}, + {0xa6, 0x3e, 0x09}, {0xa6, 0x3d, 0x09}, {0xa6, 0x3d, 0x09}, {0xa5, 0x3d, 0x09}, {0xa5, 0x3d, 0x09}, {0xa5, 0x3c, 0x09}, + {0xa5, 0x3c, 0x09}, {0xa4, 0x3c, 0x09}, {0xa4, 0x3c, 0x09}, {0xa4, 0x3b, 0x09}, {0xa3, 0x3b, 0x09}, {0xa3, 0x3b, 0x09}, + {0xa3, 0x3a, 0x0a}, {0xa3, 0x3a, 0x0a}, {0xa2, 0x3a, 0x0a}, {0xa2, 0x3a, 0x0a}, {0xa2, 0x39, 0x0a}, {0xa1, 0x39, 0x0a}, + {0xa1, 0x39, 0x0a}, {0xa1, 0x39, 0x0a}, {0xa1, 0x38, 0x0a}, {0xa0, 0x38, 0x0a}, {0xa0, 0x38, 0x0a}, {0xa0, 0x38, 0x0a}, + {0x9f, 0x37, 0x0a}, {0x9f, 0x37, 0x0a}, {0x9f, 0x37, 0x0a}, {0x9f, 0x36, 0x0a}, {0x9e, 0x36, 0x0a}, {0x9e, 0x36, 0x0a}, + {0x9e, 0x36, 0x0a}, {0x9d, 0x35, 0x0a}, {0x9d, 0x35, 0x0a}, {0x9d, 0x35, 0x0a}, {0x9d, 0x35, 0x0a}, {0x9c, 0x34, 0x0a}, + {0x9c, 0x34, 0x0a}, {0x9c, 0x34, 0x0a}, {0x9b, 0x34, 0x0a}, {0x9b, 0x33, 0x0a}, {0x9b, 0x33, 0x0a}, {0x9b, 0x33, 0x0b}, + {0x9a, 0x33, 0x0b}, {0x9a, 0x32, 0x0b}, {0x9a, 0x32, 0x0b}, {0x99, 0x32, 0x0b}, {0x99, 0x31, 0x0b}, {0x99, 0x31, 0x0b}, + {0x99, 0x31, 0x0b}, {0x98, 0x31, 0x0b}, {0x98, 0x30, 0x0b}, {0x98, 0x30, 0x0b}, {0x97, 0x30, 0x0b}, {0x97, 0x30, 0x0b}, + {0x97, 0x2f, 0x0b}, {0x97, 0x2f, 0x0b}, {0x96, 0x2f, 0x0b}, {0x96, 0x2f, 0x0b}, {0x96, 0x2e, 0x0b}, {0x95, 0x2e, 0x0b}, + {0x95, 0x2e, 0x0b}, {0x95, 0x2e, 0x0b}, {0x94, 0x2d, 0x0b}, {0x94, 0x2d, 0x0b}, {0x94, 0x2d, 0x0b}, {0x94, 0x2c, 0x0b}, + {0x93, 0x2c, 0x0b}, {0x93, 0x2c, 0x0b}, {0x93, 0x2c, 0x0b}, {0x92, 0x2b, 0x0b}, {0x92, 0x2b, 0x0c}, {0x92, 0x2b, 0x0c}, + {0x92, 0x2b, 0x0c}, {0x91, 0x2a, 0x0c}, {0x91, 0x2a, 0x0c}, {0x91, 0x2a, 0x0c}, {0x90, 0x2a, 0x0c}, {0x90, 0x29, 0x0c}, + {0x90, 0x29, 0x0c}, {0x90, 0x29, 0x0c}, {0x8f, 0x29, 0x0c}, {0x8f, 0x28, 0x0c}, {0x8f, 0x28, 0x0c}, {0x8e, 0x28, 0x0c}, + {0x8e, 0x27, 0x0c}, {0x8e, 0x27, 0x0c}, {0x8e, 0x27, 0x0c}, {0x8d, 0x27, 0x0c}, {0x8d, 0x26, 0x0c}, {0x8d, 0x26, 0x0c}, + {0x8c, 0x26, 0x0c}, {0x8c, 0x26, 0x0c}, {0x8c, 0x25, 0x0c}, {0x8c, 0x25, 0x0c}, {0x8b, 0x25, 0x0c}, {0x8b, 0x25, 0x0c}, + {0x8b, 0x24, 0x0c}, {0x8a, 0x24, 0x0c}, {0x8a, 0x24, 0x0d}, {0x8a, 0x24, 0x0d}, {0x8a, 0x23, 0x0d}, {0x89, 0x23, 0x0d}, + {0x89, 0x23, 0x0d}, {0x89, 0x22, 0x0d}, {0x88, 0x22, 0x0d}, {0x88, 0x22, 0x0d}, {0x88, 0x22, 0x0d}, {0x88, 0x21, 0x0d}, + {0x87, 0x21, 0x0d}, {0x87, 0x21, 0x0d}, {0x87, 0x21, 0x0d}, {0x86, 0x20, 0x0d}, {0x86, 0x20, 0x0d}, {0x86, 0x20, 0x0d}, + {0x86, 0x20, 0x0d}, {0x85, 0x20, 0x0d}, {0x85, 0x20, 0x0d}, {0x85, 0x20, 0x0d}, {0x84, 0x1f, 0x0d}, {0x84, 0x1f, 0x0e}, + {0x84, 0x1f, 0x0e}, {0x84, 0x1f, 0x0e}, {0x83, 0x1f, 0x0e}, {0x83, 0x1f, 0x0e}, {0x83, 0x1f, 0x0e}, {0x82, 0x1f, 0x0e}, + {0x82, 0x1f, 0x0e}, {0x82, 0x1e, 0x0e}, {0x82, 0x1e, 0x0e}, {0x81, 0x1e, 0x0e}, {0x81, 0x1e, 0x0e}, {0x81, 0x1e, 0x0f}, + {0x80, 0x1e, 0x0f}, {0x80, 0x1e, 0x0f}, {0x80, 0x1e, 0x0f}, {0x80, 0x1e, 0x0f}, {0x7f, 0x1e, 0x0f}, {0x7f, 0x1d, 0x0f}, + {0x7f, 0x1d, 0x0f}, {0x7e, 0x1d, 0x0f}, {0x7e, 0x1d, 0x0f}, {0x7e, 0x1d, 0x0f}, {0x7e, 0x1d, 0x0f}, {0x7d, 0x1d, 0x0f}, + {0x7d, 0x1d, 0x10}, {0x7d, 0x1d, 0x10}, {0x7c, 0x1d, 0x10}, {0x7c, 0x1c, 0x10}, {0x7c, 0x1c, 0x10}, {0x7c, 0x1c, 0x10}, + {0x7b, 0x1c, 0x10}, {0x7b, 0x1c, 0x10}, {0x7b, 0x1c, 0x10}, {0x7a, 0x1c, 0x10}, {0x7a, 0x1c, 0x10}, {0x7a, 0x1c, 0x10}, + {0x7a, 0x1b, 0x11}, {0x79, 0x1b, 0x11}, {0x79, 0x1b, 0x11}, {0x79, 0x1b, 0x11}, {0x78, 0x1b, 0x11}, {0x78, 0x1b, 0x11}, + {0x78, 0x1b, 0x11}, {0x78, 0x1b, 0x11}, {0x77, 0x1b, 0x11}, {0x77, 0x1b, 0x11}, {0x77, 0x1a, 0x11}, {0x76, 0x1a, 0x11}, + {0x76, 0x1a, 0x12}, {0x76, 0x1a, 0x12}, {0x76, 0x1a, 0x12}, {0x75, 0x1a, 0x12}, {0x75, 0x1a, 0x12}, {0x75, 0x1a, 0x12}, + {0x74, 0x1a, 0x12}, {0x74, 0x1a, 0x12}, {0x74, 0x19, 0x12}, {0x74, 0x19, 0x12}, {0x73, 0x19, 0x12}, {0x73, 0x19, 0x12}, + {0x73, 0x19, 0x13}, {0x72, 0x19, 0x13}, {0x72, 0x19, 0x13}, {0x72, 0x19, 0x13}, {0x72, 0x19, 0x13}, {0x71, 0x18, 0x13}, + {0x71, 0x18, 0x13}, {0x71, 0x18, 0x13}, {0x70, 0x18, 0x13}, {0x70, 0x18, 0x13}, {0x70, 0x18, 0x13}, {0x70, 0x18, 0x13}, + {0x6f, 0x18, 0x13}, {0x6f, 0x18, 0x14}, {0x6f, 0x18, 0x14}, {0x6e, 0x17, 0x14}, {0x6e, 0x17, 0x14}, {0x6e, 0x17, 0x14}, + {0x6e, 0x17, 0x14}, {0x6d, 0x17, 0x14}, {0x6d, 0x17, 0x14}, {0x6d, 0x17, 0x14}, {0x6c, 0x17, 0x14}, {0x6c, 0x17, 0x14}, + {0x6c, 0x17, 0x14}, {0x6c, 0x16, 0x15}, {0x6b, 0x16, 0x15}, {0x6b, 0x16, 0x15}, {0x6b, 0x16, 0x15}, {0x6a, 0x16, 0x15}, + {0x6a, 0x16, 0x15}, {0x6a, 0x16, 0x15}, {0x6a, 0x16, 0x15}, {0x69, 0x16, 0x15}, {0x69, 0x15, 0x15}, {0x69, 0x15, 0x15}, + {0x69, 0x15, 0x15}, {0x68, 0x15, 0x16}, {0x68, 0x15, 0x16}, {0x68, 0x15, 0x16}, {0x67, 0x15, 0x16}, {0x67, 0x15, 0x16}, + {0x67, 0x15, 0x16}, {0x67, 0x15, 0x16}, {0x66, 0x14, 0x16}, {0x66, 0x14, 0x16}, {0x66, 0x14, 0x16}, {0x65, 0x14, 0x16}, + {0x65, 0x14, 0x16}, {0x65, 0x14, 0x16}, {0x65, 0x14, 0x17}, {0x64, 0x14, 0x17}, {0x64, 0x14, 0x17}, {0x64, 0x14, 0x17}, + {0x63, 0x13, 0x17}, {0x63, 0x13, 0x17}, {0x63, 0x13, 0x17}, {0x63, 0x13, 0x17}, {0x62, 0x13, 0x17}, {0x62, 0x13, 0x17}, + {0x62, 0x13, 0x17}, {0x61, 0x13, 0x17}, {0x61, 0x13, 0x18}, {0x61, 0x12, 0x18}, {0x61, 0x12, 0x18}, {0x60, 0x12, 0x18}, + {0x60, 0x12, 0x18}, {0x60, 0x12, 0x18}, {0x5f, 0x12, 0x18}, {0x5f, 0x12, 0x18}, {0x5f, 0x12, 0x18}, {0x5f, 0x12, 0x18}, + {0x5e, 0x12, 0x18}, {0x5e, 0x11, 0x18}, {0x5e, 0x11, 0x19}, {0x5d, 0x11, 0x19}, {0x5d, 0x11, 0x19}, {0x5d, 0x11, 0x19}, + {0x5d, 0x11, 0x19}, {0x5c, 0x11, 0x19}, {0x5c, 0x11, 0x19}, {0x5c, 0x11, 0x19}, {0x5b, 0x11, 0x19}, {0x5b, 0x10, 0x19}, + {0x5b, 0x10, 0x19}, {0x5b, 0x10, 0x19}, {0x5a, 0x10, 0x19}, {0x5a, 0x10, 0x1a}, {0x5a, 0x10, 0x1a}, {0x59, 0x10, 0x1a}, + {0x59, 0x10, 0x1a}, {0x59, 0x10, 0x1a}, {0x59, 0x0f, 0x1a}, {0x58, 0x0f, 0x1a}, {0x58, 0x0f, 0x1a}, {0x58, 0x0f, 0x1a}, + {0x57, 0x0f, 0x1a}, {0x57, 0x0f, 0x1a}, {0x57, 0x0f, 0x1a}, {0x57, 0x0f, 0x1b}, {0x56, 0x0f, 0x1b}, {0x56, 0x0f, 0x1b}, + {0x56, 0x0e, 0x1b}, {0x55, 0x0e, 0x1b}, {0x55, 0x0e, 0x1b}, {0x55, 0x0e, 0x1b}, {0x55, 0x0e, 0x1b}, {0x54, 0x0e, 0x1b}, + {0x54, 0x0e, 0x1b}, {0x54, 0x0e, 0x1b}, {0x53, 0x0e, 0x1b}, {0x53, 0x0e, 0x1c}, {0x53, 0x0d, 0x1c}, {0x53, 0x0d, 0x1c}, + {0x52, 0x0d, 0x1c}, {0x52, 0x0d, 0x1c}, {0x52, 0x0d, 0x1c}, {0x51, 0x0d, 0x1c}, {0x51, 0x0d, 0x1c}, {0x51, 0x0d, 0x1c}, + {0x51, 0x0d, 0x1c}, {0x50, 0x0c, 0x1c}, {0x50, 0x0c, 0x1c}, {0x50, 0x0c, 0x1c}, {0x4f, 0x0c, 0x1d}, {0x4f, 0x0c, 0x1d}, + {0x4f, 0x0c, 0x1d}, {0x4f, 0x0c, 0x1d}, {0x4e, 0x0c, 0x1d}, {0x4e, 0x0c, 0x1d}, {0x4e, 0x0c, 0x1d}, {0x4d, 0x0b, 0x1d}, + {0x4d, 0x0b, 0x1d}, {0x4d, 0x0b, 0x1d}, {0x4d, 0x0b, 0x1d}, {0x4c, 0x0b, 0x1d}, {0x4c, 0x0b, 0x1e}, {0x4c, 0x0b, 0x1e}, + {0x4b, 0x0b, 0x1e}, {0x4b, 0x0b, 0x1e}, {0x4b, 0x0b, 0x1e}, {0x4b, 0x0a, 0x1e}, {0x4a, 0x0a, 0x1e}, {0x4a, 0x0a, 0x1e}, + {0x4a, 0x0a, 0x1e}, {0x49, 0x0a, 0x1e}, {0x49, 0x0a, 0x1e}, {0x49, 0x0a, 0x1e}, {0x49, 0x0a, 0x1f}, {0x48, 0x0a, 0x1f}, + {0x48, 0x09, 0x1f}, {0x48, 0x09, 0x1f}, {0x48, 0x09, 0x1f}, {0x47, 0x09, 0x1f}, {0x47, 0x09, 0x1f}, {0x47, 0x09, 0x1f}, + {0x46, 0x09, 0x1f}, {0x46, 0x09, 0x1f}, {0x46, 0x09, 0x1f}, {0x46, 0x09, 0x1f}, {0x45, 0x08, 0x20}, {0x45, 0x08, 0x20}, + {0x45, 0x08, 0x20}, {0x44, 0x08, 0x20}, {0x44, 0x08, 0x20}, {0x44, 0x08, 0x20}, {0x44, 0x08, 0x20}, {0x43, 0x08, 0x20}, + {0x43, 0x08, 0x20}, {0x43, 0x08, 0x20}, {0x42, 0x07, 0x20}, {0x42, 0x07, 0x20}, {0x42, 0x07, 0x20}, {0x42, 0x07, 0x21}, + {0x41, 0x07, 0x21}, {0x41, 0x07, 0x21}, {0x41, 0x07, 0x21}, {0x40, 0x07, 0x21}, {0x40, 0x07, 0x21}, {0x40, 0x06, 0x21}, + {0x40, 0x06, 0x21}, {0x3f, 0x06, 0x21}, {0x3f, 0x06, 0x21}, {0x3f, 0x06, 0x21}, {0x3e, 0x06, 0x21}, {0x3e, 0x06, 0x22}, + {0x3e, 0x06, 0x22}, {0x3e, 0x06, 0x22}, {0x3d, 0x06, 0x22}, {0x3d, 0x05, 0x22}, {0x3d, 0x05, 0x22}, {0x3c, 0x05, 0x22}, + {0x3c, 0x05, 0x22}, {0x3c, 0x05, 0x22}, {0x3c, 0x05, 0x22}, {0x3b, 0x05, 0x22}, {0x3b, 0x05, 0x22}, {0x3b, 0x05, 0x23}, + {0x3a, 0x05, 0x23}, {0x3a, 0x04, 0x23}, {0x3a, 0x04, 0x23}, {0x3a, 0x04, 0x23}, {0x39, 0x04, 0x23}, {0x39, 0x04, 0x23}, + {0x39, 0x04, 0x23}, {0x39, 0x04, 0x23}, {0x38, 0x04, 0x24}, {0x38, 0x04, 0x24}, {0x38, 0x04, 0x24}, {0x38, 0x04, 0x24}, + {0x38, 0x04, 0x24}, {0x38, 0x04, 0x24}, {0x37, 0x04, 0x25}, {0x37, 0x04, 0x25}, {0x37, 0x04, 0x25}, {0x37, 0x04, 0x25}, + {0x37, 0x04, 0x25}, {0x37, 0x04, 0x26}, {0x36, 0x04, 0x26}, {0x36, 0x04, 0x26}, {0x36, 0x04, 0x26}, {0x36, 0x04, 0x26}, + {0x36, 0x05, 0x26}, {0x36, 0x05, 0x27}, {0x35, 0x05, 0x27}, {0x35, 0x05, 0x27}, {0x35, 0x05, 0x27}, {0x35, 0x05, 0x27}, + {0x35, 0x05, 0x28}, {0x35, 0x05, 0x28}, {0x34, 0x05, 0x28}, {0x34, 0x05, 0x28}, {0x34, 0x05, 0x28}, {0x34, 0x05, 0x29}, + {0x34, 0x05, 0x29}, {0x34, 0x05, 0x29}, {0x33, 0x05, 0x29}, {0x33, 0x05, 0x29}, {0x33, 0x05, 0x29}, {0x33, 0x05, 0x2a}, + {0x33, 0x05, 0x2a}, {0x33, 0x05, 0x2a}, {0x32, 0x05, 0x2a}, {0x32, 0x05, 0x2a}, {0x32, 0x05, 0x2b}, {0x32, 0x05, 0x2b}, + {0x32, 0x05, 0x2b}, {0x32, 0x05, 0x2b}, {0x31, 0x05, 0x2b}, {0x31, 0x05, 0x2b}, {0x31, 0x05, 0x2c}, {0x31, 0x05, 0x2c}, + {0x31, 0x05, 0x2c}, {0x31, 0x05, 0x2c}, {0x30, 0x05, 0x2c}, {0x30, 0x05, 0x2d}, {0x30, 0x05, 0x2d}, {0x30, 0x05, 0x2d}, + {0x30, 0x06, 0x2d}, {0x30, 0x06, 0x2d}, {0x2f, 0x06, 0x2d}, {0x2f, 0x06, 0x2e}, {0x2f, 0x06, 0x2e}, {0x2f, 0x06, 0x2e}, + {0x2f, 0x06, 0x2e}, {0x2f, 0x06, 0x2e}, {0x2e, 0x06, 0x2f}, {0x2e, 0x06, 0x2f}, {0x2e, 0x06, 0x2f}, {0x2e, 0x06, 0x2f}, + {0x2e, 0x06, 0x2f}, {0x2e, 0x06, 0x2f}, {0x2d, 0x06, 0x30}, {0x2d, 0x06, 0x30}, {0x2d, 0x06, 0x30}, {0x2d, 0x06, 0x30}, + {0x2d, 0x06, 0x30}, {0x2d, 0x06, 0x31}, {0x2c, 0x06, 0x31}, {0x2c, 0x06, 0x31}, {0x2c, 0x06, 0x31}, {0x2c, 0x06, 0x31}, + {0x2c, 0x06, 0x32}, {0x2c, 0x06, 0x32}, {0x2b, 0x06, 0x32}, {0x2b, 0x06, 0x32}, {0x2b, 0x06, 0x32}, {0x2b, 0x06, 0x32}, + {0x2b, 0x06, 0x33}, {0x2b, 0x06, 0x33}, {0x2a, 0x06, 0x33}, {0x2a, 0x06, 0x33}, {0x2a, 0x06, 0x33}, {0x2a, 0x06, 0x34}, + {0x2a, 0x06, 0x34}, {0x2a, 0x07, 0x34}, {0x29, 0x07, 0x34}, {0x29, 0x07, 0x34}, {0x29, 0x07, 0x34}, {0x29, 0x07, 0x35}, + {0x29, 0x07, 0x35}, {0x29, 0x07, 0x35}, {0x28, 0x07, 0x35}, {0x28, 0x07, 0x35}, {0x28, 0x07, 0x36}, {0x28, 0x07, 0x36}, + {0x28, 0x07, 0x36}, {0x28, 0x07, 0x36}, {0x27, 0x07, 0x36}, {0x27, 0x07, 0x36}, {0x27, 0x07, 0x37}, {0x27, 0x07, 0x37}, + {0x27, 0x07, 0x37}, {0x27, 0x07, 0x37}, {0x26, 0x07, 0x37}, {0x26, 0x07, 0x38}, {0x26, 0x07, 0x38}, {0x26, 0x07, 0x38}, + {0x26, 0x07, 0x38}, {0x26, 0x07, 0x38}, {0x25, 0x07, 0x38}, {0x25, 0x07, 0x39}, {0x25, 0x07, 0x39}, {0x25, 0x07, 0x39}, + {0x25, 0x07, 0x39}, {0x25, 0x07, 0x39}, {0x24, 0x07, 0x3a}, {0x24, 0x07, 0x3a}, {0x24, 0x07, 0x3a}, {0x24, 0x07, 0x3a}, + {0x24, 0x07, 0x3a}, {0x23, 0x08, 0x3b}, {0x23, 0x08, 0x3b}, {0x23, 0x08, 0x3b}, {0x23, 0x08, 0x3b}, {0x23, 0x08, 0x3b}, + {0x23, 0x08, 0x3b}, {0x22, 0x08, 0x3c}, {0x22, 0x08, 0x3c}, {0x22, 0x08, 0x3c}, {0x22, 0x08, 0x3c}, {0x22, 0x08, 0x3c}, + {0x22, 0x08, 0x3d}, {0x21, 0x08, 0x3d}, {0x21, 0x08, 0x3d}, {0x21, 0x08, 0x3d}, {0x21, 0x08, 0x3d}, {0x21, 0x08, 0x3d}, + {0x21, 0x08, 0x3e}, {0x20, 0x08, 0x3e}, {0x20, 0x08, 0x3e}, {0x20, 0x08, 0x3e}, {0x20, 0x08, 0x3e}, {0x20, 0x08, 0x3f}, + {0x20, 0x08, 0x3f}, {0x1f, 0x08, 0x3f}, {0x1f, 0x08, 0x3f}, {0x1f, 0x08, 0x3f}, {0x1f, 0x08, 0x3f}, {0x1f, 0x08, 0x40}, + {0x1f, 0x08, 0x40}, {0x1e, 0x08, 0x40}, {0x1e, 0x08, 0x40}, {0x1e, 0x08, 0x40}, {0x1e, 0x08, 0x41}, {0x1e, 0x08, 0x41}, + {0x1e, 0x08, 0x41}, {0x1d, 0x08, 0x41}, {0x1d, 0x09, 0x41}, {0x1d, 0x09, 0x41}, {0x1d, 0x09, 0x42}, {0x1d, 0x09, 0x42}, + {0x1d, 0x09, 0x42}, {0x1c, 0x09, 0x42}, {0x1c, 0x09, 0x42}, {0x1c, 0x09, 0x43}, {0x1c, 0x09, 0x43}, {0x1c, 0x09, 0x43}, + {0x1c, 0x09, 0x43}, {0x1b, 0x09, 0x43}, {0x1b, 0x09, 0x43}, {0x1b, 0x09, 0x44}, {0x1b, 0x09, 0x44}, {0x1b, 0x09, 0x44}, + {0x1b, 0x09, 0x44}, {0x1a, 0x09, 0x44}, {0x1a, 0x09, 0x45}, {0x1a, 0x09, 0x45}, {0x1a, 0x09, 0x45}, {0x1a, 0x09, 0x45}, + {0x1a, 0x09, 0x45}, {0x19, 0x09, 0x46}, {0x19, 0x09, 0x46}, {0x19, 0x09, 0x46}, {0x19, 0x09, 0x46}, {0x19, 0x09, 0x46}, + {0x19, 0x09, 0x46}, {0x18, 0x09, 0x47}, {0x18, 0x09, 0x47}, {0x18, 0x09, 0x47}, {0x18, 0x09, 0x47}, {0x18, 0x09, 0x47}, + {0x18, 0x09, 0x48}, {0x17, 0x09, 0x48}, {0x17, 0x09, 0x48}, {0x17, 0x0a, 0x48}, {0x17, 0x0a, 0x48}, {0x17, 0x0a, 0x48}, + {0x17, 0x0a, 0x49}, {0x16, 0x0a, 0x49}, {0x16, 0x0a, 0x49}, {0x16, 0x0a, 0x49}, {0x16, 0x0a, 0x49}, {0x16, 0x0a, 0x4a}, + {0x16, 0x0a, 0x4a}, {0x15, 0x0a, 0x4a}, {0x15, 0x0a, 0x4a}, {0x15, 0x0a, 0x4a}, {0x15, 0x0a, 0x4a}, {0x15, 0x0a, 0x4b}, + {0x15, 0x0a, 0x4b}, {0x14, 0x0a, 0x4b}, {0x14, 0x0a, 0x4b}, {0x14, 0x0a, 0x4b}, {0x14, 0x0a, 0x4c}, {0x14, 0x0a, 0x4c}, + {0x14, 0x0a, 0x4c}, {0x13, 0x0a, 0x4c}, {0x13, 0x0a, 0x4c}, {0x13, 0x0a, 0x4c}, {0x13, 0x0a, 0x4d}, {0x13, 0x0a, 0x4d}, + {0x13, 0x0a, 0x4d}, {0x12, 0x0a, 0x4d}, {0x12, 0x0a, 0x4d}, {0x12, 0x0a, 0x4e}, {0x12, 0x0a, 0x4e}, {0x12, 0x0a, 0x4e}, + {0x12, 0x0a, 0x4e}, {0x11, 0x0a, 0x4e}, {0x11, 0x0a, 0x4f}, {0x11, 0x0b, 0x4f}, {0x11, 0x0b, 0x4f}, {0x11, 0x0b, 0x4f}, + {0x11, 0x0b, 0x4f}, {0x10, 0x0b, 0x4f}, {0x10, 0x0b, 0x50}, {0x10, 0x0b, 0x50}, {0x10, 0x0b, 0x50}, {0x10, 0x0b, 0x50}, + {0x10, 0x0b, 0x50}, {0x0f, 0x0b, 0x51}, {0x0f, 0x0b, 0x51}, {0x0f, 0x0b, 0x51}, {0x0f, 0x0b, 0x51}, {0x0f, 0x0b, 0x51}, + {0x0f, 0x0b, 0x51}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52} +}; diff --git a/wasm3-sys/wasm3/test/wasi/mandelbrot/doubledouble.h b/wasm3-sys/wasm3/test/wasi/mandelbrot/doubledouble.h new file mode 100644 index 0000000..54e7150 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/mandelbrot/doubledouble.h @@ -0,0 +1,147 @@ +#include + +typedef struct { + double hi; + double lo; +} DoubleDouble; + +static inline DoubleDouble dd_new(double hi, double lo) { + DoubleDouble num; + num.hi = hi; + num.lo = lo; + return num; +} + +unsigned int dd_get_ui(DoubleDouble num) { + return num.hi; +} + +static inline DoubleDouble dd_sqrt(DoubleDouble num) { + double a, b, c, d, e; + d = 1 / sqrt(num.hi); + e = num.hi * d; + a = 0x08000001 * e; + a += e - a; + b = e - a; + c = e * e; + b = ((a * a - c) + a * b * 2) + b * b; + a = num.hi - c; + c = num.hi - a; + c = (a + ((((num.hi - (c + a)) + (c - c)) + num.lo) - b)) * d * 0.5; + a = e + c; + b = e - a; + return dd_new(a, (e - (b + a)) + (b + c)); +} + +static inline DoubleDouble dd_div(DoubleDouble num1, DoubleDouble num2) { + double a, b, c, d, e, f, g; + f = num1.hi / num2.hi; + a = 0x08000001 * num2.hi; + a += num2.hi - a; + b = num2.hi - a; + c = 0x08000001 * f; + c += f - c; + d = f - c; + e = num2.hi * f; + c = (((a * c - e) + (a * d + b * c)) + b * d) + num2.lo * f; + b = num1.lo - c; + d = num1.lo - b; + a = num1.hi - e; + e = (num1.hi - ((num1.hi - a) + a)) + b; + g = a + e; + e += (a - g) + ((num1.lo - (d + b)) + (d - c)); + a = g + e; + b = a / num2.hi; + f += (e + (g - a)) / num2.hi; + a = f + b; + return dd_new(a, b + (f - a)); +} + +static inline DoubleDouble dd_ui_div(unsigned int num1, DoubleDouble num2) { + return dd_div(dd_new(num1, 0), num2); +} + +static inline DoubleDouble dd_div_ui(DoubleDouble num1, unsigned int num2) { + return dd_div(num1, dd_new(num2, 0)); +} + +static inline DoubleDouble dd_si_div(signed int num1, DoubleDouble num2) { + return dd_div(dd_new(num1, 0), num2); +} + +static inline DoubleDouble dd_div_si(DoubleDouble num1, signed int num2) { + return dd_div(num1, dd_new(num2, 0)); +} + +static inline DoubleDouble dd_add(DoubleDouble num1, DoubleDouble num2) { + double a, b, c, d, e, f; + e = num1.hi + num2.hi; + d = num1.hi - e; + a = num1.lo + num2.lo; + f = num1.lo - a; + d = ((num1.hi - (d + e)) + (d + num2.hi)) + a; + b = e + d; + c = ((num1.lo - (f + a)) + (f + num2.lo)) + (d + (e - b)); + a = b + c; + return dd_new(a, c + (b - a)); +} + +static inline DoubleDouble dd_mul(DoubleDouble num1, DoubleDouble num2) { + double a, b, c, d, e; + a = 0x08000001 * num1.hi; + a += num1.hi - a; + b = num1.hi - a; + c = 0x08000001 * num2.hi; + c += num2.hi - c; + d = num2.hi - c; + e = num1.hi * num2.hi; + c = (((a * c - e) + (a * d + b * c)) + b * d) + (num1.lo * num2.hi + num1.hi * num2.lo); + a = e + c; + return dd_new(a, c + (e - a)); +} + +static inline DoubleDouble dd_mul2(DoubleDouble num1, DoubleDouble num2) { + double a, b, c, d, e; + a = 0x08000001 * num1.hi; + a += num1.hi - a; + b = num1.hi - a; + c = 0x08000001 * num2.hi; + c += num2.hi - c; + d = num2.hi - c; + e = num1.hi * num2.hi; + c = 2*((((a * c - e) + (a * d + b * c)) + b * d) + (num1.lo * num2.hi + num1.hi * num2.lo)); + a = 2*e + c; + return dd_new(a, c + (2*e - a)); +} + +static inline DoubleDouble dd_mul_ui(DoubleDouble num1, unsigned int num2) { + return dd_mul(num1, dd_new(num2, 0)); +} + +static inline DoubleDouble dd_mul_d(DoubleDouble num1, double num2) { + return dd_mul(num1, dd_new(num2, 0)); +} + +static inline DoubleDouble dd_sub(DoubleDouble num1, DoubleDouble num2) { + double a, b, c, d, e, f, g; + g = num1.lo - num2.lo; + f = num1.lo - g; + e = num1.hi - num2.hi; + d = num1.hi - e; + d = ((num1.hi - (d + e)) + (d - num2.hi)) + g; + b = e + d; + c = (d + (e - b)) + ((num1.lo - (f + g)) + (f - num2.lo)); + a = b + c; + return dd_new(a, c + (b - a)); +} + +static inline DoubleDouble dd_sqr(DoubleDouble num) { + double a, b, c; + a = 0x08000001 * num.hi; + a += num.hi - a; + b = num.hi - a; + c = num.hi * num.hi; + b = ((((a * a - c) + a * b * 2) + b * b) + num.hi * num.lo * 2) + num.lo * num.lo; + a = b + c; + return dd_new(a, b + (c - a)); +} diff --git a/wasm3-sys/wasm3/test/wasi/mandelbrot/image.png b/wasm3-sys/wasm3/test/wasi/mandelbrot/image.png new file mode 100644 index 0000000..4fb0c4c Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/mandelbrot/image.png differ diff --git a/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel.c b/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel.c new file mode 100644 index 0000000..782b47f --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include + +#include "colors.h" + +double get_time() { + struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); + return ts.tv_sec * 1000.0 + ts.tv_nsec / 1000000.0; +} + +int main(int argc, char **argv) { + unsigned width, height; + double magn; + if (argc <= 1) { + width = 1024; + height = width; + magn = 4e5; + } else if (argc == 3) { + width = atoi(argv[1]); + height = width; + magn = strtod(argv[2], NULL); + } else { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } + double eps = 1e-17; + double Q1LOG2 = 1.44269504088896340735992468100189213742664595415299; + double LOG2 = 0.69314718055994530941723212145817656807550013436026; + + int x, y; + double centerx = -0.743643887037158704752191506114774; + double centery = 0.131825904205311970493132056385139; + double bailout = 128; + double logLogBailout = log(log(bailout)); + int foundperiods = 0; + long maxiter = width * sqrt(magn); + double x0d = 4 / magn / width; + double x2 = -2 / magn + centerx; + double y1d = -4 / magn / width; + double y2 = 2 / magn * height / width + centery; + + double tbeg = get_time(); + + // write out image header + printf("P6 %d %d 255\n", width, height); + + for (y = 0; y < height; y++) { + fprintf(stderr, "\r%.2f%%", (float)(y+1)/(height)*100); + for (x = 0; x < width; x++) { + double px = x*x0d + x2; + double py = y*y1d + y2; + // no Main bulb or Cardoid check to be faster + double zx = px; + double zy = py; + long i; + // Initial maximum period to detect. + int check = 3; + // Maximum period doubles every iterations: + int whenupdate = 10; + // Period history registers. + double hx = 0; + double hy = 0; + double xx, yy; + bool inside = true; + for (i = 1; i <= maxiter; i++) { + xx = zx * zx; + yy = zy * zy; + if (xx + yy > bailout) { + inside = false; + break; + } + // iterate + zy = 2 * zx * zy + py; + zx = xx - yy + px; + + // periodicity check + double d = zx - hx; + if (d > 0.0 ? d < eps : d > -eps) { + d = zy - hy; + if (d > 0.0 ? d < eps : d > -eps) { + // Period found. + foundperiods++; + break; + } + } + if ((i & check) == 0) { + if (--whenupdate == 0) { + whenupdate = 10; + check <<= 1; + check++; + } + // period = 0; + hx = zx; + hy = zy; + } + } + + if (inside) { + const char black[3] = {}; + fwrite(black, 1, 3, stdout); + } else { + double r = sqrtl(zx*zx + zy*zy); + double c = i - 1.28 + (logLogBailout - logl(logl(r))) * Q1LOG2; + int idx = fmodl((logl(c/64+1)/LOG2+0.45), 1)*(GRADIENTLENGTH-1) + 0.5; + fwrite(&colors[idx], 1, 3, stdout); + } + } + } + + double tend = get_time(); + + fprintf(stderr, "\nElapsed time: %.2f ms\n", tend-tbeg); + + //fprintf(stderr, "\n%d periods found\n", foundperiods); + + return 0; +} diff --git a/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel.wasm b/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel.wasm new file mode 100755 index 0000000..16180b9 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel_dd.c b/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel_dd.c new file mode 100644 index 0000000..fd0d8c3 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel_dd.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include + +#include "colors.h" +#include "doubledouble.h" + +double get_time() { + struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); + return ts.tv_sec * 1000.0 + ts.tv_nsec / 1000000.0; +} + +int main(int argc, char **argv) { + unsigned width, height; + DoubleDouble magn; + if (argc <= 1) { + width = 1024; + height = width; + magn = dd_new(4e5, 0); + } else if (argc == 3) { + width = atoi(argv[1]); + height = width; + magn = dd_new(strtod(argv[2], NULL), 0); + } else { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } + DoubleDouble temp1; + double eps = 1e-17; + double Q1LOG2 = 1.44269504088896340735992468100189213742664595415299; + double LOG2 = 0.69314718055994530941723212145817656807550013436026; + unsigned int x, y; + DoubleDouble centerx, centery; + centerx = dd_new(-0.7436438870371587, -3.628952515063387E-17); + centery = dd_new(0.13182590420531198, -1.2892807754956678E-17); + double bailout = 128; // with a smaller value there are lines on magn=1 + double logLogBailout = log(log(bailout)); + int foundperiods = 0; + long maxiter = 50000; + /*// maxiter = width * sqrt(magn); + temp1 = dd_sqrt(magn); + unsigned long maxiter = width * dd_get_ui(temp1);*/ + DoubleDouble x2, y2, x0d, y1d; + // x0d = 4 / magn / width; + x0d = dd_ui_div(4, magn); + x0d = dd_div_ui(x0d, width); + // x2 = -2 / magn + centerx; + x2 = dd_si_div(-2, magn); + x2 = dd_add(x2, centerx); + // y1d = -4 / magn / width; + y1d = dd_si_div(-4, magn); + y1d = dd_div_ui(y1d, width); + // y2 = 2 / magn * height / width + centery; + y2 = dd_ui_div(2, magn); + temp1 = dd_new(height, 0); + temp1 = dd_div_ui(temp1, width); + y2 = dd_mul(y2, temp1); + y2 = dd_add(y2, centery); + DoubleDouble px, py, zx, zy, xx, yy; + double hx, hy, d; + + double tbeg = get_time(); + + // write out image header + printf("P6 %d %d 255\n", width, height); + + for (y = 0; y < height; y++) { + fprintf(stderr, "\r%.2f%%", (float)(y+1)/(height)*100); + for (x = 0; x < width; x++) { + //px = x*x0d + x2; + px = dd_mul_ui(x0d, x); + px = dd_add(px, x2); + //py = y*y1d + y2; + py = dd_mul_ui(y1d, y); + py = dd_add(py, y2); + // no Main bulb or Cardoid check to be faster + zx = dd_new(px.hi, px.lo); + zy = dd_new(py.hi, py.lo); + unsigned long i; + bool inside = true; + int check = 3; + int whenupdate = 10; + hx = 0; + hy = 0; + for (i = 1; i <= maxiter; i++) { + //xx = zx * zx; + xx = dd_sqr(zx); + //yy = zy * zy; + yy = dd_sqr(zy); + //if (xx + yy > bailout) { + if (xx.hi + yy.hi > bailout) { + inside = false; + break; + } + // iterate + //zy = 2 * zx * zy + py; + //zx = dd_mul_ui(zx, 2); + //zy = dd_mul(zx, zy); + zy = dd_add(dd_mul2(zx, zy), py); + //zx = xx - yy + px; + zx = dd_add(dd_sub(xx, yy), px); + + // period checking + d = zx.hi - hx; + if (d > 0.0 ? d < eps : d > -eps) { + d = zy.hi - hy; + if (d > 0.0 ? d < eps : d > -eps) { + // Period found. + foundperiods++; + break; + } + } + if ((i & check) == 0) { + if (--whenupdate == 0) { + whenupdate = 10; + check <<= 1; + check++; + } + // period = 0; + hx = zx.hi; + hy = zy.hi; + } + } + + if (inside) { + const char black[3] = {}; + fwrite(black, 1, 3, stdout); + } else { + double r = sqrt(zx.hi*zx.hi + zy.hi*zy.hi); + double c = i - 1.28 + (logLogBailout - log(log(r))) * Q1LOG2; + int idx = fmod((log(c/64+1)/LOG2+0.45), 1)*(GRADIENTLENGTH-1) + 0.5; + fwrite(&colors[idx], 1, 3, stdout); + } + } + } + + double tend = get_time(); + + fprintf(stderr, "\nElapsed time: %.2f ms\n", tend-tbeg); + + //fprintf(stderr, "\n%d periods found\n", foundperiods); + + return 0; +} diff --git a/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel_dd.wasm b/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel_dd.wasm new file mode 100755 index 0000000..1d96afc Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/mandelbrot/mandel_dd.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/raymarcher/raymarcher.cpp b/wasm3-sys/wasm3/test/wasi/raymarcher/raymarcher.cpp new file mode 100644 index 0000000..b69e8cf --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/raymarcher/raymarcher.cpp @@ -0,0 +1,164 @@ +/* + * Build: + * wasicc -g0 -O3 raymarcher.cpp -o raymarcher.wasm + */ +#include +#include +#include + +double t = 0.0; +#define WIDTH 80 +#define HEIGHT 40 +static char framebuffer[HEIGHT * WIDTH]; + +const char pixels[] = ".-::==+++%%%####@@@@"; +//const char pixels[] = ".-:=+%#@"; +//const char pixels[] = ".`:,;'_^\"><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"; + +const int npixels = sizeof(pixels) - 1; + +struct vec3 { + float x; + float y; + float z; + + float length() { + return sqrt(x*x + y*y + z*z); + } + + void normalize() { + float l = length(); + x = x / l; y = y / l; z = z / l; + } + + struct vec3 operator*(float fac) { + struct vec3 r; + r.x = x * fac; r.y = y * fac; r.z = z * fac; + return r; + } + + struct vec3 operator+(struct vec3 other) { + struct vec3 r; + r.x = x +other.x; r.y = y +other.y; r.z = z + other.z; + return r; + } + struct vec3 operator-(struct vec3 other) { + struct vec3 r; + r.x = x - other.x; r.y = y - other.y; r.z = z - other.z; + return r; + } + +}; + +void raymarch(); +float sdf(struct vec3); +char shade(struct vec3); + + +void raymarch() { + for (int y = 0; y < HEIGHT; y++) { + for (int x = 0; x < WIDTH; x++) { + struct vec3 pos = {0.0, 0.0, -3.0}; + struct vec3 target = { + x / (float) WIDTH - 0.5f, + (y / (float) HEIGHT - 0.5f) * (HEIGHT / (float) WIDTH) * 1.5f, + -1.5f + }; + + struct vec3 ray = target - pos; + ray.normalize(); + char pxl = ' '; + float dist; + float max = 9999.0f; + for (int i = 0; i < 15000; i++) { + if (fabs(pos.x) > max + || fabs(pos.y) > max + || fabs(pos.z) > max) + break; + + dist = sdf(pos); + if (dist < 1e-6) { + pxl = shade(pos); + break; + } + + pos = pos + ray * dist; + } // end for (i) + + framebuffer[y * WIDTH + x] = pxl; + } // end for(x) + } // end for(y) +} // end raymarch() + +float sdf(struct vec3 pos) { + struct vec3 center = {0.0, 0.0, 0.0}; + + return (pos - center).length() - 0.6; +} + +char shade(struct vec3 pos) { + struct vec3 L = { + 50.0f * sinf(t), + 20.0f, + 50.0f * cosf(t) + }; + L.normalize(); + + float dt = 1e-6; + float current_val = sdf(pos); + + struct vec3 x = {pos.x + dt, pos.y, pos.z}; + float dx = sdf(x) - current_val; + + struct vec3 y = {pos.x, pos.y + dt, pos.z}; + float dy = sdf(y) - current_val; + + struct vec3 z = {pos.x, pos.y, pos.z + dt}; + float dz = sdf(z) - current_val; + + struct vec3 N; // N for normal + N.x = (dx - pos.x) / dt; + N.y = (dy - pos.y) / dt; + N.z = (dz - pos.z) / dt; + + if (N.length() < 1e-9) { + return pixels[0]; + } + + N.normalize(); + + float diffuse = L.x * N.x + L.y * N.y + L.z * N.z; + diffuse = (diffuse + 1.0) / 2.0 * npixels; + return pixels[(int) floor(diffuse) % npixels]; +} + +void cls() { + // Terminal clear sequence + write(0, "\33[2J\33[1;1H", 10); +} + +void printfb() { + char *fb = framebuffer; + char nl = '\n'; + cls(); + for (int y = 0; y < HEIGHT; y++) { + write(1, fb, WIDTH); + write(1, &nl, 1); + fb += WIDTH; + + } +} + +int main() { + for (int i = 0; i < WIDTH * HEIGHT; i++) { + framebuffer[i] = ' '; + } + + for (int i = 0; i < 100; i++) { + raymarch(); + printfb(); + usleep(20000); + t += 0.1; + } +} diff --git a/wasm3-sys/wasm3/test/wasi/raymarcher/raymarcher.wasm b/wasm3-sys/wasm3/test/wasi/raymarcher/raymarcher.wasm new file mode 100755 index 0000000..a94a5a5 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/raymarcher/raymarcher.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/simple/0.txt b/wasm3-sys/wasm3/test/wasi/simple/0.txt new file mode 100644 index 0000000..70c379b --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/simple/0.txt @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/wasm3-sys/wasm3/test/wasi/simple/README.md b/wasm3-sys/wasm3/test/wasi/simple/README.md new file mode 100644 index 0000000..56ae6c1 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/simple/README.md @@ -0,0 +1,23 @@ +## Compile + +```sh +wasicc -g -O0 -Wl,--stack-first test.c -o test.wasm +wasm-opt --strip-debug -Os test.wasm -o test-opt.wasm +``` + +## Run + +```sh +../../build/wasm3 test.wasm + +$ENGINES_PATH/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm test.wasm + +$ENGINES_PATH/wac/wax test.wasm + +$ENGINES_PATH/WAVM/Release/bin/wavm run test.wasm + +wasmer run test.wasm + +wasmer-js run test.wasm +``` + diff --git a/wasm3-sys/wasm3/test/wasi/simple/test-opt.wasm b/wasm3-sys/wasm3/test/wasi/simple/test-opt.wasm new file mode 100644 index 0000000..94f2401 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/simple/test-opt.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/simple/test.c b/wasm3-sys/wasm3/test/wasi/simple/test.c new file mode 100644 index 0000000..dc3bd12 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/simple/test.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include + +#include "wasm_api.h" + +/* + * Helpers + */ + +static inline +struct timespec timespec_diff(struct timespec start, struct timespec end) +{ + struct timespec temp; + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + return temp; +} + +static inline +int rand_range(int min, int max){ + return min + rand() / (RAND_MAX / (max - min + 1) + 1); +} + +WASM_EXPORT +uint32_t fib(uint32_t n) +{ + if(n < 2) { + return n; + } + return fib(n-1) + fib(n-2); +} + +/* + * Tests + */ + +static char gString[16]; + +__attribute__((constructor)) +void test_init_some_global() { + static const char data[] = "Constructor OK\n"; + memcpy(gString, data, sizeof(data)); +} + +void test_constructor() { + fwrite(gString, 1, sizeof(gString)-1, stdout); +} + +void test_write() { + fwrite("Hello world\n", 1, 12, stdout); +} + +void test_printf() { + printf("Hello %s!\n", "printf"); +} + +void test_args(int argc, char **argv) { + printf("Args: "); + for (int i = 0; i < argc; i++) { + printf("%s; ", argv[i]); + } + puts(""); +} + +void test_random() { + unsigned entropy; + getentropy(&entropy, sizeof(entropy)); + srand(entropy); + int x = rand_range(0, 10); + int y = rand_range(0, 10); + printf("%d + %d = %d\n", x, y, x+y); +} + +void test_gettime() { + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); + printf("Now: %lld sec, %ld ns\n", now.tv_sec, now.tv_nsec); +} + +void test_perf_fib(uint32_t n) { + struct timespec start, finish; + uint32_t result; + + printf("fib(%d) = ", n); + fflush(stdout); + + // Chew up some CPU time + clock_gettime(CLOCK_REALTIME, &start); + result = fib(n); + clock_gettime(CLOCK_REALTIME, &finish); + + struct timespec delta = timespec_diff(start, finish); + + //unsigned ms = (delta.tv_sec*1000) + (delta.tv_nsec/1000000); + //printf("%d [%u ms]\n", result, ms); + + double fms = (delta.tv_sec*1000.0) + (delta.tv_nsec/1000000.0); + printf("%d [%.3f ms]\n", result, fms); +} + +void test_cat(char* fn) { + int file = open(fn, O_RDONLY); + if (file >= 0) { + char c = 0; + while (read(file, &c, sizeof(c)) > 0) { + printf("%02x ", c); + } + close(file); + puts(""); + } else { + printf("Cannot open %s\n", fn); + } +} + +__attribute__((noinline)) void c() { __builtin_trap(); } +__attribute__((noinline)) void b() { c(); } +__attribute__((noinline)) void a() { b(); } +__attribute__((noinline)) void test_trap() { a(); } + +/* + * Main + */ + +int main(int argc, char **argv) +{ + test_write(); + test_constructor(); + test_printf(); + test_args(argc, argv); + test_gettime(); + test_random(); + if (0 == strcmp(argv[1], "trap")) { + test_trap(); + } + + test_perf_fib(20); + + if (0 == strcmp(argv[1], "cat")) { + test_cat(argv[2]); + } + + puts("=== done ==="); + return 0; +} diff --git a/wasm3-sys/wasm3/test/wasi/simple/test.wasm b/wasm3-sys/wasm3/test/wasi/simple/test.wasm new file mode 100755 index 0000000..5b5891e Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/simple/test.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/simple/wasm_api.h b/wasm3-sys/wasm3/test/wasi/simple/wasm_api.h new file mode 100644 index 0000000..7c430ff --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/simple/wasm_api.h @@ -0,0 +1,10 @@ +#ifndef wasm_api_h +#define wasm_api_h + +#include + +#define WASM_EXPORT __attribute__((used)) __attribute__((visibility ("default"))) +#define WASM_EXPORT_AS(NAME) WASM_EXPORT __attribute__((export_name(NAME))) +#define WASM_IMPORT(MODULE,NAME) __attribute__((import_module(MODULE))) __attribute__((import_name(NAME))) + +#endif diff --git a/wasm3-sys/wasm3/test/wasi/simple/wasm_api.syms b/wasm3-sys/wasm3/test/wasi/simple/wasm_api.syms new file mode 100644 index 0000000..06ac8d4 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/simple/wasm_api.syms @@ -0,0 +1 @@ +wasm3_raw_sum diff --git a/wasm3-sys/wasm3/test/wasi/smallpt/README.md b/wasm3-sys/wasm3/test/wasi/smallpt/README.md new file mode 100644 index 0000000..066a2d4 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/smallpt/README.md @@ -0,0 +1,48 @@ +# smallpt + +Based on https://www.kevinbeason.com/smallpt/ + +

+ +### Results + +```log +TODO +``` + +### Building + +```sh +wasic++ -g0 -Oz -Wl,--stack-first -Wl,-z,stack-size=$[1024*1024] smallpt-ex.cpp -o smallpt-ex.wasm +``` + +### Running + +```sh +export ENGINES_PATH=/opt/wasm_engines + +# Wasm3 +../../../build/wasm3 smallpt-ex.wasm > image.ppm + +# WAC +$ENGINES_PATH/wac/wax smallpt-ex.wasm > image.ppm + +# wasm-micro-runtime +$ENGINES_PATH/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm smallpt-ex.wasm > image.ppm + +# wasmtime +wasmtime --optimize smallpt-ex.wasm > image.ppm + +# Wasmer +wasmer run smallpt-ex.wasm > image.ppm +wasmer run --backend singlepass smallpt-ex.wasm > image.ppm +wasmer run --backend llvm smallpt-ex.wasm > image.ppm + +# Wasmer-JS (V8) +wasmer-js run smallpt-ex.wasm > image.ppm + +node --wasm_interpret_all $(which wasmer-js) run smallpt-ex.wasm > image.ppm + +# WAVM +$ENGINES_PATH/WAVM/Release/bin/wavm run smallpt-ex.wasm > image.ppm +``` diff --git a/wasm3-sys/wasm3/test/wasi/smallpt/image.jpg b/wasm3-sys/wasm3/test/wasi/smallpt/image.jpg new file mode 100644 index 0000000..2461c7d Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/smallpt/image.jpg differ diff --git a/wasm3-sys/wasm3/test/wasi/smallpt/smallpt-ex-mv.wasm b/wasm3-sys/wasm3/test/wasi/smallpt/smallpt-ex-mv.wasm new file mode 100644 index 0000000..1c2de15 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/smallpt/smallpt-ex-mv.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/smallpt/smallpt-ex.cpp b/wasm3-sys/wasm3/test/wasi/smallpt/smallpt-ex.cpp new file mode 100644 index 0000000..10b571e --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/smallpt/smallpt-ex.cpp @@ -0,0 +1,130 @@ +#include // smallpt, a Path Tracer by Kevin Beason, 2009 +#include // Make : g++ -O3 -fopenmp explicit.cpp -o explicit +#include // Remove "-fopenmp" for g++ version < 4.2 +#include +double get_time() { + struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); + return ts.tv_sec * 1000.0 + ts.tv_nsec / 1000000.0; +} +struct Vec { // Usage: time ./explicit 16 && xv image.ppm + double x, y, z; // position, also color (r,g,b) + Vec(double x_=0, double y_=0, double z_=0){ x=x_; y=y_; z=z_; } + Vec operator+(const Vec &b) const { return Vec(x+b.x,y+b.y,z+b.z); } + Vec operator-(const Vec &b) const { return Vec(x-b.x,y-b.y,z-b.z); } + Vec operator*(double b) const { return Vec(x*b,y*b,z*b); } + Vec mult(const Vec &b) const { return Vec(x*b.x,y*b.y,z*b.z); } + Vec& norm(){ return *this = *this * (1/sqrt(x*x+y*y+z*z)); } + double dot(const Vec &b) const { return x*b.x+y*b.y+z*b.z; } // cross: + Vec operator%(Vec&b){return Vec(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);} +}; +struct Ray { Vec o, d; Ray(Vec o_, Vec d_) : o(o_), d(d_) {} }; +enum Refl_t { DIFF, SPEC, REFR }; // material types, used in radiance() +struct Sphere { + double rad; // radius + Vec p, e, c; // position, emission, color + Refl_t refl; // reflection type (DIFFuse, SPECular, REFRactive) + Sphere(double rad_, Vec p_, Vec e_, Vec c_, Refl_t refl_): + rad(rad_), p(p_), e(e_), c(c_), refl(refl_) {} + double intersect(const Ray &r) const { // returns distance, 0 if nohit + Vec op = p-r.o; // Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0 + double t, eps=1e-4, b=op.dot(r.d), det=b*b-op.dot(op)+rad*rad; + if (det<0) return 0; else det=sqrt(det); + return (t=b-det)>eps ? t : ((t=b+det)>eps ? t : 0); + } +}; +Sphere spheres[] = {//Scene: radius, position, emission, color, material + Sphere(1e5, Vec( 1e5+1,40.8,81.6), Vec(),Vec(.75,.25,.25),DIFF),//Left + Sphere(1e5, Vec(-1e5+99,40.8,81.6),Vec(),Vec(.25,.25,.75),DIFF),//Rght + Sphere(1e5, Vec(50,40.8, 1e5), Vec(),Vec(.75,.75,.75),DIFF),//Back + Sphere(1e5, Vec(50,40.8,-1e5+170), Vec(),Vec(), DIFF),//Frnt + Sphere(1e5, Vec(50, 1e5, 81.6), Vec(),Vec(.75,.75,.75),DIFF),//Botm + Sphere(1e5, Vec(50,-1e5+81.6,81.6),Vec(),Vec(.75,.75,.75),DIFF),//Top + Sphere(16.5,Vec(27,16.5,47), Vec(),Vec(1,1,1)*.6, SPEC),//Mirr + Sphere(16.5,Vec(73,16.5,78), Vec(),Vec(.75,1.,.95), REFR),//Glas + Sphere(4.0, Vec(50,81.6-16.5,81.6),Vec(4,4,4)*12, Vec(), DIFF),//Lite +}; +int numSpheres = sizeof(spheres)/sizeof(Sphere); +inline double clamp(double x){ return x<0 ? 0 : x>1 ? 1 : x; } +inline int toInt(double x){ return int(pow(clamp(x),1/2.2)*255+.5); } +inline bool intersect(const Ray &r, double &t, int &id){ + double n=sizeof(spheres)/sizeof(Sphere), d, inf=t=1e20; + for(int i=int(n);i--;) if((d=spheres[i].intersect(r))&&df.y && f.x>f.z ? f.x : f.y>f.z ? f.y : f.z; // max refl + if (++depth>5||!p) if (erand48(Xi).1?Vec(0,1):Vec(1))%w).norm(), v=w%u; + Vec d = (u*cos(r1)*r2s + v*sin(r1)*r2s + w*sqrt(1-r2)).norm(); + + // Loop over any lights + Vec e; + for (int i=0; i.1?Vec(0,1):Vec(1))%sw).norm(), sv=sw%su; + double cos_a_max = sqrt(1-s.rad*s.rad/(x-s.p).dot(x-s.p)); + double eps1 = erand48(Xi), eps2 = erand48(Xi); + double cos_a = 1-eps1+eps1*cos_a_max; + double sin_a = sqrt(1-cos_a*cos_a); + double phi = 2*M_PI*eps2; + Vec l = su*cos(phi)*sin_a + sv*sin(phi)*sin_a + sw*cos_a; + l.norm(); + if (intersect(Ray(x,l), t, id) && id==i){ // shadow ray + double omega = 2*M_PI*(1-cos_a_max); + e = e + f.mult(s.e*l.dot(nl)*omega)*M_1_PI; // 1/pi for brdf + } + } + + return obj.e*E+e+f.mult(radiance(Ray(x,d),depth,Xi,0)); + } else if (obj.refl == SPEC) // Ideal SPECULAR reflection + return obj.e + f.mult(radiance(Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi)); + Ray reflRay(x, r.d-n*2*n.dot(r.d)); // Ideal dielectric REFRACTION + bool into = n.dot(nl)>0; // Ray from outside going in? + double nc=1, nt=1.5, nnt=into?nc/nt:nt/nc, ddn=r.d.dot(nl), cos2t; + if ((cos2t=1-nnt*nnt*(1-ddn*ddn))<0) // Total internal reflection + return obj.e + f.mult(radiance(reflRay,depth,Xi)); + Vec tdir = (r.d*nnt - n*((into?1:-1)*(ddn*nnt+sqrt(cos2t)))).norm(); + double a=nt-nc, b=nt+nc, R0=a*a/(b*b), c = 1-(into?-ddn:tdir.dot(n)); + double Re=R0+(1-R0)*c*c*c*c*c,Tr=1-Re,P=.25+.5*Re,RP=Re/P,TP=Tr/(1-P); + return obj.e + f.mult(depth>2 ? (erand48(Xi)

= 2) samps = atoi(argv[1])/4; + if (argc >= 3) w = h = atoi(argv[2]); + double tbeg = get_time(); + Ray cam(Vec(50,52,295.6), Vec(0,-0.042612,-1).norm()); // cam pos, dir + Vec cx=Vec(w*.5135/h), cy=(cx%cam.d).norm()*.5135, r, *c=new Vec[w*h]; +#pragma omp parallel for schedule(dynamic, 1) private(r) // OpenMP + for (int y=0; y // smallpt, a Path Tracer by Kevin Beason, 2008 +#include // Make : g++ -O3 -fopenmp smallpt.cpp -o smallpt +#include // Remove "-fopenmp" for g++ version < 4.2 +#include +double get_time() { + struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); + return ts.tv_sec * 1000.0 + ts.tv_nsec / 1000000.0; +} +struct Vec { // Usage: time ./smallpt 5000 && xv image.ppm + double x, y, z; // position, also color (r,g,b) + Vec(double x_=0, double y_=0, double z_=0){ x=x_; y=y_; z=z_; } + Vec operator+(const Vec &b) const { return Vec(x+b.x,y+b.y,z+b.z); } + Vec operator-(const Vec &b) const { return Vec(x-b.x,y-b.y,z-b.z); } + Vec operator*(double b) const { return Vec(x*b,y*b,z*b); } + Vec mult(const Vec &b) const { return Vec(x*b.x,y*b.y,z*b.z); } + Vec& norm(){ return *this = *this * (1/sqrt(x*x+y*y+z*z)); } + double dot(const Vec &b) const { return x*b.x+y*b.y+z*b.z; } // cross: + Vec operator%(Vec&b){return Vec(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);} +}; +struct Ray { Vec o, d; Ray(Vec o_, Vec d_) : o(o_), d(d_) {} }; +enum Refl_t { DIFF, SPEC, REFR }; // material types, used in radiance() +struct Sphere { + double rad; // radius + Vec p, e, c; // position, emission, color + Refl_t refl; // reflection type (DIFFuse, SPECular, REFRactive) + Sphere(double rad_, Vec p_, Vec e_, Vec c_, Refl_t refl_): + rad(rad_), p(p_), e(e_), c(c_), refl(refl_) {} + double intersect(const Ray &r) const { // returns distance, 0 if nohit + Vec op = p-r.o; // Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0 + double t, eps=1e-4, b=op.dot(r.d), det=b*b-op.dot(op)+rad*rad; + if (det<0) return 0; else det=sqrt(det); + return (t=b-det)>eps ? t : ((t=b+det)>eps ? t : 0); + } +}; +Sphere spheres[] = {//Scene: radius, position, emission, color, material + Sphere(1e5, Vec( 1e5+1,40.8,81.6), Vec(),Vec(.75,.25,.25),DIFF),//Left + Sphere(1e5, Vec(-1e5+99,40.8,81.6),Vec(),Vec(.25,.25,.75),DIFF),//Rght + Sphere(1e5, Vec(50,40.8, 1e5), Vec(),Vec(.75,.75,.75),DIFF),//Back + Sphere(1e5, Vec(50,40.8,-1e5+170), Vec(),Vec(), DIFF),//Frnt + Sphere(1e5, Vec(50, 1e5, 81.6), Vec(),Vec(.75,.75,.75),DIFF),//Botm + Sphere(1e5, Vec(50,-1e5+81.6,81.6),Vec(),Vec(.75,.75,.75),DIFF),//Top + Sphere(16.5,Vec(27,16.5,47), Vec(),Vec(1,1,1)*.6, SPEC),//Mirr + Sphere(16.5,Vec(73,16.5,78), Vec(),Vec(.75,1.,.95), REFR),//Glas + Sphere(4.0, Vec(50,81.6-16.5,81.6),Vec(4,4,4)*12, Vec(), DIFF),//Lite +}; +inline double clamp(double x){ return x<0 ? 0 : x>1 ? 1 : x; } +inline int toInt(double x){ return int(pow(clamp(x),1/2.2)*255+.5); } +inline bool intersect(const Ray &r, double &t, int &id){ + double n=sizeof(spheres)/sizeof(Sphere), d, inf=t=1e20; + for(int i=int(n);i--;) if((d=spheres[i].intersect(r))&&df.y && f.x>f.z ? f.x : f.y>f.z ? f.y : f.z; // max refl + if (++depth>5) if (erand48(Xi).1?Vec(0,1):Vec(1))%w).norm(), v=w%u; + Vec d = (u*cos(r1)*r2s + v*sin(r1)*r2s + w*sqrt(1-r2)).norm(); + return obj.e + f.mult(radiance(Ray(x,d),depth,Xi)); + } else if (obj.refl == SPEC) // Ideal SPECULAR reflection + return obj.e + f.mult(radiance(Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi)); + Ray reflRay(x, r.d-n*2*n.dot(r.d)); // Ideal dielectric REFRACTION + bool into = n.dot(nl)>0; // Ray from outside going in? + double nc=1, nt=1.5, nnt=into?nc/nt:nt/nc, ddn=r.d.dot(nl), cos2t; + if ((cos2t=1-nnt*nnt*(1-ddn*ddn))<0) // Total internal reflection + return obj.e + f.mult(radiance(reflRay,depth,Xi)); + Vec tdir = (r.d*nnt - n*((into?1:-1)*(ddn*nnt+sqrt(cos2t)))).norm(); + double a=nt-nc, b=nt+nc, R0=a*a/(b*b), c = 1-(into?-ddn:tdir.dot(n)); + double Re=R0+(1-R0)*c*c*c*c*c,Tr=1-Re,P=.25+.5*Re,RP=Re/P,TP=Tr/(1-P); + return obj.e + f.mult(depth>2 ? (erand48(Xi)

= 2) samps = atoi(argv[1])/4; + if (argc >= 3) w = h = atoi(argv[2]); + double tbeg = get_time(); + Ray cam(Vec(50,52,295.6), Vec(0,-0.042612,-1).norm()); // cam pos, dir + Vec cx=Vec(w*.5135/h), cy=(cx%cam.d).norm()*.5135, r, *c=new Vec[w*h]; +#pragma omp parallel for schedule(dynamic, 1) private(r) // OpenMP + for (int y=0; y +# include +# include +# include +# include +# include + +/*----------------------------------------------------------------------- + * INSTRUCTIONS: + * + * 1) STREAM requires different amounts of memory to run on different + * systems, depending on both the system cache size(s) and the + * granularity of the system timer. + * You should adjust the value of 'STREAM_ARRAY_SIZE' (below) + * to meet *both* of the following criteria: + * (a) Each array must be at least 4 times the size of the + * available cache memory. I don't worry about the difference + * between 10^6 and 2^20, so in practice the minimum array size + * is about 3.8 times the cache size. + * Example 1: One Xeon E3 with 8 MB L3 cache + * STREAM_ARRAY_SIZE should be >= 4 million, giving + * an array size of 30.5 MB and a total memory requirement + * of 91.5 MB. + * Example 2: Two Xeon E5's with 20 MB L3 cache each (using OpenMP) + * STREAM_ARRAY_SIZE should be >= 20 million, giving + * an array size of 153 MB and a total memory requirement + * of 458 MB. + * (b) The size should be large enough so that the 'timing calibration' + * output by the program is at least 20 clock-ticks. + * Example: most versions of Windows have a 10 millisecond timer + * granularity. 20 "ticks" at 10 ms/tic is 200 milliseconds. + * If the chip is capable of 10 GB/s, it moves 2 GB in 200 msec. + * This means the each array must be at least 1 GB, or 128M elements. + * + * Version 5.10 increases the default array size from 2 million + * elements to 10 million elements in response to the increasing + * size of L3 caches. The new default size is large enough for caches + * up to 20 MB. + * Version 5.10 changes the loop index variables from "register int" + * to "ssize_t", which allows array indices >2^32 (4 billion) + * on properly configured 64-bit systems. Additional compiler options + * (such as "-mcmodel=medium") may be required for large memory runs. + * + * Array size can be set at compile time without modifying the source + * code for the (many) compilers that support preprocessor definitions + * on the compile line. E.g., + * gcc -O -DSTREAM_ARRAY_SIZE=100000000 stream.c -o stream.100M + * will override the default size of 10M with a new size of 100M elements + * per array. + */ +#ifndef STREAM_ARRAY_SIZE +# define STREAM_ARRAY_SIZE 10000000 +#endif + +/* 2) STREAM runs each kernel "NTIMES" times and reports the *best* result + * for any iteration after the first, therefore the minimum value + * for NTIMES is 2. + * There are no rules on maximum allowable values for NTIMES, but + * values larger than the default are unlikely to noticeably + * increase the reported performance. + * NTIMES can also be set on the compile line without changing the source + * code using, for example, "-DNTIMES=7". + */ +#ifdef NTIMES +#if NTIMES<=1 +# define NTIMES 10 +#endif +#endif +#ifndef NTIMES +# define NTIMES 10 +#endif + +/* Users are allowed to modify the "OFFSET" variable, which *may* change the + * relative alignment of the arrays (though compilers may change the + * effective offset by making the arrays non-contiguous on some systems). + * Use of non-zero values for OFFSET can be especially helpful if the + * STREAM_ARRAY_SIZE is set to a value close to a large power of 2. + * OFFSET can also be set on the compile line without changing the source + * code using, for example, "-DOFFSET=56". + */ +#ifndef OFFSET +# define OFFSET 0 +#endif + +/* + * 3) Compile the code with optimization. Many compilers generate + * unreasonably bad code before the optimizer tightens things up. + * If the results are unreasonably good, on the other hand, the + * optimizer might be too smart for me! + * + * For a simple single-core version, try compiling with: + * cc -O stream.c -o stream + * This is known to work on many, many systems.... + * + * To use multiple cores, you need to tell the compiler to obey the OpenMP + * directives in the code. This varies by compiler, but a common example is + * gcc -O -fopenmp stream.c -o stream_omp + * The environment variable OMP_NUM_THREADS allows runtime control of the + * number of threads/cores used when the resulting "stream_omp" program + * is executed. + * + * To run with single-precision variables and arithmetic, simply add + * -DSTREAM_TYPE=float + * to the compile line. + * Note that this changes the minimum array sizes required --- see (1) above. + * + * The preprocessor directive "TUNED" does not do much -- it simply causes the + * code to call separate functions to execute each kernel. Trivial versions + * of these functions are provided, but they are *not* tuned -- they just + * provide predefined interfaces to be replaced with tuned code. + * + * + * 4) Optional: Mail the results to mccalpin@cs.virginia.edu + * Be sure to include info that will help me understand: + * a) the computer hardware configuration (e.g., processor model, memory type) + * b) the compiler name/version and compilation flags + * c) any run-time information (such as OMP_NUM_THREADS) + * d) all of the output from the test case. + * + * Thanks! + * + *-----------------------------------------------------------------------*/ + +# define HLINE "-------------------------------------------------------------\n" + +# ifndef MIN +# define MIN(x,y) ((x)<(y)?(x):(y)) +# endif +# ifndef MAX +# define MAX(x,y) ((x)>(y)?(x):(y)) +# endif + +#ifndef STREAM_TYPE +#define STREAM_TYPE double +#endif + +static STREAM_TYPE a[STREAM_ARRAY_SIZE+OFFSET], + b[STREAM_ARRAY_SIZE+OFFSET], + c[STREAM_ARRAY_SIZE+OFFSET]; + +static double avgtime[4] = {0}, maxtime[4] = {0}, + mintime[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX}; + +static char *label[4] = {"Copy: ", "Scale: ", + "Add: ", "Triad: "}; + +static double bytes[4] = { + 2 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE, + 2 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE, + 3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE, + 3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE + }; + +extern double mysecond(); +extern void checkSTREAMresults(); +#ifdef TUNED +extern void tuned_STREAM_Copy(); +extern void tuned_STREAM_Scale(STREAM_TYPE scalar); +extern void tuned_STREAM_Add(); +extern void tuned_STREAM_Triad(STREAM_TYPE scalar); +#endif +#ifdef _OPENMP +extern int omp_get_num_threads(); +#endif +int +main() + { + int quantum, checktick(); + int BytesPerWord; + int k; + ssize_t j; + STREAM_TYPE scalar; + double t, times[4][NTIMES]; + + /* --- SETUP --- determine precision and check timing --- */ + + printf(HLINE); + printf("STREAM version $Revision: 5.10 $\n"); + printf(HLINE); + BytesPerWord = sizeof(STREAM_TYPE); + printf("This system uses %d bytes per array element.\n", + BytesPerWord); + + printf(HLINE); +#ifdef N + printf("***** WARNING: ******\n"); + printf(" It appears that you set the preprocessor variable N when compiling this code.\n"); + printf(" This version of the code uses the preprocessor variable STREAM_ARRAY_SIZE to control the array size\n"); + printf(" Reverting to default value of STREAM_ARRAY_SIZE=%llu\n",(unsigned long long) STREAM_ARRAY_SIZE); + printf("***** WARNING: ******\n"); +#endif + + printf("Array size = %llu (elements), Offset = %d (elements)\n" , (unsigned long long) STREAM_ARRAY_SIZE, OFFSET); + printf("Memory per array = %.1f MiB (= %.1f GiB).\n", + BytesPerWord * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.0), + BytesPerWord * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.0/1024.0)); + printf("Total memory required = %.1f MiB (= %.1f GiB).\n", + (3.0 * BytesPerWord) * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.), + (3.0 * BytesPerWord) * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024./1024.)); + printf("Each kernel will be executed %d times.\n", NTIMES); + printf(" The *best* time for each kernel (excluding the first iteration)\n"); + printf(" will be used to compute the reported bandwidth.\n"); + +#ifdef _OPENMP + printf(HLINE); +#pragma omp parallel + { +#pragma omp master + { + k = omp_get_num_threads(); + printf ("Number of Threads requested = %i\n",k); + } + } +#endif + +#ifdef _OPENMP + k = 0; +#pragma omp parallel +#pragma omp atomic + k++; + printf ("Number of Threads counted = %i\n",k); +#endif + + /* Get initial value for system clock. */ +#pragma omp parallel for + for (j=0; j= 1) + printf("Your clock granularity/precision appears to be " + "%d microseconds.\n", quantum); + else { + printf("Your clock granularity appears to be " + "less than one microsecond.\n"); + quantum = 1; + } + + t = mysecond(); +#pragma omp parallel for + for (j = 0; j < STREAM_ARRAY_SIZE; j++) + a[j] = 2.0E0 * a[j]; + t = 1.0E6 * (mysecond() - t); + + printf("Each test below will take on the order" + " of %d microseconds.\n", (int) t ); + printf(" (= %d clock ticks)\n", (int) (t/quantum) ); + printf("Increase the size of the arrays if this shows that\n"); + printf("you are not getting at least 20 clock ticks per test.\n"); + + printf(HLINE); + + printf("WARNING -- The above is only a rough guideline.\n"); + printf("For best results, please be sure you know the\n"); + printf("precision of your system timer.\n"); + printf(HLINE); + + /* --- MAIN LOOP --- repeat test cases NTIMES times --- */ + + scalar = 3.0; + for (k=0; k + +double mysecond() +{ + struct timeval tp; + struct timezone tzp; + int i; + + i = gettimeofday(&tp,&tzp); + return ( (double) tp.tv_sec + (double) tp.tv_usec * 1.e-6 ); +} + +#ifndef abs +#define abs(a) ((a) >= 0 ? (a) : -(a)) +#endif +void checkSTREAMresults () +{ + STREAM_TYPE aj,bj,cj,scalar; + STREAM_TYPE aSumErr,bSumErr,cSumErr; + STREAM_TYPE aAvgErr,bAvgErr,cAvgErr; + double epsilon; + ssize_t j; + int k,ierr,err; + + /* reproduce initialization */ + aj = 1.0; + bj = 2.0; + cj = 0.0; + /* a[] is modified during timing check */ + aj = 2.0E0 * aj; + /* now execute timing loop */ + scalar = 3.0; + for (k=0; k epsilon) { + err++; + printf ("Failed Validation on array a[], AvgRelAbsErr > epsilon (%e)\n",epsilon); + printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",aj,aAvgErr,abs(aAvgErr)/aj); + ierr = 0; + for (j=0; j epsilon) { + ierr++; +#ifdef VERBOSE + if (ierr < 10) { + printf(" array a: index: %ld, expected: %e, observed: %e, relative error: %e\n", + j,aj,a[j],abs((aj-a[j])/aAvgErr)); + } +#endif + } + } + printf(" For array a[], %d errors were found.\n",ierr); + } + if (abs(bAvgErr/bj) > epsilon) { + err++; + printf ("Failed Validation on array b[], AvgRelAbsErr > epsilon (%e)\n",epsilon); + printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",bj,bAvgErr,abs(bAvgErr)/bj); + printf (" AvgRelAbsErr > Epsilon (%e)\n",epsilon); + ierr = 0; + for (j=0; j epsilon) { + ierr++; +#ifdef VERBOSE + if (ierr < 10) { + printf(" array b: index: %ld, expected: %e, observed: %e, relative error: %e\n", + j,bj,b[j],abs((bj-b[j])/bAvgErr)); + } +#endif + } + } + printf(" For array b[], %d errors were found.\n",ierr); + } + if (abs(cAvgErr/cj) > epsilon) { + err++; + printf ("Failed Validation on array c[], AvgRelAbsErr > epsilon (%e)\n",epsilon); + printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",cj,cAvgErr,abs(cAvgErr)/cj); + printf (" AvgRelAbsErr > Epsilon (%e)\n",epsilon); + ierr = 0; + for (j=0; j epsilon) { + ierr++; +#ifdef VERBOSE + if (ierr < 10) { + printf(" array c: index: %ld, expected: %e, observed: %e, relative error: %e\n", + j,cj,c[j],abs((cj-c[j])/cAvgErr)); + } +#endif + } + } + printf(" For array c[], %d errors were found.\n",ierr); + } + if (err == 0) { + printf ("Solution Validates: avg error less than %e on all three arrays\n",epsilon); + } +#ifdef VERBOSE + printf ("Results Validation Verbose Results: \n"); + printf (" Expected a(1), b(1), c(1): %f %f %f \n",aj,bj,cj); + printf (" Observed a(1), b(1), c(1): %f %f %f \n",a[1],b[1],c[1]); + printf (" Rel Errors on a, b, c: %e %e %e \n",abs(aAvgErr/aj),abs(bAvgErr/bj),abs(cAvgErr/cj)); +#endif +} + +#ifdef TUNED +/* stubs for "tuned" versions of the kernels */ +void tuned_STREAM_Copy() +{ + ssize_t j; +#pragma omp parallel for + for (j=0; j

+ +To run WasmBoy, you need a Gameboy ROM file. For example, you can download [`tobudx.gb` (Tobu Tobu Girl ROM)](https://tangramgames.itch.io/tobu-tobu-girl-deluxe/purchase?popup=1) + +`wasm3.wasm` is a normal WASI build of Wasm3. + +### Run with Webassembly.sh + +Drag'n'drop `wasm3.wasm`, `wasmerboy.wasm`, `tobudx.gb` to [Webassembly.sh](https://webassembly.sh) and run: + +```sh +wasm3 /tmp/wasmerboy.wasm /tmp/tobudx.gb +``` + +To speed it up (at your own risk, this disables security features): +```sh +chromium-browser --no-sandbox --js-flags="--wasm-opt --wasm-no-bounds-checks --wasm-no-stack-checks" "https://webassembly.sh" +``` + +### Run with Wasmer + +```sh +mkdir fs +cp wasmerboy.wasm tobudx.gb ./fs +wasmer run --dir=fs --enable-experimental-io-devices wasm3.wasm -- fs/wasmerboy.wasm fs/tobudx.gb +``` + +### Also + +Check out [Aaron Turner's article on Wasmer and WasmBoy](https://medium.com/wasmer/wasmer-io-devices-announcement-6f2a6fe23081). diff --git a/wasm3-sys/wasm3/test/wasi/wasmboy/image.png b/wasm3-sys/wasm3/test/wasi/wasmboy/image.png new file mode 100644 index 0000000..2f579a6 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/wasmboy/image.png differ diff --git a/wasm3-sys/wasm3/test/wasi/wasmboy/wasmerboy.wasm b/wasm3-sys/wasm3/test/wasi/wasmboy/wasmerboy.wasm new file mode 100644 index 0000000..e7ee466 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/wasmboy/wasmerboy.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/wasmsynth/README.md b/wasm3-sys/wasm3/test/wasi/wasmsynth/README.md new file mode 100644 index 0000000..c9eb9d7 --- /dev/null +++ b/wasm3-sys/wasm3/test/wasi/wasmsynth/README.md @@ -0,0 +1,24 @@ +# Wasm Synth + +

+ +Here is some music created by [Peter Salomonsen](https://petersalomonsen.com/) in his [wasm music experiment](https://petersalomonsen.com/webassemblymusic/livecodev2/): + +- **Hondarribia (Wasm Summit opening track)**, `hondarribia.wasm` │ [SoundCloud](https://soundcloud.com/psalomo/hondarribia) +- **WASM song**, `wasm-song.wasm` │ [SoundCloud](https://soundcloud.com/psalomo/wasm-song) +- **Shuffle Chill**, `shuffle-chill.wasm` │ [SoundCloud](https://soundcloud.com/psalomo/shuffle-chill) +- **"WebChip" music**, `webchip-music.wasm` │ [SoundCloud](https://soundcloud.com/psalomo/webchip-music) + +Check out Peter's [excellent talk on WebAssembly Summit 2020](https://www.youtube.com/watch?v=WZp0sPDvWfw&t=18670). + +### Running + +Generate a `wav` file: +``` +wasm3 hondarribia.wasm | sox -S -t raw -b 32 -e float -r 44100 -c 2 - hondarribia.wav +``` + +Play live (choppy on most machines): +``` +wasm3 hondarribia.wasm | sox -S -t raw -b 32 -e float -r 44100 -c 2 - -d +``` diff --git a/wasm3-sys/wasm3/test/wasi/wasmsynth/hondarribia.wasm b/wasm3-sys/wasm3/test/wasi/wasmsynth/hondarribia.wasm new file mode 100644 index 0000000..e58fbd7 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/wasmsynth/hondarribia.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/wasmsynth/image.png b/wasm3-sys/wasm3/test/wasi/wasmsynth/image.png new file mode 100644 index 0000000..992c4c4 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/wasmsynth/image.png differ diff --git a/wasm3-sys/wasm3/test/wasi/wasmsynth/shuffle-chill.wasm b/wasm3-sys/wasm3/test/wasi/wasmsynth/shuffle-chill.wasm new file mode 100644 index 0000000..413456f Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/wasmsynth/shuffle-chill.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/wasmsynth/wasm-song.wasm b/wasm3-sys/wasm3/test/wasi/wasmsynth/wasm-song.wasm new file mode 100644 index 0000000..f89fb87 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/wasmsynth/wasm-song.wasm differ diff --git a/wasm3-sys/wasm3/test/wasi/wasmsynth/webchip-music.wasm b/wasm3-sys/wasm3/test/wasi/wasmsynth/webchip-music.wasm new file mode 100644 index 0000000..9149023 Binary files /dev/null and b/wasm3-sys/wasm3/test/wasi/wasmsynth/webchip-music.wasm differ