[
  {
    "path": ".clang-format",
    "content": "---\nBasedOnStyle: Chromium\nIndentWidth: 4\nObjCBlockIndentWidth: 4\nColumnLimit: 200\n"
  },
  {
    "path": ".devcontainer/Dockerfile",
    "content": "FROM ubuntu:latest\n\nRUN sed -i 's/^# \\(.*export LS_OPTIONS.*$\\)/\\1/g' ~/.bashrc && \\\n    sed -i 's/^# \\(.*alias ll.*$\\)/\\1/g' ~/.bashrc\n\nRUN ln -fs /usr/share/zoneinfo/America/Los_Angeles /etc/localtime\nRUN DEBIAN_FRONTEND=noninteractive \\\n    apt-get update && \\\n    apt-get install -y \\\n        tzdata\\\n        git \\\n        sudo \\\n        gdb \\\n        clang-format-14 \\\n        python3-pip \\\n        pre-commit \\\n        vim\n\nWORKDIR /app\nCOPY .github/install_dependencies /app/\nRUN /app/install_dependencies\n\nRUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*\n"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "content": "// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:\n// https://github.com/microsoft/vscode-dev-containers/tree/v0.177.0/containers/docker-existing-dockerfile\n{\n\t\"name\": \"Existing Dockerfile\",\n\n\t// Sets the run context to one level up instead of the .devcontainer folder.\n\t\"context\": \"..\",\n\n\t\"dockerFile\": \"Dockerfile\",\n\n\t\"updateContentCommand\" : \"apt-get install git\",\n\n\t\"postCreateCommand\" : \"cmake -B /app/build -DCMAKE_BUILD_TYPE=Debug -DNFM=TRUE -DBUILD_UNITTESTS=true ; pre-commit install\",\n\n\t// vs code extensions to install in the dev container\n\t\"customizations\": {\n\t\t\"vscode\": {\n\t\t\t\"extensions\": [\n\t\t\t\t\"ms-vscode.cpptools\",\n\t\t\t\t\"ms-vscode.cmake-tools\",\n\t\t\t\t\"ms-vscode.cpptools-extension-pack\",\n\t\t\t\t\"twxs.cmake\",\n\t\t\t\t\"streetsidesoftware.code-spell-checker\",\n\t\t\t\t\"ms-azuretools.vscode-docker\",\n\t\t\t\t\"GitHub.vscode-github-actions\",\n\t\t\t\t\"xaver.clang-format\"\n\t\t\t]\n\t\t}\n\t},\n\n\t// Use 'forwardPorts' to make a list of ports inside the container available locally.\n\t// \"forwardPorts\": [],\n\n\t\"runArgs\": [ \"--cap-add=SYS_PTRACE\", \"--security-opt\", \"seccomp=unconfined\" ]\n}\n"
  },
  {
    "path": ".devcontainer/shell",
    "content": "#!/bin/bash -e\n\ncd `dirname $0`/../\n\n# build container\ndocker build -t rtl_airband-dev -f .devcontainer/Dockerfile .\n\n# run bash in container\ndocker run --rm -v $(pwd):/app/ -it --entrypoint bash rtl_airband-dev\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Report a bug you found when using RTLSDR-Airband\ntitle: \"[BUG]\"\nlabels: ''\nassignees: ''\n\n---\n\n<!--\nPlease use this template to create your bug report. By providing as much info as possible you help understand the issue, reproduce it and resolve it for you quicker. Therefore take a couple of extra minutes to make sure you have provided all information needed.\n-->\n\n**Describe your environment**\n\n  - RTLSDR-Airband version you are using (stable release number or branch/commit):\n  - `make` options used to build the program:\n  - Hardware platform (eg. x86_64, Raspberry Pi v4):\n  - Operating system name and version:\n\n**What happened?**\n\n**What you expected to happen?**\n\n**Steps to Reproduce**\n\n**Additional context**\nAdd any other relevant information about the problem here.\n\n**Your rtl_airband.conf file**\nRemove passwords, server addresses and other private information.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Questions & Help\n    url: https://github.com/rtl-airband/RTLSDR-Airband/discussions/categories/q-a\n    about: Please ask and answer questions here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: \"[FEATURE]\"\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? If so, please describe.**\nA description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\n\n**Describe alternative solutions or features you've considered**\n\n**Additional context**\nAdd any other relevant information about the feature request here.\n"
  },
  {
    "path": ".github/install_dependencies",
    "content": "#!/bin/bash\n\nunameOut=\"$(uname -s)\"\n\necho \"Running on ${unameOut} as ${USER}\"\n\ncase \"${unameOut}\" in\n    Linux*)\n        echo \"Installing Linux dependencies\"\n        sudo apt-get update -y\n        sudo apt-get install -y \\\n            build-essential \\\n            cmake \\\n            libmp3lame-dev \\\n            libshout3-dev \\\n            libconfig++-dev \\\n            libfftw3-dev \\\n            librtlsdr-dev \\\n            libsoapysdr-dev \\\n            libpulse-dev\n\n        (\n            git clone https://github.com/f4exb/libmirisdr-4\n            cd libmirisdr-4\n            mkdir build\n            cd build\n            cmake ../\n            sudo make install\n            sudo ldconfig\n        )\n        ;;\n\n    Darwin*)\n        echo \"Installing MacOS dependencies\"\n\n        # detect when running in github workflow and skip `brew update` (relay on fresh OS image)\n        if [ -n \"${GITHUB_ACTION}\" ] ; then\n            echo \"running in GitHub Workflow, skipping brew update\"\n            export HOMEBREW_NO_AUTO_UPDATE=1\n            export HOMEBREW_NO_INSTALL_UPGRADE=1\n            export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1\n            echo \"running ${ImageOS} vsersion ${ImageVersion}\"\n        else\n            brew update\n        fi\n\n        brew install \\\n            lame \\\n            libshout \\\n            libconfig \\\n            fftw \\\n            librtlsdr \\\n            soapysdr \\\n            pulseaudio \\\n            pkg-config\n\n        ;;\n\n    *)\n        echo \"Error: Machine not supported\"\n        exit -1\nesac\n"
  },
  {
    "path": ".github/platform_build",
    "content": "#!/bin/bash -e\n\nplatform=\"${1}\"\n\nif [ -z \"${platform}\" ]; then\n    echo \"Error: platform not set\"\n    exit -1\nfi\n\necho \"running build for ${platform} on $(source /etc/os-release ; echo ${VERSION})\"\n\ncase \"${platform}\" in\n    rpi3b)\n        CMAKE_ARGS=\"-DPLATFORM=rpiv2 -DCMAKE_BUILD_TYPE=Release -DNFM=TRUE -DBUILD_UNITTESTS=TRUE\"\n        ;;\n    ubuntu-22.04-arm)\n        CMAKE_ARGS=\"-DPLATFORM=native -DCMAKE_BUILD_TYPE=Release -DNFM=TRUE -DBUILD_UNITTESTS=TRUE\"\n        ;;\n\n    *)\n        echo \"Error: Platform '${platform}' not supported\"\n        exit -1\nesac\n\n# make a build dir\nrm -rf build || true ; mkdir build\ncd build\n\n# configure and build\ncmake ${CMAKE_ARGS} ../\nVERBOSE=1 make -j\n\n# run unit tests\nsrc/unittests\n\n# run rtl_airband to get version string and exit\nsrc/rtl_airband -v\n"
  },
  {
    "path": ".github/workflows/build_docker_containers.yml",
    "content": "name: Build and Publish Containers\n\non:\n  push:\n    branches: [main, unstable]\n    tags: ['v*']\n  pull_request:\n  workflow_dispatch:\n  schedule:\n    - cron: '29 13 * * *' # run daily\n\njobs:\n  build:\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - os: ubuntu-latest\n            platform: linux/amd64\n          - os: ubuntu-latest\n            platform: linux/386\n          - os: ubuntu-24.04-arm\n            platform: linux/arm64\n          - os: ubuntu-24.04-arm\n            platform: linux/arm/v6\n          - os: ubuntu-24.04-arm\n            platform: linux/arm/v7\n    runs-on: ${{ matrix.os }}\n    permissions:\n      contents: read\n      packages: write\n      attestations: write\n      id-token: write\n    steps:\n\n    - name: Runner Info\n      run: printenv | sort\n\n    - name: Prepare\n      id: prep\n      run: |\n        echo \"platform_pair=${platform//\\//-}\" >> $GITHUB_OUTPUT\n        echo \"repo_lowercase=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')\" >> $GITHUB_OUTPUT\n      env:\n        platform: ${{ matrix.platform }}\n\n    - name: Checkout\n      uses: actions/checkout@v4\n      with:\n        fetch-depth: '0' # need full history to get version from git tag\n\n    - name: Container metadata\n      id: metadata\n      uses: docker/metadata-action@v5\n      with:\n        images: ghcr.io/${{ steps.prep.outputs.repo_lowercase }}\n\n    - name: Set up QEMU\n      uses: docker/setup-qemu-action@v3\n\n    - name: Set up Docker Buildx\n      uses: docker/setup-buildx-action@v3\n\n    - name: Login to GitHub Container Registry\n      uses: docker/login-action@v3\n      with:\n        registry: ghcr.io\n        username: ${{ github.actor }}\n        password: ${{ secrets.GITHUB_TOKEN }}\n\n    - name: Build and push by digest\n      id: build\n      uses: docker/build-push-action@v6\n      with:\n        platforms: ${{ matrix.platform }}\n        cache-from: type=gha,scope=build-${{ steps.prep.outputs.platform_pair }}\n        cache-to: type=gha,mode=max,scope=build-${{ steps.prep.outputs.platform_pair }}\n        context: .\n        outputs: type=image,name=ghcr.io/${{ steps.prep.outputs.repo_lowercase }},push-by-digest=true,name-canonical=true,push=true\n\n    - name: Export digest\n      run: |\n        mkdir -p /tmp/digests\n        digest=\"${{ steps.build.outputs.digest }}\"\n        touch \"/tmp/digests/${digest#sha256:}\"\n\n    - name: Upload digest\n      uses: actions/upload-artifact@v4\n      with:\n        name: digests-${{ steps.prep.outputs.platform_pair }}\n        path: /tmp/digests/*\n        if-no-files-found: error\n        retention-days: 1\n\n  merge:\n    runs-on: ubuntu-latest\n    needs: build\n    permissions:\n      contents: read\n      packages: write\n    steps:\n\n    - name: Runner Info\n      run: printenv | sort\n\n    - name: Prepare\n      id: prep\n      run: |\n        echo \"repo_lowercase=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')\" >> $GITHUB_OUTPUT\n\n    - name: Download digests\n      uses: actions/download-artifact@v4\n      with:\n        path: /tmp/digests\n        pattern: digests-*\n        merge-multiple: true\n\n    - name: Set up Docker Buildx\n      uses: docker/setup-buildx-action@v3\n\n    - name: Container metadata\n      id: metadata\n      uses: docker/metadata-action@v5\n      with:\n        images: ghcr.io/${{ steps.prep.outputs.repo_lowercase }}\n\n    - name: Login to GitHub Container Registry\n      uses: docker/login-action@v3\n      with:\n        registry: ghcr.io\n        username: ${{ github.actor }}\n        password: ${{ secrets.GITHUB_TOKEN }}\n\n    - name: Create manifest list and push\n      working-directory: /tmp/digests\n      run: |\n        docker buildx imagetools create $(jq -cr '.tags | map(\"-t \" + .) | join(\" \")' <<< \"$DOCKER_METADATA_OUTPUT_JSON\") \\\n          $(printf 'ghcr.io/${{ steps.prep.outputs.repo_lowercase }}@sha256:%s ' *)\n\n    - name: Inspect image\n      run: |\n        docker buildx imagetools inspect ghcr.io/${{ steps.prep.outputs.repo_lowercase }}:${{ steps.metadata.outputs.version }}\n"
  },
  {
    "path": ".github/workflows/ci_build.yml",
    "content": "name: Run CI\n\non:\n  push:\n    branches: [main]\n    tags: ['v*']\n  pull_request:\n  workflow_dispatch:\n  schedule:\n    - cron: '39 13 * * *' # run daily\n\njobs:\n  ci_build:\n    strategy:\n      matrix:\n        os: [ ubuntu-22.04, macos-14, ubuntu-22.04-arm ]\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 35 # runtime across all OSs, runs can get queued\n    steps:\n    - name: Runner Info\n      run: printenv | sort\n\n    - name: Checkout\n      uses: actions/checkout@v4\n      with:\n        fetch-depth: '0' # need full history to get version from git tag\n\n    - name: Install packaged dependencies\n      run: .github/install_dependencies\n\n    - name: Configure\n      run: |\n        cmake -B ${{github.workspace}}/build_Debug -DCMAKE_BUILD_TYPE=Debug -DBUILD_UNITTESTS=TRUE\n        cmake -B ${{github.workspace}}/build_Debug_NFM -DCMAKE_BUILD_TYPE=Debug -DNFM=TRUE -DBUILD_UNITTESTS=TRUE\n        cmake -B ${{github.workspace}}/build_Release -DCMAKE_BUILD_TYPE=Release -DBUILD_UNITTESTS=TRUE\n        cmake -B ${{github.workspace}}/build_Release_NFM -DCMAKE_BUILD_TYPE=Release -DNFM=TRUE -DBUILD_UNITTESTS=TRUE\n\n    - name: Build\n      run: |\n        VERBOSE=1 cmake --build ${{github.workspace}}/build_Debug -j4\n        VERBOSE=1 cmake --build ${{github.workspace}}/build_Debug_NFM -j4\n        VERBOSE=1 cmake --build ${{github.workspace}}/build_Release -j4\n        VERBOSE=1 cmake --build ${{github.workspace}}/build_Release_NFM -j4\n\n    - name: Unit Tests\n      run: |\n        ${{github.workspace}}/build_Debug/src/unittests\n        ${{github.workspace}}/build_Debug_NFM/src/unittests\n        ${{github.workspace}}/build_Release/src/unittests\n        ${{github.workspace}}/build_Release_NFM/src/unittests\n\n    - name: Install\n      run: sudo cmake --install ${{github.workspace}}/build_Release_NFM\n\n    - name: Test run\n      run: /usr/local/bin/rtl_airband -v\n"
  },
  {
    "path": ".github/workflows/code_formatting.yml",
    "content": "name: Code Formatting\n\non:\n  pull_request:\n  schedule:\n    - cron: '39 13 * * *' # run daily\n\njobs:\n  code_formatting:\n    runs-on: ubuntu-latest\n    steps:\n\n    - name: Runner Info\n      run: printenv | sort\n\n    - name: Checkout\n      uses: actions/checkout@v4\n\n    - name: Install Clang Format\n      run: sudo apt-get install clang-format-14\n\n    - name: Run Clang Format\n      run: |\n        ./scripts/reformat_code\n        git diff --exit-code\n"
  },
  {
    "path": ".github/workflows/platform_build.yml",
    "content": "name: Platform Build\n\non:\n  push:\n    branches: [main]\n    tags: ['v*']\n  pull_request:\n  workflow_dispatch:\n  schedule:\n    - cron: '39 13 * * *' # run daily\n\njobs:\n  platform_build:\n    strategy:\n      matrix:\n        # os: [ rpi3b ]\n        os: [ ubuntu-22.04-arm ]\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 35 # runtime across all OSs, runs can get queued\n    steps:\n    - name: Runner Info\n      run: printenv | sort\n\n    - name: Checkout\n      uses: actions/checkout@v4\n      with:\n        fetch-depth: '0' # need full history to get version from git tag\n\n    - name: Install packaged dependencies\n      run: .github/install_dependencies\n\n    - name: Configure Build and Test\n      run: .github/platform_build ${{ matrix.os }}\n"
  },
  {
    "path": ".github/workflows/version_bump.yml",
    "content": "name: Bump version\non:\n  pull_request:\n    types:\n      - closed\n    branches:\n      - main\njobs:\n  version_bump:\n    if: github.event.pull_request.merged == true\n    runs-on: ubuntu-22.04\n    permissions:\n      contents: write\n      actions: write\n    steps:\n    - uses: actions/checkout@v4\n      with:\n        ref: ${{ github.event.pull_request.merge_commit_sha }}\n        fetch-depth: '0'\n\n    - name: Bump version and push tag\n      id: tag\n      uses: anothrNick/github-tag-action@1.64.0\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        WITH_V: true\n        DEFAULT_BUMP: patch\n\n    - name: Create release for ${{ steps.tag.outputs.new_tag }}\n      if: steps.tag.outputs.part != 'patch'\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        tag: ${{ steps.tag.outputs.new_tag }}\n      run: |\n        gh release create \"$tag\" \\\n          --repo=\"$GITHUB_REPOSITORY\" \\\n          --title=\"Version ${tag#v}\" \\\n          --generate-notes\n\n    - name: Run CI on ${{ steps.tag.outputs.new_tag }}\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      run: |\n        gh workflow run ci_build.yml --ref ${{ steps.tag.outputs.new_tag }}\n\n    - name: Run Platform Build ${{ steps.tag.outputs.new_tag }}\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      run: |\n        gh workflow run platform_build.yml --ref ${{ steps.tag.outputs.new_tag }}\n\n    - name: Build and Publish Containers for ${{ steps.tag.outputs.new_tag }}\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      run: |\n        gh workflow run build_docker_containers.yml --ref ${{ steps.tag.outputs.new_tag }}\n"
  },
  {
    "path": ".gitignore",
    "content": "build*/\n.DS_Store\n.cache\ncompile_commands.json\nrtl_airband*.log\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "repos:\n-   repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v4.5.0\n    hooks:\n    - id: check-yaml\n    - id: end-of-file-fixer\n    - id: trailing-whitespace\n    - id: check-shebang-scripts-are-executable\n\n- repo: https://github.com/pre-commit/mirrors-clang-format\n  rev: v14.0.6\n  hooks:\n  - id: clang-format\n    files: src/.*\\.cpp|src/.*\\.h\n"
  },
  {
    "path": ".vscode/c_cpp_properties.json",
    "content": "{\n    \"configurations\": [\n        {\n            \"name\": \"Linux\",\n            \"includePath\": [\n                \"${workspaceFolder}/**\",\n                \"${workspaceFolder}/build/_deps/googletest-src/googletest/include/\",\n                \"${workspaceFolder}/build/src/\"\n            ],\n            \"defines\": [],\n            \"compilerPath\": \"/usr/bin/gcc\",\n            \"cStandard\": \"c17\",\n            \"cppStandard\": \"gnu++17\",\n            \"intelliSenseMode\": \"linux-gcc-arm64\",\n            \"configurationProvider\": \"ms-vscode.cmake-tools\"\n        }\n    ],\n    \"version\": 4\n}\n"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n    // Use IntelliSense to learn about possible attributes.\n    // Hover to view descriptions of existing attributes.\n    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"(gdb) Launch Unit Test\",\n            \"type\": \"cppdbg\",\n            \"request\": \"launch\",\n            \"program\": \"${workspaceFolder}/build/src/unittests\",\n            \"args\": [],\n            \"stopAtEntry\": false,\n            \"cwd\": \"${fileDirname}\",\n            \"environment\": [],\n            \"externalConsole\": false,\n            \"MIMode\": \"gdb\",\n            \"setupCommands\": [\n                {\n                    \"description\": \"Enable pretty-printing for gdb\",\n                    \"text\": \"-enable-pretty-printing\",\n                    \"ignoreFailures\": true\n                },\n                {\n                    \"description\": \"Set Disassembly Flavor to Intel\",\n                    \"text\": \"-gdb-set disassembly-flavor intel\",\n                    \"ignoreFailures\": true\n                }\n            ]\n        }\n\n    ]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n    \"editor.formatOnPaste\": true,\n    \"editor.formatOnSave\": true,\n    \"editor.formatOnType\": true,\n    \"editor.defaultFormatter\": \"xaver.clang-format\",\n    \"clang-format.executable\": \"clang-format-14\"\n}\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.1...3.18 FATAL_ERROR)\nproject (RTLSDR-Airband CXX)\n\nexecute_process(COMMAND ${PROJECT_SOURCE_DIR}/scripts/find_version\n   OUTPUT_VARIABLE RTL_AIRBAND_VERSION\n   OUTPUT_STRIP_TRAILING_WHITESPACE\n   ERROR_VARIABLE RTL_AIRBAND_VERSION_ERROR\n   ERROR_STRIP_TRAILING_WHITESPACE)\n\nstring(COMPARE EQUAL \"${RTL_AIRBAND_VERSION}\" \"\" RTL_AIRBAND_VERSION_UNSET)\n\nif(RTL_AIRBAND_VERSION_UNSET)\n   message(FATAL_ERROR \"Failed to detect RTL_AIRBAND_VERSION - \\\"${RTL_AIRBAND_VERSION_ERROR}\\\"\")\nendif()\n\nset (CMAKE_CXX_STANDARD 11)\nset (CXX_STANDARD_REQUIRED ON)\nset (CMAKE_CXX_EXTENSIONS OFF)\nset (CMAKE_COMPILE_WARNING_AS_ERROR ON)\n\nif(NOT CMAKE_BUILD_TYPE)\n   set(CMAKE_BUILD_TYPE Release)\n   message(STATUS \"Build type not specified: defaulting to Release\")\nendif(NOT CMAKE_BUILD_TYPE)\n\n# TODO: flags to add: -Wfloat-equal -Wconversion -Wstrict-overflow=5 -Waggregate-return -Wpedantic -Wcast-align\n# TODO: these could be added except for gtest: -Wswitch-enum -Wundef -Wswitch-default\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wall -Wextra -Wshadow -Wdate-time -Wpointer-arith -Wwrite-strings -Wcast-qual  -Wunreachable-code -Werror\")\nset(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} -Og -DDEBUG\")\n\nif(DEBUG_SQUELCH)\n   set(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG_SQUELCH\")\nendif()\n\nadd_subdirectory (src)\n"
  },
  {
    "path": "Dockerfile",
    "content": "# build container\nFROM debian:bookworm-slim AS build\n\n# install build dependencies\nRUN apt-get update && \\\n    apt-get upgrade -y && \\\n    apt-get install -y --no-install-recommends \\\n      build-essential \\\n      cmake \\\n      libmp3lame-dev \\\n      libshout3-dev \\\n      libconfig++-dev \\\n      libfftw3-dev \\\n      libsoapysdr-dev \\\n      libpulse-dev \\\n      \\\n      git \\\n      ca-certificates \\\n      libusb-1.0-0-dev \\\n      debhelper \\\n      pkg-config \\\n      && \\\n    apt-get clean && \\\n    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*\n\n# set working dir for compiling dependencies\nWORKDIR /build_dependencies\n\n# compile / install rtl-sdr-blog version of rtl-sdr for v4 support\nRUN git clone https://github.com/rtlsdrblog/rtl-sdr-blog && \\\n    cd rtl-sdr-blog/ && \\\n    dpkg-buildpackage -b --no-sign && \\\n    cd .. && \\\n    dpkg -i librtlsdr0_*.deb && \\\n    dpkg -i librtlsdr-dev_*.deb && \\\n    dpkg -i rtl-sdr_*.deb\n\n# compile / install libmirisdr-4\nRUN git clone https://github.com/f4exb/libmirisdr-4 && \\\n  cd libmirisdr-4 && \\\n  mkdir build && \\\n  cd build && \\\n  cmake ../ && \\\n  VERBOSE=1 make install && \\\n  ldconfig\n\n# TODO: build anything from source?\n\n# set working dir for project build\nWORKDIR /rtl_airband_build\n\n# copy in the rtl_airband source, coping in the full repo so find_version will be correct\nCOPY ./ .\n\n# configure and build\n# TODO: detect platforms\nRUN cmake -B build_dir -DPLATFORM=generic -DCMAKE_BUILD_TYPE=Release -DNFM=TRUE -DBUILD_UNITTESTS=TRUE && \\\n    VERBOSE=1 cmake --build build_dir -j4\n\n# make sure unit tests pass\nRUN ./build_dir/src/unittests\n\n\n# application container\nFROM debian:bookworm-slim\n\n# install runtime dependencies\nRUN apt-get update && \\\n  apt-get upgrade -y && \\\n  apt-get install -y --no-install-recommends \\\n    tini \\\n    libc6 \\\n    libmp3lame0 \\\n    libshout3 \\\n    libconfig++9v5 \\\n    libfftw3-single3 \\\n    libsoapysdr0.8 \\\n    libpulse0 \\\n    libusb-1.0-0-dev \\\n    ca-certificates \\\n  && \\\n  apt-get clean && \\\n  rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*\n\n# install (from build container) rtl-sdr-blog version of rtl-sdr for v4 support\nCOPY --from=build /build_dependencies/librtlsdr0_*.deb /build_dependencies/librtlsdr-dev_*.deb /build_dependencies/rtl-sdr_*.deb /tmp/\nRUN dpkg -i /tmp/librtlsdr0_*.deb && \\\n    dpkg -i /tmp/librtlsdr-dev_*.deb && \\\n    dpkg -i /tmp/rtl-sdr_*.deb && \\\n    rm -rf /tmp/*.deb && \\\n    echo '' | tee --append /etc/modprobe.d/rtl_sdr.conf && \\\n    echo 'blacklist dvb_usb_rtl28xxun' | tee --append /etc/modprobe.d/rtl_sdr.conf && \\\n    echo 'blacklist rtl2832' | tee --append /etc/modprobe.d/rtl_sdr.conf && \\\n    echo 'blacklist rtl2830' | tee --append /etc/modprobe.d/rtl_sdr.conf\n\n# copy (from build container) libmirisdr-4 library\nCOPY --from=build /usr/local/lib/libmirisdr.so.4 /usr/local/lib/\n\n# Copy rtl_airband from the build container\nCOPY LICENSE /app/\nCOPY --from=build /rtl_airband_build/build_dir/src/unittests /app/\nCOPY --from=build /rtl_airband_build/build_dir/src/rtl_airband /app/\nRUN chmod a+x /app/unittests /app/rtl_airband\n\n# make sure unit tests pass\nRUN /app/unittests\n\n# Use tini as init and run rtl_airband from /app/\nENTRYPOINT [\"/usr/bin/tini\", \"--\"]\nWORKDIR /app/\nCMD [\"/app/rtl_airband\", \"-F\", \"-e\", \"-c\", \"/app/rtl_airband.conf\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "GNU GENERAL PUBLIC LICENSE\n\nVersion 2, June 1991\n\nCopyright (C) 1989, 1991 Free Software Foundation, Inc.\n<https://fsf.org/>\nEveryone is permitted to copy and distribute verbatim copies\nof this license document, but changing it is not allowed.\nPreamble\n\nThe licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.\n\nWhen we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.\n\nTo protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.\n\nFor example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.\n\nWe protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.\n\nAlso, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.\n\nFinally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.\n\nThe precise terms and conditions for copying, distribution and modification follow.\n\nTERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The \"Program\", below, refers to any such program or work, and a \"work based on the Program\" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term \"modification\".) Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.\n\n1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.\n\n2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:\n\na) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.\nb) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.\nc) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)\nThese requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.\n\n3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:\n\na) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,\nb) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,\nc) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)\nThe source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.\n\nIf distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.\n\n4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.\n\n5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.\n\n6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.\n\n7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.\n\nIt is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.\n\nThis section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.\n\n8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.\n\n9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and \"any later version\", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.\n\n10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.\n\nNO WARRANTY\n\n11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\nEND OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "NEWS.md",
    "content": "# NEWS\n\nThis file will no longer be updated with each release, for changes between releases, see PRs merged to the repo\n\nVersion 5.0.0 (Jan 21, 2024):\n\n* NOTE: Going forward a release tag will be automatically created on each merge to `main`, and changes will not be reflected in this file.  For changes between versions see the repo's [release history](https://github.com/rtl-airband/RTLSDR-Airband/releases).\n* NOTE: Going forward PRs will be opened directly against `main` and the `unstable` branch will no longer be used.\n* NOTE: This repo has significantly diverged from the original project [microtony/RTLSDR-Airband](https://github.com/microtony/RTLSDR-Airband) so it has been been detached (ie no longer a fork).\n\n* Changes in this release, see [#444](https://github.com/rtl-airband/RTLSDR-Airband/pull/444):\n  * build and publish docker containers\n  * changes to supported `cmake` platforms:\n    * depreciate `rpiv1`, `armv7-generic`, and `armv8-generic` and build platforms\n    * change default build platform to `native`\n    * rename `default` to `generic`\n  * enable a series of compile warnings and cleanup code\n  * remove `SSE` specific code - let the compiler \"do the right thing\"\n  * remove some no longer supported windows `ifdef`'s\n  * fix CTCSS bug that could miss a tone when multiple tones have the same power (happens with less accurate floating point operations, ie i386)\n\nVersion 4.2.0 (Oct 13, 2023):\n\n* Changes in this release:\n  * Add support for building with libshout v2.4.6, see [#382](https://github.com/rtl-airband/RTLSDR-Airband/pull/382) and [#422](https://github.com/rtl-airband/RTLSDR-Airband/pull/422)\n  * Add error checking for lowpass <= highpass, see [#399](https://github.com/rtl-airband/RTLSDR-Airband/pull/399) and [#412](https://github.com/rtl-airband/RTLSDR-Airband/pull/412)\n  * Remove limit on count of mixer inputs (thanks @cdknox), see [#408](https://github.com/rtl-airband/RTLSDR-Airband/pull/408)\n  * Add `dated_subdirectories` config option for output files (thanks, @marcin-osowski), see [#413](https://github.com/rtl-airband/RTLSDR-Airband/pull/413)\n\nVersion 4.1.1 (May 1, 2023):\n\n* Changes in this release:\n  * Fix build issues when using VideoCore GPU, see [#378](https://github.com/rtl-airband/RTLSDR-Airband/pull/378)\n\nVersion 4.1.0 (April 23, 2023):\n\n* Changes in this release:\n  * Add `channel_dbfs_noise_level` and `channel_dbfs_signal_level` to the stats file, see [#355](https://github.com/rtl-airband/RTLSDR-Airband/pull/355)\n  * Add squelch support for CTCSS, add `channel_ctcss_counter` and `channel_no_ctcss_counter` to the stats file, see [#368](https://github.com/rtl-airband/RTLSDR-Airband/pull/368)\n  * Support `ampfactor` on a per-channel basis (in addition to mixer inputs), see [#369](https://github.com/rtl-airband/RTLSDR-Airband/pull/369)\n  * Fix config error messages, see [#371](https://github.com/rtl-airband/RTLSDR-Airband/pull/371)\n  * Multiple CI / workflow improvements, including:\n    * Addition of Dockerfiles and shell scripts for multiple build environments\n    * Addition of vscode devcontainer configuration\n    * Addition of gtest, code refactoring, addition of unit tests, running unit tests on each pull request\n    * Running more combinations of OSs, build types, and build options on each pull request\n\nVersion 4.0.3 (Jan 10, 2023):\n\n* Changes in this release:\n  * Add `channel_squelch_level` to stats file, see [#332](https://github.com/rtl-airband/RTLSDR-Airband/pull/332)\n  * Support \"default\" values in lists for `squelch_snr_threshold` and `notch_q`,\n   see [#334](https://github.com/rtl-airband/RTLSDR-Airband/pull/334)\n  * Set cmake `ENABLE_EXPORTS` property, see [#339](https://github.com/rtl-airband/RTLSDR-Airband/pull/339)\n\n* Other items to note:\n  * Repo maintainer has changed, see [#342](https://github.com/rtl-airband/RTLSDR-Airband/discussions/342)\n  * Repo URL has moved to https://github.com/rtl-airband/RTLSDR-Airband\n  * Default branch / Top of Tree has been renamed to `main`\n\nVersion 4.0.2 (Dec 26, 2021):\n\n* Added a new `PLATFORM` value `default` (which, as the name says, is the new\n  default). It results in a portable binary without any architecture-specific\n  optimizations. This also allows the program to be built with compilers that\n  do not support `-march=native` option (notably Clang on Apple M1) (#303).\n\nVersion 4.0.1 (Nov 14, 2021):\n\n* Fixed compilation error on RaspberryPi OS 11 (Bullseye)\n\nVersion 4.0.0 (Oct 19, 2021):\n\n* RTLSDR-Airband is now built with CMake. Refer to the wiki for updated\n  compilation instructions.\n* When compiling the program, a new `PLATFORM` value `native` can now be\n  specified. It enables `-march=native -mtune=native` compilation options. This\n  causes the compiler to apply the most appropriate optimizations for the\n  hardware on which the app is being built (thx @charlie-foxtrot).\n* BACKWARDS-INCOMPATIBLE CHANGE: Signal level and noise level estimates\n  displayed in the textual waterfalls are now expressed in dBFS (decibels\n  related to the full scale of the analog-to-digital converter). The main\n  benefit of the new approach is that these values do not depend on the\n  `fft_size` value(thx @charlie-foxtrot).\n* BACKWARDS-INCOMPATIBLE CHANGE: Improved squelch algorithm with new\n  configuration parameters. `squelch` keyword has been replaced with\n  `squelch_threshold` which takes an absolute signal value in dBFS as an\n  argument. Alternatively, a minimum signal-to-noise ratio (in dB) that should\n  trigger the squelch might be configured using `squelch_snr_threshold` option\n  (thx @charlie-foxtrot).\n* BACKWARDS-INCOMPATIBLE CHANGE: `include_freq` config option for file outputs\n  now causes the frequency to be appended after the timestamp rather than\n  before it. This feature now works correctly in scan mode, when\n  `split_on_transmission` feature is enabled. (thx @charlie-foxtrot).\n* BACKWARDS-INCOMPATIBLE CHANGE: sample format in files produced by `rawfile`\n  outputs has been changed from CS16 to CF32. File name suffix is now `.cf32`.\n* Improved squelch indicator in the textual waterfalls. In addition to the `*`\n  character indicating that the squelch is open, there is also a `~` character\n  indicating that the channel has a signal that is being suppressed because it\n  is outside the band of the channel filter (thx @charlie-foxtrot).\n* New output type `udp_stream` for sending uncompressed audio to another host\n  via UDP/IP (thx @charlie-foxtrot).\n* Added `multiple_output_threads` global option. When set to `true`, a separate\n  output thread is spawned for each device (thx @charlie-foxtrot).\n* Modulation in scan mode is now configurable per channel (thx\n  @charlie-foxtrot).\n* SoapySDR errors like TIMEOUT or OVERFLOW are no longer treated as fatal. They\n  often appear intermittently, especially when the CPU usage is high. There is\n  no point in failing the input in this case.\n* Added `.tmp` suffix to the names of the output files currently being written\n  to. The suffix is removed when the file is closed. External applications that\n  consume recorded files can now figure out which files are not yet complete.\n* Added logging and statistics for output thread overruns and mixer\n  input/output overruns (thx @charlie-foxtrot).\n* The program can now be built on MacOS.\n* Miscellaneous bug fixes and code cleanups.\n\nVersion 3.2.1 (Nov 13, 2020):\n\n* Fixed a compile error when using libshout older than 2.4.0\n\nVersion 3.2.0 (Nov 08, 2020):\n\n* Added `split_on_transmission` output file option which allows creating\n  a new file for every transmission on the channel (thx @charlie-foxtrot).\n* Added `include_freq` output file option, which causes the channel frequency\n  to be appended to the file name (thx @charlie-foxtrot).\n* Added support for notch filters for eliminating narrowband interference,\n  like CTCSS tones (thx @charlie-foxtrot).\n* Added `bandwidth` channel option which causes the channelized I/Q signal\n  to be lowpass-filtered before demodulation. This might help in situations\n  where neighboring channels are closely spaced and interfere with the channel\n  of interest. It also reduces the bandwidth of the resulting audio signal,\n  and thus eliminates the high-frequency noise (thx @charlie-foxtrot).\n* Added support for multithreaded demodulation. Each device can now have its\n  own demodulation thread. This allows spreading the demodulation work across\n  multiple CPU cores. Enable with `multiple_demod_threads` global option\n  (thx @charlie-foxtrot).\n* Added support for highpass/lowpass MP3 filters for mixers (thx @charlie-foxtrot)\n* Added support for frequency usage statistics (thx @charlie-foxtrot).\n* Workaround for Fitipower tuner problem of not honoring the first gain\n  setting when the device is first used (thx @eshaz).\n* Finalize the MP3 file properly before opening a new one (thx @jratke).\n* Close the RTL device properly on program exit (thx @jratke).\n* Updated the SoapySDR input driver to reflect changes in SoapySDR library API.\n* Minor cleanups.\n\nVersion 3.1.0 (Jan 19, 2020):\n\n* SoapySDR: added support for complex float 32-bit samples\n* SoapySDR: allow using AGC if the device supports it. Gain setting for\n  soapy devices is now optional - if it's not specified, the program will\n  try to enable AGC.\n* Use lowpass/highpass filters provided by LAME library to improve audio\n  quality of MP3 streams. Filter cutoff frequencies may be configured per\n  output, using `highpass` and `lowpass` config options. Credit: clydebarrow.\n* Added `log_scan_activity` global config option. When set to `true`, a\n  log message is written whenever a squelch opens on a scanned channel,\n  effectively producing a channel activity log. Credit: clam-i-am.\n* Improved squelch behaviour in some corner cases.\n* Fix for incorrect naming of pulseaudio context. Name set in the config\n  was not used as it should. Credit: Darryl Pogue.\n* Don't fail when the configured gain value is negative. Some SDRs support\n  this (eg. FC0012-based dongles).\n* Fix a bug which in some cases could prevent the icecast output from\n  reconnecting with the Icecast server after the connection has failed.\n\nVersion 3.0.1 (Feb 16, 2018):\n\n* Fix for squelch staying constantly open when configured manually\n  with NFM=off (#84)\n\nVersion 3.0.0 (Feb 10, 2018):\n\n* Major overhaul of the SDR input code - now it's modular and\n  hardware-agnostic (no longer tightly coupled with librtlsdr).\n* Support for SoapySDR vendor-neutral SDR library - any SDR which has\n  a plugin for SoapySDR shall now work in RTLSDR-Airband.\n* Support for Mirics DVB-T dongles via libmirisdr-4 library.\n* Support for RTLSDR is now optional and can be disabled at compilation\n  stage.\n* Removed the 8-channels-per-device limit in multichannel mode.\n* Configurable per-device sampling rate.\n* Configurable FFT size.\n* Support for multibyte input samples.\n* Support for rawfile outputs (ie. writing raw I/Q data from a\n  narrowband channel to a file for processing with other programs,\n  line GNUradio or csdr).\n* INCOMPATIBLE CHANGE: removed `rtlsdr_buffers` global configuration\n  option; buffer count can now be adjusted with a per-device\n  \"buffers\" option.\n* INCOMPATIBLE CHANGE: removed `syslog` global configuration option;\n  syslog logging is now enabled by default, both in foreground and\n  background mode. To force logging to standard error, use -e command\n  line option.\n* Added -F command line option for better cooperation with systemd.\n  Runs the program in foreground, but without textual waterfalls.\n  Together with -e it allows running rtl_airband as a service of type\n  \"simple\" under systemd. Example rtl_airband.service file has been\n  adjusted to reflect this change.\n* Added `type` device configuration option. It sets the device type\n  (ie. the input driver which shall be used to talk to the device).\n  \"rtlsdr\" is assumed as a default type for backward compatibility.\n  If RTLSDR support has been disabled at compilation stage, then\n  there is no default type - it must be set manually, or the program\n  will throw an error on startup.\n* Frequencies in the config can now be expressed in Hz, kHz, MHz or GHz\n  for improved readability.\n* Lots of bugfixes.\n* Rewritten documentation on [Github Wiki](https://github.com/rtl-airband/RTLSDR-Airband/wiki).\n\nVersion 2.4.0 (Oct 15, 2017):\n\n* Support for PulseAudio output via new output type `pulse`. With this\n  feature you can eg. play the sound via the soundcard of the Raspberry\n  Pi you run RTLSDR-Airband on (you need to install and run pulseaudio\n  daemon on it, though). Or you can stream the audio from a Pi located\n  near the antenna (eg. in the attic) to speakers connected to the desktop\n  PC you are sitting at, without launching a local Icecast server,\n  as before. Because the audio stream is sent uncompressed, it is\n  not recommended to run it across the Internet - jitter or packet loss\n  will easily cause the audio to become choppy. However in a local network\n  PulseAudio is a good choice. And it gives much lower latency as compared\n  to Icecast (typically under 0.5 seconds). Thanks to Marcus Ströbel\n  for the idea and initial implementation.\n* Support for referring to RTL devices by their serial numbers in the\n  config file. Instead of `index = <dongle_index>` parameter, use `serial =\n  <dongle_serial_number>` to get consistent behavior across reboots\n  and hardware reconfigurations.\n* Set RTL gain to the nearest gain value supported by the device. This is\n  required for E4000 tuners, which do not round the given gain value to\n  the nearest supported setting, which causes the gain setting operation\n  to fail.\n* Improved squelch operation in scan mode. All squelch-related variables\n  (noise floor, AGC coefficients, etc) are now calculated and stored\n  separately for each scanned channel. Earlier their values were common\n  to all channels, which caused squelch problems in case when noise floor\n  varied considerably between channels. Thanks to @strix-technica.\n* Added build target for FreeBSD on x86. Use `PLATFORM=x86-freebsd` to\n  compile and `PLATFORM=x86-freebsd gmake install` to install. Thanks\n  to @nyammy.\n* Display squelch setting in waterfall in place of noise floor value when\n  squelch is set manually.\n* Bug fixes, performance improvements.\n* Decluttered and more understandable documentation.\n\nVersion 2.3.0 (Jan 2, 2017):\n\n* Added support for mixers. It is now possible to produce audio streams\n  combined from several input channels. Both mono and stereo mixing is\n  supported. Usage example is provided in config/mixers.conf. All\n  mixer-related parameters are documented in config/reference.conf.\n* Added build options for 64-bit ARM architectures, like Odroid C2.\n  Please use PLATFORM=armv8-generic when compiling.\n* Fixed a long-standing bug in RTL sample processing, which caused some\n  samples to be processed twice. If you were annoyed by these regular\n  clicks in NFM audio every 125 ms, they are now gone.\n* Reduced CPU usage on x86\n* Some code restructuring and cleanups\n* Added several configuration file examples for typical real-life\n  scenarios. They are placed in config/ subdirectory. rtl_airband.conf.example\n  file has been moved to config/reference.conf. It is meant to be a reference\n  for all supported config knobs together with their description. This is\n  still an interim solution before some more readable and understandable\n  documentation gets written.\n\nVersion 2.2.0 (Oct 8, 2016):\n\n* Support for Icecast stream metadata updates in scanning mode. When enabled,\n  every time the scanner stops on a channel, current frequency is written into\n  Icecast song title, which in turn is displayed in the player. Alternatively,\n  textual labels can be configured for each frequency. It is possible\n  to configure the amount of delay between the stream and metadata updates to\n  synchronize them with the audio. There are some caveats however - read\n  comments in rtl_airband.conf.example for details.\n* Added global option 'localtime'. When enabled, rtl_airband uses local time\n  instead of UTC time for output file names. (Credit: ScanOC).\n* Auto gain feature removed. RTL auto gain does not work well for narrowband\n  channels. Most often it sets the gain too high which causes problems for\n  auto squelch and audio bleeding between adjacent channels. Gain must be\n  configured manually from now on.\n* Dropped unmaintained Windows build.\n* Reverted to power level calculation algorithm from version 2.0.2. The new\n  algo didn't really do much to sensitivity, but introduced annoying clicks\n  on squelch open/close.\n* Improved DC offset estimator for AM mode. This one hardly ever clicks\n  on squelch opening.\n* Boosted AM audio volume.\n* Reduced squelch flapping in NFM mode.\n\nVersion 2.1.0 (Aug 11, 2016):\n\n* Narrowband FM demodulation support\n* Automatic Frequency Control\n* Append mode for recording (enabled by default)\n* Dongles, channels and outputs can be individually enabled and disabled\n  by a simple config flag (no need to comment out or delete large\n  configuration sections)\n* Use VBR for MP3 encoding\n* Modified power level calculation algorithm (better sensitivity)\n* Support for manual squelch setting\n* Bug fixes\n\nVersion 2.0.2 (Mar 26, 2016):\n\n* Fixed a problem with running three dongles or more, simultaneously\n\nVersion 2.0.1 (Jan 24, 2016):\n\n* Fixed crash on output initialization\n\nVersion 2.0.0 (Dec 27, 2015):\n\n* util/convert_cfg: can be used to convert old-style config.txt to the new format\n* Syslog logging (enabled by default)\n* Daemon mode\n* Reworked makefiles, added install rule\n* /dev/vcio is now used to access GPU on RPi; creating char_dev no longer necessary\n* Startup scripts for Debian and Gentoo\n* Support for auto gain setting\n* Support for multiple outputs per channel\n* Support for recording streams to local MP3 files\n* Support for ARMv7-based platforms other than RPi (eg. Cubieboard)\n* Updated documentation\n* Numerous bugfixes and stability improvements\n\nVersion 1.0.0 (May 12, 2015):\n\n* Linux x86/x86_64 support (Windows build is currently unmaintained and might not work)\n* Raspberry Pi V2 support\n* Bundled hello_fft code (v2.0)\n* More robust interaction with Icecast servers\n* Important stability fixes\n"
  },
  {
    "path": "README.md",
    "content": "# RTLSDR-Airband\n\n![main](https://github.com/rtl-airband/RTLSDR-Airband/actions/workflows/ci_build.yml/badge.svg?branch=main)\n![main](https://github.com/rtl-airband/RTLSDR-Airband/actions/workflows/platform_build.yml/badge.svg?branch=main)\n![main](https://github.com/rtl-airband/RTLSDR-Airband/actions/workflows/build_docker_containers.yml/badge.svg?branch=main)\n![main](https://github.com/rtl-airband/RTLSDR-Airband/actions/workflows/code_formatting.yml/badge.svg?branch=main)\n\nChanges as of v5.1.0:\n - License is now GPLv2 [#503](https://github.com/rtl-airband/RTLSDR-Airband/discussions/503)\n\nNOTE: Repo URL has moved to https://github.com/rtl-airband/RTLSDR-Airband see [#502](https://github.com/rtl-airband/RTLSDR-Airband/discussions/502) for info\n\nChanges as of v5.0.0:\n - PRs will be opened directly against `main` and the `unstable` branch will no longer be used\n - Version tags will be automatically created on each merge to `main`\n - A release will be created on each `major` or `minor` version tag but not `minor` tags\n - Checking out `main` is recommended over using a release artifact to stay on the latest version\n - This repo has significantly diverged from the original project [microtony/RTLSDR-Airband](https://github.com/microtony/RTLSDR-Airband) so it has been been detached (ie no longer a fork).\n - Specific build support for `rpiv1`, `armv7-generic`, and `armv8-generic` have been deprecated for the new default `native`, see [#447](https://github.com/rtl-airband/RTLSDR-Airband/discussions/447)\n\n\n## Overview\n\nRTLSDR-Airband receives analog radio voice channels and produces\naudio streams which can be routed to various outputs, such as online\nstreaming services like LiveATC.net. Originally the only SDR type\nsupported by the program was Realtek DVB-T dongle (hence the project's\nname). However, thanks to SoapySDR vendor-neutral SDR library, other\nradios are now supported as well.\n\n## Documentation\n\nUser's manual is now on the [wiki](https://github.com/rtl-airband/RTLSDR-Airband/wiki).\n\n## Credits and thanks\n\nI hereby express my gratitude to everybody who helped with the development and testing\nof RTLSDR-Airband. Special thanks go to:\n\n* Dave Pascoe\n* SDR Guru\n* Marcus Ströbel\n* strix-technica\n* charlie-foxtrot\n\n## License\n\nCopyright (C) 2022-2025 charlie-foxtrot\n\nCopyright (C) 2015-2022 Tomasz Lemiech <szpajder@gmail.com>\n\nBased on original work by Wong Man Hang <microtony@gmail.com>\n\nThis program is free software; you can redistribute it and/or\nmodify it under the terms of the GNU General Public License\nas published by the Free Software Foundation; either version 2\nof the License, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, see <https://www.gnu.org/licenses/>.\n\n## Open Source Licenses of bundled code\n\n### gpu_fft\n\nBCM2835 \"GPU_FFT\" release 2.0\nCopyright (c) 2014, Andrew Holme.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright\n  notice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright\n  notice, this list of conditions and the following disclaimer in the\n  documentation and/or other materials provided with the distribution.\n* Neither the name of the copyright holder nor the\n  names of its contributors may be used to endorse or promote products\n  derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n### rtl-sdr\n\n* Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de>\n* Copyright (C) 2015 by Kyle Keen <keenerd@gmail.com>\n* GNU General Public License Version 2\n"
  },
  {
    "path": "config/basic_multichannel.conf",
    "content": "# This is a minimalistic configuration file for RTLSDR-Airband.\n# Just a single RTL dongle with two AM channels in multichannel mode.\n# Each channel is sent to a single Icecast output.\n# Refer to https://github.com/rtl-airband/RTLSDR-Airband/wiki\n# for description of keywords and config syntax.\n\ndevices:\n({\n  type = \"rtlsdr\";\n  index = 0;\n  gain = 25;\n  centerfreq = 120.0;\n  correction = 80;\n  channels:\n  (\n    {\n      freq = 119.5;\n      outputs: (\n        {\n          type = \"icecast\";\n          server = \"icecast.server.example.org\";\n          port = 8080;\n          mountpoint = \"TWR.mp3\";\n          name = \"Tower\";\n          genre = \"ATC\";\n          username = \"source\";\n          password = \"mypassword\";\n        }\n      );\n    },\n    {\n      freq = 120.225;\n      outputs: (\n        {\n          type = \"icecast\";\n          server = \"icecast.server.example.org\";\n          port = 8080;\n          mountpoint = \"GND.mp3\";\n          name = \"Ground\";\n          genre = \"ATC\";\n          description = \"My local airport - ground feed\";\n          username = \"source\";\n          password = \"mypassword\";\n        }\n      );\n    }\n  );\n }\n);\n"
  },
  {
    "path": "config/basic_scanning.conf",
    "content": "# Scanning mode example\n# Single dongle, three frequencies, output to Icecast server and to a file.\n# Refer to https://github.com/rtl-airband/RTLSDR-Airband/wiki\n# for description of keywords and config syntax.\n\ndevices:\n({\n  type = \"rtlsdr\";\n  index = 0;\n  gain = 25;\n  correction = 80;\n  mode = \"scan\";\n  channels:\n  (\n    {\n      freqs = ( 118.15, 124.7, 132.1 );\n      labels = ( \"Tower\", \"Ground\", \"Approach\" );\n      outputs: (\n        {\n          type = \"icecast\";\n          server = \"icecast.server.example.org\";\n          port = 8080;\n          mountpoint = \"stream.mp3\";\n          name = \"Tower + Ground + Approach\";\n          genre = \"ATC\";\n          description = \"My local airport - aggregated feed\";\n          username = \"source\";\n          password = \"mypassword\";\n          send_scan_freq_tags = false;\n        },\n        {\n          type = \"file\";\n          directory = \"/home/pi/recordings\";\n          filename_template = \"TWR+GND+APP\";\n        }\n      );\n    }\n  );\n }\n);\n"
  },
  {
    "path": "config/big_mixer.conf",
    "content": "mixers: {\n  big_mixer: {\n    outputs: (\n      {\n        type = \"file\";\n        directory = \"./\";\n        filename_template = \"big_mixer\";\n      }\n    );\n  }\n};\n\ndevices:\n({\n  type = \"rtlsdr\";\n  index = 0;\n  gain = 25;\n  centerfreq = 156.7375;\n  channels:\n  (\n    {\n      freq = 156.050;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.175;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.250;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.275;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.300;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.325;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.350;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.375;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.400;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.425;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.450;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.475;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.500;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.525;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.550;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.575;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.600;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.625;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.650;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.675;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.700;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.725;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.750;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.800;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.850;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.875;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.900;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.925;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.950;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 156.975;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.000;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.025;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.050;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.075;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.100;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.125;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.150;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.175;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.200;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.225;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.250;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.275;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.300;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.325;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.350;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.375;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.400;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    },\n    {\n      freq = 157.425;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"big_mixer\";\n        }\n      );\n    }\n  )\n});\n"
  },
  {
    "path": "config/mixers.conf",
    "content": "# This config file demonstrates the usage of mixers.\n# First, two mixers are defined:\n#\n# - mixer1: sends the mixed stream to Icecast and saves it to a file\n# - mixer2: sends the mixed stream to Icecast\n#\n# Two dongles are used, both in AM, multichannel mode:\n#\n# - dongle 1: 3 channels:\n#   - channel 1 goes to mixer1 (center, volume decreased to 30%)\n#   - channel 2 goes to mixer1 (full left)\n#   - channel 3 goes to mixer2 (85% right)\n#\n# - dongle 2: 2 channels:\n#   - channel 1 goes to mixer1 (full right)\n#   - channel 2 goes to mixer2 (85% left, volume set to 200%)\n#\n# Refer to https://github.com/rtl-airband/RTLSDR-Airband/wiki\n# for description of keywords and config syntax.\nmixers: {\n  mixer1: {\n    outputs: (\n        {\n          type = \"icecast\";\n          server = \"icecast.server.example.org\";\n          port = 8080;\n          mountpoint = \"mixer1.mp3\";\n          name = \"VOLMET + Approach + Director\"\n          genre = \"ATC\";\n          username = \"source\";\n          password = \"mypassword\";\n        },\n        {\n          type = \"file\";\n          directory = \"/home/pi/recordings\";\n          filename_template = \"mixer1\";\n        }\n    );\n  },\n  mixer2: {\n    outputs: (\n        {\n          type = \"icecast\";\n          server = \"icecast.server.example.org\";\n          port = 8080;\n          mountpoint = \"mixer2.mp3\";\n          name = \"Ground + Delivery\"\n          genre = \"ATC\";\n          username = \"source\";\n          password = \"mypassword\";\n        }\n    );\n  }\n};\n\ndevices:\n({\n  type = \"rtlsdr\";\n  index = 0;\n  gain = 25;\n  centerfreq = 121.2;\n  correction = 81;\n  channels:\n  (\n# VOLMET\n    {\n      freq = 120.875;\n# VOLMET/ATIS/AWOS channels often transmit continuously.\n# Auto squelch does not perform well in such cases, so it's best to set the\n# squelch threshold manually. squelch_threshold defines an absolute signal\n# level (in dBFS).\n      squelch_threshold = -40;\n      lowpass = 5;\n      highpass = 5;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"mixer1\";\n          ampfactor = 0.3;\n        }\n      );\n    },\n# Approach\n    {\n      freq = 121.8;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"mixer1\";\n          balance = -1.0;\n        }\n      );\n    },\n# Director\n    {\n      freq = 121.925;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"mixer2\";\n          balance = 0.85;\n        }\n      );\n    }\n  );\n },\n {\n  type = \"rtlsdr\";\n  index = 1;\n  gain = 33;\n  centerfreq = 131.2;\n  correction = 48;\n  channels:\n  (\n# Ground\n    {\n      freq = 130.925;\n# Another way of tweaking the squelch is to specify custom SNR threshold (in dB)\n      squelch_snr_threshold = 5.0;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"mixer1\";\n          balance = 1.0;\n        }\n      );\n    },\n# Delivery\n    {\n      freq = 131.4;\n      outputs: (\n        {\n          type = \"mixer\";\n          name = \"mixer2\";\n          balance = -0.85;\n          ampfactor = 2.0;\n        }\n      );\n    }\n  );\n }\n);\n"
  },
  {
    "path": "config/noaa.conf",
    "content": "fft_size = 1024;\nlocaltime = true;\nmultiple_demod_threads = true;\nmultiple_output_threads = true;\ndevices:\n(\n  {\n    type = \"rtlsdr\";\n    index = 0;\n    gain = 19.7;\n    centerfreq = 162.48200;\n    correction = 0;\n    sample_rate = 2.40;\n    channels:\n    (\n      {\n        freq = 162.40000;\n        label = \"NOAA 162.400\";\n        modulation = \"nfm\";\n        lowpass = -1;\n        highpass = -1;\n        bandwidth = 5000;\n        ampfactor = 2.00;\n        squelch_snr_threshold = 0.00;\n        outputs:\n        (\n          {\n            type = \"file\";\n            directory = \"/recordings\";\n            filename_template = \"NOAA_162.400\";\n          }\n        );\n      },\n      {\n        freq = 162.42500;\n        label = \"NOAA 162.425\";\n        modulation = \"nfm\";\n        lowpass = -1;\n        highpass = -1;\n        bandwidth = 5000;\n        ampfactor = 2.00;\n        squelch_snr_threshold = 0.00;\n        outputs:\n        (\n          {\n            type = \"file\";\n            directory = \"/recordings\";\n            filename_template = \"NOAA_162.425\";\n          }\n        );\n      },\n      {\n        freq = 162.45000;\n        label = \"NOAA 162.450\";\n        modulation = \"nfm\";\n        lowpass = -1;\n        highpass = -1;\n        bandwidth = 5000;\n        ampfactor = 2.00;\n        squelch_snr_threshold = 0.00;\n        outputs:\n        (\n          {\n            type = \"file\";\n            directory = \"/recordings\";\n            filename_template = \"NOAA_162.450\";\n          }\n        );\n      },\n      {\n        freq = 162.47500;\n        label = \"NOAA 162.475\";\n        modulation = \"nfm\";\n        lowpass = -1;\n        highpass = -1;\n        bandwidth = 5000;\n        ampfactor = 2.00;\n        squelch_snr_threshold = 0.00;\n        outputs:\n        (\n          {\n            type = \"file\";\n            directory = \"/recordings\";\n            filename_template = \"NOAA_162.475\";\n          }\n        );\n      },\n      {\n        freq = 162.50000;\n        label = \"NOAA 162.500\";\n        modulation = \"nfm\";\n        lowpass = -1;\n        highpass = -1;\n        bandwidth = 5000;\n        ampfactor = 2.00;\n        squelch_snr_threshold = 0.00;\n        outputs:\n        (\n          {\n            type = \"file\";\n            directory = \"/recordings\";\n            filename_template = \"NOAA_162.500\";\n          }\n        );\n      },\n      {\n        freq = 162.52500;\n        label = \"NOAA 162.525\";\n        modulation = \"nfm\";\n        lowpass = -1;\n        highpass = -1;\n        bandwidth = 5000;\n        ampfactor = 2.00;\n        squelch_snr_threshold = 0.00;\n        outputs:\n        (\n          {\n            type = \"file\";\n            directory = \"/recordings\";\n            filename_template = \"NOAA_162.525\";\n          }\n        );\n      },\n      {\n        freq = 162.55000;\n        label = \"NOAA 162.550\";\n        modulation = \"nfm\";\n        lowpass = -1;\n        highpass = -1;\n        bandwidth = 5000;\n        ampfactor = 2.00;\n        squelch_snr_threshold = 0.00;\n        outputs:\n        (\n          {\n            type = \"file\";\n            directory = \"/recordings\";\n            filename_template = \"NOAA_162.550\";\n          }\n        );\n      }\n    );\n  }\n);\n"
  },
  {
    "path": "config/two_dongles_multiple_outputs.conf",
    "content": "# Example configuration file for 2 dongles.\n# First dongle - scanning mode, NFM modulation, three frequencies,\n# output to Icecast stream, to a file and to PulseAudio server\n# on a local network.\n# Second dongle - multichannel mode, three channels:\n#\n# - channel 1: AM, goes to Icecast stream\n# - channel 2: AM, goes to two Icecast streams\n# - channel 3: NFM, goes to two files\n#\n# Dongles are specified with their serial numbers instead of\n# indexes, because the latter can change when devices are\n# reconnected into different USB ports.\n#\n# Refer to https://github.com/rtl-airband/RTLSDR-Airband/wiki\n# for description of keywords and config syntax.\n\ndevices:\n({\n  type = \"rtlsdr\";\n  serial = \"777755221\";\n  gain = 25;\n  correction = 80;\n  mode = \"scan\";\n  channels:\n  (\n    {\n      modulation = \"nfm\";\n      freqs = ( 152.1, 168.25, 168.375 );\n      outputs: (\n        {\n          type = \"icecast\";\n          server = \"icecast.server.example.org\";\n          port = 8080;\n          mountpoint = \"utility.mp3\";\n          name = \"Utility channels\";\n          username = \"source\";\n          password = \"mypassword\";\n        },\n        {\n          type = \"file\";\n          directory = \"/home/pi/recordings\";\n          filename_template = \"utility\";\n        },\n        {\n          type = \"pulse\";\n          server = \"192.168.11.10\";\n          stream_name = \"Utility channels\";\n          continuous = false;\n        }\n      );\n    }\n  );\n },\n {\n  type = \"rtlsdr\";\n  serial = \"33433123\";\n  gain = 20;\n  centerfreq = 118.5;\n  correction = 43;\n  mode = \"multichannel\";\n  channels:\n  (\n    {\n      freq = 118.15;\n      outputs: (\n        {\n          type = \"icecast\";\n          server = \"icecast.server.example.org\";\n          port = 8080;\n          mountpoint = \"TWR.mp3\";\n          name = \"Tower\";\n          genre = \"ATC\";\n          username = \"source\";\n          password = \"mypassword\";\n        }\n      );\n    },\n    {\n      freq = 119.425;\n      outputs: (\n        {\n          type = \"icecast\";\n          server = \"icecast.server.example.org\";\n          port = 8080;\n          mountpoint = \"ACC.mp3\";\n          name = \"Radar\";\n          genre = \"ATC\";\n          username = \"source\";\n          password = \"mypassword\";\n        },\n        {\n          type = \"icecast\";\n          server = \"other.server.example.org\";\n          port = 9999;\n          mountpoint = \"feed.mp3\";\n          username = \"user\";\n          password = \"secretpass\";\n        }\n      );\n    },\n    {\n      freq = 119.6;\n      modulation = \"nfm\";\n      outputs: (\n        {\n          type = \"file\";\n          directory = \"/home/pi/recordings\";\n          filename_template = \"somechannel\";\n        },\n        {\n          type = \"file\";\n          directory = \"/home/pi/recordings\";\n          filename_template = \"somechannel_full\";\n          continuous = true;\n        }\n      );\n    }\n  );\n }\n);\n"
  },
  {
    "path": "init.d/rtl_airband-debian.sh",
    "content": "#! /bin/sh\n### BEGIN INIT INFO\n# Provides:          rtl_airband\n# Required-Start:    $remote_fs $syslog\n# Required-Stop:     $remote_fs $syslog\n# Default-Start:     2 3 4 5\n# Default-Stop:      0 1 6\n# Short-Description: rtl_airband initscript\n### END INIT INFO\n\n# Author: Tomasz Lemiech <szpajder@gmail.com>\n\nPATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin\nDESC=\"RTLSDR airband receiver\"\nNAME=rtl_airband\nDAEMON=/usr/local/bin/$NAME\nDAEMON_ARGS=\"\"\nPIDFILE=/run/$NAME.pid\nSCRIPTNAME=/etc/init.d/$NAME\n\n# Exit if the package is not installed\n[ -x \"$DAEMON\" ] || exit 0\n\n# Read configuration variable file if it is present\n[ -r /etc/default/$NAME ] && . /etc/default/$NAME\n\n# Load the VERBOSE setting and other rcS variables\n. /lib/init/vars.sh\n\n# Define LSB log_* functions.\n# Depend on lsb-base (>= 3.2-14) to ensure that this file is present\n# and status_of_proc is working.\n. /lib/lsb/init-functions\n\n#\n# Function that starts the daemon/service\n#\ndo_start()\n{\n\t# Return\n\t#   0 if daemon has been started\n\t#   1 if daemon was already running\n\t#   2 if daemon could not be started\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \\\n\t\t|| return 1\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \\\n\t\t$DAEMON_ARGS \\\n\t\t|| return 2\n\t# on this one.  As a last resort, sleep for some time.\n}\n\ndo_stop()\n{\n\t# Return\n\t#   0 if daemon has been stopped\n\t#   1 if daemon was already stopped\n\t#   2 if daemon could not be stopped\n\t#   other if a failure occurred\n\tstart-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME\n\tRETVAL=\"$?\"\n\t[ \"$RETVAL\" = 2 ] && return 2\n\t# Wait for children to finish too if this is a daemon that forks\n\t# and if the daemon is only ever run from this initscript.\n\t# If the above conditions are not satisfied then add some other code\n\t# that waits for the process to drop all resources that could be\n\t# needed by services started subsequently.  A last resort is to\n\t# sleep for some time.\n\tstart-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON\n\t[ \"$?\" = 2 ] && return 2\n\trm -f $PIDFILE\n\treturn \"$RETVAL\"\n}\n\ncase \"$1\" in\n  start)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Starting $DESC\" \"$NAME\"\n\tdo_start\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  stop)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Stopping $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  status)\n\tstatus_of_proc \"$DAEMON\" \"$NAME\" && exit 0 || exit $?\n\t;;\n  restart|force-reload)\n\tlog_daemon_msg \"Restarting $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t  0|1)\n\t\tdo_start\n\t\tcase \"$?\" in\n\t\t\t0) log_end_msg 0 ;;\n\t\t\t1) log_end_msg 1 ;; # Old process is still running\n\t\t\t*) log_end_msg 1 ;; # Failed to start\n\t\tesac\n\t\t;;\n\t  *)\n\t\t# Failed to stop\n\t\tlog_end_msg 1\n\t\t;;\n\tesac\n\t;;\n  *)\n\techo \"Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}\" >&2\n\texit 3\n\t;;\nesac\n\n:\n"
  },
  {
    "path": "init.d/rtl_airband-freebsd.sh",
    "content": "#!/bin/sh\n\n# PROVIDE: rtl_airband\n# REQUIRE: DAEMON\n# BEFORE: LOGIN\n# KEYWORD: nojail shutdown\n\n. /etc/rc.subr\n\nname=rtl_airband\nrcvar=rtl_airband_enable\n\ncommand=\"/usr/local/bin/rtl_airband\"\n\nload_rc_config ${name}\nrun_rc_command \"$1\"\n"
  },
  {
    "path": "init.d/rtl_airband-gentoo.sh",
    "content": "#!/sbin/runscript\n# rtl_airband Gentoo startup script\n# (c) 2015 Tomasz Lemiech <szpajder@gmail.com>\n\nRTLAIRBAND_CONFDIR=${RTLAIRBAND_CONFDIR:-/usr/local/etc}\nRTLAIRBAND_CONFIG=${RTLAIRBAND_CONFIG:-${RTLAIRBAND_CONFDIR}/rtl_airband.conf}\nRTLAIRBAND_PIDFILE=${RTLAIRBAND_PIDFILE:-/run/${SVCNAME}.pid}\nRTLAIRBAND_BINARY=${RTLAIRBAND_BINARY:-/usr/local/bin/rtl_airband}\n\ndepend() {\n\tuse logger dns\n}\n\ncheckconfig() {\n\tif [ ! -e \"${RTLAIRBAND_CONFIG}\" ] ; then\n\t\teerror \"You need an ${RTLAIRBAND_CONFIG} file to run rtl_airband\"\n\t\treturn 1\n\tfi\n}\n\nstart() {\n\tcheckconfig || return 1\n\n\tebegin \"Starting ${SVCNAME}\"\n\tstart-stop-daemon --start --exec \"${RTLAIRBAND_BINARY}\" \\\n\t    --pidfile \"${RTLAIRBAND_PIDFILE}\" \\\n\t    -- ${RTLAIRBAND_OPTS}\n\teend $?\n}\n\nstop() {\n\tif [ \"${RC_CMD}\" = \"restart\" ] ; then\n\t\tcheckconfig || return 1\n\tfi\n\n\tebegin \"Stopping ${SVCNAME}\"\n\tstart-stop-daemon --stop --exec \"${RTLAIRBAND_BINARY}\" \\\n\t    --pidfile \"${RTLAIRBAND_PIDFILE}\" --quiet\n\teend $?\n}\n"
  },
  {
    "path": "init.d/rtl_airband.service",
    "content": "[Unit]\nDescription=SDR AM/NFM demodulator\nDocumentation=https://github.com/rtl-airband/RTLSDR-Airband/wiki\nWants=network.target  # NOTE: `network-online.target` may be better for some use cases\nAfter=network.target  # NOTE: `network-online.target` may be better for some use cases\n\n[Service]\nType=simple\nExecStart=/usr/local/bin/rtl_airband -Fe\n# The program may exit only due to startup failure (eg. misconfiguration)\n# or due to failure of all SDR devices (eg. disconnection). In either case,\n# there is no point to restart it, because it would fail once again.\nRestart=no\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "scripts/find_version",
    "content": "#!/bin/bash\n\nPROJECT_ROOT_PATH=\"$(cd $(dirname \"$0\")/../ ; pwd)\"\nPROJECT_GIT_DIR_PATH=\"${PROJECT_ROOT_PATH}/.git\"\nPROJECT_DIR_NAME=\"$(basename ${PROJECT_ROOT_PATH})\"\n\n# if there is a .git directory at the project root then rely on git for the version string\nif [ -r \"${PROJECT_GIT_DIR_PATH}\" ] ; then\n    git describe --tags --abbrev --dirty --always\n    exit 0\nfi\n\n# if the proejct root directory matches the naming convetion of an extracted archive then\n# get the version number out of that\nif [[ \"${PROJECT_DIR_NAME}\" =~ ^RTLSDR-Airband-[0-9]*\\.[0-9]*\\.[0-9]*$ ]]; then\n    echo ${PROJECT_DIR_NAME} | cut -d '-' -f 3\n    exit 0\nfi\n\n# print an error string to stderr (any output to stdout is considered success)\n>&2 echo \"did not find a git root directory at ${PROJECT_GIT_DIR_PATH} and failed to extract a version from ${PROJECT_DIR_NAME}\"\n"
  },
  {
    "path": "scripts/reformat_code",
    "content": "#!/bin/bash\n\nfind src/*.h src/*.cpp src/hello_fft/*.h src/hello_fft/*.c | xargs clang-format-14 -i\n"
  },
  {
    "path": "src/.gitignore",
    "content": "config.h\n"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "include(CheckCXXCompilerFlag)\ninclude(CheckCXXSymbolExists)\n\nlist(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules\")\nset(CMAKE_EXPORT_COMPILE_COMMANDS 1)\n\nif(UNIX OR MINGW)\n\tadd_definitions(-D_FILE_OFFSET_BITS=64)\n\t# isnormal()\n\tadd_definitions(-D_POSIX_C_SOURCE=200112L)\nendif()\n\nCHECK_CXX_COMPILER_FLAG(-pthread CXX_HAS_PTHREAD)\nif(CXX_HAS_PTHREAD)\n    add_compile_options(-pthread)\nendif()\n\nCHECK_CXX_COMPILER_FLAG(-ffast-math CXX_HAS_FFAST_MATH)\nif(CXX_HAS_FFAST_MATH)\n    add_compile_options(-ffast-math)\nendif()\n\n# asprintf on MacOS\nif(APPLE)\n\tadd_definitions(-D_DARWIN_C_SOURCE)\nendif()\n\n# sincosf on linux vs __sincosf on MacOS\nset(CMAKE_REQUIRED_DEFINITIONS_ORIG ${CMAKE_REQUIRED_DEFINITIONS})\nlist(APPEND CMAKE_REQUIRED_DEFINITIONS \"-D_GNU_SOURCE\")\nset(CMAKE_REQUIRED_LIBRARIES_ORIG ${CMAKE_REQUIRED_LIBRARIES})\nlist(APPEND CMAKE_REQUIRED_LIBRARIES m)\nCHECK_SYMBOL_EXISTS(sincosf math.h HAVE_SINCOSF)\nif(HAVE_SINCOSF)\n\tset(SINCOSF \"sincosf\")\nelse()\n\tCHECK_SYMBOL_EXISTS(__sincosf math.h HAVE___SINCOSF)\n\tif(HAVE___SINCOSF)\n\t\tset(SINCOSF \"__sincosf\")\n\tendif()\nendif()\nif(NOT HAVE_SINCOSF AND NOT HAVE___SINCOSF)\n\tmessage(FATAL_ERROR \"Required function sincosf() is unavailable\")\nendif()\nset(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS_ORIG})\nset(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_ORIG})\n\nfind_library(LIBM m REQUIRED)\nfind_library(LIBDL dl REQUIRED)\nfind_library(LIBPTHREAD pthread REQUIRED)\n\nfind_package(PkgConfig REQUIRED)\n\npkg_check_modules(CONFIG REQUIRED libconfig++)\nlist(APPEND rtl_airband_extra_libs ${CONFIG_LIBRARIES})\nlist(APPEND rtl_airband_include_dirs ${CONFIG_INCLUDE_DIRS})\nlist(APPEND link_dirs ${CONFIG_LIBRARY_DIRS})\n\n# Can't use pkg_check_modules here, as some distros do not install lame.pc file\nfind_package(Lame REQUIRED)\nlist(APPEND rtl_airband_extra_libs ${LAME_LIBRARIES})\nlist(APPEND rtl_airband_include_dirs ${LAME_INCLUDE_DIR})\n\npkg_check_modules(SHOUT REQUIRED shout)\nlist(APPEND rtl_airband_extra_libs ${SHOUT_LIBRARIES})\nlist(APPEND rtl_airband_include_dirs ${SHOUT_INCLUDE_DIRS})\nlist(APPEND link_dirs ${SHOUT_LIBRARY_DIRS})\n\nset(CMAKE_REQUIRED_INCLUDES_SAVE ${CMAKE_REQUIRED_INCLUDES})\nset(CMAKE_REQUIRED_LIBRARIES_SAVE ${CMAKE_REQUIRED_LIBRARIES})\nset(CMAKE_REQUIRED_LINK_OPTIONS_SAVE ${CMAKE_REQUIRED_LINK_OPTIONS})\nset(CMAKE_REQUIRED_INCLUDES \"${CMAKE_REQUIRED_INCLUDES} ${SHOUT_INCLUDE_DIRS}\")\nset(CMAKE_REQUIRED_LIBRARIES \"${CMAKE_REQUIRED_LIBRARIES} ${SHOUT_LIBRARIES}\")\nif ( NOT \"${SHOUT_LIBRARY_DIRS}\" STREQUAL \"\" )\n\tset(CMAKE_REQUIRED_LINK_OPTIONS \"-L${SHOUT_LIBRARY_DIRS}\")\nendif()\nset(LIBSHOUT_HEADER \"shout/shout.h\")\nCHECK_CXX_SYMBOL_EXISTS(\"SHOUT_TLS_AUTO\" ${LIBSHOUT_HEADER}\n\tHAVE_SHOUT_TLS_AUTO)\nCHECK_CXX_SYMBOL_EXISTS(\"SHOUT_TLS_AUTO_NO_PLAIN\" ${LIBSHOUT_HEADER}\n\tHAVE_SHOUT_TLS_AUTO_NO_PLAIN)\nCHECK_CXX_SYMBOL_EXISTS(\"SHOUT_TLS_RFC2818\" ${LIBSHOUT_HEADER}\n\tHAVE_SHOUT_TLS_RFC2818)\nCHECK_CXX_SYMBOL_EXISTS(\"SHOUT_TLS_RFC2817\" ${LIBSHOUT_HEADER}\n\tHAVE_SHOUT_TLS_RFC2817)\nCHECK_CXX_SYMBOL_EXISTS(\"SHOUT_TLS_DISABLED\" ${LIBSHOUT_HEADER}\n\tHAVE_SHOUT_TLS_DISABLED)\nCHECK_CXX_SYMBOL_EXISTS(\"shout_set_tls\" ${LIBSHOUT_HEADER}\n\tHAVE_SHOUT_SET_TLS)\nCHECK_CXX_SYMBOL_EXISTS(\"shout_set_content_format\" ${LIBSHOUT_HEADER}\n\tLIBSHOUT_HAS_CONTENT_FORMAT)\n\nif(HAVE_SHOUT_TLS_AUTO AND HAVE_SHOUT_TLS_AUTO_NO_PLAIN AND\n\t\tHAVE_SHOUT_TLS_RFC2818 AND HAVE_SHOUT_TLS_RFC2817 AND\n\t\tHAVE_SHOUT_TLS_DISABLED AND HAVE_SHOUT_SET_TLS)\n\tset(LIBSHOUT_HAS_TLS TRUE)\nelse()\n\tset(LIBSHOUT_HAS_TLS FALSE)\nendif()\n\n# check for shout_set_metadata_utf8() - introduced in libshout v2.4.6\nCHECK_CXX_SYMBOL_EXISTS(\"shout_set_metadata_utf8\" ${LIBSHOUT_HEADER}\n\tHAVE_SHOUT_SET_METADATA_UTF8)\nif(HAVE_SHOUT_SET_METADATA_UTF8)\n\tset(SHOUT_SET_METADATA \"shout_set_metadata_utf8\")\nelse()\n\tset(SHOUT_SET_METADATA \"shout_set_metadata\")\nendif()\n\nset(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_SAVE})\nset(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_SAVE})\nset(CMAKE_REQUIRED_LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS_SAVE})\n\noption(NFM \"Enable support for narrow FM channels\" OFF)\n\nset(PLATFORM \"native\" CACHE STRING \"Optimize the build for the given hardware platform\")\n\noption(RTLSDR \"Enable RTL-SDR support\" ON)\nset(WITH_RTLSDR FALSE)\n\noption(MIRISDR \"Enable Mirics support\" ON)\nset(WITH_MIRISDR FALSE)\n\noption(SOAPYSDR \"Enable SoapySDR support\" ON)\nset(WITH_SOAPYSDR FALSE)\n\noption(PULSEAUDIO \"Enable PulseAudio support\" ON)\nset(WITH_PULSEAUDIO FALSE)\n\noption(PROFILING \"Enable profiling with gperftools\")\nset(WITH_PROFILING FALSE)\n\nif(RTLSDR)\n\tfind_package(RTLSDR)\n\tif(RTLSDR_FOUND)\n\t\tlist(APPEND rtl_airband_extra_sources input-rtlsdr.cpp)\n\t\tlist(APPEND rtl_airband_extra_libs ${RTLSDR_LIBRARIES})\n\t\tlist(APPEND rtl_airband_include_dirs ${RTLSDR_INCLUDE_DIRS})\n\t\tlist(APPEND link_dirs ${RTLSDR_LIBRARY_DIRS})\n\t\tset(WITH_RTLSDR TRUE)\n\tendif()\nendif()\n\nif(MIRISDR)\n\tfind_package(MiriSDR)\n\tif(MIRISDR_FOUND)\n\t\tset(WITH_MIRISDR TRUE)\n\t\tlist(APPEND rtl_airband_extra_sources input-mirisdr.cpp)\n\t\tlist(APPEND rtl_airband_extra_libs ${MIRISDR_LIBRARIES})\n\t\tlist(APPEND rtl_airband_include_dirs ${MIRISDR_INCLUDE_DIRS})\n\t\tlist(APPEND link_dirs ${MIRISDR_LIBRARY_DIRS})\n\tendif()\nendif()\n\nif(SOAPYSDR)\n\tmessage(STATUS \"Checking for SoapySDR\")\n\tfind_package(SoapySDR NO_MODULE)\n\tif(SoapySDR_FOUND)\n\t\tlist(APPEND rtl_airband_extra_sources input-soapysdr.cpp)\n\t\tmessage(STATUS \"  SoapySDR found, ${SoapySDR_INCLUDE_DIRS}, ${SoapySDR_LIBRARIES}\")\n\t\tlist(APPEND rtl_airband_extra_libs ${SoapySDR_LIBRARIES})\n\t\tlist(APPEND rtl_airband_include_dirs ${SoapySDR_INCLUDE_DIRS})\n\t\tset(WITH_SOAPYSDR TRUE)\n\telse()\n\t\tmessage(STATUS \"  SoapySDR not found\")\n\tendif()\nendif()\n\nif(PULSEAUDIO)\n\tpkg_check_modules(PULSEAUDIO libpulse)\n\tif(PULSEAUDIO_FOUND)\n\t\tlist(APPEND rtl_airband_extra_sources pulse.cpp)\n\t\tlist(APPEND rtl_airband_extra_libs ${PULSEAUDIO_LIBRARIES})\n\t\tlist(APPEND rtl_airband_include_dirs ${PULSEAUDIO_INCLUDE_DIRS})\n\t\tlist(APPEND link_dirs ${PULSEAUDIO_LIBRARY_DIRS})\n\t\tset(WITH_PULSEAUDIO TRUE)\n\tendif()\nendif()\n\nif(PROFILING)\n\tpkg_check_modules(PROFILING libprofiler)\n\tif(PROFILING_FOUND)\n\t\tset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -g\")\n\t\tlist(APPEND rtl_airband_extra_libs ${PROFILING_LIBRARIES})\n\t\tlist(APPEND rtl_airband_include_dirs ${PROFILING_INCLUDE_DIRS})\n\t\tlist(APPEND link_dirs ${PROFILING_LIBRARY_DIRS})\n\t\tset(WITH_PROFILING TRUE)\n\tendif()\nendif()\n\n\noption(BCM_VC \"Enable Broadcom Videocore 3 support\" OFF)\nset(WITH_BCM_VC FALSE)\n\n# error out on depricated PLATFORM values\nif(PLATFORM STREQUAL \"rpiv1\" OR PLATFORM STREQUAL \"armv7-generic\" OR PLATFORM STREQUAL \"armv8-generic\")\n\tmessage(FATAL_ERROR \"platform '${PLATFORM}' has been deprecated, see https://github.com/rtl-airband/RTLSDR-Airband/discussions/447\")\n# rpiv2 - Raspberry Pi 2 or Raspberry Pi 3 using Broadcom VideoCore IV GPU for FFT\n# NOTE: use 'native' to not use the GPU for FFT\nelseif(PLATFORM STREQUAL \"rpiv2\")\n\tset(BCM_VC ON)\n\tadd_compile_options(-march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard)\n\tenable_language(ASM)\n\tlist(APPEND rtl_airband_extra_sources rtl_airband_neon.s)\n# native - let the complier optimize to run on local hardware (default)\nelseif(PLATFORM STREQUAL \"native\")\n\tCHECK_CXX_COMPILER_FLAG(-march=native CXX_HAS_MARCH_NATIVE)\n\tif(CXX_HAS_MARCH_NATIVE)\n\t\tadd_compile_options(-march=native)\n\telse()\n\t\tmessage(FATAL_ERROR \"Cannot build with PLATFORM=native: the compiler does not support -march=native option\")\n\tendif()\n# generic - dont add any hardware related flags, used to build a \"portable\" binary\nelseif(PLATFORM STREQUAL \"generic\")\n\t# NO-OP\n# error out on unrecongnnized PLATFORM value\nelse()\n\tmessage(FATAL_ERROR \"Unknown platform '${PLATFORM}'. Valid options are: rpiv2, native, and generic\")\nendif()\n\n# Try using VC GPU if enabled. Fallback to fftw3f if disabled or if VC lib not found\nif(BCM_VC)\n\tfind_package(BCM_VC)\n\tif(BCM_VC_FOUND)\n\t\tadd_subdirectory(hello_fft)\n\t\tlist(APPEND rtl_airband_obj_files $<TARGET_OBJECTS:hello_fft>)\n\t\tlist(APPEND rtl_airband_extra_libs ${BCM_VC_LIBRARIES})\n\t\tset(WITH_BCM_VC TRUE)\n\tendif()\nendif()\nif(NOT BCM_VC_FOUND)\n\tpkg_check_modules(FFTW3F REQUIRED fftw3f)\n\tif(FFTW3F_FOUND)\n\t\tlist(APPEND rtl_airband_extra_libs ${FFTW3F_LIBRARIES})\n\t\tlist(APPEND rtl_airband_include_dirs ${FFTW3F_INCLUDE_DIRS})\n\t\tlist(APPEND link_dirs ${FFTW3F_LIBRARY_DIRS})\n\tendif()\nendif()\n\nif(CMAKE_SYSTEM_NAME STREQUAL \"FreeBSD\")\n\tlist(APPEND rtl_airband_extra_libs c++)\nendif()\n\nif(BUILD_UNITTESTS)\n\tset(BUILD_UNITTESTS TRUE)\nelse()\n\tset(BUILD_UNITTESTS FALSE)\nendif()\n\nmessage(STATUS \"RTLSDR-Airband configuration summary:\\n\")\nmessage(STATUS \"- Version string:\\t\\t${RTL_AIRBAND_VERSION}\")\nmessage(STATUS \"- Build type:\\t\\t${CMAKE_BUILD_TYPE}\")\nmessage(STATUS \"- Operating system:\\t\\t${CMAKE_SYSTEM_NAME}\")\nmessage(STATUS \"- SDR drivers:\")\nmessage(STATUS \"  - librtlsdr:\\t\\trequested: ${RTLSDR}, enabled: ${WITH_RTLSDR}\")\nmessage(STATUS \"  - mirisdr:\\t\\t\\trequested: ${MIRISDR}, enabled: ${WITH_MIRISDR}\")\nmessage(STATUS \"  - soapysdr:\\t\\trequested: ${SOAPYSDR}, enabled: ${WITH_SOAPYSDR}\")\nmessage(STATUS \"- Other options:\")\nmessage(STATUS \"  - Platform:\\t\\t${PLATFORM}\")\nmessage(STATUS \"  - Build Unit Tests:\\t${BUILD_UNITTESTS}\")\nmessage(STATUS \"  - Broadcom VideoCore GPU:\\t${WITH_BCM_VC}\")\nmessage(STATUS \"  - NFM support:\\t\\t${NFM}\")\nmessage(STATUS \"  - PulseAudio:\\t\\trequested: ${PULSEAUDIO}, enabled: ${WITH_PULSEAUDIO}\")\nmessage(STATUS \"  - Profiling:\\t\\trequested: ${PROFILING}, enabled: ${WITH_PROFILING}\")\nmessage(STATUS \"  - Icecast TLS support:\\t${LIBSHOUT_HAS_TLS}\")\n\nif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/config.h)\n\tmessage(FATAL_ERROR \"${CMAKE_CURRENT_SOURCE_DIR}/config.h nolonger used, delete before continuing\")\nendif()\n\nconfigure_file(\n\t\"${CMAKE_CURRENT_SOURCE_DIR}/config.h.in\"\n\t\"${CMAKE_CURRENT_BINARY_DIR}/config.h\"\n\t@ONLY\n)\n\nadd_custom_command(\n\tOUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version.cpp\n\t\t${CMAKE_CURRENT_BINARY_DIR}/_version.cpp\n\tCOMMAND ${CMAKE_COMMAND} -DRTL_AIRBAND_VERSION=${RTL_AIRBAND_VERSION} -P\n\t${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/version.cmake\n)\n\nadd_library (rtl_airband_base OBJECT\n\tconfig.cpp\n\tinput-common.cpp\n\tinput-file.cpp\n\tinput-helpers.cpp\n\tmixer.cpp\n\toutput.cpp\n\trtl_airband.cpp\n\tsquelch.cpp\n\tctcss.cpp\n\tutil.cpp\n\tudp_stream.cpp\n\tlogging.cpp\n\tfilters.cpp\n\thelper_functions.cpp\n\t${CMAKE_CURRENT_BINARY_DIR}/version.cpp\n\t${rtl_airband_extra_sources}\n\t)\n\ntarget_include_directories (rtl_airband_base PUBLIC\n\t${CMAKE_CURRENT_BINARY_DIR} # needed for config.h\n\t${rtl_airband_include_dirs}\n)\n\n# can't do this per target with cmake <3.13\nlink_directories(${link_dirs})\n\nlist(APPEND rtl_airband_obj_files $<TARGET_OBJECTS:rtl_airband_base>)\n\nadd_executable (rtl_airband ${rtl_airband_obj_files})\nset_property(TARGET rtl_airband PROPERTY ENABLE_EXPORTS 1)\n\n# add include for config.h\ntarget_include_directories (rtl_airband PUBLIC\n\t${CMAKE_CURRENT_BINARY_DIR}\n)\n\ntarget_link_libraries (rtl_airband\n\tdl\n\tm\n\tpthread\n\t${rtl_airband_extra_libs}\n)\n\ninstall(TARGETS rtl_airband\n\tRUNTIME DESTINATION bin\n)\n\n# TODO: install config if not present\n\n\nif(BUILD_UNITTESTS)\n\tcmake_minimum_required(VERSION 3.1...3.18 FATAL_ERROR)\n\n\t# GoogleTest requires at least C++14\n\tset(CMAKE_CXX_STANDARD 14)\n\n\t# set timestamps of URL extracted files to the extraction time\n\tif(POLICY CMP0135)\n\t\tcmake_policy(SET CMP0135 NEW)\n\tendif()\n\n\t# pull in GoogleTest as a dependency\n\tinclude(FetchContent)\n\tFetchContent_Declare(\n\t\tgoogletest\n\t\tURL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip\n\t)\n\tFetchContent_MakeAvailable(googletest)\n\n\tenable_testing()\n\n\tfile(GLOB_RECURSE TEST_FILES \"test_*.cpp\")\n\tlist(APPEND TEST_FILES\n\t\tsquelch.cpp\n\t\tlogging.cpp\n\t\tfilters.cpp\n\t\tctcss.cpp\n\t\tgenerate_signal.cpp\n\t\thelper_functions.cpp\n\t)\n\n\tadd_executable(\n\t\tunittests\n\t\t${TEST_FILES}\n\t)\n\ttarget_link_libraries(\n\t\tunittests\n\t\tGTest::gtest_main\n\t\tdl\n\t\t${rtl_airband_extra_libs}\n\t)\n\n\t# add include for config.h\n\ttarget_include_directories (unittests PUBLIC\n\t\t${CMAKE_CURRENT_BINARY_DIR}\n\t)\n\n\tinclude(GoogleTest)\n\tgtest_discover_tests(unittests)\n\nendif()\n"
  },
  {
    "path": "src/CMakeModules/FindBCM_VC.cmake",
    "content": "if(NOT BCM_VC_FOUND)\n\n\tset(BCM_VC_PATH \"/opt/vc\" CACHE STRING \"List of paths to search for Broadcom VideoCore library\")\n\n\tfind_path(BCM_VC_INCLUDE_DIR bcm_host.h PATHS ${BCM_VC_PATH}/include)\n\tfind_library(BCM_VC_LIBRARY NAMES bcm_host PATHS ${BCM_VC_PATH}/lib)\n\n\tset(BCM_VC_LIBRARIES ${BCM_VC_LIBRARY} )\n\tset(BCM_VC_INCLUDE_DIRS ${BCM_VC_INCLUDE_DIR} )\n\n\tinclude(FindPackageHandleStandardArgs)\n\t# handle the QUIETLY and REQUIRED arguments and set BCM_VC_FOUND to TRUE\n\t# if all listed variables are TRUE\n\tfind_package_handle_standard_args(BCM_VC DEFAULT_MSG\n\t\t\t\t\t  BCM_VC_LIBRARY BCM_VC_INCLUDE_DIR)\n\n\tmark_as_advanced(BCM_VC_INCLUDE_DIR BCM_VC_LIBRARY)\n\nendif()\n"
  },
  {
    "path": "src/CMakeModules/FindLame.cmake",
    "content": "FIND_PATH(LAME_INCLUDE_DIR lame/lame.h)\nFIND_LIBRARY(LAME_LIBRARIES NAMES mp3lame)\n\nIF(LAME_INCLUDE_DIR AND LAME_LIBRARIES)\n\tSET(LAME_FOUND TRUE)\nENDIF(LAME_INCLUDE_DIR AND LAME_LIBRARIES)\n\nIF(LAME_FOUND)\n\tIF (NOT Lame_FIND_QUIETLY)\n\t\tMESSAGE(STATUS \"Found lame includes:\t${LAME_INCLUDE_DIR}/lame/lame.h\")\n\t\tMESSAGE(STATUS \"Found lame library: ${LAME_LIBRARIES}\")\n\tENDIF (NOT Lame_FIND_QUIETLY)\nELSE(LAME_FOUND)\n\tIF (Lame_FIND_REQUIRED)\n\t\tMESSAGE(FATAL_ERROR \"lame library required but not found\")\n\tENDIF (Lame_FIND_REQUIRED)\nENDIF(LAME_FOUND)\n"
  },
  {
    "path": "src/CMakeModules/FindMiriSDR.cmake",
    "content": "# - Try to find mirisdr - the hardware driver for Mirics chip in the dvb receivers\n# Once done this will define\n#  MIRISDR_FOUND - System has mirisdr\n#  MIRISDR_LIBRARIES - The mirisdr libraries\n#  MIRISDR_INCLUDE_DIRS - The mirisdr include directories\n#  MIRISDR_LIB_DIRS - The mirisdr library directories\n\nif(NOT MIRISDR_FOUND)\n\n    find_package(PkgConfig)\n    pkg_check_modules (MIRISDR_PKG libmirisdr)\n    set(MIRISDR_DEFINITIONS ${PC_MIRISDR_CFLAGS_OTHER})\n\n    find_path(MIRISDR_INCLUDE_DIR\n                NAMES mirisdr.h\n                HINTS ${MIRISDR_PKG_INCLUDE_DIRS} $ENV{MIRISDR_DIR}/include\n                PATHS /usr/local/include /usr/include /opt/include /opt/local/include)\n\n    find_library(MIRISDR_LIBRARY\n                NAMES mirisdr\n                HINTS ${MIRISDR_PKG_LIBRARY_DIRS} $ENV{MIRISDR_DIR}/include\n                PATHS /usr/local/lib /usr/lib /opt/lib /opt/local/lib)\n\n    set(MIRISDR_LIBRARIES ${MIRISDR_LIBRARY} )\n    set(MIRISDR_INCLUDE_DIRS ${MIRISDR_INCLUDE_DIR} )\n\n    include(FindPackageHandleStandardArgs)\n    # handle the QUIETLY and REQUIRED arguments and set LibMIRISDR_FOUND to TRUE\n    # if all listed variables are TRUE\n    find_package_handle_standard_args(MiriSDR  DEFAULT_MSG\n                                      MIRISDR_LIBRARY MIRISDR_INCLUDE_DIR)\n\n    mark_as_advanced(MIRISDR_INCLUDE_DIR MIRISDR_LIBRARY)\n\nendif(NOT MIRISDR_FOUND)\n"
  },
  {
    "path": "src/CMakeModules/FindRTLSDR.cmake",
    "content": "#\n# Copyright 2012-2013 The Iris Project Developers. See the\n# COPYRIGHT file at the top-level directory of this distribution\n# and at http://www.softwareradiosystems.com/iris/copyright.html.\n#\n# This file is part of the Iris Project.\n#\n# Iris is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser General Public License as\n# published by the Free Software Foundation, either version 3 of\n# the License, or (at your option) any later version.\n#\n# Iris is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# A copy of the GNU Lesser General Public License can be found in\n# the LICENSE file in the top-level directory of this distribution\n# and at http://www.gnu.org/licenses/.\n#\n\n# - Try to find rtlsdr - the hardware driver for the realtek chip in the dvb receivers\n# Once done this will define\n#  RTLSDR_FOUND - System has rtlsdr\n#  RTLSDR_LIBRARIES - The rtlsdr libraries\n#  RTLSDR_INCLUDE_DIRS - The rtlsdr include directories\n#  RTLSDR_LIB_DIRS - The rtlsdr library directories\n\nif(NOT RTLSDR_FOUND)\n\n    find_package(PkgConfig)\n    pkg_check_modules (RTLSDR_PKG librtlsdr)\n    set(RTLSDR_DEFINITIONS ${PC_RTLSDR_CFLAGS_OTHER})\n\n    find_path(RTLSDR_INCLUDE_DIR\n                NAMES rtl-sdr.h\n                HINTS ${RTLSDR_PKG_INCLUDE_DIRS} $ENV{RTLSDR_DIR}/include\n                PATHS /usr/local/include /usr/include /opt/include /opt/local/include)\n\n    find_library(RTLSDR_LIBRARY\n                NAMES rtlsdr\n                HINTS ${RTLSDR_PKG_LIBRARY_DIRS} $ENV{RTLSDR_DIR}/include\n                PATHS /usr/local/lib /usr/lib /opt/lib /opt/local/lib)\n\n    set(RTLSDR_LIBRARIES ${RTLSDR_LIBRARY} )\n    set(RTLSDR_INCLUDE_DIRS ${RTLSDR_INCLUDE_DIR} )\n\n    include(FindPackageHandleStandardArgs)\n    # handle the QUIETLY and REQUIRED arguments and set LibRTLSDR_FOUND to TRUE\n    # if all listed variables are TRUE\n    find_package_handle_standard_args(RTLSDR  DEFAULT_MSG\n                                      RTLSDR_LIBRARY RTLSDR_INCLUDE_DIR)\n\n    mark_as_advanced(RTLSDR_INCLUDE_DIR RTLSDR_LIBRARY)\n\nendif(NOT RTLSDR_FOUND)\n"
  },
  {
    "path": "src/CMakeModules/version.cmake",
    "content": "set (VERSION \"char const *RTL_AIRBAND_VERSION=\\\"${RTL_AIRBAND_VERSION}\\\";\\n\")\n\nif(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/version.cpp)\n\tfile(READ ${CMAKE_CURRENT_BINARY_DIR}/version.cpp VERSION_)\nelse()\n\tset(VERSION_ \"\")\nendif()\n\nif (NOT \"${VERSION}\" STREQUAL \"${VERSION_}\")\n\tfile(WRITE ${CMAKE_CURRENT_BINARY_DIR}/version.cpp \"${VERSION}\")\nendif()\n"
  },
  {
    "path": "src/config.cpp",
    "content": "/*\n * config.cpp\n * Configuration parsing routines\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <assert.h>\n#include <stdint.h>  // uint32_t\n#include <syslog.h>\n#include <cmath>\n#include <cstdlib>\n#include <cstring>\n#include <iostream>\n#include <libconfig.h++>\n#include \"input-common.h\"  // input_t\n#include \"rtl_airband.h\"\n\nusing namespace std;\n\nstatic int parse_outputs(libconfig::Setting& outs, channel_t* channel, int i, int j, bool parsing_mixers) {\n    int oo = 0;\n    for (int o = 0; o < channel->output_count; o++) {\n        channel->outputs[oo].has_mp3_output = false;\n        channel->outputs[oo].lame = NULL;\n        channel->outputs[oo].lamebuf = NULL;\n\n        if (outs[o].exists(\"disable\") && (bool)outs[o][\"disable\"] == true) {\n            continue;\n        }\n        if (!strncmp(outs[o][\"type\"], \"icecast\", 7)) {\n            channel->outputs[oo].data = XCALLOC(1, sizeof(struct icecast_data));\n            channel->outputs[oo].type = O_ICECAST;\n            icecast_data* idata = (icecast_data*)(channel->outputs[oo].data);\n            idata->hostname = strdup(outs[o][\"server\"]);\n            idata->port = outs[o][\"port\"];\n            idata->mountpoint = strdup(outs[o][\"mountpoint\"]);\n            idata->username = strdup(outs[o][\"username\"]);\n            idata->password = strdup(outs[o][\"password\"]);\n            if (outs[o].exists(\"name\"))\n                idata->name = strdup(outs[o][\"name\"]);\n            if (outs[o].exists(\"genre\"))\n                idata->genre = strdup(outs[o][\"genre\"]);\n            if (outs[o].exists(\"description\"))\n                idata->description = strdup(outs[o][\"description\"]);\n            if (outs[o].exists(\"send_scan_freq_tags\"))\n                idata->send_scan_freq_tags = (bool)outs[o][\"send_scan_freq_tags\"];\n            else\n                idata->send_scan_freq_tags = 0;\n#ifdef LIBSHOUT_HAS_TLS\n            if (outs[o].exists(\"tls\")) {\n                if (outs[o][\"tls\"].getType() == libconfig::Setting::TypeString) {\n                    if (!strcmp(outs[o][\"tls\"], \"auto\")) {\n                        idata->tls_mode = SHOUT_TLS_AUTO;\n                    } else if (!strcmp(outs[o][\"tls\"], \"auto_no_plain\")) {\n                        idata->tls_mode = SHOUT_TLS_AUTO_NO_PLAIN;\n                    } else if (!strcmp(outs[o][\"tls\"], \"transport\")) {\n                        idata->tls_mode = SHOUT_TLS_RFC2818;\n                    } else if (!strcmp(outs[o][\"tls\"], \"upgrade\")) {\n                        idata->tls_mode = SHOUT_TLS_RFC2817;\n                    } else if (!strcmp(outs[o][\"tls\"], \"disabled\")) {\n                        idata->tls_mode = SHOUT_TLS_DISABLED;\n                    } else {\n                        if (parsing_mixers) {\n                            cerr << \"Configuration error: mixers.[\" << i << \"] outputs.[\" << o << \"]: \";\n                        } else {\n                            cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o << \"]: \";\n                        }\n                        cerr << \"invalid value for tls; must be one of: auto, auto_no_plain, transport, upgrade, disabled\\n\";\n                        error();\n                    }\n                } else {\n                    if (parsing_mixers) {\n                        cerr << \"Configuration error: mixers.[\" << i << \"] outputs.[\" << o << \"]: \";\n                    } else {\n                        cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o << \"]: \";\n                    }\n                    cerr << \"tls value must be a string\\n\";\n                    error();\n                }\n            } else {\n                idata->tls_mode = SHOUT_TLS_DISABLED;\n            }\n#endif /* LIBSHOUT_HAS_TLS */\n\n            channel->outputs[oo].has_mp3_output = true;\n        } else if (!strncmp(outs[o][\"type\"], \"file\", 4)) {\n            channel->outputs[oo].data = XCALLOC(1, sizeof(struct file_data));\n            channel->outputs[oo].type = O_FILE;\n            file_data* fdata = (file_data*)(channel->outputs[oo].data);\n\n            fdata->type = O_FILE;\n            if (!outs[o].exists(\"directory\") || !outs[o].exists(\"filename_template\")) {\n                if (parsing_mixers) {\n                    cerr << \"Configuration error: mixers.[\" << i << \"] outputs.[\" << o << \"]: \";\n                } else {\n                    cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o << \"]: \";\n                }\n                cerr << \"both directory and filename_template required for file\\n\";\n                error();\n            }\n            fdata->basedir = outs[o][\"directory\"].c_str();\n            fdata->basename = outs[o][\"filename_template\"].c_str();\n            fdata->dated_subdirectories = outs[o].exists(\"dated_subdirectories\") ? (bool)(outs[o][\"dated_subdirectories\"]) : false;\n            fdata->suffix = \".mp3\";\n\n            fdata->continuous = outs[o].exists(\"continuous\") ? (bool)(outs[o][\"continuous\"]) : false;\n            fdata->append = (!outs[o].exists(\"append\")) || (bool)(outs[o][\"append\"]);\n            fdata->split_on_transmission = outs[o].exists(\"split_on_transmission\") ? (bool)(outs[o][\"split_on_transmission\"]) : false;\n            fdata->include_freq = outs[o].exists(\"include_freq\") ? (bool)(outs[o][\"include_freq\"]) : false;\n\n            channel->outputs[oo].has_mp3_output = true;\n\n            if (fdata->split_on_transmission) {\n                if (parsing_mixers) {\n                    cerr << \"Configuration error: mixers.[\" << i << \"] outputs.[\" << o << \"]: split_on_transmission is not allowed for mixers\\n\";\n                    error();\n                }\n                if (fdata->continuous) {\n                    cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o << \"]: can't have both continuous and split_on_transmission\\n\";\n                    error();\n                }\n            }\n\n        } else if (!strncmp(outs[o][\"type\"], \"rawfile\", 7)) {\n            if (parsing_mixers) {  // rawfile outputs not allowed for mixers\n                cerr << \"Configuration error: mixers.[\" << i << \"] outputs[\" << o << \"]: rawfile output is not allowed for mixers\\n\";\n                error();\n            }\n            channel->outputs[oo].data = XCALLOC(1, sizeof(struct file_data));\n            channel->outputs[oo].type = O_RAWFILE;\n            file_data* fdata = (file_data*)(channel->outputs[oo].data);\n\n            fdata->type = O_RAWFILE;\n            if (!outs[o].exists(\"directory\") || !outs[o].exists(\"filename_template\")) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o << \"]: both directory and filename_template required for file\\n\";\n                error();\n            }\n\n            fdata->basedir = outs[o][\"directory\"].c_str();\n            fdata->basename = outs[o][\"filename_template\"].c_str();\n            fdata->dated_subdirectories = outs[o].exists(\"dated_subdirectories\") ? (bool)(outs[o][\"dated_subdirectories\"]) : false;\n            fdata->suffix = \".cf32\";\n\n            fdata->continuous = outs[o].exists(\"continuous\") ? (bool)(outs[o][\"continuous\"]) : false;\n            fdata->append = (!outs[o].exists(\"append\")) || (bool)(outs[o][\"append\"]);\n            fdata->split_on_transmission = outs[o].exists(\"split_on_transmission\") ? (bool)(outs[o][\"split_on_transmission\"]) : false;\n            fdata->include_freq = outs[o].exists(\"include_freq\") ? (bool)(outs[o][\"include_freq\"]) : false;\n            channel->needs_raw_iq = channel->has_iq_outputs = 1;\n\n            if (fdata->continuous && fdata->split_on_transmission) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o << \"]: can't have both continuous and split_on_transmission\\n\";\n                error();\n            }\n        } else if (!strncmp(outs[o][\"type\"], \"mixer\", 5)) {\n            if (parsing_mixers) {  // mixer outputs not allowed for mixers\n                cerr << \"Configuration error: mixers.[\" << i << \"] outputs.[\" << o << \"]: mixer output is not allowed for mixers\\n\";\n                error();\n            }\n            channel->outputs[oo].data = XCALLOC(1, sizeof(struct mixer_data));\n            channel->outputs[oo].type = O_MIXER;\n            mixer_data* mdata = (mixer_data*)(channel->outputs[oo].data);\n            const char* name = (const char*)outs[o][\"name\"];\n            if ((mdata->mixer = getmixerbyname(name)) == NULL) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o << \"]: unknown mixer \\\"\" << name << \"\\\"\\n\";\n                error();\n            }\n            float ampfactor = outs[o].exists(\"ampfactor\") ? (float)outs[o][\"ampfactor\"] : 1.0f;\n            float balance = outs[o].exists(\"balance\") ? (float)outs[o][\"balance\"] : 0.0f;\n            if (balance < -1.0f || balance > 1.0f) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o << \"]: balance out of allowed range <-1.0;1.0>\\n\";\n                error();\n            }\n            if ((mdata->input = mixer_connect_input(mdata->mixer, ampfactor, balance)) < 0) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o\n                     << \"]: \"\n                        \"could not connect to mixer \"\n                     << name << \": \" << mixer_get_error() << \"\\n\";\n                error();\n            }\n            debug_print(\"dev[%d].chan[%d].out[%d] connected to mixer %s as input %d (ampfactor=%.1f balance=%.1f)\\n\", i, j, o, name, mdata->input, ampfactor, balance);\n        } else if (!strncmp(outs[o][\"type\"], \"udp_stream\", 6)) {\n            channel->outputs[oo].data = XCALLOC(1, sizeof(struct udp_stream_data));\n            channel->outputs[oo].type = O_UDP_STREAM;\n\n            udp_stream_data* sdata = (udp_stream_data*)channel->outputs[oo].data;\n\n            sdata->continuous = outs[o].exists(\"continuous\") ? (bool)(outs[o][\"continuous\"]) : false;\n\n            if (outs[o].exists(\"dest_address\")) {\n                sdata->dest_address = strdup(outs[o][\"dest_address\"]);\n            } else {\n                if (parsing_mixers) {\n                    cerr << \"Configuration error: mixers.[\" << i << \"] outputs.[\" << o << \"]: \";\n                } else {\n                    cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o << \"]: \";\n                }\n                cerr << \"missing dest_address\\n\";\n                error();\n            }\n\n            if (outs[o].exists(\"dest_port\")) {\n                if (outs[o][\"dest_port\"].getType() == libconfig::Setting::TypeInt) {\n                    char buffer[12];\n                    sprintf(buffer, \"%d\", (int)outs[o][\"dest_port\"]);\n                    sdata->dest_port = strdup(buffer);\n                } else {\n                    sdata->dest_port = strdup(outs[o][\"dest_port\"]);\n                }\n            } else {\n                if (parsing_mixers) {\n                    cerr << \"Configuration error: mixers.[\" << i << \"] outputs.[\" << o << \"]: \";\n                } else {\n                    cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o << \"]: \";\n                }\n                cerr << \"missing dest_port\\n\";\n                error();\n            }\n#ifdef WITH_PULSEAUDIO\n        } else if (!strncmp(outs[o][\"type\"], \"pulse\", 5)) {\n            channel->outputs[oo].data = XCALLOC(1, sizeof(struct pulse_data));\n            channel->outputs[oo].type = O_PULSE;\n\n            pulse_data* pdata = (pulse_data*)(channel->outputs[oo].data);\n            pdata->continuous = outs[o].exists(\"continuous\") ? (bool)(outs[o][\"continuous\"]) : false;\n            pdata->server = outs[o].exists(\"server\") ? strdup(outs[o][\"server\"]) : NULL;\n            pdata->name = outs[o].exists(\"name\") ? strdup(outs[o][\"name\"]) : \"rtl_airband\";\n            pdata->sink = outs[o].exists(\"sink\") ? strdup(outs[o][\"sink\"]) : NULL;\n\n            if (outs[o].exists(\"stream_name\")) {\n                pdata->stream_name = strdup(outs[o][\"stream_name\"]);\n            } else {\n                if (parsing_mixers) {\n                    cerr << \"Configuration error: mixers.[\" << i << \"] outputs.[\" << o << \"]: PulseAudio outputs of mixers must have stream_name defined\\n\";\n                    error();\n                }\n                char buf[1024];\n                snprintf(buf, sizeof(buf), \"%.3f MHz\", (float)channel->freqlist[0].frequency / 1000000.0f);\n                pdata->stream_name = strdup(buf);\n            }\n#endif /* WITH_PULSEAUDIO */\n        } else {\n            if (parsing_mixers) {\n                cerr << \"Configuration error: mixers.[\" << i << \"] outputs.[\" << o << \"]: \";\n            } else {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] outputs.[\" << o << \"]: \";\n            }\n            cerr << \"unknown output type\\n\";\n            error();\n        }\n        channel->outputs[oo].enabled = true;\n        channel->outputs[oo].active = false;\n        oo++;\n    }\n    return oo;\n}\n\nstatic struct freq_t* mk_freqlist(int n) {\n    if (n < 1) {\n        cerr << \"mk_freqlist: invalid list length \" << n << \"\\n\";\n        error();\n    }\n    struct freq_t* fl = (struct freq_t*)XCALLOC(n, sizeof(struct freq_t));\n    for (int i = 0; i < n; i++) {\n        fl[i].frequency = 0;\n        fl[i].label = NULL;\n        fl[i].agcavgfast = 0.5f;\n        fl[i].ampfactor = 1.0f;\n        fl[i].squelch = Squelch();\n        fl[i].active_counter = 0;\n        fl[i].modulation = MOD_AM;\n    }\n    return fl;\n}\n\nstatic void warn_if_freq_not_in_range(int devidx, int chanidx, int freq, int centerfreq, int sample_rate) {\n    static const float soft_bw_threshold = 0.9f;\n    float bw_limit = (float)sample_rate / 2.f * soft_bw_threshold;\n    if ((float)abs(freq - centerfreq) >= bw_limit) {\n        log(LOG_WARNING, \"Warning: dev[%d].channel[%d]: frequency %.3f MHz is outside of SDR operating bandwidth (%.3f-%.3f MHz)\\n\", devidx, chanidx, (double)freq / 1e6,\n            (double)(centerfreq - bw_limit) / 1e6, (double)(centerfreq + bw_limit) / 1e6);\n    }\n}\n\nstatic int parse_anynum2int(libconfig::Setting& f) {\n    int ret = 0;\n    if (f.getType() == libconfig::Setting::TypeInt) {\n        ret = (int)f;\n    } else if (f.getType() == libconfig::Setting::TypeFloat) {\n        ret = (int)((double)f * 1e6);\n    } else if (f.getType() == libconfig::Setting::TypeString) {\n        char* s = strdup((char const*)f);\n        ret = (int)atofs(s);\n        free(s);\n    }\n    return ret;\n}\n\nstatic int parse_channels(libconfig::Setting& chans, device_t* dev, int i) {\n    int jj = 0;\n    for (int j = 0; j < chans.getLength(); j++) {\n        if (chans[j].exists(\"disable\") && (bool)chans[j][\"disable\"] == true) {\n            continue;\n        }\n        channel_t* channel = dev->channels + jj;\n        for (int k = 0; k < AGC_EXTRA; k++) {\n            channel->wavein[k] = 20;\n            channel->waveout[k] = 0.5;\n        }\n        channel->axcindicate = NO_SIGNAL;\n        channel->mode = MM_MONO;\n        channel->freq_count = 1;\n        channel->freq_idx = 0;\n        channel->highpass = chans[j].exists(\"highpass\") ? (int)chans[j][\"highpass\"] : 100;\n        channel->lowpass = chans[j].exists(\"lowpass\") ? (int)chans[j][\"lowpass\"] : 2500;\n#ifdef NFM\n        channel->pr = 0;\n        channel->pj = 0;\n        channel->prev_waveout = 0.5;\n        channel->alpha = dev->alpha;\n#endif /* NFM */\n\n        // Make sure lowpass / highpass aren't flipped.\n        // If lowpass is enabled (greater than zero) it must be larger than highpass\n        if (channel->lowpass > 0 && channel->lowpass < channel->highpass) {\n            cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: lowpass (\" << channel->lowpass << \") must be greater than or equal to highpass (\" << channel->highpass << \")\\n\";\n            error();\n        }\n\n        modulations channel_modulation = MOD_AM;\n        if (chans[j].exists(\"modulation\")) {\n#ifdef NFM\n            if (strncmp(chans[j][\"modulation\"], \"nfm\", 3) == 0) {\n                channel_modulation = MOD_NFM;\n            } else\n#endif /* NFM */\n                if (strncmp(chans[j][\"modulation\"], \"am\", 2) != 0) {\n                    cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: unknown modulation\\n\";\n                    error();\n                }\n        }\n        channel->afc = chans[j].exists(\"afc\") ? (unsigned char)(unsigned int)chans[j][\"afc\"] : 0;\n        if (dev->mode == R_MULTICHANNEL) {\n            channel->freqlist = mk_freqlist(1);\n            channel->freqlist[0].frequency = parse_anynum2int(chans[j][\"freq\"]);\n            warn_if_freq_not_in_range(i, j, channel->freqlist[0].frequency, dev->input->centerfreq, dev->input->sample_rate);\n            if (chans[j].exists(\"label\")) {\n                channel->freqlist[0].label = strdup(chans[j][\"label\"]);\n            }\n            channel->freqlist[0].modulation = channel_modulation;\n        } else { /* R_SCAN */\n            channel->freq_count = chans[j][\"freqs\"].getLength();\n            if (channel->freq_count < 1) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: freqs should be a list with at least one element\\n\";\n                error();\n            }\n            channel->freqlist = mk_freqlist(channel->freq_count);\n            if (chans[j].exists(\"labels\") && chans[j][\"labels\"].getLength() < channel->freq_count) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: labels should be a list with at least \" << channel->freq_count << \" elements\\n\";\n                error();\n            }\n            if (chans[j].exists(\"squelch_threshold\") && libconfig::Setting::TypeList == chans[j][\"squelch_threshold\"].getType() && chans[j][\"squelch_threshold\"].getLength() < channel->freq_count) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: squelch_threshold should be an int or a list of ints with at least \" << channel->freq_count\n                     << \" elements\\n\";\n                error();\n            }\n            if (chans[j].exists(\"squelch_snr_threshold\") && libconfig::Setting::TypeList == chans[j][\"squelch_snr_threshold\"].getType() &&\n                chans[j][\"squelch_snr_threshold\"].getLength() < channel->freq_count) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j\n                     << \"]: squelch_snr_threshold should be an int, a float or a list of \"\n                        \"ints or floats with at least \"\n                     << channel->freq_count << \" elements\\n\";\n                error();\n            }\n            if (chans[j].exists(\"notch\") && libconfig::Setting::TypeList == chans[j][\"notch\"].getType() && chans[j][\"notch\"].getLength() < channel->freq_count) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: notch should be an float or a list of floats with at least \" << channel->freq_count << \" elements\\n\";\n                error();\n            }\n            if (chans[j].exists(\"notch_q\") && libconfig::Setting::TypeList == chans[j][\"notch_q\"].getType() && chans[j][\"notch_q\"].getLength() < channel->freq_count) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: notch_q should be a float or a list of floats with at least \" << channel->freq_count << \" elements\\n\";\n                error();\n            }\n            if (chans[j].exists(\"ctcss\") && libconfig::Setting::TypeList == chans[j][\"ctcss\"].getType() && chans[j][\"ctcss\"].getLength() < channel->freq_count) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: ctcss should be an float or a list of floats with at least \" << channel->freq_count << \" elements\\n\";\n                error();\n            }\n            if (chans[j].exists(\"modulation\") && chans[j].exists(\"modulations\")) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: can't set both modulation and modulations\\n\";\n                error();\n            }\n            if (chans[j].exists(\"modulations\") && chans[j][\"modulations\"].getLength() < channel->freq_count) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: modulations should be a list with at least \" << channel->freq_count << \" elements\\n\";\n                error();\n            }\n\n            for (int f = 0; f < channel->freq_count; f++) {\n                channel->freqlist[f].frequency = parse_anynum2int((chans[j][\"freqs\"][f]));\n                if (chans[j].exists(\"labels\")) {\n                    channel->freqlist[f].label = strdup(chans[j][\"labels\"][f]);\n                }\n                if (chans[j].exists(\"modulations\")) {\n#ifdef NFM\n                    if (strncmp(chans[j][\"modulations\"][f], \"nfm\", 3) == 0) {\n                        channel->freqlist[f].modulation = MOD_NFM;\n                    } else\n#endif /* NFM */\n                        if (strncmp(chans[j][\"modulations\"][f], \"am\", 2) == 0) {\n                            channel->freqlist[f].modulation = MOD_AM;\n                        } else {\n                            cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] modulations.[\" << f << \"]: unknown modulation\\n\";\n                            error();\n                        }\n                } else {\n                    channel->freqlist[f].modulation = channel_modulation;\n                }\n            }\n            // Set initial frequency for scanning\n            // We tune 20 FFT bins higher to avoid DC spike\n            dev->input->centerfreq = channel->freqlist[0].frequency + 20 * (double)(dev->input->sample_rate / fft_size);\n        }\n        if (chans[j].exists(\"squelch\")) {\n            cerr << \"Warning: 'squelch' no longer supported and will be ignored, use 'squelch_threshold' or 'squelch_snr_threshold' instead\\n\";\n        }\n        if (chans[j].exists(\"squelch_threshold\") && chans[j].exists(\"squelch_snr_threshold\")) {\n            cerr << \"Warning: Both 'squelch_threshold' and 'squelch_snr_threshold' are set and may conflict\\n\";\n        }\n        if (chans[j].exists(\"squelch_threshold\")) {\n            // Value is dBFS, zero disables manual threshold (ie use auto squelch), negative is valid, positive is invalid\n            if (libconfig::Setting::TypeList == chans[j][\"squelch_threshold\"].getType()) {\n                // New-style array of per-frequency squelch settings\n                for (int f = 0; f < channel->freq_count; f++) {\n                    int threshold_dBFS = (int)chans[j][\"squelch_threshold\"][f];\n                    if (threshold_dBFS > 0) {\n                        cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: squelch_threshold must be less than or equal to 0\\n\";\n                        error();\n                    } else if (threshold_dBFS == 0) {\n                        channel->freqlist[f].squelch.set_squelch_level_threshold(0);\n                    } else {\n                        channel->freqlist[f].squelch.set_squelch_level_threshold(dBFS_to_level(threshold_dBFS));\n                    }\n                }\n            } else if (libconfig::Setting::TypeInt == chans[j][\"squelch_threshold\"].getType()) {\n                // Legacy (single squelch for all frequencies)\n                int threshold_dBFS = (int)chans[j][\"squelch_threshold\"];\n                float level;\n                if (threshold_dBFS > 0) {\n                    cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: squelch_threshold must be less than or equal to 0\\n\";\n                    error();\n                } else if (threshold_dBFS == 0) {\n                    level = 0;\n                } else {\n                    level = dBFS_to_level(threshold_dBFS);\n                }\n\n                for (int f = 0; f < channel->freq_count; f++) {\n                    channel->freqlist[f].squelch.set_squelch_level_threshold(level);\n                }\n            } else {\n                cerr << \"Invalid value for squelch_threshold (should be int or list - use parentheses)\\n\";\n                error();\n            }\n        }\n        if (chans[j].exists(\"squelch_snr_threshold\")) {\n            // Value is SNR in dB, zero disables squelch (ie always open), -1 uses default value, positive is valid, other negative values are invalid\n            if (libconfig::Setting::TypeList == chans[j][\"squelch_snr_threshold\"].getType()) {\n                // New-style array of per-frequency squelch settings\n                for (int f = 0; f < channel->freq_count; f++) {\n                    float snr = 0.f;\n                    if (libconfig::Setting::TypeFloat == chans[j][\"squelch_snr_threshold\"][f].getType()) {\n                        snr = (float)chans[j][\"squelch_snr_threshold\"][f];\n                    } else if (libconfig::Setting::TypeInt == chans[j][\"squelch_snr_threshold\"][f].getType()) {\n                        snr = (int)chans[j][\"squelch_snr_threshold\"][f];\n                    } else {\n                        cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: squelch_snr_threshold list must be of int or float\\n\";\n                        error();\n                    }\n\n                    if (snr == -1.0) {\n                        continue;  // \"disable\" for this channel in list\n                    } else if (snr < 0) {\n                        cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: squelch_snr_threshold must be greater than or equal to 0\\n\";\n                        error();\n                    } else {\n                        channel->freqlist[f].squelch.set_squelch_snr_threshold(snr);\n                    }\n                }\n            } else if (libconfig::Setting::TypeFloat == chans[j][\"squelch_snr_threshold\"].getType() || libconfig::Setting::TypeInt == chans[j][\"squelch_snr_threshold\"].getType()) {\n                // Legacy (single squelch for all frequencies)\n                float snr = (libconfig::Setting::TypeFloat == chans[j][\"squelch_snr_threshold\"].getType()) ? (float)chans[j][\"squelch_snr_threshold\"] : (int)chans[j][\"squelch_snr_threshold\"];\n\n                if (snr == -1.0) {\n                    continue;  // \"disable\" so use the default without error message\n                } else if (snr < 0) {\n                    cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: squelch_snr_threshold must be greater than or equal to 0\\n\";\n                    error();\n                }\n\n                for (int f = 0; f < channel->freq_count; f++) {\n                    channel->freqlist[f].squelch.set_squelch_snr_threshold(snr);\n                }\n            } else {\n                cerr << \"Invalid value for squelch_snr_threshold (should be float, int, or list of int/float - use parentheses)\\n\";\n                error();\n            }\n        }\n        if (chans[j].exists(\"notch\")) {\n            static const float default_q = 10.0;\n\n            if (chans[j].exists(\"notch_q\") && chans[j][\"notch\"].getType() != chans[j][\"notch_q\"].getType()) {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: notch_q (if set) must be the same type as notch - \"\n                     << \"float or a list of floats with at least \" << channel->freq_count << \" elements\\n\";\n                error();\n            }\n            if (libconfig::Setting::TypeList == chans[j][\"notch\"].getType()) {\n                for (int f = 0; f < channel->freq_count; f++) {\n                    float freq = (float)chans[j][\"notch\"][f];\n                    float q = chans[j].exists(\"notch_q\") ? (float)chans[j][\"notch_q\"][f] : default_q;\n\n                    if (q == 0.0) {\n                        q = default_q;\n                    } else if (q <= 0.0) {\n                        cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"] freq.[\" << f << \"]: invalid value for notch_q: \" << q << \" (must be greater than 0.0)\\n\";\n                        error();\n                    }\n\n                    if (freq == 0) {\n                        continue;  // \"disable\" for this channel in list\n                    } else if (freq < 0) {\n                        cerr << \"devices.[\" << i << \"] channels.[\" << j << \"] freq.[\" << f << \"]: invalid value for notch: \" << freq << \", ignoring\\n\";\n                    } else {\n                        channel->freqlist[f].notch_filter = NotchFilter(freq, WAVE_RATE, q);\n                    }\n                }\n            } else if (libconfig::Setting::TypeFloat == chans[j][\"notch\"].getType()) {\n                float freq = (float)chans[j][\"notch\"];\n                float q = chans[j].exists(\"notch_q\") ? (float)chans[j][\"notch_q\"] : default_q;\n                if (q <= 0.0) {\n                    cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: invalid value for notch_q: \" << q << \" (must be greater than 0.0)\\n\";\n                    error();\n                }\n                for (int f = 0; f < channel->freq_count; f++) {\n                    if (freq == 0) {\n                        continue;  // \"disable\" is default so ignore without error message\n                    } else if (freq < 0) {\n                        cerr << \"devices.[\" << i << \"] channels.[\" << j << \"]: notch value '\" << freq << \"' invalid, ignoring\\n\";\n                    } else {\n                        channel->freqlist[f].notch_filter = NotchFilter(freq, WAVE_RATE, q);\n                    }\n                }\n            } else {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: notch should be an float or a list of floats with at least \" << channel->freq_count << \" elements\\n\";\n                error();\n            }\n        }\n        if (chans[j].exists(\"ctcss\")) {\n            if (libconfig::Setting::TypeList == chans[j][\"ctcss\"].getType()) {\n                for (int f = 0; f < channel->freq_count; f++) {\n                    float freq = (float)chans[j][\"ctcss\"][f];\n\n                    if (freq == 0) {\n                        continue;  // \"disable\" for this channel in list\n                    } else if (freq < 0) {\n                        cerr << \"devices.[\" << i << \"] channels.[\" << j << \"] freq.[\" << f << \"]: invalid value for ctcss: \" << freq << \", ignoring\\n\";\n                    } else {\n                        channel->freqlist[f].squelch.set_ctcss_freq(freq, WAVE_RATE);\n                    }\n                }\n            } else if (libconfig::Setting::TypeFloat == chans[j][\"ctcss\"].getType()) {\n                float freq = (float)chans[j][\"ctcss\"];\n                for (int f = 0; f < channel->freq_count; f++) {\n                    if (freq <= 0) {\n                        cerr << \"devices.[\" << i << \"] channels.[\" << j << \"]: ctcss value '\" << freq << \"' invalid, ignoring\\n\";\n                    } else {\n                        channel->freqlist[f].squelch.set_ctcss_freq(freq, WAVE_RATE);\n                    }\n                }\n            } else {\n                cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: ctcss should be an float or a list of floats with at least \" << channel->freq_count << \" elements\\n\";\n                error();\n            }\n        }\n        if (chans[j].exists(\"bandwidth\")) {\n            channel->needs_raw_iq = 1;\n\n            if (libconfig::Setting::TypeList == chans[j][\"bandwidth\"].getType()) {\n                for (int f = 0; f < channel->freq_count; f++) {\n                    int bandwidth = parse_anynum2int(chans[j][\"bandwidth\"][f]);\n\n                    if (bandwidth == 0) {\n                        continue;  // \"disable\" for this channel in list\n                    } else if (bandwidth < 0) {\n                        cerr << \"devices.[\" << i << \"] channels.[\" << j << \"] freq.[\" << f << \"]: bandwidth value '\" << bandwidth << \"' invalid, ignoring\\n\";\n                    } else {\n                        channel->freqlist[f].lowpass_filter = LowpassFilter((float)bandwidth / 2, WAVE_RATE);\n                    }\n                }\n            } else {\n                int bandwidth = parse_anynum2int(chans[j][\"bandwidth\"]);\n                if (bandwidth == 0) {\n                    continue;  // \"disable\" is default so ignore without error message\n                } else if (bandwidth < 0) {\n                    cerr << \"devices.[\" << i << \"] channels.[\" << j << \"]: bandwidth value '\" << bandwidth << \"' invalid, ignoring\\n\";\n                } else {\n                    for (int f = 0; f < channel->freq_count; f++) {\n                        channel->freqlist[f].lowpass_filter = LowpassFilter((float)bandwidth / 2, WAVE_RATE);\n                    }\n                }\n            }\n        }\n        if (chans[j].exists(\"ampfactor\")) {\n            if (libconfig::Setting::TypeList == chans[j][\"ampfactor\"].getType()) {\n                for (int f = 0; f < channel->freq_count; f++) {\n                    float ampfactor = (float)chans[j][\"ampfactor\"][f];\n\n                    if (ampfactor < 0) {\n                        cerr << \"devices.[\" << i << \"] channels.[\" << j << \"] freq.[\" << f << \"]: ampfactor '\" << ampfactor << \"' must not be negative\\n\";\n                        error();\n                    }\n\n                    channel->freqlist[f].ampfactor = ampfactor;\n                }\n            } else {\n                float ampfactor = (float)chans[j][\"ampfactor\"];\n\n                if (ampfactor < 0) {\n                    cerr << \"devices.[\" << i << \"] channels.[\" << j << \"]: ampfactor '\" << ampfactor << \"' must not be negative\\n\";\n                    error();\n                }\n\n                for (int f = 0; f < channel->freq_count; f++) {\n                    channel->freqlist[f].ampfactor = ampfactor;\n                }\n            }\n        }\n\n#ifdef NFM\n        if (chans[j].exists(\"tau\")) {\n            channel->alpha = ((int)chans[j][\"tau\"] == 0 ? 0.0f : exp(-1.0f / (WAVE_RATE * 1e-6 * (int)chans[j][\"tau\"])));\n        }\n#endif /* NFM */\n        libconfig::Setting& outputs = chans[j][\"outputs\"];\n        channel->output_count = outputs.getLength();\n        if (channel->output_count < 1) {\n            cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: no outputs defined\\n\";\n            error();\n        }\n        channel->outputs = (output_t*)XCALLOC(channel->output_count, sizeof(struct output_t));\n        int outputs_enabled = parse_outputs(outputs, channel, i, j, false);\n        if (outputs_enabled < 1) {\n            cerr << \"Configuration error: devices.[\" << i << \"] channels.[\" << j << \"]: no outputs defined\\n\";\n            error();\n        }\n        channel->outputs = (output_t*)XREALLOC(channel->outputs, outputs_enabled * sizeof(struct output_t));\n        channel->output_count = outputs_enabled;\n\n        dev->base_bins[jj] = dev->bins[jj] =\n            (size_t)ceil((channel->freqlist[0].frequency + dev->input->sample_rate - dev->input->centerfreq) / (double)(dev->input->sample_rate / fft_size) - 1.0) % fft_size;\n        debug_print(\"bins[%d]: %zu\\n\", jj, dev->bins[jj]);\n\n#ifdef NFM\n        for (int f = 0; f < channel->freq_count; f++) {\n            if (channel->freqlist[f].modulation == MOD_NFM) {\n                channel->needs_raw_iq = 1;\n                break;\n            }\n        }\n#endif /* NFM */\n\n        if (channel->needs_raw_iq) {\n            // Downmixing is done only for NFM and raw IQ outputs. It's not critical to have some residual\n            // freq offset in AM, as it doesn't affect sound quality significantly.\n            double dm_dphi = (double)(channel->freqlist[0].frequency - dev->input->centerfreq);  // downmix freq in Hz\n\n            // In general, sample_rate is not required to be an integer multiple of WAVE_RATE.\n            // However the FFT window may only slide by an integer number of input samples. A non-zero rounding error\n            // introduces additional phase rotation which we have to compensate in order to shift the channel of interest\n            // to the center of the spectrum of the output I/Q stream. This is important for correct NFM demodulation.\n            // The error value (in Hz):\n            // - has an absolute value 0..WAVE_RATE/2\n            // - is linear with the error introduced by rounding the value of sample_rate/WAVE_RATE to the nearest integer\n            //   (range of -0.5..0.5)\n            // - is linear with the distance between center frequency and the channel frequency, normalized to 0..1\n            double decimation_factor = ((double)dev->input->sample_rate / (double)WAVE_RATE);\n            double dm_dphi_correction = (double)WAVE_RATE / 2.0;\n            dm_dphi_correction *= (decimation_factor - round(decimation_factor));\n            dm_dphi_correction *= (double)(channel->freqlist[0].frequency - dev->input->centerfreq) / ((double)dev->input->sample_rate / 2.0);\n\n            debug_print(\"dev[%d].chan[%d]: dm_dphi: %f Hz dm_dphi_correction: %f Hz\\n\", i, jj, dm_dphi, dm_dphi_correction);\n            dm_dphi -= dm_dphi_correction;\n            debug_print(\"dev[%d].chan[%d]: dm_dphi_corrected: %f Hz\\n\", i, jj, dm_dphi);\n            // Normalize\n            dm_dphi /= (double)WAVE_RATE;\n            // Unalias it, to prevent overflow of int during cast\n            dm_dphi -= trunc(dm_dphi);\n            debug_print(\"dev[%d].chan[%d]: dm_dphi_normalized=%f\\n\", i, jj, dm_dphi);\n            // Translate this to uint32_t range 0x00000000-0x00ffffff\n            dm_dphi *= 256.0 * 65536.0;\n            // Cast it to signed int first, because casting negative float to uint is not portable\n            channel->dm_dphi = (uint32_t)((int)dm_dphi);\n            debug_print(\"dev[%d].chan[%d]: dm_dphi_scaled=%f cast=0x%x\\n\", i, jj, dm_dphi, channel->dm_dphi);\n            channel->dm_phi = 0.f;\n        }\n\n#ifdef DEBUG_SQUELCH\n        // Setup squelch debug file, if enabled\n        char tmp_filepath[1024];\n        for (int f = 0; f < channel->freq_count; f++) {\n            snprintf(tmp_filepath, sizeof(tmp_filepath), \"./squelch_debug-%d-%d.dat\", j, f);\n            channel->freqlist[f].squelch.set_debug_file(tmp_filepath);\n        }\n#endif /* DEBUG_SQUELCH */\n\n        jj++;\n    }\n    return jj;\n}\n\nint parse_devices(libconfig::Setting& devs) {\n    int devcnt = 0;\n    for (int i = 0; i < devs.getLength(); i++) {\n        if (devs[i].exists(\"disable\") && (bool)devs[i][\"disable\"] == true)\n            continue;\n        device_t* dev = devices + devcnt;\n        if (devs[i].exists(\"type\")) {\n            dev->input = input_new(devs[i][\"type\"]);\n            if (dev->input == NULL) {\n                cerr << \"Configuration error: devices.[\" << i << \"]: unsupported device type\\n\";\n                error();\n            }\n        } else {\n#ifdef WITH_RTLSDR\n            cerr << \"Warning: devices.[\" << i << \"]: assuming device type \\\"rtlsdr\\\", please set \\\"type\\\" in the device section.\\n\";\n            dev->input = input_new(\"rtlsdr\");\n#else\n            cerr << \"Configuration error: devices.[\" << i << \"]: mandatory parameter missing: type\\n\";\n            error();\n#endif /* WITH_RTLSDR */\n        }\n        assert(dev->input != NULL);\n        if (devs[i].exists(\"sample_rate\")) {\n            int sample_rate = parse_anynum2int(devs[i][\"sample_rate\"]);\n            if (sample_rate < WAVE_RATE) {\n                cerr << \"Configuration error: devices.[\" << i << \"]: sample_rate must be greater than \" << WAVE_RATE << \"\\n\";\n                error();\n            }\n            dev->input->sample_rate = sample_rate;\n        }\n        if (devs[i].exists(\"mode\")) {\n            if (!strncmp(devs[i][\"mode\"], \"multichannel\", 12)) {\n                dev->mode = R_MULTICHANNEL;\n            } else if (!strncmp(devs[i][\"mode\"], \"scan\", 4)) {\n                dev->mode = R_SCAN;\n            } else {\n                cerr << \"Configuration error: devices.[\" << i << \"]: invalid mode (must be one of: \\\"scan\\\", \\\"multichannel\\\")\\n\";\n                error();\n            }\n        } else {\n            dev->mode = R_MULTICHANNEL;\n        }\n        if (dev->mode == R_MULTICHANNEL) {\n            dev->input->centerfreq = parse_anynum2int(devs[i][\"centerfreq\"]);\n        }  // centerfreq for R_SCAN will be set by parse_channels() after frequency list has been read\n#ifdef NFM\n        if (devs[i].exists(\"tau\")) {\n            dev->alpha = ((int)devs[i][\"tau\"] == 0 ? 0.0f : exp(-1.0f / (WAVE_RATE * 1e-6 * (int)devs[i][\"tau\"])));\n        } else {\n            dev->alpha = alpha;\n        }\n#endif /* NFM */\n\n        // Parse hardware-dependent configuration parameters\n        if (input_parse_config(dev->input, devs[i]) < 0) {\n            // FIXME: get and display error string from input_parse_config\n            // Right now it exits the program on failure.\n        }\n        // Some basic sanity checks for crucial parameters which have to be set\n        // (or can be modified) by the input driver\n        assert(dev->input->sfmt != SFMT_UNDEF);\n        assert(dev->input->fullscale > 0);\n        assert(dev->input->bytes_per_sample > 0);\n        assert(dev->input->sample_rate > WAVE_RATE);\n\n        // For the input buffer size use a base value and round it up to the nearest multiple\n        // of FFT_BATCH blocks of input samples.\n        // ceil is required here because sample rate is not guaranteed to be an integer multiple of WAVE_RATE.\n        size_t fft_batch_len = FFT_BATCH * (2 * dev->input->bytes_per_sample * (size_t)ceil((double)dev->input->sample_rate / (double)WAVE_RATE));\n        dev->input->buf_size = MIN_BUF_SIZE;\n        if (dev->input->buf_size % fft_batch_len != 0)\n            dev->input->buf_size += fft_batch_len - dev->input->buf_size % fft_batch_len;\n        debug_print(\"dev->input->buf_size: %zu\\n\", dev->input->buf_size);\n        dev->input->buffer = (unsigned char*)XCALLOC(sizeof(unsigned char), dev->input->buf_size + 2 * dev->input->bytes_per_sample * fft_size);\n        dev->input->bufs = dev->input->bufe = 0;\n        dev->input->overflow_count = 0;\n        dev->output_overrun_count = 0;\n        dev->waveend = dev->waveavail = dev->row = dev->tq_head = dev->tq_tail = 0;\n        dev->last_frequency = -1;\n\n        libconfig::Setting& chans = devs[i][\"channels\"];\n        if (chans.getLength() < 1) {\n            cerr << \"Configuration error: devices.[\" << i << \"]: no channels configured\\n\";\n            error();\n        }\n        dev->channels = (channel_t*)XCALLOC(chans.getLength(), sizeof(channel_t));\n        dev->bins = (size_t*)XCALLOC(chans.getLength(), sizeof(size_t));\n        dev->base_bins = (size_t*)XCALLOC(chans.getLength(), sizeof(size_t));\n        dev->channel_count = 0;\n        int channel_count = parse_channels(chans, dev, i);\n        if (channel_count < 1) {\n            cerr << \"Configuration error: devices.[\" << i << \"]: no channels enabled\\n\";\n            error();\n        }\n        if (dev->mode == R_SCAN && channel_count > 1) {\n            cerr << \"Configuration error: devices.[\" << i << \"]: only one channel is allowed in scan mode\\n\";\n            error();\n        }\n        dev->channels = (channel_t*)XREALLOC(dev->channels, channel_count * sizeof(channel_t));\n        dev->bins = (size_t*)XREALLOC(dev->bins, channel_count * sizeof(size_t));\n        dev->base_bins = (size_t*)XREALLOC(dev->base_bins, channel_count * sizeof(size_t));\n        dev->channel_count = channel_count;\n        devcnt++;\n    }\n    return devcnt;\n}\n\nint parse_mixers(libconfig::Setting& mx) {\n    const char* name;\n    int mm = 0;\n    for (int i = 0; i < mx.getLength(); i++) {\n        if (mx[i].exists(\"disable\") && (bool)mx[i][\"disable\"] == true)\n            continue;\n        if ((name = mx[i].getName()) == NULL) {\n            cerr << \"Configuration error: mixers.[\" << i << \"]: undefined mixer name\\n\";\n            error();\n        }\n        debug_print(\"mm=%d name=%s\\n\", mm, name);\n        mixer_t* mixer = &mixers[mm];\n        mixer->name = strdup(name);\n        mixer->enabled = false;\n        mixer->interval = MIX_DIVISOR;\n        mixer->output_overrun_count = 0;\n        mixer->input_count = 0;\n        mixer->inputs = NULL;\n        mixer->inputs_todo = NULL;\n        mixer->input_mask = NULL;\n        channel_t* channel = &mixer->channel;\n        channel->highpass = mx[i].exists(\"highpass\") ? (int)mx[i][\"highpass\"] : 100;\n        channel->lowpass = mx[i].exists(\"lowpass\") ? (int)mx[i][\"lowpass\"] : 2500;\n        channel->mode = MM_MONO;\n\n        // Make sure lowpass / highpass aren't flipped.\n        // If lowpass is enabled (greater than zero) it must be larger than highpass\n        if (channel->lowpass > 0 && channel->lowpass < channel->highpass) {\n            cerr << \"Configuration error: mixers.[\" << i << \"]: lowpass (\" << channel->lowpass << \") must be greater than or equal to highpass (\" << channel->highpass << \")\\n\";\n            error();\n        }\n\n        libconfig::Setting& outputs = mx[i][\"outputs\"];\n        channel->output_count = outputs.getLength();\n        if (channel->output_count < 1) {\n            cerr << \"Configuration error: mixers.[\" << i << \"]: no outputs defined\\n\";\n            error();\n        }\n        channel->outputs = (output_t*)XCALLOC(channel->output_count, sizeof(struct output_t));\n        int outputs_enabled = parse_outputs(outputs, channel, i, 0, true);\n        if (outputs_enabled < 1) {\n            cerr << \"Configuration error: mixers.[\" << i << \"]: no outputs defined\\n\";\n            error();\n        }\n        channel->outputs = (output_t*)XREALLOC(channel->outputs, outputs_enabled * sizeof(struct output_t));\n        channel->output_count = outputs_enabled;\n        mm++;\n    }\n    return mm;\n}\n\n// vim: ts=4\n"
  },
  {
    "path": "src/config.h.in",
    "content": "/*\n * config.h.in\n * Template for cmake-generated config.h\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#ifndef _CONFIG_H\n#define _CONFIG_H\n#cmakedefine WITH_RTLSDR\n#cmakedefine WITH_MIRISDR\n#cmakedefine WITH_SOAPYSDR\n#cmakedefine WITH_PROFILING\n#cmakedefine WITH_PULSEAUDIO\n#cmakedefine NFM\n#cmakedefine WITH_BCM_VC\n#cmakedefine LIBSHOUT_HAS_TLS\n#cmakedefine LIBSHOUT_HAS_CONTENT_FORMAT\n#define SINCOSF @SINCOSF@\n\n#define SHOUT_SET_METADATA @SHOUT_SET_METADATA@\n\n#endif /* _CONFIG_H */\n"
  },
  {
    "path": "src/ctcss.cpp",
    "content": "/*\n * ctcss.h\n *\n * Copyright (C) 2022-2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <math.h>     // M_PI\n#include <algorithm>  // sort\n\n#include \"logging.h\"  // debug_print()\n\n#include \"ctcss.h\"\n\nusing namespace std;\n\n// Implementation of https://www.embedded.com/detecting-ctcss-tones-with-goertzels-algorithm/\n// also https://www.embedded.com/the-goertzel-algorithm/\nToneDetector::ToneDetector(float tone_freq, float sample_rate, int window_size) {\n    tone_freq_ = tone_freq;\n    magnitude_ = 0.0;\n\n    window_size_ = window_size;\n\n    int k = (0.5 + window_size * tone_freq / sample_rate);\n    float omega = (2.0 * M_PI * k) / window_size;\n    coeff_ = 2.0 * cos(omega);\n\n    reset();\n}\n\nvoid ToneDetector::process_sample(const float& sample) {\n    q0_ = coeff_ * q1_ - q2_ + sample;\n    q2_ = q1_;\n    q1_ = q0_;\n\n    count_++;\n    if (count_ == window_size_) {\n        magnitude_ = q1_ * q1_ + q2_ * q2_ - q1_ * q2_ * coeff_;\n        count_ = 0;\n    }\n}\n\nvoid ToneDetector::reset(void) {\n    count_ = 0;\n    q0_ = q1_ = q2_ = 0.0;\n}\n\nbool ToneDetectorSet::add(const float& tone_freq, const float& sample_rate, int window_size) {\n    ToneDetector new_tone = ToneDetector(tone_freq, sample_rate, window_size);\n\n    for (const auto tone : tones_) {\n        if (new_tone.coefficient() == tone.coefficient()) {\n            debug_print(\"Skipping tone %f, too close to other tones\\n\", tone_freq);\n            return false;\n        }\n    }\n\n    tones_.push_back(new_tone);\n    return true;\n}\n\nvoid ToneDetectorSet::process_sample(const float& sample) {\n    for (vector<ToneDetector>::iterator it = tones_.begin(); it != tones_.end(); ++it) {\n        it->process_sample(sample);\n    }\n}\n\nvoid ToneDetectorSet::reset(void) {\n    for (vector<ToneDetector>::iterator it = tones_.begin(); it != tones_.end(); ++it) {\n        it->reset();\n    }\n}\n\nfloat ToneDetectorSet::sorted_powers(vector<ToneDetectorSet::PowerIndex>& powers) {\n    powers.clear();\n\n    float total_power = 0.0;\n    for (size_t i = 0; i < tones_.size(); ++i) {\n        powers.push_back({tones_[i].relative_power(), tones_[i].freq()});\n        total_power += tones_[i].relative_power();\n    }\n\n    sort(powers.begin(), powers.end(), [](PowerIndex a, PowerIndex b) { return a.power > b.power; });\n\n    return total_power / tones_.size();\n}\n\nvector<float> CTCSS::standard_tones = {67.0,  69.3,  71.9,  74.4,  77.0,  79.7,  82.5,  85.4,  88.5,  91.5,  94.8,  97.4,  100.0, 103.5, 107.2, 110.9, 114.8,\n                                       118.8, 123.0, 127.3, 131.8, 136.5, 141.3, 146.2, 150.0, 151.4, 156.7, 159.8, 162.2, 165.5, 167.9, 171.3, 173.8, 177.3,\n                                       179.9, 183.5, 186.2, 189.9, 192.8, 196.6, 199.5, 203.5, 206.5, 210.7, 218.1, 225.7, 229.1, 233.6, 241.8, 250.3, 254.1};\n\nCTCSS::CTCSS(const float& ctcss_freq, const float& sample_rate, int window_size) : enabled_(true), ctcss_freq_(ctcss_freq), window_size_(window_size), found_count_(0), not_found_count_(0) {\n    debug_print(\"Adding CTCSS detector for %f Hz with a sample rate of %f and window %d\\n\", ctcss_freq, sample_rate, window_size_);\n\n    // Add the target CTCSS frequency first followed by the other \"standard tones\", except those\n    // within +/- 5 Hz\n    powers_.add(ctcss_freq, sample_rate, window_size_);\n\n    for (const auto tone : standard_tones) {\n        if (abs(ctcss_freq - tone) < 5) {\n            debug_print(\"Skipping tone %f, too close to other tones\\n\", tone);\n            continue;\n        }\n        powers_.add(tone, sample_rate, window_size_);\n    }\n\n    // clear all values to start NOTE: has_tone_ will be true until the first window count of samples are processed\n    reset();\n}\n\nvoid CTCSS::process_audio_sample(const float& sample) {\n    if (!enabled_) {\n        return;\n    }\n\n    powers_.process_sample(sample);\n\n    sample_count_++;\n    if (sample_count_ < window_size_) {\n        return;\n    }\n\n    enough_samples_ = true;\n\n    // if this is sample fills out the window then check if one of the \"strongest\"\n    // tones is the CTCSS tone we are looking for.  NOTE: there can be multiple \"strongest\"\n    // tones based on floating point math\n    vector<ToneDetectorSet::PowerIndex> tone_powers;\n    float avg_power = powers_.sorted_powers(tone_powers);\n    float ctcss_tone_power = 0.0;\n    for (const auto i : tone_powers) {\n        if (i.freq == ctcss_freq_) {\n            ctcss_tone_power = i.power;\n            break;\n        }\n    }\n    if (ctcss_tone_power == tone_powers[0].power && ctcss_tone_power > avg_power) {\n        debug_print(\"CTCSS tone of %f Hz detected\\n\", ctcss_freq_);\n        has_tone_ = true;\n        found_count_++;\n    } else {\n        debug_print(\"CTCSS tone of %f Hz not detected - highest power was %f Hz at %f vs %f\\n\", ctcss_freq_, tone_powers[0].freq, tone_powers[0].power, ctcss_tone_power);\n        has_tone_ = false;\n        not_found_count_++;\n    }\n\n    // reset everything for the next window's worth of samples\n    powers_.reset();\n    sample_count_ = 0;\n}\n\nvoid CTCSS::reset(void) {\n    if (enabled_) {\n        powers_.reset();\n        enough_samples_ = false;\n        sample_count_ = 0;\n        has_tone_ = false;\n    }\n}\n"
  },
  {
    "path": "src/ctcss.h",
    "content": "/*\n * ctcss.h\n *\n * Copyright (C) 2022-2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#ifndef _CTCSS_H\n#define _CTCSS_H 1\n\n#include <cstddef>  // size_t\n#include <vector>\n\nclass ToneDetector {\n   public:\n    ToneDetector(float tone_freq, float sample_freq, int window_size);\n    void process_sample(const float& sample);\n    void reset(void);\n\n    const float& relative_power(void) const { return magnitude_; }\n    const float& freq(void) const { return tone_freq_; }\n    const float& coefficient(void) const { return coeff_; }\n\n   private:\n    float tone_freq_;\n    float magnitude_;\n\n    int window_size_;\n    float coeff_;\n\n    int count_;\n    float q0_;\n    float q1_;\n    float q2_;\n};\n\nclass ToneDetectorSet {\n   public:\n    struct PowerIndex {\n        float power;\n        float freq;\n    };\n\n    ToneDetectorSet() {}\n\n    bool add(const float& tone_freq, const float& sample_freq, int window_size);\n    void process_sample(const float& sample);\n    void reset(void);\n\n    float sorted_powers(std::vector<PowerIndex>& powers);\n\n   private:\n    std::vector<ToneDetector> tones_;\n};\n\nclass CTCSS {\n   public:\n    CTCSS(void) : enabled_(false), found_count_(0), not_found_count_(0) {}\n    CTCSS(const float& ctcss_freq, const float& sample_rate, int window_size);\n    void process_audio_sample(const float& sample);\n    void reset(void);\n\n    const size_t& found_count(void) const { return found_count_; }\n    const size_t& not_found_count(void) const { return not_found_count_; }\n\n    bool is_enabled(void) const { return enabled_; }\n    bool enough_samples(void) const { return enough_samples_; }\n    bool has_tone(void) const { return !enabled_ || has_tone_; }\n\n    static std::vector<float> standard_tones;\n\n   private:\n    bool enabled_;\n    float ctcss_freq_;\n    int window_size_;\n    size_t found_count_;\n    size_t not_found_count_;\n\n    ToneDetectorSet powers_;\n\n    bool enough_samples_;\n    int sample_count_;\n    bool has_tone_;\n};\n\n#endif /* _CTCSS_H */\n"
  },
  {
    "path": "src/filters.cpp",
    "content": "/*\n * filters.cpp\n *\n * Copyright (C) 2022-2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"logging.h\"  // debug_print()\n\n#include \"filters.h\"\n\nusing namespace std;\n\n// Default constructor is no filter\nNotchFilter::NotchFilter(void) : enabled_(false) {}\n\n// Notch Filter based on https://www.dsprelated.com/showcode/173.php\nNotchFilter::NotchFilter(float notch_freq, float sample_freq, float q) : enabled_(true), x{0.0}, y{0.0} {\n    if (notch_freq <= 0.0) {\n        debug_print(\"Invalid frequency %f Hz, disabling notch filter\\n\", notch_freq);\n        enabled_ = false;\n        return;\n    }\n\n    debug_print(\"Adding notch filter for %f Hz with parameters {%f, %f}\\n\", notch_freq, sample_freq, q);\n\n    float wo = 2 * M_PI * (notch_freq / sample_freq);\n\n    e = 1 / (1 + tan(wo / (q * 2)));\n    p = cos(wo);\n    d[0] = e;\n    d[1] = 2 * e * p;\n    d[2] = (2 * e - 1);\n\n    debug_print(\"wo:%f e:%f p:%f d:{%f,%f,%f}\\n\", wo, e, p, d[0], d[1], d[2]);\n}\n\nvoid NotchFilter::apply(float& value) {\n    if (!enabled_) {\n        return;\n    }\n\n    x[0] = x[1];\n    x[1] = x[2];\n    x[2] = value;\n\n    y[0] = y[1];\n    y[1] = y[2];\n    y[2] = d[0] * x[2] - d[1] * x[1] + d[0] * x[0] + d[1] * y[1] - d[2] * y[0];\n\n    value = y[2];\n}\n\n// Default constructor is no filter\nLowpassFilter::LowpassFilter(void) : enabled_(false) {}\n\n// 2nd order lowpass Bessel filter, based entirely on a simplification of https://www-users.cs.york.ac.uk/~fisher/mkfilter/\nLowpassFilter::LowpassFilter(float freq, float sample_freq) : enabled_(true) {\n    if (freq <= 0.0) {\n        debug_print(\"Invalid frequency %f Hz, disabling lowpass filter\\n\", freq);\n        enabled_ = false;\n        return;\n    }\n\n    debug_print(\"Adding lowpass filter at %f Hz with a sample rate of %f\\n\", freq, sample_freq);\n\n    double raw_alpha = (double)freq / sample_freq;\n    double warped_alpha = tan(M_PI * raw_alpha) / M_PI;\n\n    complex<double> zeros[2] = {-1.0, -1.0};\n    complex<double> poles[2];\n    poles[0] = blt(M_PI * 2 * warped_alpha * complex<double>(-1.10160133059e+00, 6.36009824757e-01));\n    poles[1] = blt(M_PI * 2 * warped_alpha * conj(complex<double>(-1.10160133059e+00, 6.36009824757e-01)));\n\n    complex<double> topcoeffs[3];\n    complex<double> botcoeffs[3];\n    expand(zeros, 2, topcoeffs);\n    expand(poles, 2, botcoeffs);\n    complex<double> gain_complex = evaluate(topcoeffs, 2, botcoeffs, 2, 1.0);\n    gain = hypot(gain_complex.imag(), gain_complex.real());\n\n    for (int i = 0; i <= 2; i++) {\n        ycoeffs[i] = -(botcoeffs[i].real() / botcoeffs[2].real());\n    }\n\n    debug_print(\"gain: %f, ycoeffs: {%f, %f}\\n\", gain, ycoeffs[0], ycoeffs[1]);\n}\n\ncomplex<double> LowpassFilter::blt(complex<double> pz) {\n    return (2.0 + pz) / (2.0 - pz);\n}\n\n/* evaluate response, substituting for z */\ncomplex<double> LowpassFilter::evaluate(complex<double> topco[], int nz, complex<double> botco[], int np, complex<double> z) {\n    return eval(topco, nz, z) / eval(botco, np, z);\n}\n\n/* evaluate polynomial in z, substituting for z */\ncomplex<double> LowpassFilter::eval(complex<double> coeffs[], int npz, complex<double> z) {\n    complex<double> sum(0.0);\n    for (int i = npz; i >= 0; i--) {\n        sum = (sum * z) + coeffs[i];\n    }\n    return sum;\n}\n\n/* compute product of poles or zeros as a polynomial of z */\nvoid LowpassFilter::expand(complex<double> pz[], int npz, complex<double> coeffs[]) {\n    coeffs[0] = 1.0;\n    for (int i = 0; i < npz; i++) {\n        coeffs[i + 1] = 0.0;\n    }\n    for (int i = 0; i < npz; i++) {\n        multin(pz[i], npz, coeffs);\n    }\n    /* check computed coeffs of z^k are all real */\n    for (int i = 0; i < npz + 1; i++) {\n        if (fabs(coeffs[i].imag()) > 1e-10) {\n            log(LOG_ERR, \"coeff of z^%d is not real; poles/zeros are not complex conjugates\\n\", i);\n            error();\n        }\n    }\n}\n\nvoid LowpassFilter::multin(complex<double> w, int npz, complex<double> coeffs[]) {\n    /* multiply factor (z-w) into coeffs */\n    complex<double> nw = -w;\n    for (int i = npz; i >= 1; i--) {\n        coeffs[i] = (nw * coeffs[i]) + coeffs[i - 1];\n    }\n    coeffs[0] = nw * coeffs[0];\n}\n\nvoid LowpassFilter::apply(float& r, float& j) {\n    if (!enabled_) {\n        return;\n    }\n\n    complex<float> input(r, j);\n\n    xv[0] = xv[1];\n    xv[1] = xv[2];\n    xv[2] = input / gain;\n\n    yv[0] = yv[1];\n    yv[1] = yv[2];\n    yv[2] = (xv[0] + xv[2]) + (2.0f * xv[1]) + (ycoeffs[0] * yv[0]) + (ycoeffs[1] * yv[1]);\n\n    r = yv[2].real();\n    j = yv[2].imag();\n}\n"
  },
  {
    "path": "src/filters.h",
    "content": "/*\n * filters.h\n *\n * Copyright (C) 2022-2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#ifndef _FILTERS_H\n#define _FILTERS_H 1\n\n#include <complex>\n\nclass NotchFilter {\n   public:\n    NotchFilter(void);\n    NotchFilter(float notch_freq, float sample_freq, float q);\n    void apply(float& value);\n    bool enabled(void) { return enabled_; }\n\n   private:\n    bool enabled_;\n    float e;\n    float p;\n    float d[3];\n    float x[3];\n    float y[3];\n};\n\nclass LowpassFilter {\n   public:\n    LowpassFilter(void);\n    LowpassFilter(float freq, float sample_freq);\n    void apply(float& r, float& j);\n    bool enabled(void) const { return enabled_; }\n\n   private:\n    static std::complex<double> blt(std::complex<double> pz);\n    static void expand(std::complex<double> pz[], int npz, std::complex<double> coeffs[]);\n    static void multin(std::complex<double> w, int npz, std::complex<double> coeffs[]);\n    static std::complex<double> evaluate(std::complex<double> topco[], int nz, std::complex<double> botco[], int np, std::complex<double> z);\n    static std::complex<double> eval(std::complex<double> coeffs[], int npz, std::complex<double> z);\n\n    bool enabled_;\n    float ycoeffs[3];\n    float gain;\n\n    std::complex<float> xv[3];\n    std::complex<float> yv[3];\n};\n\n#endif /* _FILTERS_H */\n"
  },
  {
    "path": "src/generate_signal.cpp",
    "content": "/*\n * generate_signal.cpp\n *\n * Copyright (C) 2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <cmath>\n\n#include \"generate_signal.h\"\n\nusing namespace std;\n\nfloat Tone::WEAK = 0.05;\nfloat Tone::NORMAL = 0.2;\nfloat Tone::STRONG = 0.4;\n\nTone::Tone(int sample_rate, const float& freq, const float& ampl) : sample_rate_(sample_rate), freq_(freq), ampl_(ampl), sample_count_(0) {}\n\nfloat Tone::get_sample(void) {\n    sample_count_++;\n    return ampl_ * sin(2 * M_PI * sample_count_ * freq_ / sample_rate_);\n}\n\nfloat Noise::WEAK = 0.05;\nfloat Noise::NORMAL = 0.2;\nfloat Noise::STRONG = 0.5;\n\nNoise::Noise(const float& ampl) : ampl_(ampl) {\n    // create a seeded generator\n    std::random_device r;\n    std::seed_seq s{r(), r(), r(), r(), r(), r(), r(), r()};\n    generator = std::mt19937(s);\n\n    // centered at 0.0, standard deviation of 0.1\n    distribution = normal_distribution<float>(0.0, 0.1);\n}\nfloat Noise::get_sample(void) {\n    return ampl_ * distribution(generator);\n}\n\nGenerateSignal::GenerateSignal(int sample_rate) : sample_rate_(sample_rate) {}\n\nvoid GenerateSignal::add_tone(const float& freq, const float& ampl) {\n    tones_.push_back(Tone(sample_rate_, freq, ampl));\n}\n\nvoid GenerateSignal::add_noise(const float& ampl) {\n    noises_.push_back(Noise(ampl));\n}\n\nfloat GenerateSignal::get_sample(void) {\n    float value = 0.0;\n\n    for (vector<Tone>::iterator tone = tones_.begin(); tone != tones_.end(); ++tone) {\n        value += tone->get_sample();\n    }\n\n    for (vector<Noise>::iterator noise = noises_.begin(); noise != noises_.end(); ++noise) {\n        value += noise->get_sample();\n    }\n\n    return value;\n}\n\nvoid GenerateSignal::write_file(const string& filepath, const float& seconds) {\n    FILE* fp = fopen(filepath.c_str(), \"wb\");\n\n    for (int i = 0; i < sample_rate_ * seconds; ++i) {\n        float sample = get_sample();\n        fwrite(&sample, sizeof(float), 1, fp);\n    }\n    fclose(fp);\n}\n"
  },
  {
    "path": "src/generate_signal.h",
    "content": "/*\n * generate_signal.h\n *\n * Copyright (C) 2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#ifndef _GENERATE_SIGNAL_H\n#define _GENERATE_SIGNAL_H\n\n#include <random>\n#include <string>\n#include <vector>\n\nclass Tone {\n   public:\n    static float WEAK;\n    static float NORMAL;\n    static float STRONG;\n\n    Tone(int sample_rate, const float& freq, const float& ampl);\n    float get_sample(void);\n\n   private:\n    int sample_rate_;\n    float freq_;\n    float ampl_;\n    size_t sample_count_;\n};\n\nclass Noise {\n   public:\n    static float WEAK;\n    static float NORMAL;\n    static float STRONG;\n\n    Noise(const float& ampl);\n    float get_sample(void);\n\n   private:\n    float ampl_;\n    std::mt19937 generator;\n    std::normal_distribution<float> distribution;\n};\n\nclass GenerateSignal {\n   public:\n    GenerateSignal(int sample_rate);\n\n    void add_tone(const float& freq, const float& ampl);\n    void add_noise(const float& ampl);\n\n    float get_sample(void);\n\n    void write_file(const std::string& filepath, const float& seconds);\n\n   private:\n    int sample_rate_;\n    std::vector<Tone> tones_;\n    std::vector<Noise> noises_;\n};\n\n#endif /* _GENERATE_SIGNAL_H */\n"
  },
  {
    "path": "src/hello_fft/CMakeLists.txt",
    "content": "set(hello_fft_source_files\n\tmailbox.c\n\tgpu_fft.c\n\tgpu_fft_twiddles.c\n\tgpu_fft_shaders.c\n\tgpu_fft_base.c\n)\n# Temp hack due to the fact that mailbox.c includes ../rtl_airband.h which\n# is a C++ header.\nSET_SOURCE_FILES_PROPERTIES(${hello_fft_source_files} PROPERTIES LANGUAGE CXX )\nadd_library(hello_fft OBJECT\n\t${hello_fft_source_files}\n)\ntarget_include_directories(hello_fft PUBLIC\n\t\"..\" # needed for rtl_airband.h\n\t\"${CMAKE_CURRENT_BINARY_DIR}/..\" # needed for config.h\n\t${BCM_VC_INCLUDE_DIRS}\n)\n\n# disable -Wcast-qual for this folder\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wno-cast-qual\")\n"
  },
  {
    "path": "src/hello_fft/gpu_fft.c",
    "content": "/*\nBCM2835 \"GPU_FFT\" release 2.0\nCopyright (c) 2014, Andrew Holme.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the copyright holder nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <string.h>\n\n#include \"gpu_fft.h\"\n\n#define GPU_FFT_BUSY_WAIT_LIMIT (5 << 12)  // ~1ms\n\ntypedef struct GPU_FFT_COMPLEX COMPLEX;\n\nint gpu_fft_prepare(int mb,         // mailbox file_desc\n                    int log2_N,     // log2(FFT_length) = 8...20\n                    int direction,  // GPU_FFT_FWD: fft(); GPU_FFT_REV: ifft()\n                    int jobs,       // number of transforms in batch\n                    struct GPU_FFT** fft) {\n    unsigned info_bytes, twid_bytes, data_bytes, code_bytes, unif_bytes, mail_bytes;\n    unsigned size, *uptr, vc_tw, vc_data;\n    int i, q, shared, unique, passes, ret;\n\n    struct GPU_FFT_BASE* base;\n    struct GPU_FFT_PTR ptr;\n    struct GPU_FFT* info;\n\n    if (gpu_fft_twiddle_size(log2_N, &shared, &unique, &passes))\n        return -2;\n\n    info_bytes = 4096;\n    data_bytes = (1 + ((sizeof(COMPLEX) << log2_N) | 4095));\n    code_bytes = gpu_fft_shader_size(log2_N);\n    twid_bytes = sizeof(COMPLEX) * 16 * (shared + GPU_FFT_QPUS * unique);\n    unif_bytes = sizeof(int) * GPU_FFT_QPUS * (5 + jobs * 2);\n    mail_bytes = sizeof(int) * GPU_FFT_QPUS * 2;\n\n    size = info_bytes +             // header\n           data_bytes * jobs * 2 +  // ping-pong data, aligned\n           code_bytes +             // shader, aligned\n           twid_bytes +             // twiddles\n           unif_bytes +             // uniforms\n           mail_bytes;              // mailbox message\n\n    ret = gpu_fft_alloc(mb, size, &ptr);\n    if (ret)\n        return ret;\n\n    // Header\n    info = (struct GPU_FFT*)ptr.arm.vptr;\n    base = (struct GPU_FFT_BASE*)info;\n    gpu_fft_ptr_inc(&ptr, info_bytes);\n\n    // For transpose\n    info->x = 1 << log2_N;\n    info->y = jobs;\n\n    // Ping-pong buffers leave results in or out of place\n    info->in = info->out = ptr.arm.cptr;\n    info->step = data_bytes / sizeof(COMPLEX);\n    if (passes & 1)\n        info->out += info->step * jobs;  // odd => out of place\n    vc_data = gpu_fft_ptr_inc(&ptr, data_bytes * jobs * 2);\n\n    // Shader code\n    memcpy(ptr.arm.vptr, gpu_fft_shader_code(log2_N), code_bytes);\n    base->vc_code = gpu_fft_ptr_inc(&ptr, code_bytes);\n\n    // Twiddles\n    gpu_fft_twiddle_data(log2_N, direction, ptr.arm.fptr);\n    vc_tw = gpu_fft_ptr_inc(&ptr, twid_bytes);\n\n    uptr = ptr.arm.uptr;\n\n    // Uniforms\n    for (q = 0; q < GPU_FFT_QPUS; q++) {\n        *uptr++ = vc_tw;\n        *uptr++ = vc_tw + sizeof(COMPLEX) * 16 * (shared + q * unique);\n        *uptr++ = q;\n        for (i = 0; i < jobs; i++) {\n            *uptr++ = vc_data + data_bytes * i;\n            *uptr++ = vc_data + data_bytes * i + data_bytes * jobs;\n        }\n        *uptr++ = 0;\n        *uptr++ = (q == 0);  // For mailbox: IRQ enable, master only\n\n        base->vc_unifs[q] = gpu_fft_ptr_inc(&ptr, sizeof(int) * (5 + jobs * 2));\n    }\n\n    if ((jobs << log2_N) <= GPU_FFT_BUSY_WAIT_LIMIT) {\n        // Direct register poking with busy wait\n        base->vc_msg = 0;\n    } else {\n        // Mailbox message\n        for (q = 0; q < GPU_FFT_QPUS; q++) {\n            *uptr++ = base->vc_unifs[q];\n            *uptr++ = base->vc_code;\n        }\n\n        base->vc_msg = ptr.vc;\n    }\n\n    *fft = info;\n    return 0;\n}\n\nunsigned gpu_fft_execute(struct GPU_FFT* info) {\n    return gpu_fft_base_exec(&info->base, GPU_FFT_QPUS);\n}\n\nvoid gpu_fft_release(struct GPU_FFT* info) {\n    gpu_fft_base_release(&info->base);\n}\n"
  },
  {
    "path": "src/hello_fft/gpu_fft.h",
    "content": "/*\nBCM2835 \"GPU_FFT\" release 2.0\nCopyright (c) 2014, Andrew Holme.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the copyright holder nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef __GPU_FFT__\n#define __GPU_FFT__\n\n#define GPU_FFT_QPUS 8\n\n#define GPU_FFT_PI 3.14159265358979323846\n\n#define GPU_FFT_FWD 0  // forward FFT\n#define GPU_FFT_REV 1  // inverse FFT\n\nstruct GPU_FFT_COMPLEX {\n    float re, im;\n};\n\nstruct GPU_FFT_PTR {\n    unsigned vc;\n    union {\n        struct GPU_FFT_COMPLEX* cptr;\n        void* vptr;\n        char* bptr;\n        float* fptr;\n        unsigned* uptr;\n    } arm;\n};\n\nstruct GPU_FFT_BASE {\n    int mb;\n    unsigned handle, size, vc_msg, vc_code, vc_unifs[GPU_FFT_QPUS];\n    volatile unsigned* peri;\n};\n\nstruct GPU_FFT {\n    struct GPU_FFT_BASE base;\n    struct GPU_FFT_COMPLEX *in, *out;\n    int x, y, step;\n};\n\nint gpu_fft_prepare(int mb,         // mailbox file_desc\n                    int log2_N,     // log2(FFT_length) = 8...20\n                    int direction,  // GPU_FFT_FWD: fft(); GPU_FFT_REV: ifft()\n                    int jobs,       // number of transforms in batch\n                    struct GPU_FFT** fft);\n\nunsigned gpu_fft_execute(struct GPU_FFT* info);\n\nvoid gpu_fft_release(struct GPU_FFT* info);\n\n// private\nint gpu_fft_twiddle_size(int, int*, int*, int*);\nvoid gpu_fft_twiddle_data(int, int, float*);\nunsigned int gpu_fft_shader_size(int);\nunsigned int* gpu_fft_shader_code(int);\n\n// gpu_fft_base:\n\nunsigned gpu_fft_base_exec(struct GPU_FFT_BASE* base, unsigned num_qpus);\n\nint gpu_fft_alloc(int mb, unsigned size, struct GPU_FFT_PTR* ptr);\n\nvoid gpu_fft_base_release(struct GPU_FFT_BASE* base);\n\nunsigned gpu_fft_ptr_inc(struct GPU_FFT_PTR* ptr, int bytes);\n\n#endif  // __GPU_FFT__\n"
  },
  {
    "path": "src/hello_fft/gpu_fft.txt",
    "content": "BCM2835 \"GPU_FFT\" release 2.0 by Andrew Holme, 2014.\n\nGPU_FFT is an FFT library for the Raspberry Pi which exploits the BCM2835 SoC\n3D hardware to deliver ten times more data throughput than is possible on the\n700 MHz ARM.  Kernels are provided for all power-of-2 FFT lengths between 256\nand 2,097,152 points inclusive.  A transpose function, which also uses the 3D\nhardware, is provided to support 2-dimensional transforms.\n\n\n*** Accuracy ***\n\nGPU_FFT uses single-precision floats for data and twiddle factors.  The output\nis not scaled.  The relative root-mean-square (rms) error in parts-per-million\n(ppm) for different transform lengths (N) is typically:\n\nlog2(N) |  8    | 9    | 10   |  11   |  12  |  13  |  14  |  15  |  16 |  17\nppm rms |  0.27 | 0.42 | 0.50 |  0.70 |  2.3 |  4.4 |  7.6 |  9.2 |  18 |  70\n\nlog2(N) |  18 |  19 |  20 |  21 |                8...17 batch of 10\nppm rms | 100 | 180 | 360 | 720 |               18...21 batch of  1\n\n\n*** Throughput ***\n\nGPU_FFT 1.0 had to be invoked through a \"mailbox\" which added a 100us overhead\non every call.  To mitigate this, batches of transforms could be submitted via\na single call.  GPU_FFT 2.0 avoids this 100us overhead by poking GPU registers\ndirectly from the ARM if total batch runtime will be short; but still uses the\nmailbox for longer jobs to avoid busy waiting at 100% CPU for too long.\n\nTypical per-transform runtimes for batch sizes of 1 and 10; and comparative\nfigures for FFTW (FFTW_MEASURE mode) are:\n\nlog2(N) |   8   |   9   |  10   |  11   |  12  |  13  |  14  |  15  |\n      1 | 0.036 | 0.051 | 0.070 | 0.11  | 0.24 | 0.58 |  1.2 |  3.3 |\n     10 | 0.016 | 0.027 | 0.045 | 0.095 | 0.25 | 0.61 |  1.2 |  3.2 |\n   FFTW | 0.092 | 0.22  | 0.48  | 0.95  | 3.0  | 5.1  | 12   | 31   |\n\nlog2(N) |  16  |  17 |  18 |  19 |   20 |   21 |       All times in\n      1 |  6.8 |  16 |  42 |  95 |  190 |  380 |       milliseconds\n   FFTW | 83   | 180 | 560 | 670 | 1600 | 3400 |       2 sig. figs.\n\n\n*** API functions ***\n\n    gpu_fft_prepare()       Call once to allocate memory and initialise data\n                            structures.  Returns 0 for success.\n\n    gpu_fft_execute()       Call one or more times to execute a previously\n                            prepared FFT batch.  Returns 0 for success.\n\n    gpu_fft_release()       Call once to release resources after use.\n                            GPU memory is permanently lost if not freed.\n\n\n*** Parameters ***\n\n    int mb          Mailbox file descriptor obtained by calling mbox_open()\n\n    int log2_N      log2(FFT length) = 8 to 21\n\n    int direction   FFT direction:  GPU_FFT_FWD for forward FFT\n                                    GPU_FFT_REV for inverse FFT\n\n    int jobs        Number of transforms in batch = 1 or more\n\n    GPU_FFT **      Output parameter from prepare: control structure.\n    GPU_FFT *       Input parameter to execute and release\n\n\n*** Data format ***\n\nComplex data arrays are stored as alternate real and imaginary parts:\n\n    struct GPU_FFT_COMPLEX {\n        float re, im;\n    };\n\nThe GPU_FFT struct created by gpu_fft_prepare() contains pointers to the input\nand output arrays:\n\n    struct GPU_FFT {\n       struct GPU_FFT_COMPLEX *in, *out;\n\nWhen executing a batch of transforms, buffer pointers are obtained as follows:\n\n    struct GPU_FFT *fft = gpu_fft_prepare( ... , jobs);\n    for (int j=0; j<jobs; j++) {\n       struct GPU_FFT_COMPLEX *in  = fft->in  + j*fft->step;\n       struct GPU_FFT_COMPLEX *out = fft->out + j*fft->step;\n\nGPU_FFT.step is greater than FFT length because a guard space is left between\nbuffers for caching and alignment reasons.\n\nGPU_FFT performs multiple passes between ping-pong buffers.  The final output\nlands in the same buffer as input after an even number of passes.  Transforms\nwhere log2_N=12...16 use an odd number of passes and the final result is left\nout-of-place.  The input data is never preserved.\n\n\n*** Example program ***\n\nThe code that produced the above accuracy and performance figures is included\nas a demo with the latest Raspbian distro.  Build and run it as follows:\n\ncd /opt/vc/src/hello_pi/hello_fft\nmake\nsudo mknod char_dev c 100 0\nsudo ./hello_fft.bin 12\n\nIt accepts three optional command-line arguments: <log2_N> <batch> <loops>\n\nThe special character device is required for the ioctl mailbox through which\nthe ARM communicates with the Videocore GPU.\n\n\n*** With Open GL ***\n\nGPU_FFT and Open GL will run concurrently if the GPU_FFT_MEM_* defines in\nfile gpu_fft.c are changed as follows:\n\n#define GPU_FFT_MEM_FLG 0x4        // cached=0xC; direct=0x4\n#define GPU_FFT_MEM_MAP 0x20000000 // cached=0x0; direct=0x20000000\n\nOverall performance will probably be higher if GPU_FFT and Open GL take turns\nat using the 3D hardware.  Since eglSwapBuffers() returns immediately without\nwaiting for rendering, call glFlush() and glFinish() afterwards as follows:\n\n    for (;;) {\n        ....\n        eglSwapBuffers(....); // non-blocking call returns immediately\n        glFlush();\n        glFinish(); // wait until V3D hardware is idle\n        ....\n        gpu_fft_execute(....); // blocking call\n        ....\n    }\n\n\n*** 2-dimensional FFT ***\n\nPlease study the hello_fft_2d demo source, which is built and executed thus:\n\nmake hello_fft_2d.bin\nsudo ./hello_fft_2d.bin\n\nThis generates a Windows BMP file: \"hello_fft_2d.bmp\"\n\nThe demo uses a square 512x512 array; however, rectangular arrays are allowed.\nThe following lines in gpu_fft_trans.c will do what is safe:\n\n    ptr.arm.uptr[6] = src->x < dst->y? src->x : dst->y;\n    ptr.arm.uptr[7] = src->y < dst->x? src->y : dst->x;\n\nOne may transpose the output from the second FFT pass back into the first pass\ninput buffer, by preparing and executing a second transposition; however, this\nis probably unnecessary.  It depends on how the final output will be accessed.\n"
  },
  {
    "path": "src/hello_fft/gpu_fft_base.c",
    "content": "/*\nBCM2835 \"GPU_FFT\" release 2.0\nCopyright (c) 2014, Andrew Holme.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the copyright holder nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"bcm_host.h\"\n#include \"gpu_fft.h\"\n#include \"mailbox.h\"\n\n#define BUS_TO_PHYS(x) ((x) & ~0xC0000000)\n\n// V3D spec: http://www.broadcom.com/docs/support/videocore/VideoCoreIV-AG100-R.pdf\n#define V3D_L2CACTL (0xC00020 >> 2)\n#define V3D_SLCACTL (0xC00024 >> 2)\n#define V3D_SRQPC (0xC00430 >> 2)\n#define V3D_SRQUA (0xC00434 >> 2)\n#define V3D_SRQCS (0xC0043c >> 2)\n#define V3D_DBCFG (0xC00e00 >> 2)\n#define V3D_DBQITE (0xC00e2c >> 2)\n#define V3D_DBQITC (0xC00e30 >> 2)\n\n#define GPU_FFT_MEM_MAP 0x0  // cached=0x0; direct=0x20000000\n\n#define GPU_FFT_NO_FLUSH 1\n#define GPU_FFT_TIMEOUT 2000  // ms\n\nunsigned gpu_fft_base_exec_direct(struct GPU_FFT_BASE* base, unsigned num_qpus) {\n    unsigned q;\n\n    base->peri[V3D_DBCFG] = 0;    // Disallow IRQ\n    base->peri[V3D_DBQITE] = 0;   // Disable IRQ\n    base->peri[V3D_DBQITC] = -1;  // Resets IRQ flags\n\n    base->peri[V3D_L2CACTL] = 1 << 2;  // Clear L2 cache\n    base->peri[V3D_SLCACTL] = -1;      // Clear other caches\n\n    base->peri[V3D_SRQCS] = (1 << 7) | (1 << 8) | (1 << 16);  // Reset error bit and counts\n\n    for (q = 0; q < num_qpus; q++) {  // Launch shader(s)\n        base->peri[V3D_SRQUA] = base->vc_unifs[q];\n        base->peri[V3D_SRQPC] = base->vc_code;\n    }\n\n    // Busy wait polling\n    for (;;) {\n        if (((base->peri[V3D_SRQCS] >> 16) & 0xff) == num_qpus)\n            break;  // All done?\n    }\n\n    return 0;\n}\n\nunsigned gpu_fft_base_exec(struct GPU_FFT_BASE* base, unsigned num_qpus) {\n    if (base->vc_msg) {\n        // Use mailbox\n        // Returns: 0x0 for success; 0x80000000 for timeout\n        return execute_qpu(base->mb, num_qpus, base->vc_msg, GPU_FFT_NO_FLUSH, GPU_FFT_TIMEOUT);\n    } else {\n        // Direct register poking\n        return gpu_fft_base_exec_direct(base, num_qpus);\n    }\n}\n\nint gpu_fft_alloc(int mb, unsigned size, struct GPU_FFT_PTR* ptr) {\n    struct GPU_FFT_BASE* base;\n    volatile unsigned* peri;\n    unsigned handle;\n\n    if (qpu_enable(mb, 1))\n        return -1;\n\n    // Shared memory : cached=0xC; direct=0x4\n    unsigned mem_flg = bcm_host_get_sdram_address() == 0x40000000 ? 0xC : 0x4;\n    handle = mem_alloc(mb, size, 4096, mem_flg);\n    if (!handle) {\n        qpu_enable(mb, 0);\n        return -3;\n    }\n\n    peri = (volatile unsigned*)mapmem(bcm_host_get_peripheral_address(), bcm_host_get_peripheral_size());\n    if (!peri) {\n        mem_free(mb, handle);\n        qpu_enable(mb, 0);\n        return -4;\n    }\n\n    ptr->vc = mem_lock(mb, handle);\n    ptr->arm.vptr = mapmem(BUS_TO_PHYS(ptr->vc + GPU_FFT_MEM_MAP), size);\n\n    base = (struct GPU_FFT_BASE*)ptr->arm.vptr;\n    base->peri = peri;\n    base->mb = mb;\n    base->handle = handle;\n    base->size = size;\n\n    return 0;\n}\n\nvoid gpu_fft_base_release(struct GPU_FFT_BASE* base) {\n    int mb = base->mb;\n    unsigned handle = base->handle, size = base->size;\n    unmapmem((void*)base->peri, bcm_host_get_peripheral_size());\n    unmapmem((void*)base, size);\n    mem_unlock(mb, handle);\n    mem_free(mb, handle);\n    qpu_enable(mb, 0);\n}\n\nunsigned gpu_fft_ptr_inc(struct GPU_FFT_PTR* ptr, int bytes) {\n    unsigned vc = ptr->vc;\n    ptr->vc += bytes;\n    ptr->arm.bptr += bytes;\n    return vc;\n}\n"
  },
  {
    "path": "src/hello_fft/gpu_fft_shaders.c",
    "content": "/*\nBCM2835 \"GPU_FFT\" release 2.0\nCopyright (c) 2014, Andrew Holme.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the copyright holder nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\nstatic unsigned int shader_256[] = {\n#include \"hex/shader_256.hex\"\n};\nstatic unsigned int shader_512[] = {\n#include \"hex/shader_512.hex\"\n};\nstatic unsigned int shader_1k[] = {\n#include \"hex/shader_1k.hex\"\n};\nstatic unsigned int shader_2k[] = {\n#include \"hex/shader_2k.hex\"\n};\nstatic unsigned int shader_4k[] = {\n#include \"hex/shader_4k.hex\"\n};\nstatic unsigned int shader_8k[] = {\n#include \"hex/shader_8k.hex\"\n};\nstatic unsigned int shader_16k[] = {\n#include \"hex/shader_16k.hex\"\n};\nstatic unsigned int shader_32k[] = {\n#include \"hex/shader_32k.hex\"\n};\nstatic unsigned int shader_64k[] = {\n#include \"hex/shader_64k.hex\"\n};\nstatic unsigned int shader_128k[] = {\n#include \"hex/shader_128k.hex\"\n};\nstatic unsigned int shader_256k[] = {\n#include \"hex/shader_256k.hex\"\n};\nstatic unsigned int shader_512k[] = {\n#include \"hex/shader_512k.hex\"\n};\nstatic unsigned int shader_1024k[] = {\n#include \"hex/shader_1024k.hex\"\n};\nstatic unsigned int shader_2048k[] = {\n#include \"hex/shader_2048k.hex\"\n};\n\nstatic struct {\n    unsigned int size, *code;\n} shaders[] = {{sizeof(shader_256), shader_256},   {sizeof(shader_512), shader_512},   {sizeof(shader_1k), shader_1k},       {sizeof(shader_2k), shader_2k},      {sizeof(shader_4k), shader_4k},\n               {sizeof(shader_8k), shader_8k},     {sizeof(shader_16k), shader_16k},   {sizeof(shader_32k), shader_32k},     {sizeof(shader_64k), shader_64k},    {sizeof(shader_128k), shader_128k},\n               {sizeof(shader_256k), shader_256k}, {sizeof(shader_512k), shader_512k}, {sizeof(shader_1024k), shader_1024k}, {sizeof(shader_2048k), shader_2048k}};\n\nunsigned int gpu_fft_shader_size(int log2_N) {\n    return shaders[log2_N - 8].size;\n}\n\nunsigned int* gpu_fft_shader_code(int log2_N) {\n    return shaders[log2_N - 8].code;\n}\n"
  },
  {
    "path": "src/hello_fft/gpu_fft_trans.h",
    "content": "/*\nBCM2835 \"GPU_FFT\" release 2.0\nCopyright (c) 2014, Andrew Holme.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the copyright holder nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"gpu_fft.h\"\n\nstruct GPU_FFT_TRANS {\n    struct GPU_FFT_BASE base;\n};\n\nint gpu_fft_trans_prepare(int mb, struct GPU_FFT* src, struct GPU_FFT* dst, struct GPU_FFT_TRANS** out);\n\nunsigned gpu_fft_trans_execute(  // src->out ==> T ==> dst->in\n    struct GPU_FFT_TRANS* info);\n\nvoid gpu_fft_trans_release(struct GPU_FFT_TRANS* info);\n"
  },
  {
    "path": "src/hello_fft/gpu_fft_twiddles.c",
    "content": "/*\nBCM2835 \"GPU_FFT\" release 2.0\nCopyright (c) 2014, Andrew Holme.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the copyright holder nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <math.h>\n\n#include \"gpu_fft.h\"\n\n#define ALPHA(dx) (2 * pow(sin((dx) / 2), 2))\n#define BETA(dx) (sin(dx))\n\nstatic double k[16] = {0, 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1};\nstatic double m[16] = {0, 0, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7};\n\n/****************************************************************************/\n\nstatic float* twiddles_base_16(double two_pi, float* out, double theta) {\n    int i;\n    for (i = 0; i < 16; i++) {\n        *out++ = cos(two_pi / 16 * k[i] * m[i] + theta * k[i]);\n        *out++ = sin(two_pi / 16 * k[i] * m[i] + theta * k[i]);\n    }\n    return out;\n}\n\nstatic float* twiddles_base_32(double two_pi, float* out, double theta) {\n    int i;\n    for (i = 0; i < 16; i++) {\n        *out++ = cos(two_pi / 32 * i + theta);\n        *out++ = sin(two_pi / 32 * i + theta);\n    }\n    return twiddles_base_16(two_pi, out, 2 * theta);\n}\n\nstatic float* twiddles_base_64(double two_pi, float* out) {\n    int i;\n    for (i = 0; i < 32; i++) {\n        *out++ = cos(two_pi / 64 * i);\n        *out++ = sin(two_pi / 64 * i);\n    }\n    return twiddles_base_32(two_pi, out, 0);\n}\n\n/****************************************************************************/\n\nstatic float* twiddles_step_16(double /*two_pi*/, float* out, double theta) {\n    int i;\n    for (i = 0; i < 16; i++) {\n        *out++ = ALPHA(theta * k[i]);\n        *out++ = BETA(theta * k[i]);\n    }\n    return out;\n}\n\nstatic float* twiddles_step_32(double two_pi, float* out, double theta) {\n    int i;\n    for (i = 0; i < 16; i++) {\n        *out++ = ALPHA(theta);\n        *out++ = BETA(theta);\n    }\n    return twiddles_step_16(two_pi, out, 2 * theta);\n}\n\n/****************************************************************************/\n\nstatic void twiddles_256(double two_pi, float* out) {\n    double N = 256;\n    int q;\n\n    out = twiddles_base_16(two_pi, out, 0);\n    out = twiddles_step_16(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_16(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_512(double two_pi, float* out) {\n    double N = 512;\n    int q;\n\n    out = twiddles_base_32(two_pi, out, 0);\n    out = twiddles_step_16(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_16(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_1k(double two_pi, float* out) {\n    double N = 1024;\n    int q;\n\n    out = twiddles_base_32(two_pi, out, 0);\n    out = twiddles_step_32(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_32(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_2k(double two_pi, float* out) {\n    double N = 2048;\n    int q;\n\n    out = twiddles_base_64(two_pi, out);\n    out = twiddles_step_32(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_32(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_4k(double two_pi, float* out) {\n    double N = 4096;\n    int q;\n\n    out = twiddles_base_16(two_pi, out, 0);\n    out = twiddles_step_16(two_pi, out, two_pi / N * 16);\n    out = twiddles_step_16(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_16(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_8k(double two_pi, float* out) {\n    double N = 8192;\n    int q;\n\n    out = twiddles_base_32(two_pi, out, 0);\n    out = twiddles_step_16(two_pi, out, two_pi / N * 16);\n    out = twiddles_step_16(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_16(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_16k(double two_pi, float* out) {\n    double N = 16384;\n    int q;\n\n    out = twiddles_base_32(two_pi, out, 0);\n    out = twiddles_step_32(two_pi, out, two_pi / N * 16);\n    out = twiddles_step_16(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_16(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_32k(double two_pi, float* out) {\n    double N = 32768;\n    int q;\n\n    out = twiddles_base_32(two_pi, out, 0);\n    out = twiddles_step_32(two_pi, out, two_pi / N * 32);\n    out = twiddles_step_32(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_32(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_64k(double two_pi, float* out) {\n    double N = 65536;\n    int q;\n\n    out = twiddles_base_64(two_pi, out);\n    out = twiddles_step_32(two_pi, out, two_pi / N * 32);\n    out = twiddles_step_32(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_32(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_128k(double two_pi, float* out) {\n    double N = 128 * 1024;\n    int q;\n\n    out = twiddles_base_32(two_pi, out, 0);\n    out = twiddles_step_16(two_pi, out, two_pi / N * 16 * 16);\n    out = twiddles_step_16(two_pi, out, two_pi / N * 16);\n    out = twiddles_step_16(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_16(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_256k(double two_pi, float* out) {\n    double N = 256 * 1024;\n    int q;\n\n    out = twiddles_base_32(two_pi, out, 0);\n    out = twiddles_step_16(two_pi, out, two_pi / N * 32 * 16);\n    out = twiddles_step_16(two_pi, out, two_pi / N * 32);\n    out = twiddles_step_32(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_32(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_512k(double two_pi, float* out) {\n    double N = 512 * 1024;\n    int q;\n\n    out = twiddles_base_32(two_pi, out, 0);\n    out = twiddles_step_16(two_pi, out, two_pi / N * 32 * 32);\n    out = twiddles_step_32(two_pi, out, two_pi / N * 32);\n    out = twiddles_step_32(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_32(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_1024k(double two_pi, float* out) {\n    double N = 1024 * 1024;\n    int q;\n\n    out = twiddles_base_32(two_pi, out, 0);\n    out = twiddles_step_32(two_pi, out, two_pi / N * 32 * 32);\n    out = twiddles_step_32(two_pi, out, two_pi / N * 32);\n    out = twiddles_step_32(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_32(two_pi, out, two_pi / N * q);\n}\n\nstatic void twiddles_2048k(double two_pi, float* out) {\n    double N = 2048 * 1024;\n    int q;\n\n    out = twiddles_base_64(two_pi, out);\n    out = twiddles_step_32(two_pi, out, two_pi / N * 32 * 32);\n    out = twiddles_step_32(two_pi, out, two_pi / N * 32);\n    out = twiddles_step_32(two_pi, out, two_pi / N * GPU_FFT_QPUS);\n\n    for (q = 0; q < GPU_FFT_QPUS; q++)\n        out = twiddles_base_32(two_pi, out, two_pi / N * q);\n}\n\n/****************************************************************************/\n\nstatic struct {\n    int passes, shared, unique;\n    void (*twiddles)(double, float*);\n} shaders[] = {{2, 2, 1, twiddles_256}, {2, 3, 1, twiddles_512}, {2, 4, 2, twiddles_1k},   {2, 6, 2, twiddles_2k},   {3, 3, 1, twiddles_4k},   {3, 4, 1, twiddles_8k},    {3, 5, 1, twiddles_16k},\n               {3, 6, 2, twiddles_32k}, {3, 8, 2, twiddles_64k}, {4, 5, 1, twiddles_128k}, {4, 6, 2, twiddles_256k}, {4, 7, 2, twiddles_512k}, {4, 8, 2, twiddles_1024k}, {4, 10, 2, twiddles_2048k}};\n\nint gpu_fft_twiddle_size(int log2_N, int* shared, int* unique, int* passes) {\n    if (log2_N < 8 || log2_N > 21)\n        return -1;\n    *shared = shaders[log2_N - 8].shared;\n    *unique = shaders[log2_N - 8].unique;\n    *passes = shaders[log2_N - 8].passes;\n    return 0;\n}\n\nvoid gpu_fft_twiddle_data(int log2_N, int direction, float* out) {\n    shaders[log2_N - 8].twiddles((direction == GPU_FFT_FWD ? -2 : 2) * GPU_FFT_PI, out);\n}\n"
  },
  {
    "path": "src/hello_fft/hex/shader_1024k.hex",
    "content": "0x00000014, 0xe0021227, // mov rb_STAGES,  STAGES\n0x00000010, 0xe00216e7, // mov rb_0x10,    0x10\n0x00000040, 0xe0021727, // mov rb_0x40,    0x40\n0x00000080, 0xe0021767, // mov rb_0x80,    0x80\n0x000000f0, 0xe00217a7, // mov rb_0xF0,    0xF0\n0x00000100, 0xe00217e7, // mov rb_0x100,   0x100\n0x55555555, 0xe0020767, // mov rx_0x55555555, 0x55555555\n0x33333333, 0xe00207a7, // mov rx_0x33333333, 0x33333333\n0x0f0f0f0f, 0xe00207e7, // mov rx_0x0F0F0F0F, 0x0F0F0F0F\n0x00ff00ff, 0xe0021027, // mov rx_0x00FF00FF, 0x00FF00FF\n0x0000ffff, 0xe00216a7, // mov rx_0x0000FFFF, 0x0000FFFF\n0x80904000, 0xe0020727, // mov ra_vdw_32, vdw_setup_0(1, 16, dma_h32( 0,0))\n0x80905000, 0xe0021067, // mov rb_vdw_32, vdw_setup_0(1, 16, dma_h32(32,0))\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020327, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020367, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020427, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020467, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100204a7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021327, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021367, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021427, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021467, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100214a7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100204e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020527, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100214e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021527, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x100246a0, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100246e0, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000002e8, 0xf0f802a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156e7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x15727d80, 0x10020827, // mov r0, ra_vdw_32\n0x8c05cdf6, 0x10024061, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov r1, ra_save_ptr\n0x00000080, 0xe00208a7, // mov r2, vdw_setup_0(1, 16, dma_h32(1,0)) - vdw_setup_0(1, 16, dma_h32(0,0))\n0x00040000, 0xe00208e7, // mov r3, PASS32_STRIDE\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000050, 0xf0f812a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156e7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x156a7d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x000005d8, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x205a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d6039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22096cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x205a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x205e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d7039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22097cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x205e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20627030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d8039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22098cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20627031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20667030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d9039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22099cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20667031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149c01c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149c01c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9db1c0, 0x10020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119db3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c91c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffd78, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149c01c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149c01c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9db1c0, 0x10020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119db3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c91c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffc30, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x20567006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d500f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2056700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22095c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f549e7, // bra -, ra_save_32\n0x95682ff6, 0x10024682, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x956c7ff6, 0x100246c7, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffba0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffb50, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x20567006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d500f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2056700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22095c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f549e7, // bra -, ra_save_32\n0x95682ff6, 0x10024682, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x956c7ff6, 0x100246c7, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159cafc0, 0x100602a7, // mov.ifnz ra_save_32, rx_save_slave_32\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x000008d0, 0xf00809e7, // brr.allz -, r:end\n0x952cbdbf, 0x10024555, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c662, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d663, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149c01c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149c01c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9db1c0, 0x10020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119db3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c91c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffa50, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffffa28, 0xf00809e7, // brr.allz -, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x952cbdbf, 0x10024555, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c662, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d663, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffbf0, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00007fff, 0xe0020827, // mov r0, 0x7FFF\n0x141e7c00, 0x100229e7, // and.setf -, ra_points, r0\n0xfffffbc0, 0xf01809e7, // brr.allnz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100601e7, // add.ifnz ra_points, ra_points, rb_0x100\n0x95555dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x20367016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209cd017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209cd01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x2136709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02567c80, 0x10020567, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d5ec0, 0x10021567, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x95659dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x203a7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209ce017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209ce01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x213a709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02667c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d9ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c662, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d663, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffffab8, 0xf00809e7, // brr.allz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x952cbdbf, 0x10024555, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c662, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d663, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff9b0, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0xfffff990, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0xfffff970, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0xfffff950, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x95555dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x203e7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209cf017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209cf01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x213e709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02567c80, 0x10020567, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d5ec0, 0x10021567, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x95659dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20427016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209d0017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209d001f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2142709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02667c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d9ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c662, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d663, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff848, 0xf00809e7, // brr.allz -, r:pass_3\n0x00000060, 0xe0020827, // mov r0, 3*4*8\n0x0d227c00, 0x10020227, // sub ra_link_1, ra_link_1, r0\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x954d3dbf, 0x10024555, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x95514dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c662, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d663, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff740, 0xf0f80227, // brr ra_link_1, r:pass_4\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x95555dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x20467016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209d1017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209d101f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x2146709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02567c80, 0x10020567, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d5ec0, 0x10021567, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x95659dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x204a7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209d2017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209d201f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x214a709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02667c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d9ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c662, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d663, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff638, 0xf00809e7, // brr.allz -, r:pass_4\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffff700, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_128k.hex",
    "content": "0x00000011, 0xe0021227, // mov rb_STAGES,  STAGES\n0x00000010, 0xe00216a7, // mov rb_0x10,    0x10\n0x00000040, 0xe00216e7, // mov rb_0x40,    0x40\n0x00000080, 0xe0021727, // mov rb_0x80,    0x80\n0x000000f0, 0xe0021767, // mov rb_0xF0,    0xF0\n0x00000100, 0xe00217a7, // mov rb_0x100,   0x100\n0x00000fff, 0xe00217e7, // mov rb_0xFFF,   0xFFF\n0x55555555, 0xe0020767, // mov rx_0x55555555, 0x55555555\n0x33333333, 0xe00207a7, // mov rx_0x33333333, 0x33333333\n0x0f0f0f0f, 0xe00207e7, // mov rx_0x0F0F0F0F, 0x0F0F0F0F\n0x00ff00ff, 0xe0021627, // mov rx_0x00FF00FF, 0x00FF00FF\n0x0000ffff, 0xe0021667, // mov rx_0x0000FFFF, 0x0000FFFF\n0x88104000, 0xe00206e7, // mov ra_vdw_16, vdw_setup_0(16, 16, dma_h32( 0,0))\n0x88105000, 0xe0021027, // mov rb_vdw_16, vdw_setup_0(16, 16, dma_h32(32,0))\n0x90104000, 0xe0020727, // mov ra_vdw_32, vdw_setup_0(32, 16, dma_h32( 0,0))\n0x90105000, 0xe0021067, // mov rb_vdw_32, vdw_setup_0(32, 16, dma_h32(32,0))\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020327, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020367, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203e7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021327, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021367, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213e7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020427, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021427, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x10024660, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100246a0, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000000b0, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x156e7d80, 0x10021c67, // mov vw_setup, arg_vdw\n0xc000ffc0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS16_STRIDE-16*4\n0x8c05bdf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000038, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10020c67, // mov vr_setup, arg_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x000000c8, 0xf0f802a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x15727d80, 0x10021c67, // mov vw_setup, ra_vdw_32\n0xc0007fc0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS32_STRIDE-16*4\n0x8c05bdf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000050, 0xf0f812a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000560, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x204a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d2039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22092cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x204a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x204e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d3039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22093cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x204e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20527030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d4039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22094cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20527031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20567030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d5039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22095cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20567031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d81c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149d81c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d91c0, 0x10020867, // and r1, r0, mask\n0x0e9da1c0, 0x10020827, // shr r0, r0, shift\n0x149d91c0, 0x10020827, // and r0, r0, mask\n0x119da3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9cc1c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffd78, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15adf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d81c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149d81c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d91c0, 0x10020867, // and r1, r0, mask\n0x0e9da1c0, 0x10020827, // shr r0, r0, shift\n0x149d91c0, 0x10020827, // and r0, r0, mask\n0x119da3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9cc1c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffc30, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x20467006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d100f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2046700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22091c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f549e7, // bra -, ra_save_32\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95687ff6, 0x10024687, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffba0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x00000000, 0xf0f489e7, // bra -, ra_save_16\n0x009e7000, 0x100009e7, // nop\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x956c0ff6, 0x100246c0, // mov ra_vdw_16, rb_vdw_16; mov rb_vdw_16, ra_vdw_16\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_16, rx_save_slave_16\n0x159cafc0, 0x100602a7, // mov.ifnz ra_save_32, rx_save_slave_32\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x000007b0, 0xf00809e7, // brr.allz -, r:end\n0x952cbdbf, 0x10024451, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15adf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d81c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149d81c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d91c0, 0x10020867, // and r1, r0, mask\n0x0e9da1c0, 0x10020827, // shr r0, r0, shift\n0x149d91c0, 0x10020827, // and r0, r0, mask\n0x119da3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9cc1c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffac0, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dedc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffffa98, 0xf00809e7, // brr.allz -, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dedc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffc68, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x141dfdc0, 0x100229e7, // and.setf -, ra_points, rb_0xFFF\n0xfffffc40, 0xf01809e7, // brr.allnz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100601e7, // add.ifnz ra_points, ra_points, rb_0x80\n0x95555dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20367016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209cd017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209cd01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2136709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02567c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d5ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffffb78, 0xf00809e7, // brr.allz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffa78, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0xfffffa58, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x95555dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x203a7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209ce017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209ce01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x213a709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02567c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d5ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff990, 0xf00809e7, // brr.allz -, r:pass_3\n0x00000020, 0xe0020827, // mov r0, 4*8\n0x0d227c00, 0x10020227, // sub ra_link_1, ra_link_1, r0\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x95410dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff890, 0xf0f80227, // brr ra_link_1, r:pass_4\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x95555dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x203e7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209cf017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209cf01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x213e709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02567c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d5ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff7c8, 0xf00809e7, // brr.allz -, r:pass_4\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffff820, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_16k.hex",
    "content": "0x00000010, 0xe00216e7, // mov rb_0x10,    0x10\n0x00000040, 0xe0021727, // mov rb_0x40,    0x40\n0x00000080, 0xe0021767, // mov rb_0x80,    0x80\n0x000000f0, 0xe00217a7, // mov rb_0xF0,    0xF0\n0x00000100, 0xe00217e7, // mov rb_0x100,   0x100\n0x00005555, 0xe0020767, // mov rx_0x5555,  0x5555\n0x00003333, 0xe00207a7, // mov rx_0x3333,  0x3333\n0x00000f0f, 0xe00207e7, // mov rx_0x0F0F,  0x0F0F\n0x000000ff, 0xe00216a7, // mov rx_0x00FF,  0x00FF\n0x88104000, 0xe00206e7, // mov ra_vdw_16, vdw_setup_0(16, 16, dma_h32( 0,0))\n0x88105000, 0xe0021027, // mov rb_vdw_16, vdw_setup_0(16, 16, dma_h32(32,0))\n0x90104000, 0xe0020727, // mov ra_vdw_32, vdw_setup_0(32, 16, dma_h32( 0,0))\n0x90105000, 0xe0021067, // mov rb_vdw_32, vdw_setup_0(32, 16, dma_h32(32,0))\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020327, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020367, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203e7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021327, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021367, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213e7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020427, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021427, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x10024660, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100246a0, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000000b0, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x156e7d80, 0x10021c67, // mov vw_setup, arg_vdw\n0xc0001fc0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS16_STRIDE-16*4\n0x8c05cdf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000038, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10020c67, // mov vr_setup, arg_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x000000c8, 0xf0f802a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x15727d80, 0x10021c67, // mov vw_setup, ra_vdw_32\n0xc0000fc0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS32_STRIDE-16*4\n0x8c05cdf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000050, 0xf0f812a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x000005f0, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x204a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d2039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22092cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x204a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x204e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d3039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22093cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x204e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20527030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d4039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22094cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20527031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20567030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d5039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22095cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20567031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c11c0, 0xd0020827, // shl r0, r0, STAGES-13\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffda0, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c11c0, 0xd0020827, // shl r0, r0, STAGES-13\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffc80, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x20467006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d100f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2046700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22091c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f549e7, // bra -, ra_save_32\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95687ff6, 0x10024687, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffbf0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffba0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x20467006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d100f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2046700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22091c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f549e7, // bra -, ra_save_32\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95687ff6, 0x10024687, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffb10, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x00000000, 0xf0f489e7, // bra -, ra_save_16\n0x009e7000, 0x100009e7, // nop\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x956c0ff6, 0x100246c0, // mov ra_vdw_16, rb_vdw_16; mov rb_vdw_16, ra_vdw_16\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_16, rx_save_slave_16\n0x159cafc0, 0x100602a7, // mov.ifnz ra_save_32, rx_save_slave_32\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x000005e0, 0xf00809e7, // brr.allz -, r:end\n0x952cbdbf, 0x10024451, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c11c0, 0xd0020827, // shl r0, r0, STAGES-13\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffa58, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x0e1cedc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffa30, 0xf00809e7, // brr.allz -, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x952cbdbf, 0x10024451, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffba8, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0xfffffb88, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x95451dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x20367016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209cd017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209cd01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x2136709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02467c80, 0x10020467, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d1ec0, 0x10021467, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x95555dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x203a7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209ce017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209ce01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x213a709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02567c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d5ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1cedc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffa80, 0xf00809e7, // brr.allz -, r:pass_2\n0x00000020, 0xe0020827, // mov r0, 4*8\n0x0d227c00, 0x10020227, // sub ra_link_1, ra_link_1, r0\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x95410dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffa60, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dddc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x95555dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x203e7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209cf017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209cf01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x213e709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02567c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d5ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1cedc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffff998, 0xf00809e7, // brr.allz -, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dddc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffff9f0, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_1k.hex",
    "content": "0x00000010, 0xe00216e7, // mov rb_0x10,    0x10\n0x00000040, 0xe0021727, // mov rb_0x40,    0x40\n0x000000f0, 0xe0021767, // mov rb_0xF0,    0xF0\n0x00005555, 0xe00207a7, // mov rx_0x5555,  0x5555\n0x00003333, 0xe00217a7, // mov rx_0x3333,  0x3333\n0x00000f0f, 0xe00207e7, // mov rx_0x0F0F,  0x0F0F\n0x000000ff, 0xe00217e7, // mov rx_0x00FF,  0x00FF\n0x90104000, 0xe0020767, // mov ra_vdw_32, vdw_setup_0(32, 16, dma_h32( 0,0))\n0x90105000, 0xe0021067, // mov rb_vdw_32, vdw_setup_0(32, 16, dma_h32(32,0))\n0x00000080, 0xe00208e7, // mov r3, 0x80\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020327, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020367, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021327, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021367, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203e7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213e7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x100246e0, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x10024720, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000000c8, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x156e7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x15727d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x15767d80, 0x10021c67, // mov vw_setup, ra_vdw_32\n0xc00000c0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS32_STRIDE-16*4\n0x8c05cdf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000050, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x156e7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x15727d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x156e7d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000588, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20467030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d1039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22091cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20467031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x204a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d2039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22092cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x204a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x204e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d3039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22093cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x204e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20527030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d4039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22094cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20527031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149de1c0, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149de1c0, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149df1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149df1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c31c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffda0, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149de1c0, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149de1c0, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149df1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149df1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c31c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffc80, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x20427006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d000f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2042700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22090c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f489e7, // bra -, ra_save_32\n0x956c2ff6, 0x100246c2, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95707ff6, 0x10024707, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95741ff6, 0x10024741, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffbf0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffba0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x20427006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d000f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2042700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22090c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f489e7, // bra -, ra_save_32\n0x956c2ff6, 0x100246c2, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95707ff6, 0x10024707, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95741ff6, 0x10024741, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_32, rx_save_slave_32\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x000003f8, 0xf00809e7, // brr.allz -, r:end\n0x9528adbf, 0x10024410, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x952cbdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c462, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d463, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149de1c0, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149de1c0, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149df1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149df1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c31c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffac8, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x0e1cadc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffaa0, 0xf00809e7, // brr.allz -, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x9538edbf, 0x10024410, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x953cfdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c462, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d463, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffc18, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x95410dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x20327016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209cc017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209cc01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x2132709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02427c80, 0x10020427, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d0ec0, 0x10021427, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x95514dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20367016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209cd017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209cd01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2136709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02527c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d4ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c462, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d463, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1cadc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffb10, 0xf00809e7, // brr.allz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffffbd8, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_2048k.hex",
    "content": "0x00000010, 0xe0021227, // mov rb_0x10,    0x10\n0x000001d0, 0xe0021967, // mov r5rep,      0x1D0\n0x00000080, 0xe00208e7, // mov r3, 0x80\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020427, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020467, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100204a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100204e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020527, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020567, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100205a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100205e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020627, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021427, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021467, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100214a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100214e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021527, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021567, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100215a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100215e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021627, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020667, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100206a7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021667, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100216a7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x10025020, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x10025060, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000002e8, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x152e7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x15327d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x153a7d80, 0x10020827, // mov r0, ra_vdw_32\n0x8c04ddf6, 0x10024061, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov r1, ra_save_ptr\n0x00000080, 0xe00208a7, // mov r2, vdw_setup_0(1, 16, dma_h32(1,0)) - vdw_setup_0(1, 16, dma_h32(0,0))\n0x00080000, 0xe00208e7, // mov r3, PASS32_STRIDE\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000050, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x152e7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x15327d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x152e7d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000520, 0xf0f802a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x159c0fc0, 0x10021c67, // mov vw_setup, rb_vpm\n0x012cbdc0, 0x10020c27, // fadd vpm, ra_64+0, rb_64+0\n0x0130cdc0, 0x10020c27, // fadd vpm, ra_64+1, rb_64+1\n0x159c1fc0, 0x10021c67, // mov vw_setup, rb_vpm_16\n0x0134ddc0, 0x10020c27, // fadd vpm, ra_64+2, rb_64+2\n0x0138edc0, 0x10020c27, // fadd vpm, ra_64+3, rb_64+3\n0x159c2fc0, 0x10021c67, // mov vw_setup, rb_vpm_32\n0x022cbdc0, 0x10020c27, // fsub vpm, ra_64+0, rb_64+0\n0x0230cdc0, 0x10020c27, // fsub vpm, ra_64+1, rb_64+1\n0x159c7fc0, 0x10021c67, // mov vw_setup, rb_vpm_48\n0x0234ddc0, 0x10020c27, // fsub vpm, ra_64+2, rb_64+2\n0x0238edc0, 0x10020c27, // fsub vpm, ra_64+3, rb_64+3\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x80904000, 0xe0020827, // mov r0, vdw_setup_0(1, 16, dma_h32(0,0))\n0x00000040, 0xe0020867, // mov r1, 0x40\n0x8c067c76, 0x10024061, // add ra_save_ptr, ra_save_ptr, r1; mov r1, ra_save_ptr\n0x00000080, 0xe00208a7, // mov r2, vdw_setup_0(1, 16, dma_h32(1,0)) - vdw_setup_0(1, 16, dma_h32(0,0))\n0x00040000, 0xe00208e7, // mov r3, PASS64_STRIDE\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x000002b8, 0xf0f812a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd00200a7, // shl ra_temp, r0, 5\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0fc49e7, // brr -, ra_temp\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x000000e0, 0xf0f809e7, // brr -, r:2f\n0x00000010, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x000000c0, 0xf0f809e7, // brr -, r:2f\n0x00000011, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x000000a0, 0xf0f809e7, // brr -, r:2f\n0x00000012, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000080, 0xf0f809e7, // brr -, r:2f\n0x00000013, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000060, 0xf0f809e7, // brr -, r:2f\n0x00000014, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000040, 0xf0f809e7, // brr -, r:2f\n0x00000015, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000020, 0xf0f809e7, // brr -, r:2f\n0x00000016, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f809e7, // brr -, r:2f\n0x00000017, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c0fc0, 0x10021c67, // mov vw_setup, rb_vpm\n0x012cbdc0, 0x10020c27, // fadd vpm, ra_64+0, rb_64+0\n0x0130cdc0, 0x10020c27, // fadd vpm, ra_64+1, rb_64+1\n0x159c1fc0, 0x10021c67, // mov vw_setup, rb_vpm_16\n0x0134ddc0, 0x10020c27, // fadd vpm, ra_64+2, rb_64+2\n0x0138edc0, 0x10020c27, // fadd vpm, ra_64+3, rb_64+3\n0x159c2fc0, 0x10021c67, // mov vw_setup, rb_vpm_32\n0x022cbdc0, 0x10020c27, // fsub vpm, ra_64+0, rb_64+0\n0x0230cdc0, 0x10020c27, // fsub vpm, ra_64+1, rb_64+1\n0x159c7fc0, 0x10021c67, // mov vw_setup, rb_vpm_48\n0x0234ddc0, 0x10020c27, // fsub vpm, ra_64+2, rb_64+2\n0x0238edc0, 0x10020c27, // fsub vpm, ra_64+3, rb_64+3\n0x00000000, 0xf0fc49e7, // brr -, ra_temp\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000008, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000009, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000a, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000b, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000c, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000d, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000e, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000f, 0xe80009e7, // mov -, srel(i+8)\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000998, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20727030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209dc039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2209ccb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20727031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20767030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209dd039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2209dcb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20767031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x207a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209de039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2209ecb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x207a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x207e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209df039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2209fcb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x207e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x55555555, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x33333333, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0f0f0f0f, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x00ff00ff, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0000ffff, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c81c0, 0x10020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c83c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c81c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffd50, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x55555555, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x33333333, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0f0f0f0f, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x00ff00ff, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0000ffff, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c81c0, 0x10020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c83c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c81c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffbe0, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x206e7006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209db00f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x206e700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x2209bc87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x01267c00, 0x100202e7, // fadd ra_64+0, ra_32_re, r0\n0x019c9e40, 0x10020327, // fadd ra_64+1, rb_32_im, r1\n0x02267c00, 0x10020367, // fsub ra_64+2, ra_32_re, r0\n0x029c9e40, 0x100203a7, // fsub ra_64+3, rb_32_im, r1\n0x8c167d76, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x55555555, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x33333333, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0f0f0f0f, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x00ff00ff, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0000ffff, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c81c0, 0x10020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c83c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c81c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffa30, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x55555555, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x33333333, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0f0f0f0f, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x00ff00ff, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0000ffff, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c81c0, 0x10020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c83c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c81c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffff8c0, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x206e7006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209db00f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x206e700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x2209bc87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x029c9e40, 0x100208e7, // fsub r3, rb_32_im, r1\n0x02267c00, 0x100208a7, // fsub r2, ra_32_re, r0\n0x019c9e40, 0x10020867, // fadd r1, rb_32_im, r1\n0x01267c00, 0x10020827, // fadd r0, ra_32_re, r0\n0x203e700e, 0x100049c9, // nop;                        fmul rb_32_im, r1, ra_tw_re+TW64_P1_BASE0\n0x209cf00f, 0x100059c9, // nop;                        fmul ra_32_re, r1, rb_tw_im+TW64_P1_BASE0\n0x209cf007, 0x100049e1, // nop;                        fmul r1,       r0, rb_tw_im+TW64_P1_BASE0\n0x213c93c6, 0x10025320, // fadd rb_64+1, r1, rb_32_im; fmul r0,       r0, ra_tw_re+TW64_P1_BASE0\n0x2225019f, 0x100252c9, // fsub rb_64+0, r0, ra_32_re; fmul ra_32_re, r3, rb_tw_im+TW64_P1_BASE1\n0x2042701e, 0x100049c9, // nop;                        fmul rb_32_im, r3, ra_tw_re+TW64_P1_BASE1\n0x00000000, 0xf0f549e7, // bra -, ra_save_64\n0x209d0017, 0x100049e3, // nop;                        fmul r3,       r2, rb_tw_im+TW64_P1_BASE1\n0x214097d6, 0x100253a2, // fadd rb_64+3, r3, rb_32_im; fmul r2,       r2, ra_tw_re+TW64_P1_BASE1\n0x02267580, 0x10021367, // fsub rb_64+2, r2, ra_32_re\n0x8c14cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff7e0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff790, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x206e7006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209db00f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x206e700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x2209bc87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f489e7, // bra -, ra_save_32\n0x952c2ff6, 0x100242c2, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95307ff6, 0x10024307, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x9538eff6, 0x1002438e, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_32, rx_save_slave_32\n0x159cafc0, 0x100602a7, // mov.ifnz ra_save_64, rx_save_slave_64\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x00000940, 0xf00809e7, // brr.allz -, r:end\n0x95451dbf, 0x100246db, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x95492dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c7e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d7e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c7a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d7a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c61c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x55555555, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x33333333, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0f0f0f0f, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x00ff00ff, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0000ffff, 0xe00208a7, // mov r2, mask\n0x149e7080, 0x10020867, // and r1, r0, r2\n0x0e9c81c0, 0x10020827, // shr r0, r0, shift\n0x149e7080, 0x10020827, // and r0, r0, r2\n0x119c83c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c81c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff660, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x00000200, 0xe0020827, // mov r0, 0x200\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000015, 0xe0020867, // mov r1, STAGES\n0x0e1e7c40, 0x100229e7, // shr.setf -, ra_points, r1\n0xfffff630, 0xf00809e7, // brr.allz -, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x00000200, 0xe0020827, // mov r0, 0x200\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x159c0fc0, 0x100202e7, // mov ra_vpm_lo, rb_vpm\n0x159c1fc0, 0x10020327, // mov ra_vpm_hi, rb_vpm_16\n0x80904000, 0xe00203a7, // mov ra_vdw_32, vdw_setup_0(1, 16, dma_h32( 0,0))\n0x80905000, 0xe00213a7, // mov rb_vdw_32, vdw_setup_0(1, 16, dma_h32(32,0))\n0x00000015, 0xe00212e7, // mov rb_STAGES, STAGES\n0x000000f0, 0xe0021327, // mov rb_0xF0, 0xF0\n0x00000040, 0xe0021367, // mov rb_0x40, 0x40\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x95451dbf, 0x100246db, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x95492dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c7e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d7e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c7a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d7a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffb80, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00007fff, 0xe0020827, // mov r0, 0x7FFF\n0x141e7c00, 0x100229e7, // and.setf -, ra_points, r0\n0xfffffb50, 0xf01809e7, // brr.allnz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100601e7, // add.ifnz ra_points, ra_points, r0\n0x956dbdbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x204e7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209d3017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209d301f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x214e709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x026e7c80, 0x100206e7, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029dbec0, 0x100216e7, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x957dfdbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20527016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209d4017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209d401f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2152709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x027e7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029dfec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c7e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d7e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c7a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d7a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1cbdc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffffa48, 0xf00809e7, // brr.allz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x95451dbf, 0x100246db, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x95492dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c7e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d7e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c7a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d7a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff940, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0xfffff920, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0xfffff900, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0xfffff8e0, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x956dbdbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x20567016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209d5017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209d501f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x2156709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x026e7c80, 0x100206e7, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029dbec0, 0x100216e7, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x957dfdbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x205a7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209d6017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209d601f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x215a709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x027e7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029dfec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c7e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d7e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c7a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d7a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1cbdc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0x00000100, 0xe0020827, // mov r0, 0x100\n0xfffff7d0, 0xf00809e7, // brr.allz -, r:pass_3\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000060, 0xe0020827, // mov r0, (4-1)*4*8\n0x0d227c00, 0x10020227, // sub ra_link_1, ra_link_1, r0\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x95659dbf, 0x100246db, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9569adbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c7e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d7e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c7a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d7a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff6c8, 0xf0f80227, // brr ra_link_1, r:pass_4\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x956dbdbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x205e7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209d7017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209d701f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x215e709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x026e7c80, 0x100206e7, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029dbec0, 0x100216e7, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x957dfdbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20627016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209d8017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209d801f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2162709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x027e7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029dfec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c7e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d7e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c7a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d7a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1cbdc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff5c0, 0xf00809e7, // brr.allz -, r:pass_4\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffff690, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_256.hex",
    "content": "0x00000040, 0xe00217a7, // mov rb_0x40,    0x40\n0x00000080, 0xe00217e7, // mov rb_0x80,    0x80\n0x00005555, 0xe0020767, // mov rx_0x5555,  0x5555\n0x00003333, 0xe00207a7, // mov rx_0x3333,  0x3333\n0x00000f0f, 0xe00207e7, // mov rx_0x0F0F,  0x0F0F\n0x88104000, 0xe0020727, // mov ra_vdw, vdw_setup_0(16, 16, dma_h32( 0,0))\n0x88104800, 0xe0021727, // mov rb_vdw, vdw_setup_0(16, 16, dma_h32(16,0))\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9df1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020227, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9df1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020267, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9df3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021227, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9df3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021267, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9df1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202a7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9df3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212a7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x100246e0, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100256e0, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100049e0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100009e7, // add out_3, r0, r2\n0x000000b0, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x156e7d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x15727d80, 0x10021c67, // mov vw_setup, arg_vdw\n0xc0000040, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS16_STRIDE-16*4\n0x8c05edf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000038, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x156e7d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x156e7d80, 0x10020c67, // mov vr_setup, arg_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000248, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x202e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209cb039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2208bcb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x202e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20327030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209cc039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2208ccb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20327031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20367030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209cd039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2208dcb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20367031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x203a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209ce039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2208ecb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x203a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f489e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0xfffffe98, 0xf0f809e7, // brr -, r:fft_16\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_16, rx_save_slave_16\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x00000420, 0xf00809e7, // brr.allz -, r:end\n0x95208dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c3a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d3a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c362, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d363, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c322, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d323, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c2e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d2e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15fdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x8c15fdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffdb0, 0xf0f80027, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x956dbff6, 0x100246db, // mov ra_vpm, rb_vpm; mov rb_vpm, ra_vpm\n0x9571cff6, 0x1002471c, // mov ra_vdw, rb_vdw; mov rb_vdw, ra_vdw\n0xfffffd90, 0xf0f80027, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x956dbff6, 0x100246db, // mov ra_vpm, rb_vpm; mov rb_vpm, ra_vpm\n0x9571cff6, 0x1002471c, // mov ra_vdw, rb_vdw; mov rb_vdw, ra_vdw\n0x00000000, 0xf0f4c027, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x9528adbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c3a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d3a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c362, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d363, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c322, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d323, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c2e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d2e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15fdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x8c15fdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffc68, 0xf0f80027, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x956dbff6, 0x100246db, // mov ra_vpm, rb_vpm; mov rb_vpm, ra_vpm\n0x9571cff6, 0x1002471c, // mov ra_vdw, rb_vdw; mov rb_vdw, ra_vdw\n0x9538edbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20267016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209c9017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209c901f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2126709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x023a7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029ceec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c3a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d3a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c362, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d363, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c322, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d323, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c2e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d2e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0xfffffba8, 0xf0f80027, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x956dbff6, 0x100246db, // mov ra_vpm, rb_vpm; mov rb_vpm, ra_vpm\n0x9571cff6, 0x1002471c, // mov ra_vdw, rb_vdw; mov rb_vdw, ra_vdw\n0x00000000, 0xf0f4c027, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0xfffffbb0, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_256k.hex",
    "content": "0x00000012, 0xe0021227, // mov rb_STAGES,  STAGES\n0x00000010, 0xe00216a7, // mov rb_0x10,    0x10\n0x00000040, 0xe00216e7, // mov rb_0x40,    0x40\n0x00000080, 0xe0021727, // mov rb_0x80,    0x80\n0x000000f0, 0xe0021767, // mov rb_0xF0,    0xF0\n0x00000100, 0xe00217a7, // mov rb_0x100,   0x100\n0x00001fff, 0xe00217e7, // mov rb_0x1FFF,  0x1FFF\n0x55555555, 0xe0020767, // mov rx_0x55555555, 0x55555555\n0x33333333, 0xe00207a7, // mov rx_0x33333333, 0x33333333\n0x0f0f0f0f, 0xe00207e7, // mov rx_0x0F0F0F0F, 0x0F0F0F0F\n0x00ff00ff, 0xe0021627, // mov rx_0x00FF00FF, 0x00FF00FF\n0x0000ffff, 0xe0021667, // mov rx_0x0000FFFF, 0x0000FFFF\n0x80904000, 0xe00206e7, // mov ra_vdw_16, vdw_setup_0( 1, 16, dma_h32( 0,0))\n0x80905000, 0xe0021027, // mov rb_vdw_16, vdw_setup_0( 1, 16, dma_h32(32,0))\n0x90104000, 0xe0020727, // mov ra_vdw_32, vdw_setup_0(32, 16, dma_h32( 0,0))\n0x90105000, 0xe0021067, // mov rb_vdw_32, vdw_setup_0(32, 16, dma_h32(32,0))\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020327, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020367, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020427, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021327, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021367, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021427, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020467, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dc1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100204a7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021467, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dc3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100214a7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x10024660, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100246a0, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000001d0, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x156e7d80, 0x10020827, // mov r0, arg_vdw\n0x8c05bdf6, 0x10024061, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov r1, ra_save_ptr\n0x00000080, 0xe00208a7, // mov r2, vdw_setup_0(1, 16, dma_h32(1,0)) - vdw_setup_0(1, 16, dma_h32(0,0))\n0x00020000, 0xe00208e7, // mov r3, PASS16_STRIDE\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000038, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10020c67, // mov vr_setup, arg_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x000000c8, 0xf0f802a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x15727d80, 0x10021c67, // mov vw_setup, ra_vdw_32\n0xc000ffc0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS32_STRIDE-16*4\n0x8c05bdf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000050, 0xf0f812a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000640, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20527030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d4039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22094cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20527031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20567030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d5039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22095cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20567031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x205a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d6039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22096cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x205a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x205e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d7039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22097cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x205e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d81c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149d81c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d91c0, 0x10020867, // and r1, r0, mask\n0x0e9da1c0, 0x10020827, // shr r0, r0, shift\n0x149d91c0, 0x10020827, // and r0, r0, mask\n0x119da3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9cb1c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffd78, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15adf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d81c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149d81c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d91c0, 0x10020867, // and r1, r0, mask\n0x0e9da1c0, 0x10020827, // shr r0, r0, shift\n0x149d91c0, 0x10020827, // and r0, r0, mask\n0x119da3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9cb1c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffc30, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x204e7006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d300f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x204e700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22093c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f549e7, // bra -, ra_save_32\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95687ff6, 0x10024687, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffba0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x00000000, 0xf0f489e7, // bra -, ra_save_16\n0x009e7000, 0x100009e7, // nop\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x956c0ff6, 0x100246c0, // mov ra_vdw_16, rb_vdw_16; mov rb_vdw_16, ra_vdw_16\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffb38, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15adf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffae8, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x204e7006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d300f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x204e700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22093c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f549e7, // bra -, ra_save_32\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95687ff6, 0x10024687, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_16, rx_save_slave_16\n0x159cafc0, 0x100602a7, // mov.ifnz ra_save_32, rx_save_slave_32\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x00000838, 0xf00809e7, // brr.allz -, r:end\n0x952cbdbf, 0x100244d3, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15adf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d81c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149d81c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d91c0, 0x10020867, // and r1, r0, mask\n0x0e9da1c0, 0x10020827, // shr r0, r0, shift\n0x149d91c0, 0x10020827, // and r0, r0, mask\n0x119da3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9cb1c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff9e0, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dedc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff9b8, 0xf00809e7, // brr.allz -, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dedc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffb88, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x141dfdc0, 0x100229e7, // and.setf -, ra_points, rb_0x1FFF\n0xfffffb60, 0xf01809e7, // brr.allnz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100601e7, // add.ifnz ra_points, ra_points, rb_0x80\n0x955d7dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20367016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209cd017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209cd01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2136709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x025e7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d7ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffffa98, 0xf00809e7, // brr.allz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff998, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0xfffff978, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0xfffff958, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0xfffff938, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x955d7dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x203a7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209ce017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209ce01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x213a709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x025e7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d7ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff870, 0xf00809e7, // brr.allz -, r:pass_3\n0x00000060, 0xe0020827, // mov r0, 3*4*8\n0x0d227c00, 0x10020227, // sub ra_link_1, ra_link_1, r0\n0x0c1dcdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x95451dbf, 0x100244d3, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x95492dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15adf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff7d0, 0xf0f80227, // brr ra_link_1, r:pass_4\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dedc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x954d3dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x203e7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209cf017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209cf01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x213e709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x024e7c80, 0x100204e7, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d3ec0, 0x100214e7, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x955d7dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20427016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209d0017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209d001f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2142709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x025e7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d7ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff6c8, 0xf00809e7, // brr.allz -, r:pass_4\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dedc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffff798, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_2k.hex",
    "content": "0x00000010, 0xe0021727, // mov rb_0x10,    0x10\n0x00000040, 0xe0021767, // mov rb_0x40,    0x40\n0x000000f0, 0xe00217a7, // mov rb_0xF0,    0xF0\n0x000001d0, 0xe00217e7, // mov rb_0x1D0,   0x1D0\n0x00005555, 0xe0020727, // mov rx_0x5555,  0x5555\n0x00003333, 0xe0020767, // mov rx_0x3333,  0x3333\n0x00000f0f, 0xe00207a7, // mov rx_0x0F0F,  0x0F0F\n0x000000ff, 0xe00207e7, // mov rx_0x00FF,  0x00FF\n0x00000080, 0xe00208e7, // mov r3, 0x80\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020427, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020467, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100204a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100204e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020527, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021427, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021467, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100214a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100214e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021527, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020567, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100205a7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021567, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100215a7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x10025020, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x10025060, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000000c8, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x152e7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x15327d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x15367d80, 0x10021c67, // mov vw_setup, ra_vdw_32\n0xc00001c0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS32_STRIDE-16*4\n0x8c05ddf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000050, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x152e7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x15327d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x152e7d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x000000f8, 0xf0f802a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x159c0fc0, 0x10021c67, // mov vw_setup, rb_vpm\n0x012cbdc0, 0x10020c27, // fadd vpm, ra_64+0, rb_64+0\n0x0130cdc0, 0x10020c27, // fadd vpm, ra_64+1, rb_64+1\n0x159c1fc0, 0x10021c67, // mov vw_setup, rb_vpm_16\n0x0134ddc0, 0x10020c27, // fadd vpm, ra_64+2, rb_64+2\n0x0138edc0, 0x10020c27, // fadd vpm, ra_64+3, rb_64+3\n0x159c2fc0, 0x10021c67, // mov vw_setup, rb_vpm_32\n0x022cbdc0, 0x10020c27, // fsub vpm, ra_64+0, rb_64+0\n0x0230cdc0, 0x10020c27, // fsub vpm, ra_64+1, rb_64+1\n0x159c7fc0, 0x10021c67, // mov vw_setup, rb_vpm_48\n0x0234ddc0, 0x10020c27, // fsub vpm, ra_64+2, rb_64+2\n0x0238edc0, 0x10020c27, // fsub vpm, ra_64+3, rb_64+3\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0xa0104000, 0xe0021c67, // mov vw_setup, vdw_setup_0(64, 16, dma_h32(0,0))\n0xc00000c0, 0xe0021c67, // mov vw_setup, vdw_setup_1(PASS64_STRIDE-16*4)\n0x8c05ddf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, step; mov vw_addr, ra_save_ptr\n0x000002b8, 0xf0f812a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd00200a7, // shl ra_temp, r0, 5\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0fc49e7, // brr -, ra_temp\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x000000e0, 0xf0f809e7, // brr -, r:2f\n0x00000010, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x000000c0, 0xf0f809e7, // brr -, r:2f\n0x00000011, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x000000a0, 0xf0f809e7, // brr -, r:2f\n0x00000012, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000080, 0xf0f809e7, // brr -, r:2f\n0x00000013, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000060, 0xf0f809e7, // brr -, r:2f\n0x00000014, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000040, 0xf0f809e7, // brr -, r:2f\n0x00000015, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000020, 0xf0f809e7, // brr -, r:2f\n0x00000016, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f809e7, // brr -, r:2f\n0x00000017, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c0fc0, 0x10021c67, // mov vw_setup, rb_vpm\n0x012cbdc0, 0x10020c27, // fadd vpm, ra_64+0, rb_64+0\n0x0130cdc0, 0x10020c27, // fadd vpm, ra_64+1, rb_64+1\n0x159c1fc0, 0x10021c67, // mov vw_setup, rb_vpm_16\n0x0134ddc0, 0x10020c27, // fadd vpm, ra_64+2, rb_64+2\n0x0138edc0, 0x10020c27, // fadd vpm, ra_64+3, rb_64+3\n0x159c2fc0, 0x10021c67, // mov vw_setup, rb_vpm_32\n0x022cbdc0, 0x10020c27, // fsub vpm, ra_64+0, rb_64+0\n0x0230cdc0, 0x10020c27, // fsub vpm, ra_64+1, rb_64+1\n0x159c7fc0, 0x10021c67, // mov vw_setup, rb_vpm_48\n0x0234ddc0, 0x10020c27, // fsub vpm, ra_64+2, rb_64+2\n0x0238edc0, 0x10020c27, // fsub vpm, ra_64+3, rb_64+3\n0x00000000, 0xf0fc49e7, // brr -, ra_temp\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000008, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000009, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000a, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000b, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000c, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000d, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000e, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000f, 0xe80009e7, // mov -, srel(i+8)\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000858, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20627030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d8039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22098cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20627031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20667030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d9039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22099cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20667031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x206a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209da039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2209acb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x206a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x206e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209db039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2209bcb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x206e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14727180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14727180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c21c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffda0, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14727180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14727180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c21c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffc80, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x205e7006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d700f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x205e700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22097c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x01267c00, 0x100202e7, // fadd ra_64+0, ra_32_re, r0\n0x019c9e40, 0x10020327, // fadd ra_64+1, rb_32_im, r1\n0x02267c00, 0x10020367, // fsub ra_64+2, ra_32_re, r0\n0x029c9e40, 0x100203a7, // fsub ra_64+3, rb_32_im, r1\n0x8c15fdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14727180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14727180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c21c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffb20, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14727180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14727180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c21c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffa00, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x205e7006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d700f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x205e700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22097c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x029c9e40, 0x100208e7, // fsub r3, rb_32_im, r1\n0x02267c00, 0x100208a7, // fsub r2, ra_32_re, r0\n0x019c9e40, 0x10020867, // fadd r1, rb_32_im, r1\n0x01267c00, 0x10020827, // fadd r0, ra_32_re, r0\n0x203e700e, 0x100049c9, // nop;                        fmul rb_32_im, r1, ra_tw_re+TW64_P1_BASE0\n0x209cf00f, 0x100059c9, // nop;                        fmul ra_32_re, r1, rb_tw_im+TW64_P1_BASE0\n0x209cf007, 0x100049e1, // nop;                        fmul r1,       r0, rb_tw_im+TW64_P1_BASE0\n0x213c93c6, 0x10025320, // fadd rb_64+1, r1, rb_32_im; fmul r0,       r0, ra_tw_re+TW64_P1_BASE0\n0x2225019f, 0x100252c9, // fsub rb_64+0, r0, ra_32_re; fmul ra_32_re, r3, rb_tw_im+TW64_P1_BASE1\n0x2042701e, 0x100049c9, // nop;                        fmul rb_32_im, r3, ra_tw_re+TW64_P1_BASE1\n0x00000000, 0xf0f549e7, // bra -, ra_save_64\n0x209d0017, 0x100049e3, // nop;                        fmul r3,       r2, rb_tw_im+TW64_P1_BASE1\n0x214097d6, 0x100253a2, // fadd rb_64+3, r3, rb_32_im; fmul r2,       r2, ra_tw_re+TW64_P1_BASE1\n0x02267580, 0x10021367, // fsub rb_64+2, r2, ra_32_re\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff920, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff8d0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x205e7006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d700f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x205e700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22097c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f489e7, // bra -, ra_save_32\n0x952c2ff6, 0x100242c2, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95307ff6, 0x10024307, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x9534dff6, 0x1002434d, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_32, rx_save_slave_32\n0x159cafc0, 0x100602a7, // mov.ifnz ra_save_64, rx_save_slave_64\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x00000418, 0xf00809e7, // brr.allz -, r:end\n0x95451dbf, 0x100245d7, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x95492dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c6e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d6e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c6a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d6a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c662, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d663, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c61c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14727180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14727180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c21c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff7f0, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x00000200, 0xe0020827, // mov r0, 0x200\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x0e1cbdc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffff7c8, 0xf00809e7, // brr.allz -, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x00000200, 0xe0020827, // mov r0, 0x200\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x159c0fc0, 0x100202e7, // mov ra_vpm_lo, rb_vpm\n0x159c1fc0, 0x10020327, // mov ra_vpm_hi, rb_vpm_16\n0x90104000, 0xe0020367, // mov ra_vdw_32, vdw_setup_0(32, 16, dma_h32( 0,0))\n0x90105000, 0xe0021367, // mov rb_vdw_32, vdw_setup_0(32, 16, dma_h32(32,0))\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x95555dbf, 0x100245d7, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x95596dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c6e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d6e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c6a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d6a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c662, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d663, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffbf0, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x955d7dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x204e7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209d3017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209d301f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x214e709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x025e7c80, 0x100205e7, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d7ec0, 0x100215e7, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x956dbdbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20527016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209d4017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209d401f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2152709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x026e7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029dbec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c6e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d6e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c6a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d6a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c662, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d663, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1cbdc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffae8, 0xf00809e7, // brr.allz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffffbb8, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_32k.hex",
    "content": "0x00000010, 0xe00216e7, // mov rb_0x10,    0x10\n0x00000040, 0xe0021727, // mov rb_0x40,    0x40\n0x00000080, 0xe0021767, // mov rb_0x80,    0x80\n0x000000f0, 0xe00217a7, // mov rb_0xF0,    0xF0\n0x00000100, 0xe00217e7, // mov rb_0x100,   0x100\n0x00005555, 0xe0020767, // mov rx_0x5555,  0x5555\n0x00003333, 0xe00207a7, // mov rx_0x3333,  0x3333\n0x00000f0f, 0xe00207e7, // mov rx_0x0F0F,  0x0F0F\n0x000000ff, 0xe00216a7, // mov rx_0x00FF,  0x00FF\n0x90104000, 0xe0020727, // mov ra_vdw_32, vdw_setup_0(32, 16, dma_h32( 0,0))\n0x90105000, 0xe0021067, // mov rb_vdw_32, vdw_setup_0(32, 16, dma_h32(32,0))\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020327, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020367, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203e7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021327, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021367, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213e7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020427, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020467, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021427, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021467, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x100246a0, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100246e0, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000000c8, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156e7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x15727d80, 0x10021c67, // mov vw_setup, ra_vdw_32\n0xc0001fc0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS32_STRIDE-16*4\n0x8c05cdf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000050, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156e7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x156a7d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000588, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x204e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d3039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22093cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x204e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20527030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d4039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22094cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20527031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20567030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d5039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22095cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20567031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x205a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d6039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22096cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x205a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c21c0, 0xd0020827, // shl r0, r0, STAGES-13\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffda0, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c21c0, 0xd0020827, // shl r0, r0, STAGES-13\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffc80, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x204a7006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d200f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x204a700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22092c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f489e7, // bra -, ra_save_32\n0x95682ff6, 0x10024682, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x956c7ff6, 0x100246c7, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffbf0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffba0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x204a7006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d200f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x204a700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22092c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f489e7, // bra -, ra_save_32\n0x95682ff6, 0x10024682, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x956c7ff6, 0x100246c7, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_32, rx_save_slave_32\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x00000668, 0xf00809e7, // brr.allz -, r:end\n0x9528adbf, 0x10024492, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x952cbdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c21c0, 0xd0020827, // shl r0, r0, STAGES-13\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffac8, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x0e1cfdc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffaa0, 0xf00809e7, // brr.allz -, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x9528adbf, 0x10024492, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x952cbdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffc18, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0xfffffbf8, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0xfffffbd8, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0xfffffbb8, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x95492dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x20327016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209cc017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209cc01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x2132709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x024a7c80, 0x100204a7, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d2ec0, 0x100214a7, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x95596dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20367016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209cd017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209cd01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2136709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x025a7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d6ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1cfdc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffab0, 0xf00809e7, // brr.allz -, r:pass_2\n0x00000060, 0xe0020827, // mov r0, 3*4*8\n0x0d227c00, 0x10020227, // sub ra_link_1, ra_link_1, r0\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x95410dbf, 0x10024492, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x95451dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff9a8, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x95492dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x203a7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209ce017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209ce01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x213a709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x024a7c80, 0x100204a7, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d2ec0, 0x100214a7, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x95596dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x203e7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209cf017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209cf01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x213e709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x025a7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d6ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1cfdc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffff8a0, 0xf00809e7, // brr.allz -, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffff968, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_4k.hex",
    "content": "0x00000020, 0xe0021767, // mov rb_0x20,    0x20\n0x00000040, 0xe00217a7, // mov rb_0x40,    0x40\n0x00000080, 0xe00217e7, // mov rb_0x80,    0x80\n0x00005555, 0xe0020727, // mov rx_0x5555,  0x5555\n0x00003333, 0xe0020767, // mov rx_0x3333,  0x3333\n0x00000f0f, 0xe00207a7, // mov rx_0x0F0F,  0x0F0F\n0x000000ff, 0xe00207e7, // mov rx_0x00FF,  0x00FF\n0x88104000, 0xe00206e7, // mov ra_vdw, vdw_setup_0(16, 16, dma_h32( 0,0))\n0x88104800, 0xe00216e7, // mov rb_vdw, vdw_setup_0(16, 16, dma_h32(16,0))\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9df1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020227, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9df1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020267, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9df1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202a7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9df3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021227, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9df3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021267, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9df3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212a7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9df1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202e7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9df3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212e7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x100246a0, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100256a0, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100049e0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100009e7, // add out_3, r0, r2\n0x000000b0, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x156a7d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x156e7d80, 0x10021c67, // mov vw_setup, arg_vdw\n0xc00007c0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS16_STRIDE-16*4\n0x8c05edf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000038, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x156a7d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x156a7d80, 0x10020c67, // mov vr_setup, arg_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x000003e8, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f409e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20327030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209cc039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2208ccb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20327031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20367030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209cd039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2208dcb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20367031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x203a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209ce039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2208ecb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x203a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x203e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209cf039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2208fcb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x203e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f489e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c15fdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14727180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14727180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c11c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x000000cc, 0xe20229e7, // mov.setf  -, [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]\n0x959fa000, 0xd002c8a0, // mov r2, r0; mov.ifnz r0, r0 << 6\n0x959fa249, 0xd002c8e1, // mov r3, r1; mov.ifnz r1, r1 << 6\n0x00003300, 0xe20229e7, // mov.setf  -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0]\n0x809f6012, 0xd000c9e0, // nop; mov.ifnz r0, r2 >> 6\n0x809f601b, 0xd000c9e1, // nop; mov.ifnz r1, r3 >> 6\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x000000cc, 0xe20229e7, // mov.setf  -, [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]\n0x959fa000, 0xd002c8a0, // mov r2, r0; mov.ifnz r0, r0 << 6\n0x959fa249, 0xd002c8e1, // mov r3, r1; mov.ifnz r1, r1 << 6\n0x00003300, 0xe20229e7, // mov.setf  -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0]\n0x809f6012, 0xd000c9e0, // nop; mov.ifnz r0, r2 >> 6\n0x809f601b, 0xd000c9e1, // nop; mov.ifnz r1, r3 >> 6\n0xfffffd40, 0xf0f809e7, // brr -, r:fft_16\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x8c15fdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffcf8, 0xf0f809e7, // brr -, r:fft_16\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_16, rx_save_slave_16\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x000005c8, 0xf00809e7, // brr.allz -, r:end\n0x95208dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c3e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d3e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c3a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d3a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c362, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d363, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c322, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d323, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15fdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14727180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14727180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c11c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x000000cc, 0xe20229e7, // mov.setf  -, [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]\n0x959fa000, 0xd002c8a0, // mov r2, r0; mov.ifnz r0, r0 << 6\n0x959fa249, 0xd002c8e1, // mov r3, r1; mov.ifnz r1, r1 << 6\n0x00003300, 0xe20229e7, // mov.setf  -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0]\n0x809f6012, 0xd000c9e0, // nop; mov.ifnz r0, r2 >> 6\n0x809f601b, 0xd000c9e1, // nop; mov.ifnz r1, r3 >> 6\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffc40, 0xf0f80027, // brr ra_link_1, r:pass_1\n0x9569aff6, 0x1002469a, // mov ra_vpm, rb_vpm; mov rb_vpm, ra_vpm\n0x956dbff6, 0x100246db, // mov ra_vdw, rb_vdw; mov rb_vdw, ra_vdw\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x0e1ccdc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffc18, 0xf00809e7, // brr.allz -, r:pass_1\n0x9569aff6, 0x1002469a, // mov ra_vpm, rb_vpm; mov rb_vpm, ra_vpm\n0x956dbff6, 0x100246db, // mov ra_vdw, rb_vdw; mov rb_vdw, ra_vdw\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c027, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x95208dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c3e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d3e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c3a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d3a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c362, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d363, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c322, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d323, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15fdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffc90, 0xf0f80027, // brr ra_link_1, r:pass_2\n0x9569aff6, 0x1002469a, // mov ra_vpm, rb_vpm; mov rb_vpm, ra_vpm\n0x956dbff6, 0x100246db, // mov ra_vdw, rb_vdw; mov rb_vdw, ra_vdw\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0xfffffc70, 0xf0f80027, // brr ra_link_1, r:pass_2\n0x9569aff6, 0x1002469a, // mov ra_vpm, rb_vpm; mov rb_vpm, ra_vpm\n0x956dbff6, 0x100246db, // mov ra_vdw, rb_vdw; mov rb_vdw, ra_vdw\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x0d01ddc0, 0x10020027, // sub ra_link_1, ra_link_1, rb_0x20\n0x953cfdbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20267016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209c9017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209c901f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2126709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x023e7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029cfec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c3e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d3e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c3a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d3a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c362, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d363, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c322, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d323, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1ccdc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffba0, 0xf00809e7, // brr.allz -, r:pass_2\n0x9569aff6, 0x1002469a, // mov ra_vpm, rb_vpm; mov rb_vpm, ra_vpm\n0x956dbff6, 0x100246db, // mov ra_vdw, rb_vdw; mov rb_vdw, ra_vdw\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c027, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x952cbdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c3e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d3e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c3a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d3a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c362, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d363, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c322, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d323, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15fdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffaa0, 0xf0f80027, // brr ra_link_1, r:pass_3\n0x9569aff6, 0x1002469a, // mov ra_vpm, rb_vpm; mov rb_vpm, ra_vpm\n0x956dbff6, 0x100246db, // mov ra_vdw, rb_vdw; mov rb_vdw, ra_vdw\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x953cfdbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x202a7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209ca017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209ca01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x212a709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x023e7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029cfec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c3e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d3e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c3a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d3a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c362, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d363, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c322, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d323, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1ccdc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffff9d8, 0xf00809e7, // brr.allz -, r:pass_3\n0x9569aff6, 0x1002469a, // mov ra_vpm, rb_vpm; mov rb_vpm, ra_vpm\n0x956dbff6, 0x100246db, // mov ra_vdw, rb_vdw; mov rb_vdw, ra_vdw\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c027, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffffa08, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_512.hex",
    "content": "0x00000010, 0xe0021727, // mov rb_0x10,    0x10\n0x00000040, 0xe0021767, // mov rb_0x40,    0x40\n0x00000080, 0xe00217a7, // mov rb_0x80,    0x80\n0x000000f0, 0xe00217e7, // mov rb_0xF0,    0xF0\n0x00005555, 0xe0020727, // mov rx_0x5555,  0x5555\n0x00003333, 0xe0020767, // mov rx_0x3333,  0x3333\n0x00000f0f, 0xe00207a7, // mov rx_0x0F0F,  0x0F0F\n0x000000ff, 0xe00207e7, // mov rx_0x00FF,  0x00FF\n0x88104000, 0xe00206a7, // mov ra_vdw_16, vdw_setup_0(16, 16, dma_h32( 0,0))\n0x88105000, 0xe0021027, // mov rb_vdw_16, vdw_setup_0(16, 16, dma_h32(32,0))\n0x90104000, 0xe00206e7, // mov ra_vdw_32, vdw_setup_0(32, 16, dma_h32( 0,0))\n0x90105000, 0xe0021067, // mov rb_vdw_32, vdw_setup_0(32, 16, dma_h32(32,0))\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9de1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9de1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020327, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9de1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020367, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9de3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9de3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021327, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9de3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021367, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9de1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203a7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9de3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213a7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x10024620, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x10024660, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000000b0, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15627d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x156a7d80, 0x10021c67, // mov vw_setup, arg_vdw\n0xc00000c0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS16_STRIDE-16*4\n0x8c05ddf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000038, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15627d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15627d80, 0x10020c67, // mov vr_setup, arg_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x000000c8, 0xf0f802a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15627d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x156e7d80, 0x10021c67, // mov vw_setup, ra_vdw_32\n0xc0000040, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS32_STRIDE-16*4\n0x8c05ddf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000050, 0xf0f812a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15627d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15627d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000510, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20427030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d0039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22090cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20427031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20467030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d1039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22091cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20467031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x204a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d2039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22092cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x204a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x204e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d3039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22093cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x204e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c15fdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14727180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14727180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c41c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffda0, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14727180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14727180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c41c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffc80, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x203e7006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209cf00f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x203e700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x2208fc87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f549e7, // bra -, ra_save_32\n0x95602ff6, 0x10024602, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95647ff6, 0x10024647, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x956c1ff6, 0x100246c1, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffbf0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x00000000, 0xf0f489e7, // bra -, ra_save_16\n0x009e7000, 0x100009e7, // nop\n0x95602ff6, 0x10024602, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95680ff6, 0x10024680, // mov ra_vdw_16, rb_vdw_16; mov rb_vdw_16, ra_vdw_16\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_16, rx_save_slave_16\n0x159cafc0, 0x100602a7, // mov.ifnz ra_save_32, rx_save_slave_32\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x000003a8, 0xf00809e7, // brr.allz -, r:end\n0x952cbdbf, 0x100243cf, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c462, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d463, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c422, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d423, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14727180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14727180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9c41c0, 0xd0020827, // shr r0, r0, 13-STAGES\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffb38, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0xfffffb18, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x9538edbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c462, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d463, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c422, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d423, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffc98, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dedc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x954d3dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20367016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209cd017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209cd01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2136709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x024e7c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d3ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c462, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d463, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c422, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d423, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c9dc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffbd0, 0xf00809e7, // brr.allz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dedc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffffc28, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_512k.hex",
    "content": "0x00000013, 0xe0021227, // mov rb_STAGES,  STAGES\n0x00000010, 0xe00216e7, // mov rb_0x10,    0x10\n0x00000040, 0xe0021727, // mov rb_0x40,    0x40\n0x00000080, 0xe0021767, // mov rb_0x80,    0x80\n0x000000f0, 0xe00217a7, // mov rb_0xF0,    0xF0\n0x00000100, 0xe00217e7, // mov rb_0x100,   0x100\n0x55555555, 0xe0020767, // mov rx_0x55555555, 0x55555555\n0x33333333, 0xe00207a7, // mov rx_0x33333333, 0x33333333\n0x0f0f0f0f, 0xe00207e7, // mov rx_0x0F0F0F0F, 0x0F0F0F0F\n0x00ff00ff, 0xe0021667, // mov rx_0x00FF00FF, 0x00FF00FF\n0x0000ffff, 0xe00216a7, // mov rx_0x0000FFFF, 0x0000FFFF\n0x80904000, 0xe00206e7, // mov ra_vdw_16, vdw_setup_0(1, 16, dma_h32( 0,0))\n0x80905000, 0xe0021027, // mov rb_vdw_16, vdw_setup_0(1, 16, dma_h32(32,0))\n0x80904000, 0xe0020727, // mov ra_vdw_32, vdw_setup_0(1, 16, dma_h32( 0,0))\n0x80905000, 0xe0021067, // mov rb_vdw_32, vdw_setup_0(1, 16, dma_h32(32,0))\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020327, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020367, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020427, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020467, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021327, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021367, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021427, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021467, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100204a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100204e7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100214a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100214e7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x10024660, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100246a0, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000001d0, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x156e7d80, 0x10020827, // mov r0, arg_vdw\n0x8c05cdf6, 0x10024061, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov r1, ra_save_ptr\n0x00000080, 0xe00208a7, // mov r2, vdw_setup_0(1, 16, dma_h32(1,0)) - vdw_setup_0(1, 16, dma_h32(0,0))\n0x00040000, 0xe00208e7, // mov r3, PASS16_STRIDE\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000038, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10020c67, // mov vr_setup, arg_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x000002e8, 0xf0f802a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x15727d80, 0x10020827, // mov r0, ra_vdw_32\n0x8c05cdf6, 0x10024061, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov r1, ra_save_ptr\n0x00000080, 0xe00208a7, // mov r2, vdw_setup_0(1, 16, dma_h32(1,0)) - vdw_setup_0(1, 16, dma_h32(0,0))\n0x00020000, 0xe00208e7, // mov r3, PASS32_STRIDE\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x8c9e7080, 0x10024831, // add r0, r0, r2; mov vw_setup, r0\n0x8c9e72c9, 0x10024872, // add r1, r1, r3; mov vw_addr,  r1\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000050, 0xf0f812a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000640, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20567030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d5039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22095cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20567031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x205a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d6039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22096cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x205a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x205e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d7039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22097cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x205e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20627030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d8039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22098cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20627031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d91c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149d91c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9db1c0, 0x10020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119db3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9ca1c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffd78, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d91c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149d91c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9db1c0, 0x10020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119db3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9ca1c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffc30, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x20527006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d400f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2052700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22094c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f549e7, // bra -, ra_save_32\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95687ff6, 0x10024687, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffba0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x00000000, 0xf0f489e7, // bra -, ra_save_16\n0x009e7000, 0x100009e7, // nop\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x956c0ff6, 0x100246c0, // mov ra_vdw_16, rb_vdw_16; mov rb_vdw_16, ra_vdw_16\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffb38, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffae8, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x20527006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d400f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2052700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22094c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f549e7, // bra -, ra_save_32\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95687ff6, 0x10024687, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_16, rx_save_slave_16\n0x159cafc0, 0x100602a7, // mov.ifnz ra_save_32, rx_save_slave_32\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x00000888, 0xf00809e7, // brr.allz -, r:end\n0x952cbdbf, 0x10024514, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149d91c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149d91c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9db1c0, 0x10020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119db3c0, 0x10020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0e9ca1c0, 0xd0020827, // shr r0, r0, 32-STAGES-3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff9e0, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff9b8, 0xf00809e7, // brr.allz -, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffb88, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dddc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00003fff, 0xe0020827, // mov r0, 0x3FFF\n0x141e7c00, 0x100229e7, // and.setf -, ra_points, r0\n0xfffffb58, 0xf01809e7, // brr.allnz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dddc0, 0x100601e7, // add.ifnz ra_points, ra_points, rb_0x80\n0x95618dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20367016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209cd017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209cd01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2136709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02627c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d8ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffffa90, 0xf00809e7, // brr.allz -, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dddc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x952cbdbf, 0x10024514, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff9f0, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0xfffff9d0, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0xfffff9b0, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0xfffff990, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x95514dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x203a7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209ce017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209ce01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x213a709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02527c80, 0x10020527, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d4ec0, 0x10021527, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x95618dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x203e7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209cf017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209cf01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x213e709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02627c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d8ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff888, 0xf00809e7, // brr.allz -, r:pass_3\n0x00000060, 0xe0020827, // mov r0, 3*4*8\n0x0d227c00, 0x10020227, // sub ra_link_1, ra_link_1, r0\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x95492dbf, 0x10024514, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x954d3dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff780, 0xf0f80227, // brr ra_link_1, r:pass_4\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x95514dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x20427016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209d0017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209d001f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x2142709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02527c80, 0x10020527, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d4ec0, 0x10021527, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x95618dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20467016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209d1017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209d101f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2146709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02627c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d8ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c622, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d623, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c5e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d5e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c5a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d5a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c562, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d563, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff678, 0xf00809e7, // brr.allz -, r:pass_4\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffff748, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_64k.hex",
    "content": "0x00000010, 0xe0021227, // mov rb_0x10,    0x10\n0x000001d0, 0xe0021967, // mov r5rep,      0x1D0\n0x00005555, 0xe00207a7, // mov rx_0x5555,  0x5555\n0x00003333, 0xe00217a7, // mov rx_0x3333,  0x3333\n0x00000f0f, 0xe00207e7, // mov rx_0x0F0F,  0x0F0F\n0x000000ff, 0xe00217e7, // mov rx_0x00FF,  0x00FF\n0x00000080, 0xe00208e7, // mov r3, 0x80\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020427, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020467, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100204a7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100204e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020527, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020567, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100205a7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021427, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021467, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100214a7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100214e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021527, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021567, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100215a7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100205e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9e70c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020627, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100215e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9e72c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021627, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x10025020, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x10025060, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000000c8, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x152e7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x15327d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x153a7d80, 0x10021c67, // mov vw_setup, ra_vdw_32\n0xc0003fc0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS32_STRIDE-16*4\n0x8c04ddf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000050, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x152e7d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x15327d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x152e7d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000100, 0xf0f802a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000040, 0xe0020827, // mov r0, 0x40\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x159c0fc0, 0x10021c67, // mov vw_setup, rb_vpm\n0x012cbdc0, 0x10020c27, // fadd vpm, ra_64+0, rb_64+0\n0x0130cdc0, 0x10020c27, // fadd vpm, ra_64+1, rb_64+1\n0x159c1fc0, 0x10021c67, // mov vw_setup, rb_vpm_16\n0x0134ddc0, 0x10020c27, // fadd vpm, ra_64+2, rb_64+2\n0x0138edc0, 0x10020c27, // fadd vpm, ra_64+3, rb_64+3\n0x159c2fc0, 0x10021c67, // mov vw_setup, rb_vpm_32\n0x022cbdc0, 0x10020c27, // fsub vpm, ra_64+0, rb_64+0\n0x0230cdc0, 0x10020c27, // fsub vpm, ra_64+1, rb_64+1\n0x159c7fc0, 0x10021c67, // mov vw_setup, rb_vpm_48\n0x0234ddc0, 0x10020c27, // fsub vpm, ra_64+2, rb_64+2\n0x0238edc0, 0x10020c27, // fsub vpm, ra_64+3, rb_64+3\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0xa0104000, 0xe0021c67, // mov vw_setup, vdw_setup_0(64, 16, dma_h32(0,0))\n0xc0001fc0, 0xe0021c67, // mov vw_setup, vdw_setup_1(PASS64_STRIDE-16*4)\n0x8c067c36, 0x10024072, // add ra_save_ptr, ra_save_ptr, step; mov vw_addr, ra_save_ptr\n0x000002b8, 0xf0f812a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd00200a7, // shl ra_temp, r0, 5\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0fc49e7, // brr -, ra_temp\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x000000e0, 0xf0f809e7, // brr -, r:2f\n0x00000010, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x000000c0, 0xf0f809e7, // brr -, r:2f\n0x00000011, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x000000a0, 0xf0f809e7, // brr -, r:2f\n0x00000012, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000080, 0xf0f809e7, // brr -, r:2f\n0x00000013, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000060, 0xf0f809e7, // brr -, r:2f\n0x00000014, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000040, 0xf0f809e7, // brr -, r:2f\n0x00000015, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000020, 0xf0f809e7, // brr -, r:2f\n0x00000016, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f809e7, // brr -, r:2f\n0x00000017, 0xe80009e7, // mov -, sacq(i)\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c0fc0, 0x10021c67, // mov vw_setup, rb_vpm\n0x012cbdc0, 0x10020c27, // fadd vpm, ra_64+0, rb_64+0\n0x0130cdc0, 0x10020c27, // fadd vpm, ra_64+1, rb_64+1\n0x159c1fc0, 0x10021c67, // mov vw_setup, rb_vpm_16\n0x0134ddc0, 0x10020c27, // fadd vpm, ra_64+2, rb_64+2\n0x0138edc0, 0x10020c27, // fadd vpm, ra_64+3, rb_64+3\n0x159c2fc0, 0x10021c67, // mov vw_setup, rb_vpm_32\n0x022cbdc0, 0x10020c27, // fsub vpm, ra_64+0, rb_64+0\n0x0230cdc0, 0x10020c27, // fsub vpm, ra_64+1, rb_64+1\n0x159c7fc0, 0x10021c67, // mov vw_setup, rb_vpm_48\n0x0234ddc0, 0x10020c27, // fsub vpm, ra_64+2, rb_64+2\n0x0238edc0, 0x10020c27, // fsub vpm, ra_64+3, rb_64+3\n0x00000000, 0xf0fc49e7, // brr -, ra_temp\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000008, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000009, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000a, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000b, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000c, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000d, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000e, 0xe80009e7, // mov -, srel(i+8)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x159c0fc0, 0x10020c67, // mov vr_setup, rb_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x0000000f, 0xe80009e7, // mov -, srel(i+8)\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000858, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x206a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209da039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2209acb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x206a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x206e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209db039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2209bcb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x206e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20727030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209dc039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2209ccb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20727031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20767030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209dd039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x2209dcb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20767031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149de1c0, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149de1c0, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149df1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149df1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c31c0, 0xd0020827, // shl r0, r0, STAGES-13\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffda0, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149de1c0, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149de1c0, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149df1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149df1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c31c0, 0xd0020827, // shl r0, r0, STAGES-13\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffc80, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x20667006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d900f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2066700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22099c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x01267c00, 0x100202e7, // fadd ra_64+0, ra_32_re, r0\n0x019c9e40, 0x10020327, // fadd ra_64+1, rb_32_im, r1\n0x02267c00, 0x10020367, // fsub ra_64+2, ra_32_re, r0\n0x029c9e40, 0x100203a7, // fsub ra_64+3, rb_32_im, r1\n0x8c167d76, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149de1c0, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149de1c0, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149df1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149df1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c31c0, 0xd0020827, // shl r0, r0, STAGES-13\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffb20, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149de1c0, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149de1c0, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149df1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149df1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c31c0, 0xd0020827, // shl r0, r0, STAGES-13\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffa00, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x20667006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d900f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2066700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22099c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x029c9e40, 0x100208e7, // fsub r3, rb_32_im, r1\n0x02267c00, 0x100208a7, // fsub r2, ra_32_re, r0\n0x019c9e40, 0x10020867, // fadd r1, rb_32_im, r1\n0x01267c00, 0x10020827, // fadd r0, ra_32_re, r0\n0x203e700e, 0x100049c9, // nop;                        fmul rb_32_im, r1, ra_tw_re+TW64_P1_BASE0\n0x209cf00f, 0x100059c9, // nop;                        fmul ra_32_re, r1, rb_tw_im+TW64_P1_BASE0\n0x209cf007, 0x100049e1, // nop;                        fmul r1,       r0, rb_tw_im+TW64_P1_BASE0\n0x213c93c6, 0x10025320, // fadd rb_64+1, r1, rb_32_im; fmul r0,       r0, ra_tw_re+TW64_P1_BASE0\n0x2225019f, 0x100252c9, // fsub rb_64+0, r0, ra_32_re; fmul ra_32_re, r3, rb_tw_im+TW64_P1_BASE1\n0x2042701e, 0x100049c9, // nop;                        fmul rb_32_im, r3, ra_tw_re+TW64_P1_BASE1\n0x00000000, 0xf0f549e7, // bra -, ra_save_64\n0x209d0017, 0x100049e3, // nop;                        fmul r3,       r2, rb_tw_im+TW64_P1_BASE1\n0x214097d6, 0x100253a2, // fadd rb_64+3, r3, rb_32_im; fmul r2,       r2, ra_tw_re+TW64_P1_BASE1\n0x02267580, 0x10021367, // fsub rb_64+2, r2, ra_32_re\n0x8c14cdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff920, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff8d0, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x20667006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d900f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2066700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22099c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f489e7, // bra -, ra_save_32\n0x952c2ff6, 0x100242c2, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95307ff6, 0x10024307, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x9538eff6, 0x1002438e, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_32, rx_save_slave_32\n0x159cafc0, 0x100602a7, // mov.ifnz ra_save_64, rx_save_slave_64\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x000006a8, 0xf00809e7, // brr.allz -, r:end\n0x95451dbf, 0x10024659, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x95492dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c6e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d6e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c6a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d6a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c61c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149de1c0, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x149de1c0, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149df1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149df1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x119c31c0, 0xd0020827, // shl r0, r0, STAGES-13\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff7f0, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x00000200, 0xe0020827, // mov r0, 0x200\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000010, 0xe0020867, // mov r1, STAGES\n0x0e1e7c40, 0x100229e7, // shr.setf -, ra_points, r1\n0xfffff7c0, 0xf00809e7, // brr.allz -, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x00000200, 0xe0020827, // mov r0, 0x200\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x159c0fc0, 0x100202e7, // mov ra_vpm_lo, rb_vpm\n0x159c1fc0, 0x10020327, // mov ra_vpm_hi, rb_vpm_16\n0x90104000, 0xe00203a7, // mov ra_vdw_32, vdw_setup_0(32, 16, dma_h32( 0,0))\n0x90105000, 0xe00213a7, // mov rb_vdw_32, vdw_setup_0(32, 16, dma_h32(32,0))\n0x00000060, 0xe00212e7, // mov rb_3x4x8, 3*4*8\n0x000000f0, 0xe0021327, // mov rb_0xF0, 0xF0\n0x00000040, 0xe0021367, // mov rb_0x40, 0x40\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x95451dbf, 0x10024659, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x95492dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c6e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d6e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c6a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d6a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffbd0, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0xfffffbb0, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0xfffffb90, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0xfffffb70, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x95659dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x204e7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209d3017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209d301f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x214e709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02667c80, 0x10020667, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d9ec0, 0x10021667, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x9575ddbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20527016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209d4017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209d401f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2152709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02767c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029ddec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c6e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d6e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c6a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d6a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffffa68, 0xf00809e7, // brr.allz -, r:pass_2\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x0d20bdc0, 0x10020227, // sub ra_link_1, ra_link_1, rb_3x4x8\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x955d7dbf, 0x10024659, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x95618dbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c6e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d6e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c6a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d6a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c148df6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffff960, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x95659dbf, 0x100248a3, // mov r2, ra_tw_re+TW32_ACTIVE; mov r3, rb_tw_im+TW32_ACTIVE\n0x20567016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw32\n0x209d5017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw32\n0x209d501f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw32\n0x2156709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw32\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02667c80, 0x10020667, // fsub ra_tw_re+TW32_ACTIVE, ra_tw_re+TW32_ACTIVE, r2\n0x029d9ec0, 0x10021667, // fsub rb_tw_im+TW32_ACTIVE, rb_tw_im+TW32_ACTIVE, r3\n0x9575ddbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x205a7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209d6017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209d601f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x215a709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02767c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029ddec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c762, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d763, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c722, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d723, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c6e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d6e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c6a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d6a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1c8dc0, 0x100229e7, // shr.setf -, ra_points, rb_STAGES\n0xfffff858, 0xf00809e7, // brr.allz -, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x00000100, 0xe0020827, // mov r0, 0x100\n0x0c1e7c00, 0x100201e7, // add ra_points, ra_points, r0\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffff928, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_8k.hex",
    "content": "0x00000010, 0xe00216e7, // mov rb_0x10,    0x10\n0x00000040, 0xe0021727, // mov rb_0x40,    0x40\n0x00000080, 0xe0021767, // mov rb_0x80,    0x80\n0x000000f0, 0xe00217a7, // mov rb_0xF0,    0xF0\n0x00000100, 0xe00217e7, // mov rb_0x100,   0x100\n0x00005555, 0xe0020767, // mov rx_0x5555,  0x5555\n0x00003333, 0xe00207a7, // mov rx_0x3333,  0x3333\n0x00000f0f, 0xe00207e7, // mov rx_0x0F0F,  0x0F0F\n0x000000ff, 0xe00216a7, // mov rx_0x00FF,  0x00FF\n0x88104000, 0xe00206e7, // mov ra_vdw_16, vdw_setup_0(16, 16, dma_h32( 0,0))\n0x88105000, 0xe0021027, // mov rb_vdw_16, vdw_setup_0(16, 16, dma_h32(32,0))\n0x90104000, 0xe0020727, // mov ra_vdw_32, vdw_setup_0(32, 16, dma_h32( 0,0))\n0x90105000, 0xe0021067, // mov rb_vdw_32, vdw_setup_0(32, 16, dma_h32(32,0))\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100202e7, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020327, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x10020367, // mov ra_tw_re+off+i, r4\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203a7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100212e7, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021327, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x10021367, // mov rb_tw_im+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213a7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10020827, // mov r0, addr\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x11983dc0, 0xd00208a7, // shl r2, elem_num, 3\n0x0c9e7080, 0x10020e27, // add t0s, r0, r2\n0x0c9dd1c0, 0xa0020827, // add r0,  r0, stride; ldtmu0\n0x159e7900, 0x100203e7, // mov ra_tw_re+off+i, r4\n0x0c9e7280, 0x10020e27, // add t0s, r1, r2\n0x0c9dd3c0, 0xa0020867, // add r1,  r1, stride; ldtmu0\n0x159e7900, 0x100213e7, // mov rb_tw_im+off+i, r4\n0x15827d80, 0x10021167, // mov rb_inst, unif\n0x00101200, 0xe0020827, // mov r0, vpm_setup(1, 1, v32( 0,0))\n0x00000010, 0xe0020867, // mov r1, vpm_setup(1, 1, v32(16,0)) - vpm_setup(1, 1, v32(0,0))\n0x00000002, 0xe00208a7, // mov r2, vpm_setup(1, 1, v32( 0,2)) - vpm_setup(1, 1, v32(0,0))\n0x409c5017, 0x100049e2, // nop; mul24 r2, r2, in_inst\n0xcc9e7081, 0x10024660, // add out_0, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100246a0, // add out_1, r0, r2; v8adds r0, r0, r1\n0xcc9e7081, 0x100250a0, // add out_2, r0, r2; v8adds r0, r0, r1\n0x0c9e7080, 0x100211e7, // add out_3, r0, r2\n0x000000b0, 0xf0f80127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x156e7d80, 0x10021c67, // mov vw_setup, arg_vdw\n0xc0000fc0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS16_STRIDE-16*4\n0x8c05cdf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000038, 0xf0f81127, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, arg\n0x159e7000, 0x10020c27, // mov vpm, r0\n0x159e7240, 0x10020c27, // mov vpm, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10020c67, // mov vr_setup, arg_vpm\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x000000c8, 0xf0f802a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x15727d80, 0x10021c67, // mov vw_setup, ra_vdw_32\n0xc00007c0, 0xe0021c67, // mov vw_setup, vdw_setup_1(0) + PASS32_STRIDE-16*4\n0x8c05cdf6, 0x10024072, // add ra_save_ptr, ra_save_ptr, rb_0x40; mov vw_addr, ra_save_ptr\n0x00000050, 0xf0f812a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10021c67, // mov vw_setup, ra_vpm_lo\n0x01267c00, 0x10020c27, // fadd vpm, ra_32_re, r0\n0x019c9e40, 0x10020c27, // fadd vpm, rb_32_im, r1\n0x156a7d80, 0x10021c67, // mov vw_setup, ra_vpm_hi\n0x02267c00, 0x10020c27, // fsub vpm, ra_32_re, r0\n0x029c9e40, 0x10020c27, // fsub vpm, rb_32_im, r1\n0x00000000, 0xf0f4c9e7, // bra -, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x15667d80, 0x10020c67, // mov vr_setup, ra_vpm_lo\n0x15c27d80, 0x100009e7, // mov -, vpm\n0x00000080, 0xf0f801a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x00000019, 0xe80009e7, // mov -, sacq(i+9)\n0x00000001, 0xe80009e7, // mov -, srel(i+1)\n0x0000001a, 0xe80009e7, // mov -, sacq(i+9)\n0x00000002, 0xe80009e7, // mov -, srel(i+1)\n0x0000001b, 0xe80009e7, // mov -, sacq(i+9)\n0x00000003, 0xe80009e7, // mov -, srel(i+1)\n0x0000001c, 0xe80009e7, // mov -, sacq(i+9)\n0x00000004, 0xe80009e7, // mov -, srel(i+1)\n0x0000001d, 0xe80009e7, // mov -, sacq(i+9)\n0x00000005, 0xe80009e7, // mov -, srel(i+1)\n0x0000001e, 0xe80009e7, // mov -, sacq(i+9)\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000006, 0xe80009e7, // mov -, srel(i+1)\n0x0000001f, 0xe80009e7, // mov -, sacq(i+9)\n0x00000007, 0xe80009e7, // mov -, srel(i+1)\n0x00000500, 0xf0f811a7, // brr rx_ptr, label\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x00000009, 0xe80009e7, // mov -, srel(i+9)\n0x00000011, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000a, 0xe80009e7, // mov -, srel(i+9)\n0x00000012, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000b, 0xe80009e7, // mov -, srel(i+9)\n0x00000013, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000c, 0xe80009e7, // mov -, srel(i+9)\n0x00000014, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000d, 0xe80009e7, // mov -, srel(i+9)\n0x00000015, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000e, 0xe80009e7, // mov -, srel(i+9)\n0x00000016, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x00000000, 0xf0f509e7, // bra -, ra_link_1\n0x0000000f, 0xe80009e7, // mov -, srel(i+9)\n0x00000017, 0xe80009e7, // mov -, sacq(i+1)\n0x009e7000, 0x100009e7, // nop\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20467030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d1039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22091cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20467031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819ff2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f1400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829ff609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f1449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x204a7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d2039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22092cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x204a7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fe2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f2400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fe609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f2449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x204e7030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d3039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22093cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x204e7031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819fc2c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f4400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x829fc609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f4449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (1<<i)\n0x20527030, 0x1000d9c2, // nop;                       fmul.ifnz ra_temp, ra_tw_re+TW16_ACTIVE+i, r0\n0x209d4039, 0x1000c9e2, // nop;                       fmul.ifnz r2,      rb_tw_im+TW16_ACTIVE+i, r1\n0x22094cb8, 0x1006c823, // fsub.ifnz r0, ra_temp, r2; fmul.ifnz r3,      rb_tw_im+TW16_ACTIVE+i, r0\n0x20527031, 0x1000c9e1, // nop;                       fmul.ifnz r1,      ra_tw_re+TW16_ACTIVE+i, r1\n0x819f82c0, 0xd0064862, // fadd.ifnz r1, r1, r3; mov r2, r0 << (1<<i)\n0x819f8400, 0xd0044823, // fadd.ifz  r0, r2, r0; mov r3, r0 >> (1<<i)\n0x00000000, 0xf0f409e7, // bra -, ra_link_0\n0x829f8609, 0xd0064822, // fsub.ifnz r0, r3, r0; mov r2, r1 << (1<<i)\n0x819f8449, 0xd0044863, // fadd.ifz  r1, r2, r1; mov r3, r1 >> (1<<i)\n0x029e7640, 0x10060867, // fsub.ifnz r1, r3, r1\n0x8c15edf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffda8, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x959e7009, 0x10024249, // mov ra_32_re, r0; mov rb_32_im, r1\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0xfffffc90, 0xf0f80027, // brr ra_link_0, call\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x20427006, 0x100059c2, // nop;                  fmul ra_temp, r0, ra_tw_re+TW32_ACTIVE\n0x209d000f, 0x100049e2, // nop;                  fmul r2,      r1, rb_tw_im+TW32_ACTIVE\n0x2042700e, 0x100049e3, // nop;                  fmul r3,      r1, ra_tw_re+TW32_ACTIVE\n0x22090c87, 0x10024821, // fsub r0, ra_temp, r2; fmul r1,      r0, rb_tw_im+TW32_ACTIVE\n0x019e72c0, 0x10020867, // fadd r1, r1,      r3\n0x00000000, 0xf0f549e7, // bra -, ra_save_32\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x95687ff6, 0x10024687, // mov ra_vpm_hi, rb_vpm_hi; mov rb_vpm_hi, ra_vpm_hi\n0x95701ff6, 0x10024701, // mov ra_vdw_32, rb_vdw_32; mov rb_vdw_32, ra_vdw_32\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffc00, 0xf0f80027, // brr ra_link_0, call\n0x009e7000, 0xa00009e7, // nop;        ldtmu0\n0x159e7900, 0xa0020827, // mov r0, r4; ldtmu0\n0x159e7900, 0x10020867, // mov r1, r4\n0x00000000, 0xf0f489e7, // bra -, ra_save_16\n0x009e7000, 0x100009e7, // nop\n0x95642ff6, 0x10024642, // mov ra_vpm_lo, rb_vpm_lo; mov rb_vpm_lo, ra_vpm_lo\n0x956c0ff6, 0x100246c0, // mov ra_vdw_16, rb_vdw_16; mov rb_vdw_16, ra_vdw_16\n0x159c5fc0, 0x10022827, // mov.setf r0, rb_inst\n0x0d9c11c0, 0xd0020827, // sub r0, r0, 1\n0x119c51c0, 0xd0020827, // shl r0, r0, 5\n0x0c9c6e00, 0x100601a7, // add.ifnz ra_sync, rx_sync_slave, r0\n0x159c4fc0, 0x10060127, // mov.ifnz ra_save_16, rx_save_slave_16\n0x159cafc0, 0x100602a7, // mov.ifnz ra_save_32, rx_save_slave_32\n0x15827d80, 0x100220e7, // mov.setf ra_addr_x, unif\n0x15827d80, 0x100210e7, // mov      rb_addr_y, unif\n0x00000590, 0xf00809e7, // brr.allz -, r:end\n0x952cbdbf, 0x10024410, // mov ra_tw_re+TW32_ACTIVE, ra_tw_re+tw32; mov rb_tw_im+TW32_ACTIVE, rb_tw_im+tw32\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c462, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d463, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c51c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15bdf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x14767180, 0x10020867, // and r1, r0, mask\n0x0e9c11c0, 0xd0020827, // shr r0, r0, shift\n0x14767180, 0x10020827, // and r0, r0, mask\n0x119c13c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147a7180, 0x10020867, // and r1, r0, mask\n0x0e9c21c0, 0xd0020827, // shr r0, r0, shift\n0x147a7180, 0x10020827, // and r0, r0, mask\n0x119c23c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x147e7180, 0x10020867, // and r1, r0, mask\n0x0e9c41c0, 0xd0020827, // shr r0, r0, shift\n0x147e7180, 0x10020827, // and r0, r0, mask\n0x119c43c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x149da1c0, 0x10020867, // and r1, r0, mask\n0x0e9c81c0, 0xd0020827, // shr r0, r0, shift\n0x149da1c0, 0x10020827, // and r0, r0, mask\n0x119c83c0, 0xd0020867, // shl r1, r1, shift\n0x159e7040, 0x10020827, // or  r0, r0, r1\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x94981dc0, 0xd00269e2, // and.setf -, elem_num, 1; mov r2, r0\n0x959f1489, 0xd004c820, // mov.ifz  r0, r2; mov.ifnz r0, r1 >> 1\n0x959ff252, 0xd0068861, // mov.ifnz r1, r1; mov.ifz  r1, r2 << 1\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffb50, 0xf0f80227, // brr ra_link_1, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x0e1cddc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffb28, 0xf00809e7, // brr.allz -, r:pass_1\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dfdc0, 0x100201e7, // add ra_points, ra_points, rb_0x100\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x9530cdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c462, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d463, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffc98, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dddc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0xfffffc78, 0xf0f80227, // brr ra_link_1, r:pass_2\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dddc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x95514dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x20367016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209cd017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209cd01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x2136709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02527c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d4ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c462, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d463, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1cddc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffffbb0, 0xf00809e7, // brr.allz -, r:pass_2\n0x00000020, 0xe0020827, // mov r0, 4*8\n0x0d227c00, 0x10020227, // sub ra_link_1, ra_link_1, r0\n0x0c1dddc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0x950c3dbf, 0x100250c3, // mov rb_addr_y, ra_addr_x; mov ra_addr_x, rb_addr_y\n0x953cfdbf, 0x100248a3, // mov r2, ra_tw_re+tw16; mov r3, rb_tw_im+tw16\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c462, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d463, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x159c5fc0, 0x10020827, // mov r0, rb_inst\n0x119c41c0, 0xd0020827, // shl r0, r0, m\n0x0c9a7180, 0x10020167, // add ra_load_idx, r0, elem_num\n0x00000000, 0xe00201e7, // mov ra_points, 0\n0x159c3fc0, 0x10020067, // mov ra_save_ptr, rb_addr_y\n0x8c15ddf6, 0x10024160, // add ra_load_idx, ra_load_idx, stride; mov r0, ra_load_idx\n0x119c31c0, 0xd0020827, // shl r0, r0, 3\n0x0c9c41c0, 0xd0020867, // add r1, r0, 4\n0x0c0e7c00, 0x10020e27, // add t0s, ra_addr_x, r0\n0x0c0e7c40, 0x10020e27, // add t0s, ra_addr_x, r1\n0xfffffab0, 0xf0f80227, // brr ra_link_1, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dddc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x95514dbf, 0x100248a3, // mov r2, ra_tw_re+TW16_ACTIVE+3; mov r3, rb_tw_im+TW16_ACTIVE+3\n0x203a7016, 0x100049e0, // nop;             fmul r0, r2, ra_tw_re+tw16\n0x209ce017, 0x100049e1, // nop;             fmul r1, r2, rb_tw_im+tw16\n0x209ce01f, 0x100049e2, // nop;             fmul r2, r3, rb_tw_im+tw16\n0x213a709e, 0x100248a3, // fadd r2, r0, r2; fmul r3, r3, ra_tw_re+tw16\n0x029e7640, 0x100208e7, // fsub r3, r3, r1\n0x02527c80, 0x100208a7, // fsub r2, ra_tw_re+TW16_ACTIVE+3, r2\n0x029d4ec0, 0x100208e7, // fsub r3, rb_tw_im+TW16_ACTIVE+3, r3\n0x14988dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f8492, 0xd002c522, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f86db, 0xd002d523, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14984dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f4492, 0xd002c4e2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f46db, 0xd002d4e3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14982dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f2492, 0xd002c4a2, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f26db, 0xd002d4a3, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x14981dc0, 0xd00229e7, // and.setf -, elem_num, (8>>i)\n0x959f1492, 0xd002c462, // mov ra_tw_re+TW16_ACTIVE+3-i, r2; mov.ifnz r2, r2 >> (8>>i)\n0x959f16db, 0xd002d463, // mov rb_tw_im+TW16_ACTIVE+3-i, r3; mov.ifnz r3, r3 >> (8>>i)\n0x0e1cddc0, 0xd00229e7, // shr.setf -, ra_points, STAGES\n0xfffff9e8, 0xf00809e7, // brr.allz -, r:pass_3\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c1dddc0, 0x100201e7, // add ra_points, ra_points, rb_0x80\n0x00000000, 0xf0f4c227, // bra ra_link_1, ra_sync\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0xa00009e7, // ldtmu0\n0x009e7000, 0xa00009e7, // ldtmu0\n0xfffffa40, 0xf0f809e7, // brr -, r:loop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x159c3fc0, 0x100209a7, // mov interrupt, flag\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/hex/shader_trans.hex",
    "content": "0x15827d80, 0x10020e27, // mov t0s, unif\n0x009e7000, 0xa00009e7, // ldtmu0\n0x0c9cc9c0, 0xd0020e27, // add t0s, r4, 3*4\n0x009e7000, 0xa00009e7, // ldtmu0\n0x0c827980, 0x100200a7, // add ra_src_base, r4, unif\n0x15827d80, 0x10020e27, // mov t0s, unif\n0x009e7000, 0xa00009e7, // ldtmu0\n0x0c9cc9c0, 0xd0020e27, // add t0s, r4, 3*4\n0x009e7000, 0xa00009e7, // ldtmu0\n0x0c827980, 0x100200e7, // add ra_dst_base, r4, unif\n0x15827d80, 0x100214a7, // mov rb_Y_STRIDE_SRC, unif\n0x15827d80, 0x100214e7, // mov rb_Y_STRIDE_DST, unif\n0x15827d80, 0x10021527, // mov rb_NX,           unif\n0x15827d80, 0x10021567, // mov rb_NY,           unif\n0x00000008, 0xe0021467, // mov rb_X_STRIDE, 2*4\n0x00000010, 0xe0021427, // mov rb_0x10, 0x10\n0xc0000000, 0xe0020827, // mov r0, vdw_setup_1(0)\n0x0c9d31c0, 0x10020827, // add r0, r0, rb_Y_STRIDE_DST\n0x00000040, 0xe0020867, // mov r1, 16*4\n0x0d9e7040, 0x100201a7, // sub ra_vdw_stride, r0, r1\n0x40991037, 0x100049e0, // nop; mul24 r0, elem_num, rb_X_STRIDE\n0x159e7000, 0x10021027, // mov rb_offsets_re+i, r0\n0x0c9c41c0, 0xd0021227, // add rb_offsets_im+i, r0, 4\n0x0c9d21c0, 0x10020827, // add r0, r0, rb_Y_STRIDE_SRC\n0x159e7000, 0x10021067, // mov rb_offsets_re+i, r0\n0x0c9c41c0, 0xd0021267, // add rb_offsets_im+i, r0, 4\n0x0c9d21c0, 0x10020827, // add r0, r0, rb_Y_STRIDE_SRC\n0x159e7000, 0x100210a7, // mov rb_offsets_re+i, r0\n0x0c9c41c0, 0xd00212a7, // add rb_offsets_im+i, r0, 4\n0x0c9d21c0, 0x10020827, // add r0, r0, rb_Y_STRIDE_SRC\n0x159e7000, 0x100210e7, // mov rb_offsets_re+i, r0\n0x0c9c41c0, 0xd00212e7, // add rb_offsets_im+i, r0, 4\n0x0c9d21c0, 0x10020827, // add r0, r0, rb_Y_STRIDE_SRC\n0x159e7000, 0x10021127, // mov rb_offsets_re+i, r0\n0x0c9c41c0, 0xd0021327, // add rb_offsets_im+i, r0, 4\n0x0c9d21c0, 0x10020827, // add r0, r0, rb_Y_STRIDE_SRC\n0x159e7000, 0x10021167, // mov rb_offsets_re+i, r0\n0x0c9c41c0, 0xd0021367, // add rb_offsets_im+i, r0, 4\n0x0c9d21c0, 0x10020827, // add r0, r0, rb_Y_STRIDE_SRC\n0x159e7000, 0x100211a7, // mov rb_offsets_re+i, r0\n0x0c9c41c0, 0xd00213a7, // add rb_offsets_im+i, r0, 4\n0x0c9d21c0, 0x10020827, // add r0, r0, rb_Y_STRIDE_SRC\n0x159e7000, 0x100211e7, // mov rb_offsets_re+i, r0\n0x0c9c41c0, 0xd00213e7, // add rb_offsets_im+i, r0, 4\n0x0c9d21c0, 0x10020827, // add r0, r0, rb_Y_STRIDE_SRC\n0x00000000, 0xe0020067, // mov ra_y, 0\n0x00000000, 0xe0020027, // mov ra_x, 0\n0x40052037, 0x100049e1, // nop; mul24 r1, ra_y, rb_Y_STRIDE_SRC\n0x40011037, 0x100049e0, // nop; mul24 r0, ra_x, rb_X_STRIDE\n0x0c9e7040, 0x10020827, // add r0, r0, r1\n0x0c0a7c00, 0x10020127, // add ra_src_cell, ra_src_base, r0\n0x40013037, 0x100049e1, // nop; mul24 r1, ra_x, rb_Y_STRIDE_DST\n0x40051037, 0x100049e0, // nop; mul24 r0, ra_y, rb_X_STRIDE\n0x0c9e7040, 0x10020827, // add r0, r0, r1\n0x0c0e7c00, 0x10020167, // add ra_dst_cell, ra_dst_base, r0\n0x00001200, 0xe0021c67, // mov vw_setup, vpm_setup(16, 1, v32(0,0))\n0x0c100dc0, 0x10020e27, // add t0s, ra_src_cell, rb_offsets_re\n0x0c108dc0, 0x10020f27, // add t1s, ra_src_cell, rb_offsets_im\n0x0c101dc0, 0x10020e27, // add t0s, ra_src_cell, rb_offsets_re+1+i\n0x0c109dc0, 0x10020f27, // add t1s, ra_src_cell, rb_offsets_im+1+i\n0x009e7000, 0xa00009e7, // ldtmu0\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x009e7000, 0xb00009e7, // ldtmu1\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x0c102dc0, 0x10020e27, // add t0s, ra_src_cell, rb_offsets_re+1+i\n0x0c10adc0, 0x10020f27, // add t1s, ra_src_cell, rb_offsets_im+1+i\n0x009e7000, 0xa00009e7, // ldtmu0\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x009e7000, 0xb00009e7, // ldtmu1\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x0c103dc0, 0x10020e27, // add t0s, ra_src_cell, rb_offsets_re+1+i\n0x0c10bdc0, 0x10020f27, // add t1s, ra_src_cell, rb_offsets_im+1+i\n0x009e7000, 0xa00009e7, // ldtmu0\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x009e7000, 0xb00009e7, // ldtmu1\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x0c104dc0, 0x10020e27, // add t0s, ra_src_cell, rb_offsets_re+1+i\n0x0c10cdc0, 0x10020f27, // add t1s, ra_src_cell, rb_offsets_im+1+i\n0x009e7000, 0xa00009e7, // ldtmu0\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x009e7000, 0xb00009e7, // ldtmu1\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x0c105dc0, 0x10020e27, // add t0s, ra_src_cell, rb_offsets_re+1+i\n0x0c10ddc0, 0x10020f27, // add t1s, ra_src_cell, rb_offsets_im+1+i\n0x009e7000, 0xa00009e7, // ldtmu0\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x009e7000, 0xb00009e7, // ldtmu1\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x0c106dc0, 0x10020e27, // add t0s, ra_src_cell, rb_offsets_re+1+i\n0x0c10edc0, 0x10020f27, // add t1s, ra_src_cell, rb_offsets_im+1+i\n0x009e7000, 0xa00009e7, // ldtmu0\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x009e7000, 0xb00009e7, // ldtmu1\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x0c107dc0, 0x10020e27, // add t0s, ra_src_cell, rb_offsets_re+1+i\n0x0c10fdc0, 0x10020f27, // add t1s, ra_src_cell, rb_offsets_im+1+i\n0x009e7000, 0xa00009e7, // ldtmu0\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x009e7000, 0xb00009e7, // ldtmu1\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x009e7000, 0xa00009e7, // ldtmu0\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x009e7000, 0xb00009e7, // ldtmu1\n0x159e7900, 0x10020c27, // mov vpm, r4\n0x88104000, 0xe0021c67, // mov vw_setup, vdw_setup_0(16, 16, dma_h32(0,0))\n0x151a7d80, 0x10021c67, // mov vw_setup, ra_vdw_stride\n0x15167d80, 0x10021ca7, // mov vw_addr, ra_dst_cell\n0x159f2fc0, 0x100009e7, // mov -, vw_wait\n0x0c010dc0, 0x10020027, // add ra_x, ra_x, rb_0x10\n0x009e7000, 0x100009e7, // nop\n0x0d014dc0, 0x100229e7, // sub.setf -, ra_x, rb_NX\n0xfffffde0, 0xf01809e7, // brr.allnz -, r:inner\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x0c048dc0, 0xd0020067, // add ra_y, ra_y, 8\n0x009e7000, 0x100009e7, // nop\n0x0d055dc0, 0x100229e7, // sub.setf -, ra_y, rb_NY\n0xfffffda0, 0xf01809e7, // brr.allnz -, r:outer\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n0x00000001, 0xe00209a7, // mov interrupt, 1\n0x009e7000, 0x300009e7, // nop; nop; thrend\n0x009e7000, 0x100009e7, // nop\n0x009e7000, 0x100009e7, // nop\n"
  },
  {
    "path": "src/hello_fft/mailbox.c",
    "content": "/*\nCopyright (c) 2012, Broadcom Europe Ltd.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the copyright holder nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <rtl_airband.h>\n\n#include <assert.h>\n#include <fcntl.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#include <syslog.h>\n#include <unistd.h>\n#include <cerrno>\n\n#include \"mailbox.h\"\n\n#define PAGE_SIZE (4 * 1024)\n\nvoid* mapmem(unsigned base, unsigned size) {\n    int mem_fd;\n    unsigned offset = base % PAGE_SIZE;\n    base = base - offset;\n    /* open /dev/mem */\n    if ((mem_fd = open(\"/dev/mem\", O_RDWR | O_SYNC)) < 0) {\n        log(LOG_CRIT, \"mapmem(): can't open /dev/mem: %s\\n\", strerror(errno));\n        exit(-1);\n    }\n    void* mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED /*|MAP_FIXED*/, mem_fd, base);\n#ifdef GPU_FFT_DEBUG\n    printf(\"base=0x%x, mem=%p\\n\", base, mem);\n#endif\n    if (mem == MAP_FAILED) {\n        log(LOG_CRIT, \"mapmem(): mmap error: %s\\n\", strerror(errno));\n        exit(-1);\n    }\n    close(mem_fd);\n    return (char*)mem + offset;\n}\n\nvoid unmapmem(void* addr, unsigned size) {\n    int s = munmap(addr, size);\n    if (s != 0) {\n        log(LOG_CRIT, \"unmapmem(): munmap error: %s\\n\", strerror(errno));\n        exit(-1);\n    }\n}\n\n/*\n * use ioctl to send mbox property message\n */\n\nstatic int mbox_property(int file_desc, void* buf) {\n    int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf);\n\n    if (ret_val < 0) {\n        log(LOG_ERR, \"mbox_property(): ioctl_set_msg failed: %s\\n\", strerror(errno));\n    }\n\n#ifdef GPU_FFT_DEBUG\n    unsigned* p = buf;\n    int i;\n    unsigned size = *(unsigned*)buf;\n    for (i = 0; i < size / 4; i++)\n        printf(\"%04x: 0x%08x\\n\", i * sizeof *p, p[i]);\n#endif\n    return ret_val;\n}\n\nunsigned mem_alloc(int file_desc, unsigned size, unsigned align, unsigned flags) {\n    int i = 0;\n    unsigned p[32];\n    p[i++] = 0;           // size\n    p[i++] = 0x00000000;  // process request\n\n    p[i++] = 0x3000c;  // (the tag id)\n    p[i++] = 12;       // (size of the buffer)\n    p[i++] = 12;       // (size of the data)\n    p[i++] = size;     // (num bytes? or pages?)\n    p[i++] = align;    // (alignment)\n    p[i++] = flags;    // (MEM_FLAG_L1_NONALLOCATING)\n\n    p[i++] = 0x00000000;   // end tag\n    p[0] = i * sizeof *p;  // actual size\n\n    mbox_property(file_desc, p);\n    return p[5];\n}\n\nunsigned mem_free(int file_desc, unsigned handle) {\n    int i = 0;\n    unsigned p[32];\n    p[i++] = 0;           // size\n    p[i++] = 0x00000000;  // process request\n\n    p[i++] = 0x3000f;  // (the tag id)\n    p[i++] = 4;        // (size of the buffer)\n    p[i++] = 4;        // (size of the data)\n    p[i++] = handle;\n\n    p[i++] = 0x00000000;   // end tag\n    p[0] = i * sizeof *p;  // actual size\n\n    mbox_property(file_desc, p);\n    return p[5];\n}\n\nunsigned mem_lock(int file_desc, unsigned handle) {\n    int i = 0;\n    unsigned p[32];\n    p[i++] = 0;           // size\n    p[i++] = 0x00000000;  // process request\n\n    p[i++] = 0x3000d;  // (the tag id)\n    p[i++] = 4;        // (size of the buffer)\n    p[i++] = 4;        // (size of the data)\n    p[i++] = handle;\n\n    p[i++] = 0x00000000;   // end tag\n    p[0] = i * sizeof *p;  // actual size\n\n    mbox_property(file_desc, p);\n    return p[5];\n}\n\nunsigned mem_unlock(int file_desc, unsigned handle) {\n    int i = 0;\n    unsigned p[32];\n    p[i++] = 0;           // size\n    p[i++] = 0x00000000;  // process request\n\n    p[i++] = 0x3000e;  // (the tag id)\n    p[i++] = 4;        // (size of the buffer)\n    p[i++] = 4;        // (size of the data)\n    p[i++] = handle;\n\n    p[i++] = 0x00000000;   // end tag\n    p[0] = i * sizeof *p;  // actual size\n\n    mbox_property(file_desc, p);\n    return p[5];\n}\n\nunsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5) {\n    int i = 0;\n    unsigned p[32];\n    p[i++] = 0;           // size\n    p[i++] = 0x00000000;  // process request\n\n    p[i++] = 0x30010;  // (the tag id)\n    p[i++] = 28;       // (size of the buffer)\n    p[i++] = 28;       // (size of the data)\n    p[i++] = code;\n    p[i++] = r0;\n    p[i++] = r1;\n    p[i++] = r2;\n    p[i++] = r3;\n    p[i++] = r4;\n    p[i++] = r5;\n\n    p[i++] = 0x00000000;   // end tag\n    p[0] = i * sizeof *p;  // actual size\n\n    mbox_property(file_desc, p);\n    return p[5];\n}\n\nunsigned qpu_enable(int file_desc, unsigned enable) {\n    int i = 0;\n    unsigned p[32];\n\n    p[i++] = 0;           // size\n    p[i++] = 0x00000000;  // process request\n\n    p[i++] = 0x30012;  // (the tag id)\n    p[i++] = 4;        // (size of the buffer)\n    p[i++] = 4;        // (size of the data)\n    p[i++] = enable;\n\n    p[i++] = 0x00000000;   // end tag\n    p[0] = i * sizeof *p;  // actual size\n\n    mbox_property(file_desc, p);\n    return p[5];\n}\n\nunsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout) {\n    int i = 0;\n    unsigned p[32];\n\n    p[i++] = 0;           // size\n    p[i++] = 0x00000000;  // process request\n    p[i++] = 0x30011;     // (the tag id)\n    p[i++] = 16;          // (size of the buffer)\n    p[i++] = 16;          // (size of the data)\n    p[i++] = num_qpus;\n    p[i++] = control;\n    p[i++] = noflush;\n    p[i++] = timeout;  // ms\n\n    p[i++] = 0x00000000;   // end tag\n    p[0] = i * sizeof *p;  // actual size\n\n    mbox_property(file_desc, p);\n    return p[5];\n}\n\nint mbox_open() {\n    int file_desc;\n\n    // open a char device file used for communicating with kernel mbox driver\n    file_desc = open(DEVICE_FILE_NAME, 0);\n    if (file_desc < 0) {\n        log(LOG_CRIT, \"Can't open device file %s: %s\\n\", DEVICE_FILE_NAME, strerror(errno));\n        exit(-1);\n    }\n    return file_desc;\n}\n\nvoid mbox_close(int file_desc) {\n    close(file_desc);\n}\n"
  },
  {
    "path": "src/hello_fft/mailbox.h",
    "content": "/*\nCopyright (c) 2012, Broadcom Europe Ltd.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the copyright holder nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <linux/ioctl.h>\n\n#define MAJOR_NUM 100\n#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char*)\n#define DEVICE_FILE_NAME \"/dev/vcio\"\n\nint mbox_open();\nvoid mbox_close(int file_desc);\n\nunsigned get_version(int file_desc);\nunsigned mem_alloc(int file_desc, unsigned size, unsigned align, unsigned flags);\nunsigned mem_free(int file_desc, unsigned handle);\nunsigned mem_lock(int file_desc, unsigned handle);\nunsigned mem_unlock(int file_desc, unsigned handle);\nvoid* mapmem(unsigned base, unsigned size);\nvoid unmapmem(void* addr, unsigned size);\n\nunsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5);\nunsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout);\nunsigned qpu_enable(int file_desc, unsigned enable);\n"
  },
  {
    "path": "src/helper_functions.cpp",
    "content": "/*\n * helper_functions.cpp\n *\n * Copyright (C) 2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <sys/stat.h>  // struct stat, S_ISDIR\n#include <cstddef>     // size_t\n#include <cstring>     // strerror\n\n#include \"helper_functions.h\"\n#include \"logging.h\"\n\nusing namespace std;\n\nbool dir_exists(const string& dir_path) {\n    struct stat st;\n    return (stat(dir_path.c_str(), &st) == 0 && S_ISDIR(st.st_mode));\n}\n\nbool file_exists(const string& file_path) {\n    struct stat st;\n    return (stat(file_path.c_str(), &st) == 0 && S_ISREG(st.st_mode));\n}\n\nbool make_dir(const string& dir_path) {\n    if (dir_exists(dir_path)) {\n        return true;\n    }\n\n    if (mkdir(dir_path.c_str(), 0755) != 0) {\n        log(LOG_ERR, \"Could not create directory %s: %s\\n\", dir_path.c_str(), strerror(errno));\n        return false;\n    }\n    return true;\n}\n\nbool make_subdirs(const string& basedir, const string& subdirs) {\n    // if final directory exists then nothing to do\n    const string delim = \"/\";\n    const string final_path = basedir + delim + subdirs;\n    if (dir_exists(final_path)) {\n        return true;\n    }\n\n    // otherwise scan through subdirs for each slash and make each directory.  start with index of 0\n    // to create basedir incase that doesn't exist\n    size_t index = 0;\n    while (index != string::npos) {\n        if (!make_dir(basedir + delim + subdirs.substr(0, index))) {\n            return false;\n        }\n        index = subdirs.find_first_of(delim, index + 1);\n    }\n\n    make_dir(final_path);\n    return dir_exists(final_path);\n}\n\nstring make_dated_subdirs(const string& basedir, const struct tm* time) {\n    // use the time to build the date subdirectories\n    char date_path[11];\n    strftime(date_path, sizeof(date_path), \"%Y/%m/%d\", time);\n    const string date_path_str = string(date_path);\n\n    // make all the subdirectories, and return the full path if successful\n    if (make_subdirs(basedir, date_path_str)) {\n        return basedir + \"/\" + date_path_str;\n    }\n\n    // on any error return empty string\n    return \"\";\n}\n"
  },
  {
    "path": "src/helper_functions.h",
    "content": "/*\n * helper_functions.h\n *\n * Copyright (C) 2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#ifndef _HELPER_FUNCTIONS_H\n#define _HELPER_FUNCTIONS_H\n\n#include <ctime>  // struct tm\n#include <string>\n\nbool dir_exists(const std::string& dir_path);\nbool file_exists(const std::string& file_path);\nbool make_dir(const std::string& dir_path);\nbool make_subdirs(const std::string& basedir, const std::string& subdirs);\nstd::string make_dated_subdirs(const std::string& basedir, const struct tm* time);\n\n#endif /* _HELPER_FUNCTIONS_H */\n"
  },
  {
    "path": "src/input-common.cpp",
    "content": "/*\n * input-common.cpp\n * common input handling routines\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"input-common.h\"\n#include <assert.h>\n#include <dlfcn.h>  // dlopen, dlsym\n#include <errno.h>\n#include <pthread.h>\n#include <stdio.h>   // asprintf\n#include <stdlib.h>  // free\n#include <string.h>\n#include <iostream>\n\nusing namespace std;\n\ntypedef input_t* (*input_new_func_t)(void);\n\ninput_t* input_new(char const* const type) {\n    assert(type != NULL);\n    void* dlhandle = dlopen(NULL, RTLD_NOW);\n    assert(dlhandle != NULL);\n    char* fname = NULL;\n    int chars_written = asprintf(&fname, \"%s_input_new\", type);\n    if (chars_written <= 0) {\n        return NULL;\n    }\n    input_new_func_t fptr = (input_new_func_t)dlsym(dlhandle, fname);\n    free(fname);\n    if (fptr == NULL) {\n        return NULL;\n    }\n    input_t* input = (*fptr)();\n    assert(input->init != NULL);\n    assert(input->run_rx_thread != NULL);\n    assert(input->set_centerfreq != NULL);\n    return input;\n}\n\nint input_init(input_t* const input) {\n    assert(input != NULL);\n    input_state_t new_state = INPUT_FAILED;  // fail-safe default\n    errno = 0;\n    int ret = input->init(input);\n    if (ret < 0) {\n        ret = -1;\n    } else if ((ret = pthread_mutex_init(&input->buffer_lock, NULL)) != 0) {\n        errno = ret;\n        ret = -1;\n    } else {\n        new_state = INPUT_INITIALIZED;\n        ret = 0;\n    }\n    input->state = new_state;\n    return ret;\n}\n\nint input_start(input_t* const input) {\n    assert(input != NULL);\n    assert(input->dev_data != NULL);\n    assert(input->state == INPUT_INITIALIZED);\n    int err = pthread_create(&input->rx_thread, NULL, input->run_rx_thread, (void*)input);\n    if (err != 0) {\n        errno = err;\n        return -1;\n    }\n    return 0;\n}\n\nint input_parse_config(input_t* const input, libconfig::Setting& cfg) {\n    assert(input != NULL);\n    if (input->parse_config != NULL) {\n        return input->parse_config(input, cfg);\n    } else {\n        // Very simple inputs (like stdin) might not necessarily have any configuration\n        // variables, so it's legal not to have parse_config defined.\n        return 0;\n    }\n}\n\nint input_stop(input_t* const input) {\n    assert(input != NULL);\n    assert(input->dev_data != NULL);\n    int err = 0;\n    errno = 0;\n    if (input->state == INPUT_RUNNING && input->stop != NULL) {\n        err = input->stop(input);\n        if (err != 0) {\n            input->state = INPUT_FAILED;\n            return -1;\n        }\n    }\n    input->state = INPUT_STOPPED;\n    err = pthread_join(input->rx_thread, NULL);\n    if (err != 0) {\n        errno = err;\n        return -1;\n    }\n    return 0;\n}\n\nint input_set_centerfreq(input_t* const input, int const centerfreq) {\n    assert(input != NULL);\n    assert(input->dev_data != NULL);\n    if (input->state != INPUT_RUNNING) {\n        return -1;\n    }\n    int ret = input->set_centerfreq(input, centerfreq);\n    if (ret != 0) {\n        input->state = INPUT_FAILED;\n        return -1;\n    }\n    input->centerfreq = centerfreq;\n    return 0;\n}\n"
  },
  {
    "path": "src/input-common.h",
    "content": "/*\n * input-common.h\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#ifndef _INPUT_COMMON_H\n#define _INPUT_COMMON_H 1\n#include <pthread.h>\n#include <libconfig.h++>\n\n#if __GNUC__ >= 4\n#define MODULE_EXPORT extern \"C\" __attribute__((visibility(\"default\")))\n#else\n#define MODULE_EXPORT extern \"C\"\n#endif /* __GNUC__ */\n\ntypedef enum { SFMT_UNDEF = 0, SFMT_U8, SFMT_S8, SFMT_S16, SFMT_F32 } sample_format_t;\n#define SAMPLE_FORMAT_CNT 5\n\ntypedef enum { INPUT_UNKNOWN = 0, INPUT_INITIALIZED, INPUT_RUNNING, INPUT_FAILED, INPUT_STOPPED, INPUT_DISABLED } input_state_t;\n#define INPUT_STATE_CNT 6\n\ntypedef struct input_t input_t;\n\nstruct input_t {\n    unsigned char* buffer;\n    void* dev_data;\n    size_t buf_size, bufs, bufe;\n    size_t overflow_count;\n    input_state_t state;\n    sample_format_t sfmt;\n    float fullscale;\n    int bytes_per_sample;\n    int sample_rate;\n    int centerfreq;\n    int (*parse_config)(input_t* const input, libconfig::Setting& cfg);\n    int (*init)(input_t* const input);\n    void* (*run_rx_thread)(void* input_ptr);  // to be launched via pthread_create()\n    int (*set_centerfreq)(input_t* const input, int const centerfreq);\n    int (*stop)(input_t* const input);\n    pthread_t rx_thread;\n    pthread_mutex_t buffer_lock;\n};\n\ninput_t* input_new(char const* const type);\nint input_init(input_t* const input);\nint input_parse_config(input_t* const input, libconfig::Setting& cfg);\nint input_start(input_t* const input);\nint input_set_centerfreq(input_t* const input, int const centerfreq);\nint input_stop(input_t* const input);\n\n#endif /* _INPUT_COMMON_H */\n"
  },
  {
    "path": "src/input-file.cpp",
    "content": "/*\n * input-file.cpp\n * binary file specific routines\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"input-file.h\"  // file_dev_data_t\n#include <assert.h>\n#include <limits.h>  // SCHAR_MAX\n#include <stdio.h>\n#include <string.h>\n#include <syslog.h>         // FIXME: get rid of this\n#include <unistd.h>         // usleep\n#include <libconfig.h++>    // Setting\n#include \"input-common.h\"   // input_t, sample_format_t, input_state_t, MODULE_EXPORT\n#include \"input-helpers.h\"  // circbuffer_append\n#include \"rtl_airband.h\"    // do_exit, fft_size, debug_print, XCALLOC, error()\n\nusing namespace std;\n\nint file_parse_config(input_t* const input, libconfig::Setting& cfg) {\n    assert(input != NULL);\n    file_dev_data_t* dev_data = (file_dev_data_t*)input->dev_data;\n    assert(dev_data != NULL);\n\n    if (cfg.exists(\"filepath\")) {\n        dev_data->filepath = strdup(cfg[\"filepath\"]);\n    } else {\n        cerr << \"File configuration error: no 'filepath' given\\n\";\n        error();\n    }\n\n    if (cfg.exists(\"speedup_factor\")) {\n        if (cfg[\"speedup_factor\"].getType() == libconfig::Setting::TypeInt) {\n            dev_data->speedup_factor = (int)cfg[\"speedup_factor\"];\n        } else if (cfg[\"speedup_factor\"].getType() == libconfig::Setting::TypeFloat) {\n            dev_data->speedup_factor = (float)cfg[\"speedup_factor\"];\n        } else {\n            cerr << \"File configuration error: 'speedup_factor' must be a float or int if set\\n\";\n            error();\n        }\n        if (dev_data->speedup_factor <= 0.0) {\n            cerr << \"File configuration error: 'speedup_factor' must be >= 0.0\\n\";\n            error();\n        }\n    } else {\n        dev_data->speedup_factor = 4;\n    }\n\n    return 0;\n}\n\nint file_init(input_t* const input) {\n    assert(input != NULL);\n    file_dev_data_t* dev_data = (file_dev_data_t*)input->dev_data;\n    assert(dev_data != NULL);\n\n    dev_data->input_file = fopen(dev_data->filepath, \"rb\");\n    if (!dev_data->input_file) {\n        cerr << \"File input failed to open '\" << dev_data->filepath << \"' - \" << strerror(errno) << endl;\n        error();\n    }\n\n    log(LOG_INFO, \"File input %s initialized\\n\", dev_data->filepath);\n    return 0;\n}\n\nvoid* file_rx_thread(void* ctx) {\n    input_t* input = (input_t*)ctx;\n    assert(input != NULL);\n    assert(input->sample_rate != 0);\n    file_dev_data_t* dev_data = (file_dev_data_t*)input->dev_data;\n    assert(dev_data != NULL);\n    assert(dev_data->input_file != NULL);\n    assert(dev_data->speedup_factor != 0.0);\n\n    size_t buf_len = (input->buf_size / 2) - 1;\n    unsigned char* buf = (unsigned char*)XCALLOC(1, buf_len);\n\n    float time_per_byte_ms = 1000 / (input->sample_rate * input->bytes_per_sample * 2 * dev_data->speedup_factor);\n\n    log(LOG_DEBUG, \"sample_rate: %d, bytes_per_sample: %d, speedup_factor: %f, time_per_byte_ms: %f\\n\", input->sample_rate, input->bytes_per_sample, dev_data->speedup_factor, time_per_byte_ms);\n\n    input->state = INPUT_RUNNING;\n\n    while (true) {\n        if (do_exit) {\n            break;\n        }\n        if (feof(dev_data->input_file)) {\n            log(LOG_INFO, \"File '%s': hit end of file at %d, disabling\\n\", dev_data->filepath, ftell(dev_data->input_file));\n            input->state = INPUT_FAILED;\n            break;\n        }\n        if (ferror(dev_data->input_file)) {\n            log(LOG_ERR, \"File '%s': read error (%d), disabling\\n\", dev_data->filepath, ferror(dev_data->input_file));\n            input->state = INPUT_FAILED;\n            break;\n        }\n\n        timeval start;\n        gettimeofday(&start, NULL);\n\n        size_t space_left;\n        pthread_mutex_lock(&input->buffer_lock);\n        if (input->bufe >= input->bufs) {\n            space_left = input->bufs + (input->buf_size - input->bufe);\n        } else {\n            space_left = input->bufs - input->bufe;\n        }\n        pthread_mutex_unlock(&input->buffer_lock);\n\n        if (space_left > buf_len) {\n            size_t len = fread(buf, sizeof(unsigned char), buf_len, dev_data->input_file);\n            circbuffer_append(input, buf, len);\n\n            timeval end;\n            gettimeofday(&end, NULL);\n\n            int time_taken_ms = delta_sec(&start, &end) * 1000;\n            int sleep_time_ms = len * time_per_byte_ms - time_taken_ms;\n\n            if (sleep_time_ms > 0) {\n                SLEEP(sleep_time_ms);\n            }\n        } else {\n            SLEEP(10);\n        }\n    }\n\n    free(buf);\n    return 0;\n}\n\nint file_set_centerfreq(input_t* const /*input*/, int const /*centerfreq*/) {\n    return 0;\n}\n\nint file_stop(input_t* const input) {\n    assert(input != NULL);\n    file_dev_data_t* dev_data = (file_dev_data_t*)input->dev_data;\n    assert(dev_data != NULL);\n    fclose(dev_data->input_file);\n    dev_data->input_file = NULL;\n    return 0;\n}\n\nMODULE_EXPORT input_t* file_input_new() {\n    file_dev_data_t* dev_data = (file_dev_data_t*)XCALLOC(1, sizeof(file_dev_data_t));\n    dev_data->input_file = NULL;\n    dev_data->speedup_factor = 0.0;\n\n    input_t* input = (input_t*)XCALLOC(1, sizeof(input_t));\n    input->dev_data = dev_data;\n    input->state = INPUT_UNKNOWN;\n    input->sfmt = SFMT_U8;\n    input->fullscale = (float)SCHAR_MAX - 0.5f;\n    input->bytes_per_sample = sizeof(unsigned char);\n    input->sample_rate = 0;\n    input->parse_config = &file_parse_config;\n    input->init = &file_init;\n    input->run_rx_thread = &file_rx_thread;\n    input->set_centerfreq = &file_set_centerfreq;\n    input->stop = &file_stop;\n\n    return input;\n}\n"
  },
  {
    "path": "src/input-file.h",
    "content": "/*\n *  input-file.h\n *  RTLSDR-specific declarations\n *\n *  Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <fstream>\n#include <iostream>\n#include <string>\n\ntypedef struct {\n    char* filepath;\n    FILE* input_file;\n    float speedup_factor;\n} file_dev_data_t;\n"
  },
  {
    "path": "src/input-helpers.cpp",
    "content": "/*\n * input-helpers.cpp\n * Convenience functions to be called by input drivers\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <pthread.h>       // pthread_mutex_lock, unlock\n#include <string.h>        // memcpy\n#include <iostream>        // cerr\n#include \"input-common.h\"  // input_t\n#include \"rtl_airband.h\"   // debug_print\n\n/* Write input data into circular buffer input->buffer.\n * In general, input->buffer_size is not an exact multiple of len,\n * so we have to take care about proper wrapping.\n * input->buffer_size is an exact multiple of FFT_BATCH * bps\n * (input bytes per output audio sample) and input->buffer's real length\n * is input->buf_size + 2 * bytes_per_input-sample * fft_size. On each\n * wrap we copy 2 * fft_size bytes from the start of input->buffer to its end,\n * so that the signal windowing function could handle the whole FFT batch\n * without wrapping.\n */\nvoid circbuffer_append(input_t* const input, unsigned char* buf, size_t len) {\n    if (len == 0)\n        return;\n    pthread_mutex_lock(&input->buffer_lock);\n    size_t space_left = input->buf_size - input->bufe;\n    if (space_left >= len) {\n        memcpy(input->buffer + input->bufe, buf, len);\n        if (input->bufe == 0) {\n            memcpy(input->buffer + input->buf_size, input->buffer, std::min(len, 2 * input->bytes_per_sample * fft_size));\n            debug_print(\"tail_len=%zu bytes\\n\", std::min(len, 2 * input->bytes_per_sample * fft_size));\n        }\n    } else {\n        memcpy(input->buffer + input->bufe, buf, space_left);\n        memcpy(input->buffer, buf + space_left, len - space_left);\n        memcpy(input->buffer + input->buf_size, input->buffer, std::min(len - space_left, 2 * input->bytes_per_sample * fft_size));\n        debug_print(\"buf wrap: space_left=%zu len=%zu bufe=%zu wrap_len=%zu tail_len=%zu\\n\", space_left, len, input->bufe, len - space_left,\n                    std::min(len - space_left, 2 * input->bytes_per_sample * fft_size));\n    }\n\n    size_t old_end = input->bufe;\n    input->bufe = (input->bufe + len) % input->buf_size;\n    if (old_end < input->bufs && input->bufe >= input->bufs) {\n        std::cerr << \"Warning: buffer overflow\\n\";\n        input->overflow_count++;\n    }\n    pthread_mutex_unlock(&input->buffer_lock);\n}\n"
  },
  {
    "path": "src/input-helpers.h",
    "content": "/*\n * input-helpers.h\n * Convenience functions to be called by input drivers\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"input-common.h\"  // input_t\n\n// input-helpers.cpp\nvoid circbuffer_append(input_t* const input, unsigned char* buf, size_t len);\n"
  },
  {
    "path": "src/input-mirisdr.cpp",
    "content": "/*\n *  input-mirisdr.cpp\n *  MiriSDR-specific routines\n *\n *  Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"input-mirisdr.h\"  // mirisdr_dev_data_t\n#include <assert.h>\n#include <limits.h>  // SCHAR_MAX\n#include <mirisdr.h>\n#include <stdint.h>  // uint32_t\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <syslog.h>  // FIXME: get rid of this\n#include <iostream>\n#include <libconfig.h++>    // Setting\n#include \"input-common.h\"   // input_t, sample_format_t, input_state_t, MODULE_EXPORT\n#include \"input-helpers.h\"  // circbuffer_append\n#include \"rtl_airband.h\"    // do_exit, fft_size, debug_print, XCALLOC, error()\n\nusing namespace std;\n\nstatic void mirisdr_callback(unsigned char* buf, uint32_t len, void* ctx) {\n    if (do_exit)\n        return;\n    input_t* input = (input_t*)ctx;\n    circbuffer_append(input, buf, (size_t)len);\n}\n\n/* based on librtlsdr-keenerd, (c) Kyle Keen */\nstatic bool mirisdr_nearest_gain(mirisdr_dev_t* dev, int target_gain, int* nearest) {\n    assert(nearest != NULL);\n    int i, r, err1, err2, count;\n    int* gains;\n    r = mirisdr_set_tuner_gain_mode(dev, 1);\n    if (r < 0) {\n        return false;\n    }\n    count = mirisdr_get_tuner_gains(dev, NULL);\n    if (count <= 0) {\n        return false;\n    }\n    gains = (int*)XCALLOC(count, sizeof(int));\n    count = mirisdr_get_tuner_gains(dev, gains);\n    *nearest = gains[0];\n    for (i = 0; i < count; i++) {\n        err1 = abs(target_gain - *nearest);\n        err2 = abs(target_gain - gains[i]);\n        if (err2 < err1) {\n            *nearest = gains[i];\n        }\n    }\n    free(gains);\n    return true;\n}\n\nstatic int mirisdr_find_device_by_serial(char const* const s) {\n    char vendor[256] = {0}, product[256] = {0}, serial[256] = {0};\n    int count = mirisdr_get_device_count();\n    if (count < 1) {\n        return -1;\n    }\n    for (int i = 0; i < count; i++) {\n        mirisdr_get_device_usb_strings(i, vendor, product, serial);\n        if (strcmp(s, serial) != 0) {\n            continue;\n        }\n        return i;\n    }\n    return -1;\n}\n\nint mirisdr_init(input_t* const input) {\n    mirisdr_dev_data_t* dev_data = (mirisdr_dev_data_t*)input->dev_data;\n    if (dev_data->serial != NULL) {\n        dev_data->index = mirisdr_find_device_by_serial(dev_data->serial);\n        if (dev_data->index < 0) {\n            cerr << \"MiriSDR device with serial number \" << dev_data->serial << \" not found\\n\";\n            error();\n        }\n    }\n\n    dev_data->dev = NULL;\n    mirisdr_open(&dev_data->dev, dev_data->index);\n    if (NULL == dev_data->dev) {\n        log(LOG_ERR, \"Failed to open mirisdr device #%d.\\n\", dev_data->index);\n        error();\n    }\n\n    char transfer_str[] = \"BULK\";\n    char sample_format_str[] = \"504_S8\";\n\n    mirisdr_dev_t* miri = dev_data->dev;\n    int r = mirisdr_set_transfer(miri, transfer_str);\n    if (r < 0) {\n        log(LOG_ERR, \"Failed to set bulk transfer mode for MiriSDR device #%d: error %d\\n\", dev_data->index, r);\n        error();\n    }\n    r = mirisdr_set_sample_rate(miri, input->sample_rate);\n    if (r < 0) {\n        log(LOG_ERR, \"Failed to set sample rate for device #%d. Error %d.\\n\", dev_data->index, r);\n    }\n\n    r = mirisdr_set_center_freq(miri, input->centerfreq - dev_data->correction);\n    if (r < 0) {\n        log(LOG_ERR, \"Failed to set center freq for device #%d. Error %d.\\n\", dev_data->index, r);\n    }\n\n    int ngain = 0;\n    if (mirisdr_nearest_gain(miri, dev_data->gain, &ngain) != true) {\n        log(LOG_ERR, \"Failed to read supported gain list for device #%d\\n\", dev_data->index);\n        error();\n    }\n    r = mirisdr_set_tuner_gain_mode(miri, 1);\n    r |= mirisdr_set_tuner_gain(miri, ngain);\n    if (r < 0) {\n        log(LOG_ERR, \"Failed to set gain to %d for device #%d: error %d\\n\", ngain, dev_data->index, r);\n    } else {\n        log(LOG_INFO, \"Device #%d: gain set to %d dB\\n\", dev_data->index, mirisdr_get_tuner_gain(miri));\n    }\n    r = mirisdr_set_sample_format(miri, sample_format_str);\n    if (r < 0) {\n        log(LOG_ERR, \"Failed to set sample format for device #%d: error %d\\n\", dev_data->index, r);\n        error();\n    }\n    mirisdr_reset_buffer(miri);\n    log(LOG_INFO, \"MiriSDR device %d initialized\\n\", dev_data->index);\n    return 0;\n}\n\nvoid* mirisdr_rx_thread(void* ctx) {\n    input_t* input = (input_t*)ctx;\n    mirisdr_dev_data_t* dev_data = (mirisdr_dev_data_t*)input->dev_data;\n    assert(dev_data->dev != NULL);\n\n    input->state = INPUT_RUNNING;\n    if (mirisdr_read_async(dev_data->dev, mirisdr_callback, ctx, dev_data->bufcnt, MIRISDR_BUFSIZE) < 0) {\n        log(LOG_ERR, \"MiriSDR device #%d: async read failed, disabling\\n\", dev_data->index);\n        input->state = INPUT_FAILED;\n    }\n    return 0;\n}\n\nint mirisdr_stop(input_t* const input) {\n    mirisdr_dev_data_t* dev_data = (mirisdr_dev_data_t*)input->dev_data;\n    assert(dev_data->dev != NULL);\n\n    if (mirisdr_cancel_async(dev_data->dev) < 0) {\n        return -1;\n    }\n    return 0;\n}\n\nint mirisdr_set_centerfreq(input_t* const input, int const centerfreq) {\n    mirisdr_dev_data_t* dev_data = (mirisdr_dev_data_t*)input->dev_data;\n    assert(dev_data->dev != NULL);\n\n    int r = mirisdr_set_center_freq(dev_data->dev, centerfreq - dev_data->correction);\n    if (r < 0) {\n        log(LOG_ERR, \"Failed to set centerfreq for MiriSDR device #%d: error %d\\n\", dev_data->index, r);\n        return -1;\n    }\n    return 0;\n}\n\nint mirisdr_parse_config(input_t* const input, libconfig::Setting& cfg) {\n    mirisdr_dev_data_t* dev_data = (mirisdr_dev_data_t*)input->dev_data;\n    if (cfg.exists(\"serial\")) {\n        dev_data->serial = strdup(cfg[\"serial\"]);\n    } else if (cfg.exists(\"index\")) {\n        dev_data->index = (int)cfg[\"index\"];\n    } else {\n        cerr << \"MiriSDR configuration error: no index and no serial number given\\n\";\n        error();\n    }\n    if (cfg.exists(\"gain\")) {\n        dev_data->gain = (int)cfg[\"gain\"];\n    } else {\n        cerr << \"MiriSDR configuration error: gain is not configured\\n\";\n        error();\n    }\n    if (cfg.exists(\"correction\")) {\n        dev_data->correction = (int)cfg[\"correction\"];\n    }\n    if (cfg.exists(\"num_buffers\")) {\n        dev_data->bufcnt = (int)(cfg[\"num_buffers\"]);\n        if (dev_data->bufcnt < 1) {\n            cerr << \"MiriSDR configuration error: num_buffers must be greater than 0\\n\";\n            error();\n        }\n    }\n    return 0;\n}\n\nMODULE_EXPORT input_t* mirisdr_input_new() {\n    mirisdr_dev_data_t* dev_data = (mirisdr_dev_data_t*)XCALLOC(1, sizeof(mirisdr_dev_data_t));\n    dev_data->index = -1;  // invalid default receiver index\n    dev_data->gain = -1;   // invalid default gain value\n    dev_data->bufcnt = MIRISDR_DEFAULT_LIBUSB_BUFFER_COUNT;\n    /*\treturn &( input_t ){\n                    .dev_data = dev_data,\n                    .state = INPUT_UNKNOWN,\n                    .sfmt = SFMT_U8,\n                    .sample_rate = MIRISDR_DEFAULT_SAMPLE_RATE,\n                    .parse_config = &mirisdr_parse_config,\n                    .init = &mirisdr_init,\n                    .run_rx_thread = &mirisdr_rx_thread,\n                    .set_centerfreq = &mirisdr_set_centerfreq,\n                    .stop = &mirisdr_stop\n            }; */\n    input_t* input = (input_t*)XCALLOC(1, sizeof(input_t));\n    input->dev_data = dev_data;\n    input->state = INPUT_UNKNOWN;\n    input->sfmt = SFMT_S8;\n    input->fullscale = (float)SCHAR_MAX - 0.5f;\n    input->bytes_per_sample = sizeof(char);\n    input->sample_rate = MIRISDR_DEFAULT_SAMPLE_RATE;\n    input->parse_config = &mirisdr_parse_config;\n    input->init = &mirisdr_init;\n    input->run_rx_thread = &mirisdr_rx_thread;\n    input->set_centerfreq = &mirisdr_set_centerfreq;\n    input->stop = &mirisdr_stop;\n    return input;\n}\n"
  },
  {
    "path": "src/input-mirisdr.h",
    "content": "/*\n *  input-mirisdr.h\n *  MiriSDR-specific declarations\n *\n *  Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n#include <mirisdr.h>  // mirisdr_dev_t\n#define MIRISDR_BUFSIZE 320000\n#define MIRISDR_DEFAULT_LIBUSB_BUFFER_COUNT 10\n#define MIRISDR_DEFAULT_SAMPLE_RATE 2560000\n\ntypedef struct {\n    mirisdr_dev_t* dev;  // pointer to libmirisdr device struct\n    char* serial;        // dongle serial number\n    int index;           // dongle index\n    int correction;      // correction in Hertz (PPM correction is not supported by libmirisdr)\n    int gain;            // gain in dB\n    int bufcnt;          // libusb buffer count\n} mirisdr_dev_data_t;\n"
  },
  {
    "path": "src/input-rtlsdr.cpp",
    "content": "/*\n * input-rtlsdr.cpp\n * RTLSDR-specific routines\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"input-rtlsdr.h\"  // rtlsdr_dev_data_t\n#include <assert.h>\n#include <limits.h>  // SCHAR_MAX\n#include <rtl-sdr.h>\n#include <stdint.h>  // uint32_t\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <syslog.h>  // FIXME: get rid of this\n#include <iostream>\n#include <libconfig.h++>    // Setting\n#include \"input-common.h\"   // input_t, sample_format_t, input_state_t, MODULE_EXPORT\n#include \"input-helpers.h\"  // circbuffer_append\n#include \"rtl_airband.h\"    // do_exit, fft_size, debug_print, XCALLOC, error()\n\nusing namespace std;\n\nstatic void rtlsdr_callback(unsigned char* buf, uint32_t len, void* ctx) {\n    if (do_exit)\n        return;\n    input_t* input = (input_t*)ctx;\n    circbuffer_append(input, buf, (size_t)len);\n}\n\n/* based on librtlsdr-keenerd, (c) Kyle Keen */\nstatic bool rtlsdr_nearest_gain(rtlsdr_dev_t* dev, int target_gain, int* nearest) {\n    assert(nearest != NULL);\n    int i, r, err1, err2, count;\n    int* gains;\n    r = rtlsdr_set_tuner_gain_mode(dev, 1);\n    if (r < 0) {\n        return false;\n    }\n    count = rtlsdr_get_tuner_gains(dev, NULL);\n    if (count <= 0) {\n        return false;\n    }\n    gains = (int*)XCALLOC(count, sizeof(int));\n    count = rtlsdr_get_tuner_gains(dev, gains);\n    *nearest = gains[0];\n    for (i = 0; i < count; i++) {\n        err1 = abs(target_gain - *nearest);\n        err2 = abs(target_gain - gains[i]);\n        if (err2 < err1) {\n            *nearest = gains[i];\n        }\n    }\n    free(gains);\n    return true;\n}\n\nstatic int rtlsdr_find_device_by_serial(char const* const s) {\n    char vendor[256] = {0}, product[256] = {0}, serial[256] = {0};\n    int count = rtlsdr_get_device_count();\n    if (count < 1) {\n        return -1;\n    }\n    for (int i = 0; i < count; i++) {\n        rtlsdr_get_device_usb_strings(i, vendor, product, serial);\n        if (strcmp(s, serial) != 0) {\n            continue;\n        }\n        return i;\n    }\n    return -1;\n}\n\nint rtlsdr_init(input_t* const input) {\n    rtlsdr_dev_data_t* dev_data = (rtlsdr_dev_data_t*)input->dev_data;\n    if (dev_data->serial != NULL) {\n        dev_data->index = rtlsdr_find_device_by_serial(dev_data->serial);\n        if (dev_data->index < 0) {\n            cerr << \"RTLSDR device with serial number \" << dev_data->serial << \" not found\\n\";\n            error();\n        }\n    }\n\n    dev_data->dev = NULL;\n    rtlsdr_open(&dev_data->dev, dev_data->index);\n    if (NULL == dev_data->dev) {\n        log(LOG_ERR, \"Failed to open rtlsdr device #%d.\\n\", dev_data->index);\n        error();\n    }\n\n    rtlsdr_dev_t* rtl = dev_data->dev;\n    int r = rtlsdr_set_sample_rate(rtl, input->sample_rate);\n    if (r < 0) {\n        log(LOG_ERR, \"Failed to set sample rate for device #%d. Error %d.\\n\", dev_data->index, r);\n    }\n\n    r = rtlsdr_set_center_freq(rtl, input->centerfreq);\n    if (r < 0) {\n        log(LOG_ERR, \"Failed to set center freq for device #%d. Error %d.\\n\", dev_data->index, r);\n    }\n\n    r = rtlsdr_set_freq_correction(rtl, dev_data->correction);\n    if (r < 0 && r != -2) {\n        log(LOG_ERR, \"Failed to set freq correction for device #%d. Error %d.\\n\", dev_data->index, r);\n    }\n\n    // Fitipower FC0012 gain needs to be initialized to its lowest value before setting it to the desired value\n    if (rtlsdr_get_tuner_type(rtl) == RTLSDR_TUNER_FC0012) {\n        int initialGain = 0;\n        if (rtlsdr_nearest_gain(rtl, -99, &initialGain) != true) {\n            log(LOG_ERR, \"Failed to read supported gain list for device #%d\\n\", dev_data->index);\n            error();\n        }\n\n        r |= rtlsdr_set_tuner_gain(rtl, initialGain);\n        if (r < 0) {\n            log(LOG_ERR, \"Failed to initialize gain for device #%d: error %d\\n\", (float)initialGain / 10.f, dev_data->index, r);\n        }\n    }\n\n    int ngain = 0;\n    if (rtlsdr_nearest_gain(rtl, dev_data->gain, &ngain) != true) {\n        log(LOG_ERR, \"Failed to read supported gain list for device #%d\\n\", dev_data->index);\n        error();\n    }\n    r = rtlsdr_set_tuner_gain_mode(rtl, 1);\n    r |= rtlsdr_set_tuner_gain(rtl, ngain);\n    if (r < 0) {\n        log(LOG_ERR, \"Failed to set gain to %0.2f for device #%d: error %d\\n\", (float)ngain / 10.f, dev_data->index, r);\n    } else {\n        log(LOG_INFO, \"Device #%d: gain set to %0.2f dB\\n\", dev_data->index, (float)rtlsdr_get_tuner_gain(rtl) / 10.f);\n    }\n\n    r = rtlsdr_set_agc_mode(rtl, 0);\n    if (r < 0) {\n        log(LOG_ERR, \"Failed to disable AGC for device #%d. Error %d.\\n\", dev_data->index, r);\n    }\n    rtlsdr_reset_buffer(rtl);\n    log(LOG_INFO, \"RTLSDR device %d initialized\\n\", dev_data->index);\n    return 0;\n}\n\nvoid* rtlsdr_rx_thread(void* ctx) {\n    input_t* input = (input_t*)ctx;\n    rtlsdr_dev_data_t* dev_data = (rtlsdr_dev_data_t*)input->dev_data;\n    assert(dev_data->dev != NULL);\n\n    input->state = INPUT_RUNNING;\n    if (rtlsdr_read_async(dev_data->dev, rtlsdr_callback, ctx, dev_data->bufcnt, RTLSDR_BUFSIZE) < 0) {\n        log(LOG_ERR, \"RTLSDR device #%d: async read failed, disabling\\n\", dev_data->index);\n        input->state = INPUT_FAILED;\n    }\n    return 0;\n}\n\nint rtlsdr_stop(input_t* const input) {\n    rtlsdr_dev_data_t* dev_data = (rtlsdr_dev_data_t*)input->dev_data;\n    assert(dev_data->dev != NULL);\n\n    if (rtlsdr_cancel_async(dev_data->dev) < 0) {\n        return -1;\n    }\n    return rtlsdr_close(dev_data->dev);\n}\n\nint rtlsdr_set_centerfreq(input_t* const input, int const centerfreq) {\n    rtlsdr_dev_data_t* dev_data = (rtlsdr_dev_data_t*)input->dev_data;\n    assert(dev_data->dev != NULL);\n\n    int r = rtlsdr_set_center_freq(dev_data->dev, centerfreq);\n    if (r < 0) {\n        log(LOG_ERR, \"Failed to set centerfreq for RTLSDR device #%d: error %d\\n\", dev_data->index, r);\n        return -1;\n    }\n    return 0;\n}\n\nint rtlsdr_parse_config(input_t* const input, libconfig::Setting& cfg) {\n    rtlsdr_dev_data_t* dev_data = (rtlsdr_dev_data_t*)input->dev_data;\n    if (cfg.exists(\"serial\")) {\n        dev_data->serial = strdup(cfg[\"serial\"]);\n    } else if (cfg.exists(\"index\")) {\n        dev_data->index = (int)cfg[\"index\"];\n    } else {\n        cerr << \"RTLSDR configuration error: no index and no serial number given\\n\";\n        error();\n    }\n    if (cfg.exists(\"gain\")) {\n        if (cfg[\"gain\"].getType() == libconfig::Setting::TypeInt) {  // backward compatibility\n            dev_data->gain = (int)cfg[\"gain\"] * 10;\n        } else if (cfg[\"gain\"].getType() == libconfig::Setting::TypeFloat) {\n            dev_data->gain = (int)((float)cfg[\"gain\"] * 10.0f);\n        }\n    } else {\n        cerr << \"RTLSDR configuration error: gain is not configured\\n\";\n        error();\n    }\n    if (cfg.exists(\"correction\")) {\n        dev_data->correction = (int)cfg[\"correction\"];\n    }\n    if (cfg.exists(\"buffers\")) {\n        dev_data->bufcnt = (int)(cfg[\"buffers\"]);\n        if (dev_data->bufcnt < 1) {\n            cerr << \"RTLSDR configuration error: buffers must be greater than 0\\n\";\n            error();\n        }\n    }\n    return 0;\n}\n\nMODULE_EXPORT input_t* rtlsdr_input_new() {\n    rtlsdr_dev_data_t* dev_data = (rtlsdr_dev_data_t*)XCALLOC(1, sizeof(rtlsdr_dev_data_t));\n    dev_data->index = -1;  // invalid default receiver index\n    dev_data->gain = -1;   // invalid default gain value\n    dev_data->bufcnt = RTLSDR_DEFAULT_LIBUSB_BUFFER_COUNT;\n    /*\treturn &( input_t ){\n                    .dev_data = dev_data,\n                    .state = INPUT_UNKNOWN,\n                    .sfmt = SFMT_U8,\n                    .sample_rate = RTLSDR_DEFAULT_SAMPLE_RATE,\n                    .parse_config = &rtlsdr_parse_config,\n                    .init = &rtlsdr_init,\n                    .run_rx_thread = &rtlsdr_rx_thread,\n                    .set_centerfreq = &rtlsdr_set_centerfreq,\n                    .stop = &rtlsdr_stop\n            }; */\n    input_t* input = (input_t*)XCALLOC(1, sizeof(input_t));\n    input->dev_data = dev_data;\n    input->state = INPUT_UNKNOWN;\n    input->sfmt = SFMT_U8;\n    input->fullscale = (float)SCHAR_MAX - 0.5f;\n    input->bytes_per_sample = sizeof(unsigned char);\n    input->sample_rate = RTLSDR_DEFAULT_SAMPLE_RATE;\n    input->parse_config = &rtlsdr_parse_config;\n    input->init = &rtlsdr_init;\n    input->run_rx_thread = &rtlsdr_rx_thread;\n    input->set_centerfreq = &rtlsdr_set_centerfreq;\n    input->stop = &rtlsdr_stop;\n    return input;\n}\n"
  },
  {
    "path": "src/input-rtlsdr.h",
    "content": "/*\n *  input-rtlsdr.h\n *  RTLSDR-specific declarations\n *\n *  Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n#include <rtl-sdr.h>  // rtlsdr_dev_t\n#define RTLSDR_BUFSIZE 320000\n#define RTLSDR_DEFAULT_LIBUSB_BUFFER_COUNT 10\n#define RTLSDR_DEFAULT_SAMPLE_RATE 2560000\n\ntypedef struct {\n    rtlsdr_dev_t* dev;  // pointer to librtlsdr device struct\n    char* serial;       // dongle serial number\n    int index;          // dongle index\n    int correction;     // PPM correction\n    int gain;           // gain in tenths of dB\n    int bufcnt;         // libusb buffer count\n} rtlsdr_dev_data_t;\n"
  },
  {
    "path": "src/input-soapysdr.cpp",
    "content": "/*\n *  input-soapysdr.cpp\n *  SoapySDR-specific routines\n *\n *  Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"input-soapysdr.h\"    // soapysdr_dev_data_t\n#include <SoapySDR/Device.h>   // SoapySDRDevice, SoapySDRDevice_makeStrArgs\n#include <SoapySDR/Formats.h>  // SOAPY_SDR_CS constants\n#include <SoapySDR/Version.h>  // SOAPY_SDR_API_VERSION\n#include <assert.h>\n#include <limits.h>  // SCHAR_MAX, SHRT_MAX\n#include <math.h>    // round\n#include <stdlib.h>  // calloc\n#include <string.h>  // memcpy, strcmp\n#include <syslog.h>  // LOG_* macros\n#include <iostream>\n#include <libconfig.h++>    // Setting\n#include \"input-common.h\"   // input_t, sample_format_t, input_state_t, MODULE_EXPORT\n#include \"input-helpers.h\"  // circbuffer_append\n#include \"rtl_airband.h\"    // do_exit, fft_size, debug_print, XCALLOC, error()\n\nusing namespace std;\n\n// Map SoapySDR sample format string to our internal sample format\n// and set bytes_per_sample and fullscale values appropriately.\n// We prefer U8 and S8 over S16 to minimize CPU load.\n// If fullscale is > 0, it means it has been read by\n// SoapySDRDevice_getNativeStreamFormat, so we treat this value as valid.\n// Otherwise, guess a suitable default value.\nstatic bool soapysdr_match_sfmt(input_t* const input, char const* const fmt, double const fullscale) {\n    if (strcmp(fmt, SOAPY_SDR_CU8) == 0) {\n        input->sfmt = SFMT_U8;\n        input->bytes_per_sample = sizeof(unsigned char);\n        input->fullscale = (fullscale > 0 ? fullscale : (float)SCHAR_MAX - 0.5f);\n        goto matched;\n    } else if (strcmp(fmt, SOAPY_SDR_CS8) == 0) {\n        input->sfmt = SFMT_S8;\n        input->bytes_per_sample = sizeof(char);\n        input->fullscale = (fullscale > 0 ? fullscale : (float)SCHAR_MAX - 0.5f);\n        goto matched;\n    } else if (strcmp(fmt, SOAPY_SDR_CS16) == 0) {\n        input->sfmt = SFMT_S16;\n        input->bytes_per_sample = sizeof(short);\n        input->fullscale = (fullscale > 0 ? fullscale : (float)SHRT_MAX - 0.5f);\n        goto matched;\n    } else if (strcmp(fmt, SOAPY_SDR_CF32) == 0) {\n        input->sfmt = SFMT_F32;\n        input->bytes_per_sample = sizeof(float);\n        input->fullscale = (fullscale > 0 ? fullscale : 1.0f);\n        goto matched;\n    }\n    return false;\nmatched:\n    soapysdr_dev_data_t* dev_data = (soapysdr_dev_data_t*)input->dev_data;\n    dev_data->sample_format = strdup(fmt);\n    return true;\n}\n\n// Choose a suitable sample format.\n// Bail out if no supported sample format is found.\nstatic bool soapysdr_choose_sample_format(SoapySDRDevice* const sdr, input_t* const input) {\n    bool ret = false;\n    size_t len = 0;\n    char** formats = NULL;\n    soapysdr_dev_data_t* dev_data = (soapysdr_dev_data_t*)input->dev_data;\n    input->sfmt = SFMT_UNDEF;\n    // First try device's native format to avoid extra conversion\n    double fullscale = 0.0;\n    char* fmt = SoapySDRDevice_getNativeStreamFormat(sdr, SOAPY_SDR_RX, dev_data->channel, &fullscale);\n\n    if (soapysdr_match_sfmt(input, fmt, fullscale) == true) {\n        log(LOG_NOTICE, \"SoapySDR: device '%s': using native sample format '%s' (fullScale=%.1f)\\n\", dev_data->device_string, fmt, input->fullscale);\n        ret = true;\n        goto end;\n    }\n    // Native format is not supported by rtl_airband; find out if there is anything else.\n    formats = SoapySDRDevice_getStreamFormats(sdr, SOAPY_SDR_RX, dev_data->channel, &len);\n    if (formats == NULL || len == 0) {\n        log(LOG_ERR, \"SoapySDR: device '%s': failed to read supported sample formats\\n\", dev_data->device_string);\n        ret = false;\n        goto end;\n    }\n    for (size_t i = 0; i < len; i++) {\n        if (soapysdr_match_sfmt(input, formats[i], -1.0) == true) {\n            log(LOG_NOTICE, \"SoapySDR: device '%s': using non-native sample format '%s' (assuming fullScale=%.1f)\\n\", dev_data->device_string, formats[i], input->fullscale);\n            ret = true;\n            goto end;\n        }\n    }\n    // Nothing found; we can't use this device.\n    log(LOG_ERR, \"SoapySDR: device '%s': no supported sample format found\\n\", dev_data->device_string);\nend:\n    return ret;\n}\n\nstatic int sdrplay_get_nearest_sample_rate(SoapySDRDevice* sdr, int channel, int sample_rate) {\n    size_t len = 0;\n    double sr = (double)sample_rate;\n    SoapySDRRange* range = SoapySDRDevice_getSampleRateRange(sdr, SOAPY_SDR_RX, channel, &len);\n    if (range == NULL) {\n        log(LOG_ERR, \"SoapySDR: failed to read supported sampling rate ranges from the device\\n\");\n        return -1;\n    }\n    debug_print(\"Got %zu ranges\\n\", len);\n    double nearest_rate = range[0].minimum;\n    double offset1, offset2;\n    for (size_t i = 0; i < len; i++) {\n        debug_print(\"sr=%.1f min=%.1f max=%.1f step=%.1f\\n\", sr, range[i].minimum, range[i].maximum, range[i].step);\n        if (sr >= range[i].minimum && sr <= range[i].maximum) {\n            debug_print(\"Found suitable range: min=%.0f max=%0.f step=%0.f\\n\", range[i].minimum, range[i].maximum, range[i].step);\n            if (range[i].step == 0.0 || range[i].step >= (range[i].maximum - range[i].minimum)) {\n                return (int)(range[i].maximum - sr > sr - range[i].minimum ? range[i].minimum : range[i].maximum);\n            }\n            sr = (int)(range[i].minimum + range[i].step * round((sr - range[i].minimum) / range[i].step));\n            if (sr > range[i].maximum) {\n                sr = (int)range[i].maximum;\n            }\n            return (int)sr;\n        } else {\n            offset1 = abs(sr - nearest_rate);\n            offset2 = abs(sr - range[i].minimum);\n            if (offset2 < offset1)\n                nearest_rate = range[i].minimum;\n            offset1 = abs(sr - nearest_rate);\n            offset2 = abs(sr - range[i].maximum);\n            if (offset2 < offset1)\n                nearest_rate = range[i].maximum;\n        }\n    }\n    return (int)nearest_rate;\n}\n\nint soapysdr_parse_config(input_t* const input, libconfig::Setting& cfg) {\n    soapysdr_dev_data_t* dev_data = (soapysdr_dev_data_t*)input->dev_data;\n\n    if (cfg.exists(\"device_string\")) {\n        dev_data->device_string = strdup(cfg[\"device_string\"]);\n    } else {\n        cerr << \"SoapySDR configuration error: mandatory parameter missing: device_string\\n\";\n        error();\n    }\n    if (cfg.exists(\"gain\")) {\n        if (cfg[\"gain\"].getType() == libconfig::Setting::TypeInt) {\n            dev_data->gain = (double)((int)cfg[\"gain\"]);\n        } else if (cfg[\"gain\"].getType() == libconfig::Setting::TypeFloat) {\n            dev_data->gain = (double)cfg[\"gain\"];\n        } else {\n            // Either it's a string or an unsupported type which will cause an exception - this is fine\n            dev_data->gains = SoapySDRKwargs_fromString((const char*)cfg[\"gain\"]);\n            if (dev_data->gains.size < 1) {\n                cerr << \"SoapySDR configuration error: device '\" << dev_data->device_string << \"': gain: syntax error (must be a sequence of 'name1=value1,name2=value2,...')\\n\";\n                error();\n            }\n        }\n        dev_data->agc = false;\n    } else {\n        dev_data->agc = true;\n    }\n    if (cfg.exists(\"correction\")) {\n        if (cfg[\"correction\"].getType() == libconfig::Setting::TypeInt) {\n            dev_data->correction = (double)((int)cfg[\"correction\"]);\n        } else if (cfg[\"correction\"].getType() == libconfig::Setting::TypeFloat) {\n            dev_data->correction = (float)cfg[\"correction\"];\n        } else {\n            cerr << \"SoapySDR configuration error: device '\" << dev_data->device_string << \"': correction value must be numeric\\n\";\n            error();\n        }\n    }\n    if (cfg.exists(\"channel\")) {\n        dev_data->channel = (size_t)(int)cfg[\"channel\"];\n    }\n    if (cfg.exists(\"antenna\")) {\n        dev_data->antenna = strdup(cfg[\"antenna\"]);\n    }\n    // Find a suitable sample format and sample rate (unless set in the config)\n    // based on device capabilities.\n    // We have to do this here and not in soapysdr_init, because parse_devices()\n    // requires sample_rate and bytes_per_sample to be set correctly in order to\n    // calculate the size of the sample buffer, which has to be done before\n    // soapysdr_init() is run.\n    SoapySDRDevice* sdr = SoapySDRDevice_makeStrArgs(dev_data->device_string);\n    if (sdr == NULL) {\n        log(LOG_ERR, \"Failed to open SoapySDR device '%s': %s\\n\", dev_data->device_string, SoapySDRDevice_lastError());\n        error();\n    }\n    if (soapysdr_choose_sample_format(sdr, input) == false) {\n        cerr << \"SoapySDR configuration error: device '\" << dev_data->device_string << \"': no suitable sample format found\\n\";\n        error();\n    }\n    if (input->sample_rate < 0) {\n        input->sample_rate = sdrplay_get_nearest_sample_rate(sdr, dev_data->channel, SOAPYSDR_DEFAULT_SAMPLE_RATE);\n        if (input->sample_rate < 0) {\n            log(LOG_ERR, \"Failed to find a suitable sample rate for SoapySDR device '%s'\\n\", dev_data->device_string);\n            log(LOG_ERR, \"Specify a supported value using \\\"sample_rate\\\" option in the device configuration\\n\");\n            error();\n        }\n    }\n    SoapySDRDevice_unmake(sdr);\n    return 0;\n}\n\nint soapysdr_init(input_t* const input) {\n    soapysdr_dev_data_t* dev_data = (soapysdr_dev_data_t*)input->dev_data;\n\n    dev_data->dev = SoapySDRDevice_makeStrArgs(dev_data->device_string);\n    if (dev_data->dev == NULL) {\n        log(LOG_ERR, \"Failed to open SoapySDR device '%s': %s\\n\", dev_data->device_string, SoapySDRDevice_lastError());\n        error();\n    }\n    SoapySDRDevice* sdr = dev_data->dev;\n\n    if (SoapySDRDevice_setSampleRate(sdr, SOAPY_SDR_RX, dev_data->channel, input->sample_rate) != 0) {\n        log(LOG_ERR, \"Failed to set sample rate for SoapySDR device '%s': %s\\n\", dev_data->device_string, SoapySDRDevice_lastError());\n        error();\n    }\n    log(LOG_INFO, \"SoapySDR: device '%s': sample rate set to %.0f sps\\n\", dev_data->device_string, SoapySDRDevice_getSampleRate(sdr, SOAPY_SDR_RX, dev_data->channel));\n    if (SoapySDRDevice_setFrequency(sdr, SOAPY_SDR_RX, dev_data->channel, input->centerfreq, NULL) != 0) {\n        log(LOG_ERR, \"Failed to set frequency for SoapySDR device '%s': %s\\n\", dev_data->device_string, SoapySDRDevice_lastError());\n        error();\n    }\n    if (SoapySDRDevice_setFrequencyCorrection(sdr, SOAPY_SDR_RX, dev_data->channel, dev_data->correction) != 0) {\n        log(LOG_ERR, \"Failed to set frequency correction for SoapySDR device '%s': %s\\n\", dev_data->device_string, SoapySDRDevice_lastError());\n        error();\n    }\n    if (dev_data->antenna != NULL) {\n        if (SoapySDRDevice_setAntenna(sdr, SOAPY_SDR_RX, dev_data->channel, dev_data->antenna) != 0) {\n            log(LOG_ERR, \"Failed to set antenna to '%s' for SoapySDR device '%s': %s\\n\", dev_data->device_string, dev_data->antenna, SoapySDRDevice_lastError());\n            error();\n        }\n        log(LOG_INFO, \"SoapySDR: device '%s': antenna set to '%s'\\n\", dev_data->device_string, SoapySDRDevice_getAntenna(sdr, SOAPY_SDR_RX, dev_data->channel));\n    }\n    if (SoapySDRDevice_setGainMode(sdr, SOAPY_SDR_RX, dev_data->channel, dev_data->agc) != 0) {\n        log(LOG_ERR, \"Failed to %s AGC for SoapySDR device '%s': %s\\n\", dev_data->agc ? \"enable\" : \"disable\", dev_data->device_string, SoapySDRDevice_lastError());\n        error();\n    }\n    log(LOG_INFO, \"SoapySDR: device '%s': AGC %s (requested: %s)\\n\", dev_data->device_string, SoapySDRDevice_getGainMode(sdr, SOAPY_SDR_RX, dev_data->channel) ? \"on\" : \"off\",\n        dev_data->agc ? \"on\" : \"off\");\n    if (!dev_data->agc) {\n        if (dev_data->gains.size > 0) {\n            for (size_t i = 0; i < dev_data->gains.size; i++) {\n                char* const key = dev_data->gains.keys[i];\n                double val = atof(dev_data->gains.vals[i]);\n                if (SoapySDRDevice_setGainElement(sdr, SOAPY_SDR_RX, dev_data->channel, key, val) != 0) {\n                    log(LOG_ERR, \"Failed to set gain element '%s' for SoapySDR device '%s': %s\\n\", key, dev_data->device_string, SoapySDRDevice_lastError());\n                    error();\n                }\n                log(LOG_INFO, \"SoapySDR: device '%s': gain '%s' set to %.1f dB\\n\", dev_data->device_string, key, SoapySDRDevice_getGainElement(sdr, SOAPY_SDR_RX, dev_data->channel, key));\n            }\n        } else {\n            if (SoapySDRDevice_setGain(sdr, SOAPY_SDR_RX, dev_data->channel, dev_data->gain) != 0) {\n                log(LOG_ERR, \"Failed to set gain for SoapySDR device '%s': %s\\n\", dev_data->device_string, SoapySDRDevice_lastError());\n                error();\n            }\n            log(LOG_INFO, \"SoapySDR: device '%s': gain set to %.1f dB\\n\", dev_data->device_string, SoapySDRDevice_getGain(sdr, SOAPY_SDR_RX, dev_data->channel));\n        }\n    }\n    log(LOG_INFO, \"SoapySDR: device '%s' initialized\\n\", dev_data->device_string);\n    return 0;\n}\n\nvoid* soapysdr_rx_thread(void* ctx) {\n    input_t* input = (input_t*)ctx;\n    soapysdr_dev_data_t* dev_data = (soapysdr_dev_data_t*)input->dev_data;\n    SoapySDRDevice* sdr = dev_data->dev;\n    assert(sdr != NULL);\n\n    unsigned char buf[SOAPYSDR_BUFSIZE];\n    // size of the buffer in number of I/Q sample pairs\n    size_t num_elems = SOAPYSDR_BUFSIZE / (2 * input->bytes_per_sample);\n\n    SoapySDRStream* rxStream = NULL;\n#if SOAPY_SDR_API_VERSION < 0x00080000\n    if (SoapySDRDevice_setupStream(sdr, &rxStream, SOAPY_SDR_RX, dev_data->sample_format, &dev_data->channel, 1, NULL) != 0) {\n#else\n    if ((rxStream = SoapySDRDevice_setupStream(sdr, SOAPY_SDR_RX, dev_data->sample_format, &dev_data->channel, 1, NULL)) == NULL) {\n#endif /* SOAPY_SDR_API_VERSION */\n        log(LOG_ERR, \"Failed to set up stream for SoapySDR device '%s': %s\\n\", dev_data->device_string, SoapySDRDevice_lastError());\n        input->state = INPUT_FAILED;\n        goto cleanup;\n    }\n    if (SoapySDRDevice_activateStream(sdr, rxStream, 0, 0, 0)) {  // start streaming\n        log(LOG_ERR, \"Failed to activate stream for SoapySDR device '%s': %s\\n\", dev_data->device_string, SoapySDRDevice_lastError());\n        input->state = INPUT_FAILED;\n        goto cleanup;\n    }\n    input->state = INPUT_RUNNING;\n    log(LOG_NOTICE, \"SoapySDR: device '%s' started\\n\", dev_data->device_string);\n\n    while (!do_exit) {\n        void* bufs[] = {buf};  // array of buffers\n        int flags;             // flags set by receive operation\n        long long timeNs;      // timestamp for receive buffer\n        int samples_read = SoapySDRDevice_readStream(sdr, rxStream, bufs, num_elems, &flags, &timeNs, SOAPYSDR_READSTREAM_TIMEOUT_US);\n        if (samples_read < 0) {  // when it's negative, it's the error code\n            log(LOG_ERR, \"SoapySDR device '%s': readStream failed: %s\\n\", dev_data->device_string, SoapySDR_errToStr(samples_read));\n            continue;\n        }\n        circbuffer_append(input, buf, (size_t)(samples_read * 2 * input->bytes_per_sample));\n    }\ncleanup:\n    SoapySDRDevice_deactivateStream(sdr, rxStream, 0, 0);\n    SoapySDRDevice_closeStream(sdr, rxStream);\n    SoapySDRDevice_unmake(sdr);\n    return 0;\n}\n\nint soapysdr_set_centerfreq(input_t* const input, int const centerfreq) {\n    soapysdr_dev_data_t* dev_data = (soapysdr_dev_data_t*)input->dev_data;\n    assert(dev_data->dev != NULL);\n\n    if (SoapySDRDevice_setFrequency(dev_data->dev, SOAPY_SDR_RX, dev_data->channel, centerfreq, NULL) != 0) {\n        log(LOG_ERR, \"Failed to set frequency for SoapySDR device '%s': %s\\n\", dev_data->device_string, SoapySDRDevice_lastError());\n        return -1;\n    }\n    return 0;\n}\n\nMODULE_EXPORT input_t* soapysdr_input_new() {\n    soapysdr_dev_data_t* dev_data = (soapysdr_dev_data_t*)XCALLOC(1, sizeof(soapysdr_dev_data_t));\n    dev_data->gain = -1.0;  // invalid default gain value\n    dev_data->agc = false;\n    memset(&dev_data->gains, 0, sizeof(dev_data->gains));\n    dev_data->channel = 0;\n    dev_data->antenna = NULL;\n    /*\treturn &( input_t ){\n                    .dev_data = dev_data,\n                    .state = INPUT_UNKNOWN,\n                    .sfmt = SFMT_U8,\n                    .sample_rate = -1,\n                    .parse_config = &soapysdr_parse_config,\n                    .init = &soapysdr_init,\n                    .run_rx_thread = &soapysdr_rx_thread,\n                    .set_centerfreq = &soapysdr_set_centerfreq,\n                    .stop = &soapysdr_stop\n            }; */\n    input_t* input = (input_t*)XCALLOC(1, sizeof(input_t));\n    input->dev_data = dev_data;\n    // invalid values as defaults\n    input->state = INPUT_UNKNOWN;\n    input->sfmt = SFMT_UNDEF;\n    input->fullscale = 0.0f;\n    input->bytes_per_sample = 0;\n    input->sample_rate = -1;\n\n    input->parse_config = &soapysdr_parse_config;\n    input->init = &soapysdr_init;\n    input->run_rx_thread = &soapysdr_rx_thread;\n    input->set_centerfreq = &soapysdr_set_centerfreq;\n    input->stop = NULL;\n    return input;\n}\n"
  },
  {
    "path": "src/input-soapysdr.h",
    "content": "/*\n *  input-soapysdr.h\n *  SoapySDR-specific declarations\n *\n *  Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n#include <SoapySDR/Device.h>  // SoapySDRDevice\n#include <SoapySDR/Types.h>   // SoapySDRKwargs\n#define SOAPYSDR_DEFAULT_SAMPLE_RATE 2560000\n#define SOAPYSDR_BUFSIZE 320000\n#define SOAPYSDR_READSTREAM_TIMEOUT_US 1000000L\n\ntypedef struct {\n    SoapySDRDevice* dev;        // pointer to device struct\n    char const* device_string;  // SoapySDR device arg string\n    char const* sample_format;  // sample format\n    char const* antenna;        // antenna name\n    SoapySDRKwargs gains;       // gain elements and their values\n    double correction;          // PPM correction\n    double gain;                // gain in dB\n    size_t channel;             // HW channel number\n    bool agc;                   // enable AGC\n} soapysdr_dev_data_t;\n"
  },
  {
    "path": "src/logging.cpp",
    "content": "/*\n * logging.cpp\n *\n * Copyright (C) 2022-2023 charlie-foxtrot\n * Copyright (c) 2015-2022 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <stdarg.h>  // va_start() / va_end()\n#include <cstdio>    // fopen()\n#include <cstring>   // strerror()\n#include <iostream>  // cerr()\n\n#include \"logging.h\"\n\nLogDestination log_destination = SYSLOG;\nFILE* debugf = NULL;\n\nvoid error() {\n    close_debug();\n    _Exit(1);\n}\n\nvoid init_debug(const char* file) {\n#ifdef DEBUG\n    if (!file)\n        return;\n    if ((debugf = fopen(file, \"a\")) == NULL) {\n        std::cerr << \"Could not open debug file \" << file << \": \" << strerror(errno) << \"\\n\";\n        error();\n    }\n#else\n    UNUSED(file);\n#endif /* DEBUG */\n}\n\nvoid close_debug() {\n#ifdef DEBUG\n    if (!debugf)\n        return;\n    fclose(debugf);\n#endif /* DEBUG */\n}\n\nvoid log(int priority, const char* format, ...) {\n    va_list args;\n    va_start(args, format);\n    switch (log_destination) {\n        case SYSLOG:\n            vsyslog(priority, format, args);\n            break;\n        case STDERR:\n            vfprintf(stderr, format, args);\n            break;\n        case NONE:\n            break;\n    }\n    va_end(args);\n}\n"
  },
  {
    "path": "src/logging.h",
    "content": "/*\n * logging.h\n *\n * Copyright (C) 2022-2023 charlie-foxtrot\n * Copyright (c) 2015-2022 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#ifndef _LOGGING_H\n#define _LOGGING_H 1\n\n#include <syslog.h>  // LOG_ERR\n#include <cstdio>    // FILE\n\n#define nop() \\\n    do {      \\\n    } while (0)\n#define UNUSED(x) (void)(x)\n\n#ifdef DEBUG\n#define DEBUG_PATH \"rtl_airband_debug.log\"\n#define debug_print(fmt, ...)                                 \\\n    do {                                                      \\\n        fprintf(debugf, \"%s(): \" fmt, __func__, __VA_ARGS__); \\\n        fflush(debugf);                                       \\\n    } while (0)\n#define debug_bulk_print(fmt, ...)                            \\\n    do {                                                      \\\n        fprintf(debugf, \"%s(): \" fmt, __func__, __VA_ARGS__); \\\n    } while (0)\n#else\n#define debug_print(fmt, ...) nop()\n#define debug_bulk_print(fmt, ...) nop()\n#endif /* DEBUG */\n\nenum LogDestination { SYSLOG, STDERR, NONE };\nextern LogDestination log_destination;\nextern FILE* debugf;\n\nvoid error();\nvoid init_debug(const char* file);\nvoid close_debug();\nvoid log(int priority, const char* format, ...);\n\n#endif /* _LOGGING_H */\n"
  },
  {
    "path": "src/mixer.cpp",
    "content": "/*\n * mixer.cpp\n * Mixer related routines\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <math.h>\n#include <sys/time.h>\n#include <syslog.h>\n#include <unistd.h>\n#include <cassert>\n#include <cstdlib>\n#include <cstring>\n#include \"config.h\"\n#include \"rtl_airband.h\"\n\nstatic char* err;\n\nstatic inline void mixer_set_error(const char* msg) {\n    err = strdup(msg);\n}\n\nconst char* mixer_get_error() {\n    return (const char*)err;\n}\n\nmixer_t* getmixerbyname(const char* name) {\n    for (int i = 0; i < mixer_count; i++) {\n        if (!strcmp(mixers[i].name, name)) {\n            debug_print(\"%s found at %d\\n\", name, i);\n            return &mixers[i];\n        }\n    }\n    debug_print(\"%s not found\\n\", name);\n    return NULL;\n}\n\nvoid mixer_disable(mixer_t* mixer) {\n    mixer->enabled = false;\n    disable_channel_outputs(&mixer->channel);\n}\n\nint mixer_connect_input(mixer_t* mixer, float ampfactor, float balance) {\n    if (!mixer) {\n        mixer_set_error(\"mixer is undefined\");\n        return (-1);\n    }\n    int i = mixer->input_count;\n\n    // allocate new mixer - this could be more efficient by pre-allocating but this\n    // is only run at startup so not a big deal\n    if (mixer->inputs == NULL) {\n        mixer->inputs = (mixinput_t*)XCALLOC(i + 1, sizeof(struct mixinput_t));\n        mixer->inputs_todo = (bool*)XCALLOC(i + 1, sizeof(bool));\n        mixer->input_mask = (bool*)XCALLOC(i + 1, sizeof(bool));\n    } else {\n        mixer->inputs = (mixinput_t*)XREALLOC(mixer->inputs, (i + 1) * sizeof(struct mixinput_t));\n        mixer->inputs_todo = (bool*)XREALLOC(mixer->inputs_todo, (i + 1) * sizeof(bool));\n        mixer->input_mask = (bool*)XREALLOC(mixer->input_mask, (i + 1) * sizeof(bool));\n    }\n\n    mixer->inputs[i].wavein = (float*)XCALLOC(WAVE_LEN, sizeof(float));\n    if ((pthread_mutex_init(&mixer->inputs[i].mutex, NULL)) != 0) {\n        mixer_set_error(\"failed to initialize input mutex\");\n        return (-1);\n    }\n    mixer->inputs[i].ampfactor = ampfactor;\n    mixer->inputs[i].ampl = fminf(1.0f, 1.0f - balance);\n    mixer->inputs[i].ampr = fminf(1.0f, 1.0f + balance);\n    if (balance != 0.0f)\n        mixer->channel.mode = MM_STEREO;\n    mixer->inputs[i].ready = false;\n    mixer->inputs[i].has_signal = false;\n    mixer->inputs[i].input_overrun_count = 0;\n    mixer->input_mask[i] = true;\n    mixer->inputs_todo[i] = true;\n    mixer->enabled = true;\n    debug_print(\"ampfactor=%.1f ampl=%.1f ampr=%.1f\\n\", mixer->inputs[i].ampfactor, mixer->inputs[i].ampl, mixer->inputs[i].ampr);\n    return (mixer->input_count++);\n}\n\nvoid mixer_disable_input(mixer_t* mixer, int input_idx) {\n    assert(mixer);\n    assert(input_idx < mixer->input_count);\n\n    mixer->input_mask[input_idx] = false;\n\n    // break out if any inputs remain true\n    for (int i = 0; i < mixer->input_count; i++) {\n        if (mixer->input_mask[i]) {\n            return;\n        }\n    }\n\n    // all inputs are false so disable the mixer\n    log(LOG_NOTICE, \"Disabling mixer '%s' - all inputs died\\n\", mixer->name);\n    mixer_disable(mixer);\n}\n\nvoid mixer_put_samples(mixer_t* mixer, int input_idx, const float* samples, bool has_signal, unsigned int len) {\n    assert(mixer);\n    assert(samples);\n    assert(input_idx < mixer->input_count);\n    mixinput_t* input = &mixer->inputs[input_idx];\n    pthread_mutex_lock(&input->mutex);\n    input->has_signal = has_signal;\n    if (has_signal) {\n        memcpy(input->wavein, samples, len * sizeof(float));\n    }\n    if (input->ready == true) {\n        debug_print(\"input %d overrun\\n\", input_idx);\n        input->input_overrun_count++;\n    } else {\n        input->ready = true;\n    }\n    pthread_mutex_unlock(&input->mutex);\n}\n\nvoid mix_waveforms(float* sum, const float* in, float mult, int size) {\n    if (mult == 0.0f) {\n        return;\n    }\n    for (int s = 0; s < size; s++) {\n        sum[s] += in[s] * mult;\n    }\n}\n\n/* Samples are delivered to mixer inputs in batches of WAVE_BATCH size (default 1000, ie. 1/8 secs\n * of audio). mixer_thread emits mixed audio in batches of the same size, but the loop runs\n * twice more often (MIX_DIVISOR = 2) in order to accomodate for any possible input jitter\n * caused by irregular process scheduling, RTL clock instability, etc. For this purpose\n * we allow each input batch to become delayed by 1/16 secs (max). This is accomplished by\n * the mixer->interval counter, which counts from 2 to 0:\n * - 2 - initial state after mixed audio output. We don't expect inputs to be ready yet,\n *       but we check their readiness anyway.\n * - 1 - here we expect most (if not all) inputs to be ready, so we mix them. If there are no\n *       inputs left to handle in this WAVE_BATCH interval, we emit the mixed audio and reset\n *       mixer->interval to the initial state (2).\n * - 0 - here we expect to get output from all delayed inputs, which were not ready in the\n *       interval. Any input which is still not ready, is skipped (filled with 0s), because\n *       here we must emit the mixed audio to keep the desired audio bitrate.\n */\nvoid* mixer_thread(void* param) {\n    assert(param != NULL);\n    Signal* signal = (Signal*)param;\n    int interval_usec = 1e+6 * WAVE_BATCH / WAVE_RATE / MIX_DIVISOR;\n\n    debug_print(\"Starting mixer thread, signal %p\\n\", signal);\n\n    if (mixer_count <= 0)\n        return 0;\n#ifdef DEBUG\n    struct timeval ts, te;\n    gettimeofday(&ts, NULL);\n#endif /* DEBUG */\n    while (!do_exit) {\n        usleep(interval_usec);\n        if (do_exit)\n            return 0;\n        for (int i = 0; i < mixer_count; i++) {\n            mixer_t* mixer = mixers + i;\n            if (mixer->enabled == false)\n                continue;\n            channel_t* channel = &mixer->channel;\n\n            if (channel->state == CH_READY) {  // previous output not yet handled by output thread\n                if (--mixer->interval > 0) {\n                    continue;\n                } else {\n                    debug_print(\"mixer[%d]: output channel overrun\\n\", i);\n                    mixer->output_overrun_count++;\n                }\n            }\n\n            for (int j = 0; j < mixer->input_count; j++) {\n                mixinput_t* input = mixer->inputs + j;\n                pthread_mutex_lock(&input->mutex);\n                if (mixer->inputs_todo[j] && mixer->input_mask[j] && input->ready) {\n                    if (channel->state == CH_DIRTY) {\n                        memset(channel->waveout, 0, WAVE_BATCH * sizeof(float));\n                        if (channel->mode == MM_STEREO)\n                            memset(channel->waveout_r, 0, WAVE_BATCH * sizeof(float));\n                        channel->axcindicate = NO_SIGNAL;\n                        channel->state = CH_WORKING;\n                    }\n                    debug_bulk_print(\"mixer[%d]: ampleft=%.1f ampright=%.1f\\n\", i, input->ampfactor * input->ampl, input->ampfactor * input->ampr);\n                    if (input->has_signal) {\n                        /* left channel */\n                        mix_waveforms(channel->waveout, input->wavein, input->ampfactor * input->ampl, WAVE_BATCH);\n                        /* right channel */\n                        if (channel->mode == MM_STEREO) {\n                            mix_waveforms(channel->waveout_r, input->wavein, input->ampfactor * input->ampr, WAVE_BATCH);\n                        }\n                        channel->axcindicate = SIGNAL;\n                    }\n                    input->ready = false;\n                    mixer->inputs_todo[j] = false;\n                }\n                pthread_mutex_unlock(&input->mutex);\n            }\n\n            // check if all \"good\" inputs have been handled.  this means there is no enabled mixer (mixer->input_mask is true) that has a\n            // input to handle (mixer->inputs_todo is true)\n            bool all_good_inputs_handled = true;\n            for (int k = 0; k < mixer->input_count && all_good_inputs_handled; k++) {\n                if (mixer->inputs_todo[k] && mixer->input_mask[k]) {\n                    all_good_inputs_handled = false;\n                }\n            }\n\n            if ((all_good_inputs_handled == true) || mixer->interval == 0) {  // all good inputs handled or last interval passed\n\n#ifdef DEBUG\n                gettimeofday(&te, NULL);\n\n                char* inputs_todo_char = (char*)XCALLOC(mixer->input_count + 1, sizeof(char));\n                char* input_mask_char = (char*)XCALLOC(mixer->input_count + 1, sizeof(char));\n                for (int k = 0; k < mixer->input_count; k++) {\n                    inputs_todo_char[k] = mixer->inputs_todo[k] ? '+' : '-';\n                    input_mask_char[k] = mixer->input_mask[k] ? '+' : '-';\n                }\n                inputs_todo_char[mixer->input_count] = '\\0';\n                input_mask_char[mixer->input_count] = '\\0';\n\n                debug_bulk_print(\"mixerinput: %lu.%lu %lu int=%d inp_unhandled=%s inp_mask=%s\\n\", te.tv_sec, (unsigned long)te.tv_usec, (te.tv_sec - ts.tv_sec) * 1000000UL + te.tv_usec - ts.tv_usec,\n                                 mixer->interval, inputs_todo_char, input_mask_char);\n\n                free(inputs_todo_char);\n                free(input_mask_char);\n\n                ts.tv_sec = te.tv_sec;\n                ts.tv_usec = te.tv_usec;\n#endif /* DEBUG */\n\n                channel->state = CH_READY;\n                signal->send();\n                mixer->interval = MIX_DIVISOR;\n                for (int k = 0; k < mixer->input_count; k++) {\n                    mixer->inputs_todo[k] = true;\n                }\n            } else {\n                mixer->interval--;\n            }\n        }\n    }\n    return 0;\n}\n"
  },
  {
    "path": "src/output.cpp",
    "content": "/*\n * output.cpp\n * Output related routines\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n#include <math.h>\n#include <ogg/ogg.h>\n#include <shout/shout.h>\n#include <stdio.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <vorbis/vorbisenc.h>\n\n// SHOUTERR_RETRY is available since libshout 2.4.0.\n// Set it to an impossible value if it's not there.\n#ifndef SHOUTERR_RETRY\n#define SHOUTERR_RETRY (-255)\n#endif /* SHOUTERR_RETRY */\n\n#include <lame/lame.h>\n\n#ifdef WITH_PULSEAUDIO\n#include <pulse/pulseaudio.h>\n#endif /* WITH_PULSEAUDIO */\n\n#include <syslog.h>\n#include <cassert>\n#include <cerrno>\n#include <cstdlib>\n#include <cstring>\n#include <ctime>\n#include <sstream>\n#include <string>\n#include \"config.h\"\n#include \"helper_functions.h\"\n#include \"input-common.h\"\n#include \"rtl_airband.h\"\n\nvoid shout_setup(icecast_data* icecast, mix_modes mixmode) {\n    int ret;\n    shout_t* shouttemp = shout_new();\n    if (shouttemp == NULL) {\n        printf(\"cannot allocate\\n\");\n    }\n    if (shout_set_host(shouttemp, icecast->hostname) != SHOUTERR_SUCCESS) {\n        shout_free(shouttemp);\n        return;\n    }\n    if (shout_set_protocol(shouttemp, SHOUT_PROTOCOL_HTTP) != SHOUTERR_SUCCESS) {\n        shout_free(shouttemp);\n        return;\n    }\n    if (shout_set_port(shouttemp, icecast->port) != SHOUTERR_SUCCESS) {\n        shout_free(shouttemp);\n        return;\n    }\n#ifdef LIBSHOUT_HAS_TLS\n    if (shout_set_tls(shouttemp, icecast->tls_mode) != SHOUTERR_SUCCESS) {\n        shout_free(shouttemp);\n        return;\n    }\n#endif /* LIBSHOUT_HAS_TLS */\n    char mp[100];\n    sprintf(mp, \"/%s\", icecast->mountpoint);\n    if (shout_set_mount(shouttemp, mp) != SHOUTERR_SUCCESS) {\n        shout_free(shouttemp);\n        return;\n    }\n    if (shout_set_user(shouttemp, icecast->username) != SHOUTERR_SUCCESS) {\n        shout_free(shouttemp);\n        return;\n    }\n    if (shout_set_password(shouttemp, icecast->password) != SHOUTERR_SUCCESS) {\n        shout_free(shouttemp);\n        return;\n    }\n#ifdef LIBSHOUT_HAS_CONTENT_FORMAT\n    if (shout_set_content_format(shouttemp, SHOUT_FORMAT_MP3, SHOUT_USAGE_AUDIO, NULL) != SHOUTERR_SUCCESS) {\n#else\n    if (shout_set_format(shouttemp, SHOUT_FORMAT_MP3) != SHOUTERR_SUCCESS) {\n#endif /* LIBSHOUT_HAS_CONTENT_FORMAT */\n        shout_free(shouttemp);\n        return;\n    }\n    if (icecast->name && shout_set_meta(shouttemp, SHOUT_META_NAME, icecast->name) != SHOUTERR_SUCCESS) {\n        shout_free(shouttemp);\n        return;\n    }\n    if (icecast->genre && shout_set_meta(shouttemp, SHOUT_META_GENRE, icecast->genre) != SHOUTERR_SUCCESS) {\n        shout_free(shouttemp);\n        return;\n    }\n    if (icecast->description && shout_set_meta(shouttemp, SHOUT_META_DESCRIPTION, icecast->description) != SHOUTERR_SUCCESS) {\n        shout_free(shouttemp);\n        return;\n    }\n    char samplerates[20];\n    sprintf(samplerates, \"%d\", MP3_RATE);\n    shout_set_audio_info(shouttemp, SHOUT_AI_SAMPLERATE, samplerates);\n    shout_set_audio_info(shouttemp, SHOUT_AI_CHANNELS, (mixmode == MM_STEREO ? \"2\" : \"1\"));\n\n    if (shout_set_nonblocking(shouttemp, 1) != SHOUTERR_SUCCESS) {\n        log(LOG_ERR, \"Error setting non-blocking mode: %s\\n\", shout_get_error(shouttemp));\n        return;\n    }\n    ret = shout_open(shouttemp);\n    if (ret == SHOUTERR_SUCCESS)\n        ret = SHOUTERR_CONNECTED;\n\n    if (ret == SHOUTERR_BUSY || ret == SHOUTERR_RETRY)\n        log(LOG_NOTICE, \"Connecting to %s:%d/%s...\\n\", icecast->hostname, icecast->port, icecast->mountpoint);\n\n    int shout_timeout = 30 * 5;  // 30 * 5 * 200ms = 30s\n    while ((ret == SHOUTERR_BUSY || ret == SHOUTERR_RETRY) && shout_timeout-- > 0) {\n        SLEEP(200);\n        ret = shout_get_connected(shouttemp);\n    }\n\n    if (ret == SHOUTERR_CONNECTED) {\n        log(LOG_NOTICE, \"Connected to %s:%d/%s\\n\", icecast->hostname, icecast->port, icecast->mountpoint);\n        SLEEP(100);\n        icecast->shout = shouttemp;\n    } else {\n        log(LOG_WARNING, \"Could not connect to %s:%d/%s: %s\\n\", icecast->hostname, icecast->port, icecast->mountpoint, shout_get_error(shouttemp));\n        shout_close(shouttemp);\n        shout_free(shouttemp);\n        return;\n    }\n}\n\nlame_t airlame_init(mix_modes mixmode, int highpass, int lowpass) {\n    lame_t lame = lame_init();\n    if (!lame) {\n        log(LOG_WARNING, \"lame_init failed\\n\");\n        return NULL;\n    }\n\n    lame_set_in_samplerate(lame, WAVE_RATE);\n    lame_set_VBR(lame, vbr_mtrh);\n    lame_set_brate(lame, 16);\n    lame_set_quality(lame, 7);\n    lame_set_lowpassfreq(lame, lowpass);\n    lame_set_highpassfreq(lame, highpass);\n    lame_set_out_samplerate(lame, MP3_RATE);\n    if (mixmode == MM_STEREO) {\n        lame_set_num_channels(lame, 2);\n        lame_set_mode(lame, JOINT_STEREO);\n    } else {\n        lame_set_num_channels(lame, 1);\n        lame_set_mode(lame, MONO);\n    }\n    debug_print(\"lame init with mixmode=%s\\n\", mixmode == MM_STEREO ? \"MM_STEREO\" : \"MM_MONO\");\n    lame_init_params(lame);\n    return lame;\n}\n\nclass LameTone {\n    unsigned char* _data;\n    int _bytes;\n\n   public:\n    LameTone(mix_modes mixmode, int msec, unsigned int hz = 0) : _data(NULL), _bytes(0) {\n        _data = (unsigned char*)XCALLOC(1, LAMEBUF_SIZE);\n\n        int samples = (msec * WAVE_RATE) / 1000;\n        float* buf = (float*)XCALLOC(samples, sizeof(float));\n\n        debug_print(\"LameTone with mixmode=%s msec=%d hz=%u\\n\", mixmode == MM_STEREO ? \"MM_STEREO\" : \"MM_MONO\", msec, hz);\n        if (hz > 0) {\n            const float period = 1.0 / (float)hz;\n            const float sample_time = 1.0 / (float)WAVE_RATE;\n            float t = 0;\n            for (int i = 0; i < samples; ++i, t += sample_time) {\n                buf[i] = 0.9 * sinf(t * 2.0 * M_PI / period);\n            }\n        } else\n            memset(buf, 0, samples * sizeof(float));\n        lame_t lame = airlame_init(mixmode, 0, 0);\n        if (lame) {\n            _bytes = lame_encode_buffer_ieee_float(lame, buf, (mixmode == MM_STEREO ? buf : NULL), samples, _data, LAMEBUF_SIZE);\n            if (_bytes > 0) {\n                int flush_ofs = _bytes;\n                if (flush_ofs & 0x1f)\n                    flush_ofs += 0x20 - (flush_ofs & 0x1f);\n                if (flush_ofs < LAMEBUF_SIZE) {\n                    int flush_bytes = lame_encode_flush(lame, _data + flush_ofs, LAMEBUF_SIZE - flush_ofs);\n                    if (flush_bytes > 0) {\n                        memmove(_data + _bytes, _data + flush_ofs, flush_bytes);\n                        _bytes += flush_bytes;\n                    }\n                }\n            } else\n                log(LOG_WARNING, \"lame_encode_buffer_ieee_float: %d\\n\", _bytes);\n            lame_close(lame);\n        }\n        free(buf);\n    }\n\n    ~LameTone() {\n        if (_data)\n            free(_data);\n    }\n\n    int write(FILE* f) {\n        if (!_data || _bytes <= 0)\n            return 1;\n\n        if (fwrite(_data, 1, _bytes, f) != (unsigned int)_bytes) {\n            log(LOG_WARNING, \"LameTone: failed to write %d bytes\\n\", _bytes);\n            return -1;\n        }\n\n        return 0;\n    }\n};\n\nint rename_if_exists(char const* oldpath, char const* newpath) {\n    int ret = rename(oldpath, newpath);\n    if (ret < 0) {\n        if (errno == ENOENT) {\n            return 0;\n        } else {\n            log(LOG_ERR, \"Could not rename %s to %s: %s\\n\", oldpath, newpath, strerror(errno));\n        }\n    }\n    return ret;\n}\n\n/*\n * Open output file (mp3 or raw IQ) for append or initial write.\n * If appending to an audio file, insert discontinuity indictor tones\n * as well as the appropriate amount of silence when in continuous mode.\n */\nstatic int open_file(file_data* fdata, mix_modes mixmode, int is_audio) {\n    int rename_result = rename_if_exists(fdata->file_path.c_str(), fdata->file_path_tmp.c_str());\n    fdata->f = fopen(fdata->file_path_tmp.c_str(), fdata->append ? \"a+\" : \"w\");\n    if (fdata->f == NULL) {\n        return -1;\n    }\n\n    struct stat st = {};\n    if (!fdata->append || fstat(fileno(fdata->f), &st) != 0 || st.st_size == 0) {\n        if (!fdata->split_on_transmission) {\n            log(LOG_INFO, \"Writing to %s\\n\", fdata->file_path.c_str());\n        } else {\n            debug_print(\"Writing to %s\\n\", fdata->file_path_tmp.c_str());\n        }\n        return 0;\n    }\n    if (rename_result < 0) {\n        log(LOG_INFO, \"Writing to %s\\n\", fdata->file_path.c_str());\n        debug_print(\"Writing to %s\\n\", fdata->file_path_tmp.c_str());\n    } else {\n        log(LOG_INFO, \"Appending from pos %llu to %s\\n\", (unsigned long long)st.st_size, fdata->file_path.c_str());\n        debug_print(\"Appending from pos %llu to %s\\n\", (unsigned long long)st.st_size, fdata->file_path_tmp.c_str());\n    }\n\n    if (is_audio) {\n        // fill missing space with marker tones\n        LameTone lt_a(mixmode, 120, 2222);\n        LameTone lt_b(mixmode, 120, 1111);\n        LameTone lt_c(mixmode, 120, 555);\n\n        int r = lt_a.write(fdata->f);\n        if (r == 0)\n            r = lt_b.write(fdata->f);\n        if (r == 0)\n            r = lt_c.write(fdata->f);\n\n        // fill in time delta with silence if continuous output mode\n        if (fdata->continuous) {\n            time_t now = time(NULL);\n            if (now > st.st_mtime) {\n                time_t delta = now - st.st_mtime;\n                if (delta > 3600) {\n                    log(LOG_WARNING, \"Too big time difference: %llu sec, limiting to one hour\\n\", (unsigned long long)delta);\n                    delta = 3600;\n                }\n                LameTone lt_silence(mixmode, 1000);\n                for (; (r == 0 && delta > 1); --delta)\n                    r = lt_silence.write(fdata->f);\n            }\n        }\n\n        if (r == 0)\n            r = lt_c.write(fdata->f);\n        if (r == 0)\n            r = lt_b.write(fdata->f);\n        if (r == 0)\n            r = lt_a.write(fdata->f);\n\n        if (r < 0)\n            fseek(fdata->f, st.st_size, SEEK_SET);\n    }\n    return 0;\n}\n\nstatic void close_file(output_t* output) {\n    file_data* fdata = (file_data*)(output->data);\n    if (!fdata) {\n        return;\n    }\n\n    // close all mp3 files for every output that has a lame context\n    if (fdata->type == O_FILE && fdata->f && output->lame) {\n        int encoded = lame_encode_flush_nogap(output->lame, output->lamebuf, LAMEBUF_SIZE);\n        debug_print(\"closing file %s flushed %d\\n\", fdata->file_path.c_str(), encoded);\n\n        if (encoded > 0) {\n            size_t written = fwrite((void*)output->lamebuf, 1, (size_t)encoded, fdata->f);\n            if (written == 0 || written < (size_t)encoded)\n                log(LOG_WARNING, \"Problem writing %s (%s)\\n\", fdata->file_path.c_str(), strerror(errno));\n        }\n\n        // write the lametag to the beginning of the file\n        const int lametag_size = lame_get_lametag_frame(output->lame, output->lamebuf, LAMEBUF_SIZE);\n        fseek(fdata->f, 0, SEEK_SET);\n        fwrite(output->lamebuf, 1, lametag_size, fdata->f);\n    }\n\n    if (fdata->f) {\n        fclose(fdata->f);\n        fdata->f = NULL;\n        rename_if_exists(fdata->file_path_tmp.c_str(), fdata->file_path.c_str());\n    }\n    fdata->file_path.clear();\n    fdata->file_path_tmp.clear();\n}\n\n/*\n * Close current output file based on certain conditions:\n * If \"split_on_transmission\" mode is true check:\n *   If current duration too long, or we've been idle too long\n * else (append or continuous) check:\n *   if hour is different.\n */\nstatic void close_if_necessary(output_t* output) {\n    file_data* fdata = (file_data*)(output->data);\n\n    static const double MIN_TRANSMISSION_TIME_SEC = 1.0;\n    static const double MAX_TRANSMISSION_TIME_SEC = 60.0 * 60.0;\n    static const double MAX_TRANSMISSION_IDLE_SEC = 0.5;\n\n    if (!fdata || !fdata->f) {\n        return;\n    }\n\n    timeval current_time;\n    gettimeofday(&current_time, NULL);\n\n    if (fdata->split_on_transmission) {\n        double duration_sec = delta_sec(&fdata->open_time, &current_time);\n        double idle_sec = delta_sec(&fdata->last_write_time, &current_time);\n\n        if (duration_sec > MAX_TRANSMISSION_TIME_SEC || (duration_sec > MIN_TRANSMISSION_TIME_SEC && idle_sec > MAX_TRANSMISSION_IDLE_SEC)) {\n            debug_print(\"closing file %s, duration %f sec, idle %f sec\\n\", fdata->file_path.c_str(), duration_sec, idle_sec);\n            close_file(output);\n        }\n        return;\n    }\n\n    // Check if the hour boundary was just crossed.  NOTE: Actual hour number doesn't matter but still\n    // need to use localtime if enabled (some timezones have partial hour offsets)\n    int start_hour;\n    int current_hour;\n    if (use_localtime) {\n        start_hour = localtime(&(fdata->open_time.tv_sec))->tm_hour;\n        current_hour = localtime(&current_time.tv_sec)->tm_hour;\n    } else {\n        start_hour = gmtime(&(fdata->open_time.tv_sec))->tm_hour;\n        current_hour = gmtime(&current_time.tv_sec)->tm_hour;\n    }\n\n    if (start_hour != current_hour) {\n        debug_print(\"closing file %s after crossing hour boundary\\n\", fdata->file_path.c_str());\n        close_file(output);\n    }\n}\n\n/*\n * For a particular channel file output, check if there is a file currently open.\n * If so, that file may need to be flushed and closed.\n *\n * If the existing open file is good for continued use, return true.\n * Otherwise, create a file name based on the current timestamp and\n * open that new file.  If that file open succeeded, return true.\n */\nstatic bool output_file_ready(channel_t* channel, output_t* output) {\n    file_data* fdata = (file_data*)(output->data);\n    if (!fdata) {\n        return false;\n    }\n\n    close_if_necessary(output);\n\n    if (fdata->f) {  // still open\n        return true;\n    }\n\n    timeval current_time;\n    gettimeofday(&current_time, NULL);\n    struct tm* time;\n    if (use_localtime) {\n        time = localtime(&current_time.tv_sec);\n    } else {\n        time = gmtime(&current_time.tv_sec);\n    }\n\n    char timestamp[32];\n    if (strftime(timestamp, sizeof(timestamp), fdata->split_on_transmission ? \"_%Y%m%d_%H%M%S\" : \"_%Y%m%d_%H\", time) == 0) {\n        log(LOG_NOTICE, \"strftime returned 0\\n\");\n        return false;\n    }\n\n    std::string output_dir;\n    if (fdata->dated_subdirectories) {\n        output_dir = make_dated_subdirs(fdata->basedir, time);\n        if (output_dir.empty()) {\n            log(LOG_ERR, \"Failed to create dated subdirectory\\n\");\n            return false;\n        }\n    } else {\n        output_dir = fdata->basedir;\n        make_dir(output_dir);\n    }\n\n    // use a string stream to build the output filepath\n    std::stringstream ss;\n    ss << output_dir << '/' << fdata->basename << timestamp;\n    if (fdata->include_freq) {\n        ss << '_' << channel->freqlist[channel->freq_idx].frequency;\n    }\n    ss << fdata->suffix;\n    fdata->file_path = ss.str();\n\n    fdata->file_path_tmp = fdata->file_path + \".tmp\";\n\n    fdata->open_time = fdata->last_write_time = current_time;\n\n    const int is_audio = output->type == O_RAWFILE ? 0 : 1;\n    if (open_file(fdata, channel->mode, is_audio) < 0) {\n        log(LOG_WARNING, \"Cannot open output file %s (%s)\\n\", fdata->file_path_tmp.c_str(), strerror(errno));\n        return false;\n    }\n\n    return true;\n}\n\n// Create all the output for a particular channel.\nvoid process_outputs(channel_t* channel, int cur_scan_freq) {\n    for (int k = 0; k < channel->output_count; k++) {\n        if (channel->outputs[k].enabled == false)\n            continue;\n        if (channel->outputs[k].type == O_ICECAST) {\n            icecast_data* icecast = (icecast_data*)(channel->outputs[k].data);\n            if (icecast->shout == NULL)\n                continue;\n\n            // encode and send mp3 to shoutcast output\n            const auto& lame = channel->outputs[k].lame;\n            const auto& lamebuf = channel->outputs[k].lamebuf;\n            int mp3_bytes = lame_encode_buffer_ieee_float(lame, channel->waveout, (channel->mode == MM_STEREO ? channel->waveout_r : NULL), WAVE_BATCH, lamebuf, LAMEBUF_SIZE);\n            if (mp3_bytes < 0) {\n                log(LOG_WARNING, \"lame_encode_buffer_ieee_float: %d\\n\", mp3_bytes);\n            }\n\n            if (mp3_bytes == 0) {\n                continue;\n            }\n\n            int ret = shout_send(icecast->shout, channel->outputs[k].lamebuf, mp3_bytes);\n\n            if (ret != SHOUTERR_SUCCESS || shout_queuelen(icecast->shout) > MAX_SHOUT_QUEUELEN) {\n                if (shout_queuelen(icecast->shout) > MAX_SHOUT_QUEUELEN)\n                    log(LOG_WARNING, \"Exceeded max backlog for %s:%d/%s, disconnecting\\n\", icecast->hostname, icecast->port, icecast->mountpoint);\n                // reset connection\n                log(LOG_WARNING, \"Lost connection to %s:%d/%s\\n\", icecast->hostname, icecast->port, icecast->mountpoint);\n                shout_close(icecast->shout);\n                shout_free(icecast->shout);\n                icecast->shout = NULL;\n            } else if (icecast->send_scan_freq_tags && cur_scan_freq >= 0) {\n                shout_metadata_t* meta = shout_metadata_new();\n                char description[32];\n                if (channel->freqlist[channel->freq_idx].label != NULL) {\n                    if (shout_metadata_add(meta, \"song\", channel->freqlist[channel->freq_idx].label) != SHOUTERR_SUCCESS) {\n                        log(LOG_WARNING, \"Failed to add shout metadata\\n\");\n                    }\n                } else {\n                    snprintf(description, sizeof(description), \"%.3f MHz\", channel->freqlist[channel->freq_idx].frequency / 1000000.0);\n                    if (shout_metadata_add(meta, \"song\", description) != SHOUTERR_SUCCESS) {\n                        log(LOG_WARNING, \"Failed to add shout metadata\\n\");\n                    }\n                }\n                if (SHOUT_SET_METADATA(icecast->shout, meta) != SHOUTERR_SUCCESS) {\n                    log(LOG_WARNING, \"Failed to add shout metadata\\n\");\n                }\n                shout_metadata_free(meta);\n            }\n        } else if (channel->outputs[k].type == O_FILE || channel->outputs[k].type == O_RAWFILE) {\n            file_data* fdata = (file_data*)(channel->outputs[k].data);\n\n            if (fdata->continuous == false && channel->axcindicate == NO_SIGNAL && channel->outputs[k].active == false) {\n                close_if_necessary(&channel->outputs[k]);\n                continue;\n            }\n\n            if (!output_file_ready(channel, &channel->outputs[k])) {\n                log(LOG_WARNING, \"Output disabled\\n\");\n                channel->outputs[k].enabled = false;\n                continue;\n            };\n\n            // encode mp3 bytes if O_FILE\n            const auto& lame = channel->outputs[k].lame;\n            const auto& lamebuf = channel->outputs[k].lamebuf;\n            int mp3_bytes = 0;\n            if (channel->outputs[k].type == O_FILE) {\n                mp3_bytes = lame_encode_buffer_ieee_float(lame, channel->waveout, (channel->mode == MM_STEREO ? channel->waveout_r : NULL), WAVE_BATCH, lamebuf, LAMEBUF_SIZE);\n                if (mp3_bytes < 0) {\n                    log(LOG_WARNING, \"lame_encode_buffer_ieee_float: %d\\n\", mp3_bytes);\n                }\n\n                if (mp3_bytes <= 0) {\n                    continue;\n                }\n            }\n\n            size_t buflen = 0, written = 0;\n            if (channel->outputs[k].type == O_FILE) {\n                buflen = (size_t)mp3_bytes;\n                written = fwrite(lamebuf, 1, buflen, fdata->f);\n            } else if (channel->outputs[k].type == O_RAWFILE) {\n                buflen = 2 * sizeof(float) * WAVE_BATCH;\n                written = fwrite(channel->iq_out, 1, buflen, fdata->f);\n            }\n            if (written < buflen) {\n                if (ferror(fdata->f))\n                    log(LOG_WARNING, \"Cannot write to %s (%s), output disabled\\n\", fdata->file_path.c_str(), strerror(errno));\n                else\n                    log(LOG_WARNING, \"Short write on %s, output disabled\\n\", fdata->file_path.c_str());\n                close_file(&channel->outputs[k]);\n                channel->outputs[k].enabled = false;\n            }\n            channel->outputs[k].active = (channel->axcindicate != NO_SIGNAL);\n            gettimeofday(&fdata->last_write_time, NULL);\n        } else if (channel->outputs[k].type == O_MIXER) {\n            mixer_data* mdata = (mixer_data*)(channel->outputs[k].data);\n            mixer_put_samples(mdata->mixer, mdata->input, channel->waveout, channel->axcindicate != NO_SIGNAL, WAVE_BATCH);\n        } else if (channel->outputs[k].type == O_UDP_STREAM) {\n            udp_stream_data* sdata = (udp_stream_data*)channel->outputs[k].data;\n\n            if (sdata->continuous == false && channel->axcindicate == NO_SIGNAL) {\n                continue;\n            }\n\n            if (channel->mode == MM_MONO) {\n                udp_stream_write(sdata, channel->waveout, (size_t)WAVE_BATCH * sizeof(float));\n            } else {\n                udp_stream_write(sdata, channel->waveout, channel->waveout_r, (size_t)WAVE_BATCH * sizeof(float));\n            }\n\n#ifdef WITH_PULSEAUDIO\n        } else if (channel->outputs[k].type == O_PULSE) {\n            pulse_data* pdata = (pulse_data*)(channel->outputs[k].data);\n            if (pdata->continuous == false && channel->axcindicate == NO_SIGNAL)\n                continue;\n\n            pulse_write_stream(pdata, channel->mode, channel->waveout, channel->waveout_r, (size_t)WAVE_BATCH * sizeof(float));\n#endif /* WITH_PULSEAUDIO */\n        }\n    }\n}\n\nvoid disable_channel_outputs(channel_t* channel) {\n    for (int k = 0; k < channel->output_count; k++) {\n        output_t* output = channel->outputs + k;\n        output->enabled = false;\n        if (output->type == O_ICECAST) {\n            icecast_data* icecast = (icecast_data*)(channel->outputs[k].data);\n            if (icecast->shout == NULL)\n                continue;\n            log(LOG_WARNING, \"Closing connection to %s:%d/%s\\n\", icecast->hostname, icecast->port, icecast->mountpoint);\n            shout_close(icecast->shout);\n            shout_free(icecast->shout);\n            icecast->shout = NULL;\n        } else if (output->type == O_FILE || output->type == O_RAWFILE) {\n            close_file(&channel->outputs[k]);\n        } else if (output->type == O_MIXER) {\n            mixer_data* mdata = (mixer_data*)(output->data);\n            mixer_disable_input(mdata->mixer, mdata->input);\n        } else if (output->type == O_UDP_STREAM) {\n            udp_stream_data* sdata = (udp_stream_data*)output->data;\n            udp_stream_shutdown(sdata);\n#ifdef WITH_PULSEAUDIO\n        } else if (output->type == O_PULSE) {\n            pulse_data* pdata = (pulse_data*)(output->data);\n            pulse_shutdown(pdata);\n#endif /* WITH_PULSEAUDIO */\n        }\n    }\n}\n\nvoid disable_device_outputs(device_t* dev) {\n    log(LOG_INFO, \"Disabling device outputs\\n\");\n    for (int j = 0; j < dev->channel_count; j++) {\n        disable_channel_outputs(dev->channels + j);\n    }\n}\n\nstatic void print_channel_metric(FILE* f, char const* name, float freq, char* label) {\n    fprintf(f, \"%s{freq=\\\"%.3f\\\"\", name, freq / 1000000.0);\n    if (label != NULL) {\n        fprintf(f, \",label=\\\"%s\\\"\", label);\n    }\n    fprintf(f, \"}\");\n}\n\nstatic void output_channel_noise_levels(FILE* f) {\n    fprintf(f,\n            \"# HELP channel_noise_level Raw squelch noise_level.\\n\"\n            \"# TYPE channel_noise_level gauge\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = devices[i].channels + j;\n            for (int k = 0; k < channel->freq_count; k++) {\n                print_channel_metric(f, \"channel_noise_level\", channel->freqlist[k].frequency, channel->freqlist[k].label);\n                fprintf(f, \"\\t%.3f\\n\", channel->freqlist[k].squelch.noise_level());\n            }\n        }\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_channel_dbfs_noise_levels(FILE* f) {\n    fprintf(f,\n            \"# HELP channel_dbfs_noise_level Squelch noise_level as dBFS.\\n\"\n            \"# TYPE channel_dbfs_noise_level gauge\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = devices[i].channels + j;\n            for (int k = 0; k < channel->freq_count; k++) {\n                print_channel_metric(f, \"channel_dbfs_noise_level\", channel->freqlist[k].frequency, channel->freqlist[k].label);\n                fprintf(f, \"\\t%.3f\\n\", level_to_dBFS(channel->freqlist[k].squelch.noise_level()));\n            }\n        }\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_channel_signal_levels(FILE* f) {\n    fprintf(f,\n            \"# HELP channel_signal_level Raw squelch signal_level.\\n\"\n            \"# TYPE channel_signal_level gauge\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = devices[i].channels + j;\n            for (int k = 0; k < channel->freq_count; k++) {\n                print_channel_metric(f, \"channel_signal_level\", channel->freqlist[k].frequency, channel->freqlist[k].label);\n                fprintf(f, \"\\t%.3f\\n\", channel->freqlist[k].squelch.signal_level());\n            }\n        }\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_channel_dbfs_signal_levels(FILE* f) {\n    fprintf(f,\n            \"# HELP channel_dbfs_signal_level Squelch signal_level as dBFS.\\n\"\n            \"# TYPE channel_dbfs_signal_level gauge\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = devices[i].channels + j;\n            for (int k = 0; k < channel->freq_count; k++) {\n                print_channel_metric(f, \"channel_dbfs_signal_level\", channel->freqlist[k].frequency, channel->freqlist[k].label);\n                fprintf(f, \"\\t%.3f\\n\", level_to_dBFS(channel->freqlist[k].squelch.signal_level()));\n            }\n        }\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_channel_squelch_levels(FILE* f) {\n    fprintf(f,\n            \"# HELP channel_squelch_level Squelch squelch_level.\\n\"\n            \"# TYPE channel_squelch_level gauge\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = devices[i].channels + j;\n            for (int k = 0; k < channel->freq_count; k++) {\n                print_channel_metric(f, \"channel_squelch_level\", channel->freqlist[k].frequency, channel->freqlist[k].label);\n                fprintf(f, \"\\t%.3f\\n\", channel->freqlist[k].squelch.squelch_level());\n            }\n        }\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_channel_squelch_counter(FILE* f) {\n    fprintf(f,\n            \"# HELP channel_squelch_counter Squelch open_count.\\n\"\n            \"# TYPE channel_squelch_counter counter\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = devices[i].channels + j;\n            for (int k = 0; k < channel->freq_count; k++) {\n                print_channel_metric(f, \"channel_squelch_counter\", channel->freqlist[k].frequency, channel->freqlist[k].label);\n                fprintf(f, \"\\t%zu\\n\", channel->freqlist[k].squelch.open_count());\n            }\n        }\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_channel_flappy_counter(FILE* f) {\n    fprintf(f,\n            \"# HELP channel_flappy_counter Squelch flappy_count.\\n\"\n            \"# TYPE channel_flappy_counter counter\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = devices[i].channels + j;\n            for (int k = 0; k < channel->freq_count; k++) {\n                print_channel_metric(f, \"channel_flappy_counter\", channel->freqlist[k].frequency, channel->freqlist[k].label);\n                fprintf(f, \"\\t%zu\\n\", channel->freqlist[k].squelch.flappy_count());\n            }\n        }\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_channel_ctcss_counter(FILE* f) {\n    fprintf(f,\n            \"# HELP channel_ctcss_counter count of windows with CTCSS detected.\\n\"\n            \"# TYPE channel_ctcss_counter counter\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = devices[i].channels + j;\n            for (int k = 0; k < channel->freq_count; k++) {\n                print_channel_metric(f, \"channel_ctcss_counter\", channel->freqlist[k].frequency, channel->freqlist[k].label);\n                fprintf(f, \"\\t%zu\\n\", channel->freqlist[k].squelch.ctcss_count());\n            }\n        }\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_channel_no_ctcss_counter(FILE* f) {\n    fprintf(f,\n            \"# HELP channel_no_ctcss_counter count of windows without CTCSS detected.\\n\"\n            \"# TYPE channel_no_ctcss_counter counter\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = devices[i].channels + j;\n            for (int k = 0; k < channel->freq_count; k++) {\n                print_channel_metric(f, \"channel_no_ctcss_counter\", channel->freqlist[k].frequency, channel->freqlist[k].label);\n                fprintf(f, \"\\t%zu\\n\", channel->freqlist[k].squelch.no_ctcss_count());\n            }\n        }\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_channel_activity_counters(FILE* f) {\n    fprintf(f,\n            \"# HELP channel_activity_counter Loops of output_thread with frequency active.\\n\"\n            \"# TYPE channel_activity_counter counter\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = devices[i].channels + j;\n            for (int k = 0; k < channel->freq_count; k++) {\n                print_channel_metric(f, \"channel_activity_counter\", channel->freqlist[k].frequency, channel->freqlist[k].label);\n                fprintf(f, \"\\t%zu\\n\", channel->freqlist[k].active_counter);\n            }\n        }\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_device_buffer_overflows(FILE* f) {\n    fprintf(f,\n            \"# HELP buffer_overflow_count Number of times a device's buffer has overflowed.\\n\"\n            \"# TYPE buffer_overflow_count counter\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        fprintf(f, \"buffer_overflow_count{device=\\\"%d\\\"}\\t%zu\\n\", i, dev->input->overflow_count);\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_output_overruns(FILE* f) {\n    fprintf(f,\n            \"# HELP output_overrun_count Number of times a device or mixer output has overrun.\\n\"\n            \"# TYPE output_overrun_count counter\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        fprintf(f, \"output_overrun_count{device=\\\"%d\\\"}\\t%zu\\n\", i, dev->output_overrun_count);\n    }\n    for (int i = 0; i < mixer_count; i++) {\n        mixer_t* mixer = mixers + i;\n        fprintf(f, \"output_overrun_count{mixer=\\\"%d\\\"}\\t%zu\\n\", i, mixer->output_overrun_count);\n    }\n    fprintf(f, \"\\n\");\n}\n\nstatic void output_input_overruns(FILE* f) {\n    if (mixer_count == 0) {\n        return;\n    }\n\n    fprintf(f,\n            \"# HELP input_overrun_count Number of times mixer input has overrun.\\n\"\n            \"# TYPE input_overrun_count counter\\n\");\n\n    for (int i = 0; i < mixer_count; i++) {\n        mixer_t* mixer = mixers + i;\n        for (int j = 0; j < mixer->input_count; j++) {\n            mixinput_t* input = mixer->inputs + j;\n            fprintf(f, \"input_overrun_count{mixer=\\\"%d\\\",input=\\\"%d\\\"}\\t%zu\\n\", i, j, input->input_overrun_count);\n        }\n    }\n    fprintf(f, \"\\n\");\n}\n\nvoid write_stats_file(timeval* last_stats_write) {\n    if (!stats_filepath) {\n        return;\n    }\n\n    timeval current_time;\n    gettimeofday(&current_time, NULL);\n\n    static const double STATS_FILE_TIMING = 15.0;\n    if (!do_exit && delta_sec(last_stats_write, &current_time) < STATS_FILE_TIMING) {\n        return;\n    }\n\n    *last_stats_write = current_time;\n\n    FILE* file = fopen(stats_filepath, \"w\");\n    if (!file) {\n        log(LOG_WARNING, \"Cannot open output file %s (%s)\\n\", stats_filepath, strerror(errno));\n        return;\n    }\n\n    output_channel_activity_counters(file);\n    output_channel_noise_levels(file);\n    output_channel_dbfs_noise_levels(file);\n    output_channel_signal_levels(file);\n    output_channel_dbfs_signal_levels(file);\n    output_channel_squelch_counter(file);\n    output_channel_squelch_levels(file);\n    output_channel_flappy_counter(file);\n    output_channel_ctcss_counter(file);\n    output_channel_no_ctcss_counter(file);\n    output_device_buffer_overflows(file);\n    output_output_overruns(file);\n    output_input_overruns(file);\n\n    fclose(file);\n}\n\nvoid* output_thread(void* param) {\n    assert(param != NULL);\n    output_params_t* output_param = (output_params_t*)param;\n    struct freq_tag tag;\n    struct timeval tv;\n    int new_freq = -1;\n    timeval last_stats_write = {0, 0};\n\n    debug_print(\"Starting output thread, devices %d:%d, mixers %d:%d, signal %p\\n\", output_param->device_start, output_param->device_end, output_param->mixer_start, output_param->mixer_end,\n                output_param->mp3_signal);\n\n#ifdef DEBUG\n    timeval ts, te;\n    gettimeofday(&ts, NULL);\n#endif /* DEBUG */\n    while (!do_exit) {\n        output_param->mp3_signal->wait();\n        for (int i = output_param->mixer_start; i < output_param->mixer_end; i++) {\n            if (mixers[i].enabled == false)\n                continue;\n            channel_t* channel = &mixers[i].channel;\n            if (channel->state == CH_READY) {\n                process_outputs(channel, -1);\n                channel->state = CH_DIRTY;\n            }\n        }\n#ifdef DEBUG\n        gettimeofday(&te, NULL);\n        debug_bulk_print(\"mixeroutput: %lu.%lu %lu\\n\", te.tv_sec, (unsigned long)te.tv_usec, (te.tv_sec - ts.tv_sec) * 1000000UL + te.tv_usec - ts.tv_usec);\n        ts.tv_sec = te.tv_sec;\n        ts.tv_usec = te.tv_usec;\n#endif /* DEBUG */\n        for (int i = output_param->device_start; i < output_param->device_end; i++) {\n            device_t* dev = devices + i;\n            if (dev->input->state == INPUT_RUNNING && dev->waveavail) {\n                if (dev->mode == R_SCAN) {\n                    tag_queue_get(dev, &tag);\n                    if (tag.freq >= 0) {\n                        tag.tv.tv_sec += shout_metadata_delay;\n                        gettimeofday(&tv, NULL);\n                        if (tag.tv.tv_sec < tv.tv_sec || (tag.tv.tv_sec == tv.tv_sec && tag.tv.tv_usec <= tv.tv_usec)) {\n                            new_freq = tag.freq;\n                            tag_queue_advance(dev);\n                        }\n                    }\n                }\n                for (int j = 0; j < dev->channel_count; j++) {\n                    channel_t* channel = devices[i].channels + j;\n                    process_outputs(channel, new_freq);\n                    memcpy(channel->waveout, channel->waveout + WAVE_BATCH, AGC_EXTRA * 4);\n                }\n                dev->waveavail = 0;\n            }\n            // make sure we don't carry new_freq value to the next receiver which might be working\n            // in multichannel mode\n            new_freq = -1;\n        }\n        if (output_param->device_start == 0) {\n            write_stats_file(&last_stats_write);\n        }\n    }\n    return 0;\n}\n\n// reconnect as required\nvoid* output_check_thread(void*) {\n    while (!do_exit) {\n        SLEEP(10000);\n        for (int i = 0; i < device_count; i++) {\n            device_t* dev = devices + i;\n            for (int j = 0; j < dev->channel_count; j++) {\n                for (int k = 0; k < dev->channels[j].output_count; k++) {\n                    if (dev->channels[j].outputs[k].type == O_ICECAST) {\n                        icecast_data* icecast = (icecast_data*)(dev->channels[j].outputs[k].data);\n                        if (dev->input->state == INPUT_FAILED) {\n                            if (icecast->shout) {\n                                log(LOG_WARNING, \"Device #%d failed, disconnecting stream %s:%d/%s\\n\", i, icecast->hostname, icecast->port, icecast->mountpoint);\n                                shout_close(icecast->shout);\n                                shout_free(icecast->shout);\n                                icecast->shout = NULL;\n                            }\n                        } else if (dev->input->state == INPUT_RUNNING) {\n                            if (icecast->shout == NULL) {\n                                log(LOG_NOTICE, \"Trying to reconnect to %s:%d/%s...\\n\", icecast->hostname, icecast->port, icecast->mountpoint);\n                                shout_setup(icecast, dev->channels[j].mode);\n                            }\n                        }\n                    } else if (dev->channels[j].outputs[k].type == O_UDP_STREAM) {\n                        udp_stream_data* sdata = (udp_stream_data*)dev->channels[j].outputs[k].data;\n\n                        if (dev->input->state == INPUT_FAILED) {\n                            udp_stream_shutdown(sdata);\n                        }\n#ifdef WITH_PULSEAUDIO\n                    } else if (dev->channels[j].outputs[k].type == O_PULSE) {\n                        pulse_data* pdata = (pulse_data*)(dev->channels[j].outputs[k].data);\n                        if (dev->input->state == INPUT_FAILED) {\n                            if (pdata->context) {\n                                pulse_shutdown(pdata);\n                            }\n                        } else if (dev->input->state == INPUT_RUNNING) {\n                            if (pdata->context == NULL) {\n                                pulse_setup(pdata, dev->channels[j].mode);\n                            }\n                        }\n#endif /* WITH_PULSEAUDIO */\n                    }\n                }\n            }\n        }\n        for (int i = 0; i < mixer_count; i++) {\n            if (mixers[i].enabled == false)\n                continue;\n            for (int k = 0; k < mixers[i].channel.output_count; k++) {\n                if (mixers[i].channel.outputs[k].enabled == false)\n                    continue;\n                if (mixers[i].channel.outputs[k].type == O_ICECAST) {\n                    icecast_data* icecast = (icecast_data*)(mixers[i].channel.outputs[k].data);\n                    if (icecast->shout == NULL) {\n                        log(LOG_NOTICE, \"Trying to reconnect to %s:%d/%s...\\n\", icecast->hostname, icecast->port, icecast->mountpoint);\n                        shout_setup(icecast, mixers[i].channel.mode);\n                    }\n#ifdef WITH_PULSEAUDIO\n                } else if (mixers[i].channel.outputs[k].type == O_PULSE) {\n                    pulse_data* pdata = (pulse_data*)(mixers[i].channel.outputs[k].data);\n                    if (pdata->context == NULL) {\n                        pulse_setup(pdata, mixers[i].channel.mode);\n                    }\n#endif /* WITH_PULSEAUDIO */\n                }\n            }\n        }\n    }\n    return 0;\n}\n"
  },
  {
    "path": "src/pulse.cpp",
    "content": "/*\n * pulse.cpp\n * PulseAudio output routines\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <pulse/pulseaudio.h>\n#include <syslog.h>\n#include <iostream>\n#include \"rtl_airband.h\"\n\n#define SERVER_IFNOTNULL(x) ((x) ? (x) : \"<default_server>\")\n#define PA_LOOP_LOCK(x)                       \\\n    if (!pa_threaded_mainloop_in_thread(x)) { \\\n        pa_threaded_mainloop_lock(x);         \\\n    }\n#define PA_LOOP_UNLOCK(x)                     \\\n    if (!pa_threaded_mainloop_in_thread(x)) { \\\n        pa_threaded_mainloop_unlock(x);       \\\n    }\n\nusing namespace std;\n\npa_threaded_mainloop* mainloop = NULL;\n\nvoid pulse_shutdown(pulse_data* pdata) {\n    if (!pdata)\n        return;\n    PA_LOOP_LOCK(mainloop);\n    if (pdata->left) {\n        pa_stream_disconnect(pdata->left);\n        pa_stream_unref(pdata->left);\n        pdata->left = NULL;\n    }\n    if (pdata->right) {\n        pa_stream_disconnect(pdata->right);\n        pa_stream_unref(pdata->right);\n        pdata->right = NULL;\n    }\n    if (pdata->context) {\n        pa_context_disconnect(pdata->context);\n        pa_context_unref(pdata->context);\n        pdata->context = NULL;\n    }\n    PA_LOOP_UNLOCK(mainloop);\n}\n\nstatic void pulse_stream_underflow_cb(pa_stream*, void* userdata) {\n    pulse_data* pdata = (pulse_data*)userdata;\n    if (pdata->continuous)  // do not flood the logs on every squelch closing\n        log(LOG_INFO, \"pulse: %s: stream \\\"%s\\\": underflow\\n\", SERVER_IFNOTNULL(pdata->server), pdata->stream_name);\n}\n\nstatic void pulse_stream_overflow_cb(pa_stream*, void* userdata) {\n    pulse_data* pdata = (pulse_data*)userdata;\n    log(LOG_INFO, \"pulse: %s: stream \\\"%s\\\": overflow\\n\", SERVER_IFNOTNULL(pdata->server), pdata->stream_name);\n}\n\nstatic void stream_state_cb(pa_stream* stream, void* userdata) {\n    pulse_data* pdata = (pulse_data*)userdata;\n\n    switch (pa_stream_get_state(stream)) {\n        case PA_STREAM_READY:\n            if (pdata->mode == MM_MONO || (pa_stream_get_state(pdata->left) == PA_STREAM_READY && pa_stream_get_state(pdata->right) == PA_STREAM_READY))\n                pa_stream_cork(pdata->left, 0, NULL, NULL);\n            break;\n        case PA_STREAM_UNCONNECTED:\n        case PA_STREAM_CREATING:\n            break;\n        case PA_STREAM_FAILED:\n            log(LOG_WARNING, \"pulse: %s: stream \\\"%s\\\" failed: %s\\n\", SERVER_IFNOTNULL(pdata->server), pdata->stream_name, pa_strerror(pa_context_errno(pdata->context)));\n            break;\n        case PA_STREAM_TERMINATED:\n            log(LOG_WARNING, \"pulse: %s: stream \\\"%s\\\" terminated\\n\", SERVER_IFNOTNULL(pdata->server), pdata->stream_name);\n            break;\n            break;\n    }\n}\n\nstatic pa_stream* pulse_setup_stream(pulse_data* pdata, const pa_sample_spec* ss, pa_channel_map* cmap, pa_stream* sync_stream) {\n    pa_stream* stream = NULL;\n    PA_LOOP_LOCK(mainloop);\n    if (!(stream = pa_stream_new(pdata->context, pdata->stream_name, ss, cmap))) {\n        log(LOG_ERR, \"pulse: %s: failed to create stream \\\"%s\\\": %s\\n\", SERVER_IFNOTNULL(pdata->server), pdata->stream_name, pa_strerror(pa_context_errno(pdata->context)));\n        goto fail;\n    }\n    pa_stream_set_state_callback(stream, stream_state_cb, pdata);\n    pa_stream_set_underflow_callback(stream, pulse_stream_underflow_cb, pdata);\n    pa_stream_set_overflow_callback(stream, pulse_stream_overflow_cb, pdata);\n    // Initially streams are corked (paused). For mono streams this is irrelevant,\n    // but for stereo mixers it's required to keep left and right channels in sync.\n    // Starting the left channel stream before the other stream from the sync pair is\n    // set up causes the left channel stream to fail.\n    if (pa_stream_connect_playback(stream, pdata->sink, NULL, (pa_stream_flags_t)(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_START_CORKED | PA_STREAM_AUTO_TIMING_UPDATE),\n                                   NULL, sync_stream) < 0) {\n        log(LOG_ERR, \"pulse: %s: failed to connect stream \\\"%s\\\": %s\\n\", SERVER_IFNOTNULL(pdata->server), pdata->stream_name, pa_strerror(pa_context_errno(pdata->context)));\n        goto fail;\n    }\n    log(LOG_INFO, \"pulse: %s: stream \\\"%s\\\" connected\\n\", SERVER_IFNOTNULL(pdata->server), pdata->stream_name);\n    PA_LOOP_UNLOCK(mainloop);\n    return stream;\nfail:\n    PA_LOOP_UNLOCK(mainloop);\n    return NULL;\n}\n\nstatic void pulse_setup_streams(pulse_data* pdata) {\n    const pa_sample_spec ss = {\n#if __cplusplus >= 199711L\n        .format = PA_SAMPLE_FLOAT32LE,\n        .rate = WAVE_RATE,\n        .channels = 1\n#else  // for g++ 4.6 (eg. Raspbian Wheezy)\n        PA_SAMPLE_FLOAT32LE,\n        WAVE_RATE,\n        1\n#endif /* __cplusplus */\n    };\n    pa_channel_map_init_mono(&pdata->lmap);\n    pdata->lmap.map[0] = (pdata->mode == MM_STEREO ? PA_CHANNEL_POSITION_LEFT : PA_CHANNEL_POSITION_MONO);\n    if (!(pdata->left = pulse_setup_stream(pdata, &ss, &pdata->lmap, NULL)))\n        goto fail;\n    if (pdata->mode == MM_STEREO) {\n        pa_channel_map_init_mono(&pdata->rmap);\n        pdata->rmap.map[0] = PA_CHANNEL_POSITION_RIGHT;\n        if (!(pdata->right = pulse_setup_stream(pdata, &ss, &pdata->rmap, pdata->left)))\n            goto fail;\n    }\n    return;\nfail:\n    pulse_shutdown(pdata);\n}\n\nstatic void pulse_ctx_state_cb(pa_context* c, void* userdata) {\n    pulse_data* pdata = (pulse_data*)userdata;\n    switch (pa_context_get_state(c)) {\n        case PA_CONTEXT_READY:\n            pulse_setup_streams(pdata);\n            break;\n        case PA_CONTEXT_TERMINATED:\n            break;\n        case PA_CONTEXT_FAILED:\n            log(LOG_ERR, \"pulse: %s: connection failed: %s\\n\", SERVER_IFNOTNULL(pdata->server), pa_strerror(pa_context_errno(pdata->context)));\n            pulse_shutdown(pdata);\n            break;\n        case PA_CONTEXT_CONNECTING:\n            log(LOG_INFO, \"pulse: %s: connecting...\\n\", SERVER_IFNOTNULL(pdata->server));\n            break;\n        case PA_CONTEXT_UNCONNECTED:\n        case PA_CONTEXT_AUTHORIZING:\n        case PA_CONTEXT_SETTING_NAME:\n            break;\n    }\n}\n\nvoid pulse_init() {\n    if (!mainloop && !(mainloop = pa_threaded_mainloop_new())) {\n        cerr << \"Failed to initialize PulseAudio main loop - aborting\\n\";\n        error();\n    }\n}\n\nint pulse_setup(pulse_data* pdata, mix_modes mixmode) {\n    if (!(pdata->context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), pdata->name))) {\n        log(LOG_ERR, \"%s\", \"pulse: failed to create context\\n\");\n        return -1;\n    }\n    pdata->mode = mixmode;\n    PA_LOOP_LOCK(mainloop);\n    int ret = 0;\n    pa_context_set_state_callback(pdata->context, &pulse_ctx_state_cb, pdata);\n    if (pa_context_connect(pdata->context, pdata->server, PA_CONTEXT_NOFLAGS, NULL) < 0) {\n        log(LOG_WARNING, \"pulse: %s: failed to connect: %s\\n\", SERVER_IFNOTNULL(pdata->server), pa_strerror(pa_context_errno(pdata->context)));\n        // Don't clean up things here, context state is now set to PA_CONTEXT_FAILED,\n        // so pulse_ctx_state_cb will take care of that.\n        ret = -1;\n    }\n    PA_LOOP_UNLOCK(mainloop);\n    return ret;\n}\n\nvoid pulse_start() {\n    if (!mainloop)\n        return;\n    PA_LOOP_LOCK(mainloop);\n    pa_threaded_mainloop_start(mainloop);\n    PA_LOOP_UNLOCK(mainloop);\n}\n\nstatic int pulse_write_single_stream(pa_stream* stream, pulse_data* pdata, const float* data, size_t len, bool is_master) {\n    pa_usec_t latency;\n    int ret = -1;\n    int lret;\n\n    PA_LOOP_LOCK(mainloop);\n    if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY)\n        goto end;\n\n    if (is_master) { /* latency info is only meaningful for master stream) */\n        lret = pa_stream_get_latency(stream, &latency, NULL);\n        if (lret < 0) {\n            log(LOG_WARNING, \"pulse: %s: failed to get latency info for stream \\\"%s\\\" (error is: %s), disconnecting\\n\", SERVER_IFNOTNULL(pdata->server), pdata->stream_name, pa_strerror(lret));\n            goto end;\n        }\n        if (latency > PULSE_STREAM_LATENCY_LIMIT) {\n            log(LOG_INFO, \"pulse: %s: exceeded max backlog for stream \\\"%s\\\", disconnecting\\n\", SERVER_IFNOTNULL(pdata->server), pdata->stream_name);\n            goto end;\n        }\n        debug_bulk_print(\"pulse: %s: stream=\\\"%s\\\" lret=%d latency=%f ms\\n\", SERVER_IFNOTNULL(pdata->server), pdata->stream_name, lret, (float)latency / 1000.0f);\n    }\n    if (pa_stream_write(stream, data, len, NULL, 0LL, PA_SEEK_RELATIVE) < 0) {\n        log(LOG_WARNING, \"pulse: %s: could not write to stream \\\"%s\\\", disconnecting\\n\", SERVER_IFNOTNULL(pdata->server), pdata->stream_name);\n        goto end;\n    }\n    ret = 0;\nend:\n    PA_LOOP_UNLOCK(mainloop);\n    return ret;\n}\n\nvoid pulse_write_stream(pulse_data* pdata, mix_modes mode, const float* data_left, const float* data_right, size_t len) {\n    PA_LOOP_LOCK(mainloop);\n    if (!pdata->context || pa_context_get_state(pdata->context) != PA_CONTEXT_READY)\n        goto end;\n    if (pulse_write_single_stream(pdata->left, pdata, data_left, len, true) < 0)\n        goto fail;\n    if (mode == MM_STEREO && pulse_write_single_stream(pdata->right, pdata, data_right, len, false) < 0)\n        goto fail;\n    goto end;\nfail:\n    pulse_shutdown(pdata);\nend:\n    PA_LOOP_UNLOCK(mainloop);\n    return;\n}\n"
  },
  {
    "path": "src/rtl_airband.cpp",
    "content": "/*\n * RTLSDR AM/NFM demodulator, mixer, streamer and recorder\n *\n * Copyright (c) 2014 Wong Man Hang <microtony@gmail.com>\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"config.h\"\n\n#if defined WITH_BCM_VC && !defined __arm__\n#error Broadcom VideoCore support can only be enabled on ARM builds\n#endif\n\n// From this point we may safely assume that WITH_BCM_VC implies __arm__\n\n#ifdef WITH_BCM_VC\n#include \"hello_fft/gpu_fft.h\"\n#include \"hello_fft/mailbox.h\"\n#endif /* WITH_BCM_VC */\n\n#include <fcntl.h>\n#include <lame/lame.h>\n#include <ogg/ogg.h>\n#include <pthread.h>\n#include <shout/shout.h>\n#include <stdint.h>  // uint8_t\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <syslog.h>\n#include <unistd.h>\n#include <vorbis/vorbisenc.h>\n#include <algorithm>\n#include <cassert>\n#include <cerrno>\n#include <cmath>\n#include <csignal>\n#include <cstdarg>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <ctime>\n#include <iostream>\n#include <libconfig.h++>\n#include \"input-common.h\"\n#include \"logging.h\"\n#include \"rtl_airband.h\"\n#include \"squelch.h\"\n\n#ifdef WITH_PROFILING\n#include \"gperftools/profiler.h\"\n#endif /* WITH_PROFILING */\n\nusing namespace std;\nusing namespace libconfig;\n\ndevice_t* devices;\nmixer_t* mixers;\nint device_count, mixer_count;\nstatic int devices_running = 0;\nint tui = 0;  // do not display textual user interface\nint shout_metadata_delay = 3;\nvolatile int do_exit = 0;\nbool use_localtime = false;\nbool multiple_demod_threads = false;\nbool multiple_output_threads = false;\nbool log_scan_activity = false;\nchar* stats_filepath = NULL;\nsize_t fft_size_log = DEFAULT_FFT_SIZE_LOG;\nsize_t fft_size = 1 << fft_size_log;\n\n#ifdef NFM\nfloat alpha = exp(-1.0f / (WAVE_RATE * 2e-4));\nenum fm_demod_algo { FM_FAST_ATAN2, FM_QUADRI_DEMOD };\nenum fm_demod_algo fm_demod = FM_FAST_ATAN2;\n#endif /* NFM */\n\n#ifdef DEBUG\nchar* debug_path;\n#endif /* DEBUG */\n\nvoid sighandler(int sig) {\n    log(LOG_NOTICE, \"Got signal %d, exiting\\n\", sig);\n    do_exit = 1;\n}\n\nvoid* controller_thread(void* params) {\n    device_t* dev = (device_t*)params;\n    int i = 0;\n    int consecutive_squelch_off = 0;\n    int new_centerfreq = 0;\n    struct timeval tv;\n\n    if (dev->channels[0].freq_count < 2)\n        return 0;\n    while (!do_exit) {\n        SLEEP(200);\n        if (dev->channels[0].axcindicate == NO_SIGNAL) {\n            if (consecutive_squelch_off < 10) {\n                consecutive_squelch_off++;\n            } else {\n                i++;\n                i %= dev->channels[0].freq_count;\n                dev->channels[0].freq_idx = i;\n                new_centerfreq = dev->channels[0].freqlist[i].frequency + 20 * (double)(dev->input->sample_rate / fft_size);\n                if (input_set_centerfreq(dev->input, new_centerfreq) < 0) {\n                    break;\n                }\n            }\n        } else {\n            if (consecutive_squelch_off == 10) {\n                if (log_scan_activity)\n                    log(LOG_INFO, \"Activity on %7.3f MHz (%s)\\n\", dev->channels[0].freqlist[i].frequency / 1000000.0, dev->channels[0].freqlist[i].label);\n                if (i != dev->last_frequency) {\n                    // squelch has just opened on a new frequency - we might need to update outputs' metadata\n                    gettimeofday(&tv, NULL);\n                    tag_queue_put(dev, i, tv);\n                    dev->last_frequency = i;\n                }\n            }\n            consecutive_squelch_off = 0;\n        }\n    }\n    return 0;\n}\n\nvoid multiply(float ar, float aj, float br, float bj, float* cr, float* cj) {\n    *cr = ar * br - aj * bj;\n    *cj = aj * br + ar * bj;\n}\n\n#ifdef NFM\nfloat fast_atan2(float y, float x) {\n    float yabs, angle;\n    float pi4 = M_PI_4, pi34 = 3 * M_PI_4;\n    if (x == 0.0f && y == 0.0f) {\n        return 0;\n    }\n    yabs = y;\n    if (yabs < 0.0f) {\n        yabs = -yabs;\n    }\n    if (x >= 0.0f) {\n        angle = pi4 - pi4 * (x - yabs) / (x + yabs);\n    } else {\n        angle = pi34 - pi4 * (x + yabs) / (yabs - x);\n    }\n    if (y < 0.0f) {\n        return -angle;\n    }\n    return angle;\n}\n\nfloat polar_disc_fast(float ar, float aj, float br, float bj) {\n    float cr, cj;\n    multiply(ar, aj, br, -bj, &cr, &cj);\n    return (float)(fast_atan2(cj, cr) * M_1_PI);\n}\n\nfloat fm_quadri_demod(float ar, float aj, float br, float bj) {\n    return (float)((br * aj - ar * bj) / (ar * ar + aj * aj + 1.0f) * M_1_PI);\n}\n\n#endif /* NFM */\n\nclass AFC {\n    const status _prev_axcindicate;\n\n#ifdef WITH_BCM_VC\n    float square(const GPU_FFT_COMPLEX* fft_results, size_t index) {\n        return fft_results[index].re * fft_results[index].re + fft_results[index].im * fft_results[index].im;\n    }\n#else\n    float square(const fftwf_complex* fft_results, size_t index) {\n        return fft_results[index][0] * fft_results[index][0] + fft_results[index][1] * fft_results[index][1];\n    }\n#endif /* WITH_BCM_VC */\n\n    template <class FFT_RESULTS, int STEP>\n    size_t check(const FFT_RESULTS* fft_results, const size_t base, const float base_value, unsigned char afc) {\n        float threshold = 0;\n        size_t bin;\n        for (bin = base;; bin += STEP) {\n            if (STEP < 0) {\n                if (bin < -STEP)\n                    break;\n\n            } else if ((size_t)(bin + STEP) >= fft_size)\n                break;\n\n            const float value = square(fft_results, (size_t)(bin + STEP));\n            if (value <= base_value)\n                break;\n\n            if (base == (size_t)bin) {\n                threshold = (value - base_value) / (float)afc;\n            } else {\n                if ((value - base_value) < threshold)\n                    break;\n\n                threshold += threshold / 10.0;\n            }\n        }\n        return bin;\n    }\n\n   public:\n    AFC(device_t* dev, int index) : _prev_axcindicate(dev->channels[index].axcindicate) {}\n\n    template <class FFT_RESULTS>\n    void finalize(device_t* dev, int index, const FFT_RESULTS* fft_results) {\n        channel_t* channel = &dev->channels[index];\n        if (channel->afc == 0)\n            return;\n\n        const char axcindicate = channel->axcindicate;\n        if (axcindicate != NO_SIGNAL && _prev_axcindicate == NO_SIGNAL) {\n            const size_t base = dev->base_bins[index];\n            const float base_value = square(fft_results, base);\n            size_t bin = check<FFT_RESULTS, -1>(fft_results, base, base_value, channel->afc);\n            if (bin == base)\n                bin = check<FFT_RESULTS, 1>(fft_results, base, base_value, channel->afc);\n\n            if (dev->bins[index] != bin) {\n#ifdef AFC_LOGGING\n                log(LOG_INFO, \"AFC device=%d channel=%d: base=%zu prev=%zu now=%zu\\n\", dev->device, index, base, dev->bins[index], bin);\n#endif /* AFC_LOGGING */\n                dev->bins[index] = bin;\n                if (bin > base)\n                    channel->axcindicate = AFC_UP;\n                else if (bin < base)\n                    channel->axcindicate = AFC_DOWN;\n            }\n        } else if (axcindicate == NO_SIGNAL && _prev_axcindicate != NO_SIGNAL)\n            dev->bins[index] = dev->base_bins[index];\n    }\n};\n\nvoid init_demod(demod_params_t* params, Signal* signal, int device_start, int device_end) {\n    assert(params != NULL);\n    assert(signal != NULL);\n\n    params->mp3_signal = signal;\n    params->device_start = device_start;\n    params->device_end = device_end;\n\n#ifndef WITH_BCM_VC\n    params->fftin = fftwf_alloc_complex(fft_size);\n    params->fftout = fftwf_alloc_complex(fft_size);\n    params->fft = fftwf_plan_dft_1d(fft_size, params->fftin, params->fftout, FFTW_FORWARD, FFTW_MEASURE);\n#endif /* WITH_BCM_VC */\n}\n\nbool init_output(channel_t* channel, output_t* output) {\n    if (output->has_mp3_output) {\n        output->lame = airlame_init(channel->mode, channel->highpass, channel->lowpass);\n        output->lamebuf = (unsigned char*)malloc(sizeof(unsigned char) * LAMEBUF_SIZE);\n    }\n    if (output->type == O_ICECAST) {\n        shout_setup((icecast_data*)(output->data), channel->mode);\n    } else if (output->type == O_UDP_STREAM) {\n        udp_stream_data* sdata = (udp_stream_data*)(output->data);\n        if (!udp_stream_init(sdata, channel->mode, (size_t)WAVE_BATCH * sizeof(float))) {\n            return false;\n        }\n#ifdef WITH_PULSEAUDIO\n    } else if (output->type == O_PULSE) {\n        pulse_init();\n        pulse_setup((pulse_data*)(output->data), channel->mode);\n#endif /* WITH_PULSEAUDIO */\n    }\n\n    return true;\n}\n\nvoid init_output_params(output_params_t* params, int device_start, int device_end, int mixer_start, int mixer_end) {\n    assert(params != NULL);\n\n    params->mp3_signal = new Signal;\n    params->device_start = device_start;\n    params->device_end = device_end;\n    params->mixer_start = mixer_start;\n    params->mixer_end = mixer_end;\n}\n\nint next_device(demod_params_t* params, int current) {\n    current++;\n    if (current < params->device_end) {\n        return current;\n    }\n    return params->device_start;\n}\n\nvoid* demodulate(void* params) {\n    assert(params != NULL);\n    demod_params_t* demod_params = (demod_params_t*)params;\n\n    debug_print(\"Starting demod thread, devices %d:%d, signal %p\\n\", demod_params->device_start, demod_params->device_end, demod_params->mp3_signal);\n\n    // initialize fft engine\n#ifdef WITH_BCM_VC\n    int mb = mbox_open();\n    struct GPU_FFT* fft;\n    int ret = gpu_fft_prepare(mb, fft_size_log, GPU_FFT_FWD, FFT_BATCH, &fft);\n    switch (ret) {\n        case -1:\n            log(LOG_CRIT, \"Unable to enable V3D. Please check your firmware is up to date.\\n\");\n            error();\n            break;\n        case -2:\n            log(LOG_CRIT, \"log2_N=%d not supported. Try between 8 and 17.\\n\", fft_size_log);\n            error();\n            break;\n        case -3:\n            log(LOG_CRIT, \"Out of memory. Try a smaller batch or increase GPU memory.\\n\");\n            error();\n            break;\n    }\n#else\n    fftwf_complex* fftin = demod_params->fftin;\n    fftwf_complex* fftout = demod_params->fftout;\n#endif /* WITH_BCM_VC */\n\n    float ALIGNED32 levels_u8[256], levels_s8[256];\n    float* levels_ptr = NULL;\n\n    for (int i = 0; i < 256; i++) {\n        levels_u8[i] = (i - 127.5f) / 127.5f;\n    }\n    for (int16_t i = -127; i < 128; i++) {\n        levels_s8[(uint8_t)i] = i / 128.0f;\n    }\n\n    // initialize fft window\n    // blackman 7\n    // the whole matrix is computed\n#ifdef WITH_BCM_VC\n    float ALIGNED32 window[fft_size * 2];\n#else\n    float ALIGNED32 window[fft_size];\n#endif /* WITH_BCM_VC */\n\n    const double a0 = 0.27105140069342f;\n    const double a1 = 0.43329793923448f;\n    const double a2 = 0.21812299954311f;\n    const double a3 = 0.06592544638803f;\n    const double a4 = 0.01081174209837f;\n    const double a5 = 0.00077658482522f;\n    const double a6 = 0.00001388721735f;\n\n    for (size_t i = 0; i < fft_size; i++) {\n        double x = a0 - (a1 * cos((2.0 * M_PI * i) / (fft_size - 1))) + (a2 * cos((4.0 * M_PI * i) / (fft_size - 1))) - (a3 * cos((6.0 * M_PI * i) / (fft_size - 1))) +\n                   (a4 * cos((8.0 * M_PI * i) / (fft_size - 1))) - (a5 * cos((10.0 * M_PI * i) / (fft_size - 1))) + (a6 * cos((12.0 * M_PI * i) / (fft_size - 1)));\n#ifdef WITH_BCM_VC\n        window[i * 2] = window[i * 2 + 1] = (float)x;\n#else\n        window[i] = (float)x;\n#endif /* WITH_BCM_VC */\n    }\n\n#ifdef DEBUG\n    struct timeval ts, te;\n    gettimeofday(&ts, NULL);\n#endif /* DEBUG */\n    size_t available;\n    int device_num = demod_params->device_start;\n    while (true) {\n        if (do_exit) {\n#ifdef WITH_BCM_VC\n            log(LOG_INFO, \"Freeing GPU memory\\n\");\n            gpu_fft_release(fft);\n#endif /* WITH_BCM_VC */\n            return NULL;\n        }\n\n        device_t* dev = devices + device_num;\n\n        pthread_mutex_lock(&dev->input->buffer_lock);\n        if (dev->input->bufe >= dev->input->bufs)\n            available = dev->input->bufe - dev->input->bufs;\n        else\n            available = dev->input->buf_size - dev->input->bufs + dev->input->bufe;\n        pthread_mutex_unlock(&dev->input->buffer_lock);\n\n        if (devices_running == 0) {\n            log(LOG_ERR, \"All receivers failed, exiting\\n\");\n            do_exit = 1;\n            continue;\n        }\n\n        if (dev->input->state != INPUT_RUNNING) {\n            if (dev->input->state == INPUT_FAILED) {\n                dev->input->state = INPUT_DISABLED;\n                disable_device_outputs(dev);\n                devices_running--;\n            }\n            device_num = next_device(demod_params, device_num);\n            continue;\n        }\n\n        // number of input bytes per output wave sample (x 2 for I and Q)\n        size_t bps = 2 * dev->input->bytes_per_sample * (size_t)round((double)dev->input->sample_rate / (double)WAVE_RATE);\n        if (available < bps * FFT_BATCH + fft_size * dev->input->bytes_per_sample * 2) {\n            // move to next device\n            device_num = next_device(demod_params, device_num);\n            SLEEP(10);\n            continue;\n        }\n\n        if (dev->input->sfmt == SFMT_S16) {\n            float const scale = 1.0f / dev->input->fullscale;\n#ifdef WITH_BCM_VC\n            struct GPU_FFT_COMPLEX* ptr = fft->in;\n            for (size_t b = 0; b < FFT_BATCH; b++, ptr += fft->step) {\n                short* buf2 = (short*)(dev->input->buffer + dev->input->bufs + b * bps);\n                for (size_t i = 0; i < fft_size; i++, buf2 += 2) {\n                    ptr[i].re = scale * (float)buf2[0] * window[i * 2];\n                    ptr[i].im = scale * (float)buf2[1] * window[i * 2];\n                }\n            }\n#else\n            short* buf2 = (short*)(dev->input->buffer + dev->input->bufs);\n            for (size_t i = 0; i < fft_size; i++, buf2 += 2) {\n                fftin[i][0] = scale * (float)buf2[0] * window[i];\n                fftin[i][1] = scale * (float)buf2[1] * window[i];\n            }\n#endif /* WITH_BCM_VC */\n        } else if (dev->input->sfmt == SFMT_F32) {\n            float const scale = 1.0f / dev->input->fullscale;\n#ifdef WITH_BCM_VC\n            struct GPU_FFT_COMPLEX* ptr = fft->in;\n            for (size_t b = 0; b < FFT_BATCH; b++, ptr += fft->step) {\n                float* buf2 = (float*)(dev->input->buffer + dev->input->bufs + b * bps);\n                for (size_t i = 0; i < fft_size; i++, buf2 += 2) {\n                    ptr[i].re = scale * buf2[0] * window[i * 2];\n                    ptr[i].im = scale * buf2[1] * window[i * 2];\n                }\n            }\n#else  // WITH_BCM_VC\n            float* buf2 = (float*)(dev->input->buffer + dev->input->bufs);\n            for (size_t i = 0; i < fft_size; i++, buf2 += 2) {\n                fftin[i][0] = scale * buf2[0] * window[i];\n                fftin[i][1] = scale * buf2[1] * window[i];\n            }\n#endif /* WITH_BCM_VC */\n\n        } else {  // S8 or U8\n            levels_ptr = (dev->input->sfmt == SFMT_U8 ? levels_u8 : levels_s8);\n\n#ifdef WITH_BCM_VC\n            sample_fft_arg sfa = {fft_size / 4, fft->in};\n            for (size_t i = 0; i < FFT_BATCH; i++) {\n                samplefft(&sfa, dev->input->buffer + dev->input->bufs + i * bps, window, levels_ptr);\n                sfa.dest += fft->step;\n            }\n#else\n            unsigned char* buf2 = dev->input->buffer + dev->input->bufs;\n            for (size_t i = 0; i < fft_size; i++, buf2 += 2) {\n                fftin[i][0] = levels_ptr[buf2[0]] * window[i];\n                fftin[i][1] = levels_ptr[buf2[1]] * window[i];\n            }\n#endif /* WITH_BCM_VC */\n        }\n\n#ifdef WITH_BCM_VC\n        gpu_fft_execute(fft);\n#else\n        fftwf_execute(demod_params->fft);\n#endif /* WITH_BCM_VC */\n\n#ifdef WITH_BCM_VC\n        for (int i = 0; i < dev->channel_count; i++) {\n            float* wavein = dev->channels[i].wavein + dev->waveend;\n            __builtin_prefetch(wavein, 1);\n            const int bin = dev->bins[i];\n            const GPU_FFT_COMPLEX* fftout = fft->out + bin;\n            for (int j = 0; j < FFT_BATCH; j++, ++wavein, fftout += fft->step)\n                *wavein = sqrtf(fftout->im * fftout->im + fftout->re * fftout->re);\n        }\n        for (int j = 0; j < dev->channel_count; j++) {\n            if (dev->channels[j].needs_raw_iq) {\n                struct GPU_FFT_COMPLEX* ptr = fft->out;\n                for (int job = 0; job < FFT_BATCH; job++) {\n                    dev->channels[j].iq_in[2 * (dev->waveend + job)] = ptr[dev->bins[j]].re;\n                    dev->channels[j].iq_in[2 * (dev->waveend + job) + 1] = ptr[dev->bins[j]].im;\n                    ptr += fft->step;\n                }\n            }\n        }\n#else\n        for (int j = 0; j < dev->channel_count; j++) {\n            dev->channels[j].wavein[dev->waveend] = sqrtf(fftout[dev->bins[j]][0] * fftout[dev->bins[j]][0] + fftout[dev->bins[j]][1] * fftout[dev->bins[j]][1]);\n            if (dev->channels[j].needs_raw_iq) {\n                dev->channels[j].iq_in[2 * dev->waveend] = fftout[dev->bins[j]][0];\n                dev->channels[j].iq_in[2 * dev->waveend + 1] = fftout[dev->bins[j]][1];\n            }\n        }\n#endif /* WITH_BCM_VC */\n\n        dev->waveend += FFT_BATCH;\n\n        if (dev->waveend >= WAVE_BATCH + AGC_EXTRA) {\n            for (int i = 0; i < dev->channel_count; i++) {\n                AFC afc(dev, i);\n                channel_t* channel = dev->channels + i;\n                freq_t* fparms = channel->freqlist + channel->freq_idx;\n\n                // set to NO_SIGNAL, will be updated to SIGNAL based on squelch below\n                channel->axcindicate = NO_SIGNAL;\n\n                for (int j = AGC_EXTRA; j < WAVE_BATCH + AGC_EXTRA; j++) {\n                    float& real = channel->iq_in[2 * (j - AGC_EXTRA)];\n                    float& imag = channel->iq_in[2 * (j - AGC_EXTRA) + 1];\n\n                    fparms->squelch.process_raw_sample(channel->wavein[j]);\n\n                    // If squelch is open / opening and using I/Q, then cleanup the signal and possibly update squelch.\n                    if (fparms->squelch.should_filter_sample() && channel->needs_raw_iq) {\n                        // remove phase rotation introduced by FFT sliding window\n                        float swf, cwf, re_tmp, im_tmp;\n                        sincosf_lut(channel->dm_phi, &swf, &cwf);\n                        multiply(real, imag, cwf, -swf, &re_tmp, &im_tmp);\n                        channel->dm_phi += channel->dm_dphi;\n                        channel->dm_phi &= 0xffffff;\n\n                        // apply lowpass filter, will be a no-op if not configured\n                        fparms->lowpass_filter.apply(re_tmp, im_tmp);\n\n                        // update I/Q and wave\n                        real = re_tmp;\n                        imag = im_tmp;\n                        channel->wavein[j] = sqrt(real * real + imag * imag);\n\n                        // update squelch post-cleanup\n                        if (fparms->lowpass_filter.enabled()) {\n                            fparms->squelch.process_filtered_sample(channel->wavein[j]);\n                        }\n                    }\n\n                    if (fparms->modulation == MOD_AM) {\n                        // if squelch is just opening then bootstrip agcavgfast with prior values of wavein\n                        if (fparms->squelch.first_open_sample()) {\n                            for (int k = j - AGC_EXTRA; k < j; k++) {\n                                if (channel->wavein[k] >= fparms->squelch.squelch_level()) {\n                                    fparms->agcavgfast = fparms->agcavgfast * 0.9f + channel->wavein[k] * 0.1f;\n                                }\n                            }\n                        }\n                        // if squelch is just closing then fade out the prior samples of waveout\n                        else if (fparms->squelch.last_open_sample()) {\n                            for (int k = j - AGC_EXTRA + 1; k < j; k++) {\n                                channel->waveout[k] = channel->waveout[k - 1] * 0.94f;\n                            }\n                        }\n                    }\n\n                    float& waveout = channel->waveout[j];\n\n                    // If squelch sees power then do modulation-specific processing\n                    if (fparms->squelch.should_process_audio()) {\n                        if (fparms->modulation == MOD_AM) {\n                            if (channel->wavein[j] > fparms->squelch.squelch_level()) {\n                                fparms->agcavgfast = fparms->agcavgfast * 0.995f + channel->wavein[j] * 0.005f;\n                            }\n\n                            waveout = (channel->wavein[j - AGC_EXTRA] - fparms->agcavgfast) / (fparms->agcavgfast * 1.5f);\n                            if (abs(waveout) > 0.8f) {\n                                waveout *= 0.85f;\n                                fparms->agcavgfast *= 1.15f;\n                            }\n                        }\n#ifdef NFM\n                        else if (fparms->modulation == MOD_NFM) {\n                            // FM demod\n                            if (fm_demod == FM_FAST_ATAN2) {\n                                waveout = polar_disc_fast(real, imag, channel->pr, channel->pj);\n                            } else if (fm_demod == FM_QUADRI_DEMOD) {\n                                waveout = fm_quadri_demod(real, imag, channel->pr, channel->pj);\n                            }\n                            channel->pr = real;\n                            channel->pj = imag;\n\n                            // de-emphasis IIR + DC blocking\n                            fparms->agcavgfast = fparms->agcavgfast * 0.995f + waveout * 0.005f;\n                            waveout -= fparms->agcavgfast;\n                            waveout = waveout * (1.0f - channel->alpha) + channel->prev_waveout * channel->alpha;\n\n                            // save off waveout before notch and ampfactor\n                            channel->prev_waveout = waveout;\n                        }\n#endif /* NFM */\n\n                        // process audio sample for CTCSS, will be no-op if not configured\n                        fparms->squelch.process_audio_sample(waveout);\n                    }\n\n                    // If squelch is still open then save samples to output\n                    if (fparms->squelch.is_open()) {\n                        // apply the notch filter, will be a no-op if not configured\n                        fparms->notch_filter.apply(waveout);\n\n                        // apply the ampfactor\n                        waveout *= fparms->ampfactor;\n\n                        // make sure the value is between +/- 1 (requirement for libmp3lame)\n                        if (isnan(waveout)) {\n                            waveout = 0.0;\n                        } else if (waveout > 1.0) {\n                            waveout = 1.0;\n                        } else if (waveout < -1.0) {\n                            waveout = -1.0;\n                        }\n\n                        channel->axcindicate = SIGNAL;\n                        if (channel->has_iq_outputs) {\n                            channel->iq_out[2 * (j - AGC_EXTRA)] = real;\n                            channel->iq_out[2 * (j - AGC_EXTRA) + 1] = imag;\n                        }\n\n                        // Squelch is closed\n                    } else {\n                        waveout = 0;\n                        if (channel->has_iq_outputs) {\n                            channel->iq_out[2 * (j - AGC_EXTRA)] = 0;\n                            channel->iq_out[2 * (j - AGC_EXTRA) + 1] = 0;\n                        }\n                    }\n                }\n                memmove(channel->wavein, channel->wavein + WAVE_BATCH, (dev->waveend - WAVE_BATCH) * sizeof(float));\n                if (channel->needs_raw_iq) {\n                    memmove(channel->iq_in, channel->iq_in + 2 * WAVE_BATCH, (dev->waveend - WAVE_BATCH) * sizeof(float) * 2);\n                }\n\n#ifdef WITH_BCM_VC\n                afc.finalize(dev, i, fft->out);\n#else\n                afc.finalize(dev, i, demod_params->fftout);\n#endif /* WITH_BCM_VC */\n\n                if (tui) {\n                    char symbol = fparms->squelch.signal_outside_filter() ? '~' : (char)channel->axcindicate;\n                    if (dev->mode == R_SCAN) {\n                        GOTOXY(0, device_num * 17 + dev->row + 3);\n                        printf(\"%4.0f/%3.0f%c %7.3f \", level_to_dBFS(fparms->squelch.signal_level()), level_to_dBFS(fparms->squelch.noise_level()), symbol,\n                               (dev->channels[0].freqlist[channel->freq_idx].frequency / 1000000.0));\n                    } else {\n                        GOTOXY(i * 10, device_num * 17 + dev->row + 3);\n                        printf(\"%4.0f/%3.0f%c \", level_to_dBFS(fparms->squelch.signal_level()), level_to_dBFS(fparms->squelch.noise_level()), symbol);\n                    }\n                    fflush(stdout);\n                }\n\n                if (channel->axcindicate != NO_SIGNAL) {\n                    channel->freqlist[channel->freq_idx].active_counter++;\n                }\n            }\n            if (dev->waveavail == 1) {\n                debug_print(\"devices[%d]: output channel overrun\\n\", device_num);\n                dev->output_overrun_count++;\n            } else {\n                dev->waveavail = 1;\n            }\n            dev->waveend -= WAVE_BATCH;\n#ifdef DEBUG\n            gettimeofday(&te, NULL);\n            debug_bulk_print(\"waveavail %lu.%lu %lu\\n\", te.tv_sec, (unsigned long)te.tv_usec, (te.tv_sec - ts.tv_sec) * 1000000UL + te.tv_usec - ts.tv_usec);\n            ts.tv_sec = te.tv_sec;\n            ts.tv_usec = te.tv_usec;\n#endif /* DEBUG */\n            demod_params->mp3_signal->send();\n            dev->row++;\n            if (dev->row == 12) {\n                dev->row = 0;\n            }\n        }\n\n        dev->input->bufs = (dev->input->bufs + bps * FFT_BATCH) % dev->input->buf_size;\n        device_num = next_device(demod_params, device_num);\n    }\n}\n\nvoid usage() {\n    cout << \"Usage: rtl_airband [options] [-c <config_file_path>]\\n\\\n\\t-h\\t\\t\\tDisplay this help text\\n\\\n\\t-f\\t\\t\\tRun in foreground, display textual waterfalls\\n\\\n\\t-F\\t\\t\\tRun in foreground, do not display waterfalls (for running as a systemd service)\\n\";\n#ifdef NFM\n    cout << \"\\t-Q\\t\\t\\tUse quadri correlator for FM demodulation (default is atan2)\\n\";\n#endif /* NFM */\n#ifdef DEBUG\n    cout << \"\\t-d <file>\\t\\tLog debugging information to <file> (default is \" << DEBUG_PATH << \")\\n\";\n#endif /* DEBUG */\n    cout << \"\\t-e\\t\\t\\tPrint messages to standard error (disables syslog logging)\\n\";\n    cout << \"\\t-c <config_file_path>\\tUse non-default configuration file\\n\\t\\t\\t\\t(default: \" << CFGFILE << \")\\n\\\n\\t-v\\t\\t\\tDisplay version and exit\\n\";\n    exit(EXIT_SUCCESS);\n}\n\nstatic int count_devices_running() {\n    int ret = 0;\n    for (int i = 0; i < device_count; i++) {\n        if (devices[i].input->state == INPUT_RUNNING) {\n            ret++;\n        }\n    }\n    return ret;\n}\n\nint main(int argc, char* argv[]) {\n#ifdef WITH_PROFILING\n    ProfilerStart(\"rtl_airband.prof\");\n#endif /* WITH_PROFILING */\n\n#pragma GCC diagnostic ignored \"-Wwrite-strings\"\n    char* cfgfile = CFGFILE;\n    char* pidfile = PIDFILE;\n#pragma GCC diagnostic warning \"-Wwrite-strings\"\n\n    int opt;\n    char optstring[16] = \"efFhvc:\";\n\n#ifdef NFM\n    strcat(optstring, \"Q\");\n#endif /* NFM */\n\n#ifdef DEBUG\n    strcat(optstring, \"d:\");\n#endif /* DEBUG */\n\n    int foreground = 0;  // daemonize\n    int do_syslog = 1;\n\n    while ((opt = getopt(argc, argv, optstring)) != -1) {\n        switch (opt) {\n#ifdef NFM\n            case 'Q':\n                fm_demod = FM_QUADRI_DEMOD;\n                break;\n#endif /* NFM */\n\n#ifdef DEBUG\n            case 'd':\n                debug_path = strdup(optarg);\n                break;\n#endif /* DEBUG */\n\n            case 'e':\n                do_syslog = 0;\n                break;\n            case 'f':\n                foreground = 1;\n                tui = 1;\n                break;\n            case 'F':\n                foreground = 1;\n                tui = 0;\n                break;\n            case 'c':\n                cfgfile = optarg;\n                break;\n            case 'v':\n                cout << \"RTLSDR-Airband version \" << RTL_AIRBAND_VERSION << \"\\n\";\n                exit(EXIT_SUCCESS);\n            case 'h':\n            default:\n                usage();\n                break;\n        }\n    }\n#ifdef DEBUG\n    if (!debug_path)\n        debug_path = strdup(DEBUG_PATH);\n    init_debug(debug_path);\n#endif /* DEBUG */\n\n    // If executing other than as root, GPU memory gets alloc'd and the\n    // 'permission denied' message on /dev/mem kills rtl_airband without\n    // releasing GPU memory.\n#ifdef WITH_BCM_VC\n    // XXX should probably do this check in other circumstances also.\n    if (0 != getuid()) {\n        cerr << \"FFT library requires that rtl_airband be executed as root\\n\";\n        exit(1);\n    }\n#endif /* WITH_BCM_VC */\n\n    // read config\n    try {\n        Config config;\n        config.readFile(cfgfile);\n        Setting& root = config.getRoot();\n        if (root.exists(\"pidfile\"))\n            pidfile = strdup(root[\"pidfile\"]);\n        if (root.exists(\"fft_size\")) {\n            int fsize = (int)(root[\"fft_size\"]);\n            fft_size_log = 0;\n            for (size_t i = MIN_FFT_SIZE_LOG; i <= MAX_FFT_SIZE_LOG; i++) {\n                if (fsize == 1 << i) {\n                    fft_size = (size_t)fsize;\n                    fft_size_log = i;\n                    break;\n                }\n            }\n            if (fft_size_log == 0) {\n                cerr << \"Configuration error: invalid fft_size value (must be a power of two in range \" << (1 << MIN_FFT_SIZE_LOG) << \"-\" << (1 << MAX_FFT_SIZE_LOG) << \")\\n\";\n                error();\n            }\n        }\n        if (root.exists(\"shout_metadata_delay\"))\n            shout_metadata_delay = (int)(root[\"shout_metadata_delay\"]);\n        if (shout_metadata_delay < 0 || shout_metadata_delay > 2 * TAG_QUEUE_LEN) {\n            cerr << \"Configuration error: shout_metadata_delay is out of allowed range (0-\" << 2 * TAG_QUEUE_LEN << \")\\n\";\n            error();\n        }\n        if (root.exists(\"localtime\") && (bool)root[\"localtime\"] == true)\n            use_localtime = true;\n        if (root.exists(\"multiple_demod_threads\") && (bool)root[\"multiple_demod_threads\"] == true) {\n#ifdef WITH_BCM_VC\n            cerr << \"Using multiple_demod_threads not supported with BCM VideoCore for FFT\\n\";\n            exit(1);\n#endif /* WITH_BCM_VC */\n\n            multiple_demod_threads = true;\n        }\n        if (root.exists(\"multiple_output_threads\") && (bool)root[\"multiple_output_threads\"] == true) {\n            multiple_output_threads = true;\n        }\n        if (root.exists(\"log_scan_activity\") && (bool)root[\"log_scan_activity\"] == true)\n            log_scan_activity = true;\n        if (root.exists(\"stats_filepath\"))\n            stats_filepath = strdup(root[\"stats_filepath\"]);\n#ifdef NFM\n        if (root.exists(\"tau\"))\n            alpha = ((int)root[\"tau\"] == 0 ? 0.0f : exp(-1.0f / (WAVE_RATE * 1e-6 * (int)root[\"tau\"])));\n#endif /* NFM */\n\n        Setting& devs = config.lookup(\"devices\");\n        device_count = devs.getLength();\n        if (device_count < 1) {\n            cerr << \"Configuration error: no devices defined\\n\";\n            error();\n        }\n\n        struct sigaction sigact, pipeact;\n\n        memset(&sigact, 0, sizeof(sigact));\n        memset(&pipeact, 0, sizeof(pipeact));\n        pipeact.sa_handler = SIG_IGN;\n        sigact.sa_handler = &sighandler;\n        sigaction(SIGPIPE, &pipeact, NULL);\n        sigaction(SIGHUP, &sigact, NULL);\n        sigaction(SIGINT, &sigact, NULL);\n        sigaction(SIGQUIT, &sigact, NULL);\n        sigaction(SIGTERM, &sigact, NULL);\n\n        devices = (device_t*)XCALLOC(device_count, sizeof(device_t));\n        shout_init();\n\n        if (do_syslog) {\n            openlog(\"rtl_airband\", LOG_PID, LOG_DAEMON);\n            log_destination = SYSLOG;\n        } else if (foreground) {\n            log_destination = STDERR;\n        } else {\n            log_destination = NONE;\n        }\n\n        if (root.exists(\"mixers\")) {\n            Setting& mx = config.lookup(\"mixers\");\n            mixers = (mixer_t*)XCALLOC(mx.getLength(), sizeof(struct mixer_t));\n            if ((mixer_count = parse_mixers(mx)) > 0) {\n                mixers = (mixer_t*)XREALLOC(mixers, mixer_count * sizeof(struct mixer_t));\n            } else {\n                free(mixers);\n            }\n        } else {\n            mixer_count = 0;\n        }\n\n        uint32_t devs_enabled = parse_devices(devs);\n        if (devs_enabled < 1) {\n            cerr << \"Configuration error: no devices defined\\n\";\n            error();\n        }\n        device_count = devs_enabled;\n        debug_print(\"mixer_count=%d\\n\", mixer_count);\n#ifdef DEBUG\n        for (int z = 0; z < mixer_count; z++) {\n            mixer_t* m = &mixers[z];\n            debug_print(\"mixer[%d]: name=%s, input_count=%d, output_count=%d\\n\", z, m->name, m->input_count, m->channel.output_count);\n        }\n#endif /* DEBUG */\n    } catch (const FileIOException& e) {\n        cerr << \"Cannot read configuration file \" << cfgfile << \"\\n\";\n        error();\n    } catch (const ParseException& e) {\n        cerr << \"Error while parsing configuration file \" << cfgfile << \" line \" << e.getLine() << \": \" << e.getError() << \"\\n\";\n        error();\n    } catch (const SettingNotFoundException& e) {\n        cerr << \"Configuration error: mandatory parameter missing: \" << e.getPath() << \"\\n\";\n        error();\n    } catch (const SettingTypeException& e) {\n        cerr << \"Configuration error: invalid parameter type: \" << e.getPath() << \"\\n\";\n        error();\n    } catch (const ConfigException& e) {\n        cerr << \"Unhandled config exception\\n\";\n        error();\n    }\n\n    log(LOG_INFO, \"RTLSDR-Airband version %s starting\\n\", RTL_AIRBAND_VERSION);\n\n    if (!foreground) {\n        int pid1, pid2;\n        if ((pid1 = fork()) == -1) {\n            cerr << \"Cannot fork child process: \" << strerror(errno) << \"\\n\";\n            error();\n        }\n        if (pid1) {\n            waitpid(-1, NULL, 0);\n            return (0);\n        } else {\n            if ((pid2 = fork()) == -1) {\n                cerr << \"Cannot fork child process: \" << strerror(errno) << \"\\n\";\n                error();\n            }\n            if (pid2) {\n                return (0);\n            } else {\n                int nullfd, dupfd;\n                if ((nullfd = open(\"/dev/null\", O_RDWR)) == -1) {\n                    log(LOG_CRIT, \"Cannot open /dev/null: %s\\n\", strerror(errno));\n                    error();\n                }\n                for (dupfd = 0; dupfd <= 2; dupfd++) {\n                    if (dup2(nullfd, dupfd) == -1) {\n                        log(LOG_CRIT, \"dup2(): %s\\n\", strerror(errno));\n                        error();\n                    }\n                }\n                if (nullfd > 2)\n                    close(nullfd);\n                FILE* f = fopen(pidfile, \"w\");\n                if (f == NULL) {\n                    log(LOG_WARNING, \"Cannot write pidfile: %s\\n\", strerror(errno));\n                } else {\n                    fprintf(f, \"%ld\\n\", (long)getpid());\n                    fclose(f);\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < mixer_count; i++) {\n        if (mixers[i].enabled == false) {\n            continue;  // no inputs connected = no need to initialize output\n        }\n        channel_t* channel = &mixers[i].channel;\n        for (int k = 0; k < channel->output_count; k++) {\n            output_t* output = channel->outputs + k;\n            if (!init_output(channel, output)) {\n                cerr << \"Failed to initialize mixer \" << i << \" output \" << k << \" - aborting\\n\";\n                error();\n            }\n        }\n    }\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = dev->channels + j;\n\n            for (int k = 0; k < channel->output_count; k++) {\n                output_t* output = channel->outputs + k;\n                if (!init_output(channel, output)) {\n                    cerr << \"Failed to initialize device \" << i << \" channel \" << j << \" output \" << k << \" - aborting\\n\";\n                    error();\n                }\n            }\n        }\n        if (input_init(dev->input) != 0 || dev->input->state != INPUT_INITIALIZED) {\n            if (errno != 0) {\n                cerr << \"Failed to initialize input device \" << i << \": \" << strerror(errno) << \" - aborting\\n\";\n            } else {\n                cerr << \"Failed to initialize input device \" << i << \" - aborting\\n\";\n            }\n            error();\n        }\n        if (input_start(dev->input) != 0) {\n            cerr << \"Failed to start input on device \" << i << \": \" << strerror(errno) << \" - aborting\\n\";\n            error();\n        }\n        if (dev->mode == R_SCAN) {\n            // FIXME: set errno\n            if (pthread_mutex_init(&dev->tag_queue_lock, NULL) != 0) {\n                cerr << \"Failed to initialize mutex - aborting\\n\";\n                error();\n            }\n            // FIXME: not needed when freq_count == 1?\n            pthread_create(&dev->controller_thread, NULL, &controller_thread, dev);\n        }\n    }\n\n    int timeout = 50;  // 5 seconds\n    while ((devices_running = count_devices_running()) != device_count && timeout > 0) {\n        SLEEP(100);\n        timeout--;\n    }\n    if ((devices_running = count_devices_running()) != device_count) {\n        log(LOG_ERR, \"%d device(s) failed to initialize - aborting\\n\", device_count - devices_running);\n        error();\n    }\n    if (tui) {\n        printf(\"\\e[1;1H\\e[2J\");\n\n        GOTOXY(0, 0);\n        printf(\"                                                                               \");\n        for (int i = 0; i < device_count; i++) {\n            GOTOXY(0, i * 17 + 1);\n            for (int j = 0; j < devices[i].channel_count; j++) {\n                printf(\" %7.3f  \", devices[i].channels[j].freqlist[devices[i].channels[j].freq_idx].frequency / 1000000.0);\n            }\n            if (i != device_count - 1) {\n                GOTOXY(0, i * 17 + 16);\n                printf(\"-------------------------------------------------------------------------------\");\n            }\n        }\n    }\n    THREAD output_check;\n    pthread_create(&output_check, NULL, &output_check_thread, NULL);\n\n    int demod_thread_count = multiple_demod_threads ? device_count : 1;\n    demod_params_t* demod_params = (demod_params_t*)XCALLOC(demod_thread_count, sizeof(demod_params_t));\n    THREAD* demod_threads = (THREAD*)XCALLOC(demod_thread_count, sizeof(THREAD));\n\n    int output_thread_count = 1;\n    if (multiple_output_threads) {\n        output_thread_count = demod_thread_count;\n        if (mixer_count > 0) {\n            output_thread_count++;\n        }\n    }\n    output_params_t* output_params = (output_params_t*)XCALLOC(output_thread_count, sizeof(output_params_t));\n    THREAD* output_threads = (THREAD*)XCALLOC(output_thread_count, sizeof(THREAD));\n\n    // Setup the output and demod threads\n    if (multiple_output_threads == false) {\n        init_output_params(&output_params[0], 0, device_count, 0, mixer_count);\n\n        if (multiple_demod_threads == false) {\n            init_demod(&demod_params[0], output_params[0].mp3_signal, 0, device_count);\n        } else {\n            for (int i = 0; i < demod_thread_count; i++) {\n                init_demod(&demod_params[i], output_params[0].mp3_signal, i, i + 1);\n            }\n        }\n    } else {\n        if (multiple_demod_threads == false) {\n            init_output_params(&output_params[0], 0, device_count, 0, 0);\n            init_demod(&demod_params[0], output_params[0].mp3_signal, 0, device_count);\n        } else {\n            for (int i = 0; i < device_count; i++) {\n                init_output_params(&output_params[i], i, i + 1, 0, 0);\n                init_demod(&demod_params[i], output_params[i].mp3_signal, i, i + 1);\n            }\n        }\n        if (mixer_count > 0) {\n            init_output_params(&output_params[output_thread_count - 1], 0, 0, 0, mixer_count);\n        }\n    }\n\n    // Startup the output threads\n    for (int i = 0; i < output_thread_count; i++) {\n        pthread_create(&output_threads[i], NULL, &output_thread, &output_params[i]);\n    }\n\n    // Startup the mixer thread (if there is one) using the signal for the last output thread\n    THREAD mixer;\n    if (mixer_count > 0) {\n        pthread_create(&mixer, NULL, &mixer_thread, output_params[output_thread_count - 1].mp3_signal);\n    }\n\n#ifdef WITH_PULSEAUDIO\n    pulse_start();\n#endif /* WITH_PULSEAUDIO */\n\n    sincosf_lut_init();\n\n    // Startup the demod threads\n    for (int i = 0; i < demod_thread_count; i++) {\n        pthread_create(&demod_threads[i], NULL, &demodulate, &demod_params[i]);\n    }\n\n    // Wait for demod threads to exit\n    for (int i = 0; i < demod_thread_count; i++) {\n        pthread_join(demod_threads[i], NULL);\n    }\n\n    log(LOG_INFO, \"Cleaning up\\n\");\n    for (int i = 0; i < device_count; i++) {\n        if (devices[i].mode == R_SCAN)\n            pthread_join(devices[i].controller_thread, NULL);\n        if (input_stop(devices[i].input) != 0 || devices[i].input->state != INPUT_STOPPED) {\n            if (errno != 0) {\n                log(LOG_ERR, \"Failed do stop device #%d: %s\\n\", i, strerror(errno));\n            } else {\n                log(LOG_ERR, \"Failed do stop device #%d\\n\", i);\n            }\n        }\n    }\n    log(LOG_INFO, \"Input threads closed\\n\");\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        disable_device_outputs(dev);\n    }\n\n    if (mixer_count > 0) {\n        log(LOG_INFO, \"Closing mixer thread\\n\");\n        pthread_join(mixer, NULL);\n    }\n\n    log(LOG_INFO, \"Closing output thread(s)\\n\");\n    for (int i = 0; i < output_thread_count; i++) {\n        output_params[i].mp3_signal->send();\n        pthread_join(output_threads[i], NULL);\n    }\n\n    for (int i = 0; i < device_count; i++) {\n        device_t* dev = devices + i;\n        for (int j = 0; j < dev->channel_count; j++) {\n            channel_t* channel = dev->channels + j;\n            for (int k = 0; k < channel->output_count; k++) {\n                output_t* output = channel->outputs + k;\n                if (output->lame) {\n                    lame_close(output->lame);\n                }\n            }\n        }\n    }\n\n    close_debug();\n#ifdef WITH_PROFILING\n    ProfilerStop();\n#endif /* WITH_PROFILING */\n    return 0;\n}\n"
  },
  {
    "path": "src/rtl_airband.h",
    "content": "/*\n * rtl_airband.h\n * Global declarations\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#ifndef _RTL_AIRBAND_H\n#define _RTL_AIRBAND_H 1\n#include <lame/lame.h>\n#include <netinet/in.h>  // sockaddr_in\n#include <pthread.h>\n#include <shout/shout.h>\n#include <stdint.h>  // uint32_t\n#include <sys/time.h>\n#include <complex>\n#include <cstdio>\n#include <libconfig.h++>\n#include <string>\n\n#include \"config.h\"\n\n#ifdef WITH_BCM_VC\n#include \"hello_fft/gpu_fft.h\"\n#else\n#include <fftw3.h>\n#endif /* WITH_BCM_VC */\n\n#ifdef WITH_PULSEAUDIO\n#include <pulse/context.h>\n#include <pulse/stream.h>\n#endif /* WITH_PULSEAUDIO */\n\n#include \"filters.h\"\n#include \"input-common.h\"  // input_t\n#include \"logging.h\"\n#include \"squelch.h\"\n\n#define ALIGNED32 __attribute__((aligned(32)))\n#define SLEEP(x) usleep(x * 1000)\n#define THREAD pthread_t\n#define GOTOXY(x, y) printf(\"%c[%d;%df\", 0x1B, y, x)\n\n#ifndef SYSCONFDIR\n#define SYSCONFDIR \"/usr/local/etc\"\n#endif /* SYSCONFDIR */\n\n#define CFGFILE SYSCONFDIR \"/rtl_airband.conf\"\n#define PIDFILE \"/run/rtl_airband.pid\"\n\n#define MIN_BUF_SIZE 2560000\n#define DEFAULT_SAMPLE_RATE 2560000\n\n#ifdef NFM\n#define WAVE_RATE 16000\n#else\n#define WAVE_RATE 8000\n#endif /* NFM */\n\n#define WAVE_BATCH WAVE_RATE / 8\n#define AGC_EXTRA 100\n#define WAVE_LEN 2 * WAVE_BATCH + AGC_EXTRA\n#define MP3_RATE 8000\n#define MAX_SHOUT_QUEUELEN 32768\n#define TAG_QUEUE_LEN 16\n\n#define MIN_FFT_SIZE_LOG 8\n#define DEFAULT_FFT_SIZE_LOG 9\n#define MAX_FFT_SIZE_LOG 13\n\n#define LAMEBUF_SIZE 22000  // todo: calculate\n#define MIX_DIVISOR 2\n\n#ifdef WITH_BCM_VC\nstruct sample_fft_arg {\n    size_t fft_size_by4;\n    GPU_FFT_COMPLEX* dest;\n};\nextern \"C\" void samplefft(sample_fft_arg* a, unsigned char* buffer, float* window, float* levels);\n\n#define FFT_BATCH 250\n#else\n#define FFT_BATCH 1\n#endif /* WITH_BCM_VC */\n\n//#define AFC_LOGGING\n\nenum status { NO_SIGNAL = ' ', SIGNAL = '*', AFC_UP = '<', AFC_DOWN = '>' };\nenum ch_states { CH_DIRTY, CH_WORKING, CH_READY };\nenum mix_modes { MM_MONO, MM_STEREO };\nenum output_type {\n    O_ICECAST,\n    O_FILE,\n    O_RAWFILE,\n    O_MIXER,\n    O_UDP_STREAM\n#ifdef WITH_PULSEAUDIO\n    ,\n    O_PULSE\n#endif /* WITH_PULSEAUDIO */\n};\n\nstruct icecast_data {\n    const char* hostname;\n    int port;\n#ifdef LIBSHOUT_HAS_TLS\n    int tls_mode;\n#endif /* LIBSHOUT_HAS_TLS */\n    const char* username;\n    const char* password;\n    const char* mountpoint;\n    const char* name;\n    const char* genre;\n    const char* description;\n    bool send_scan_freq_tags;\n    shout_t* shout;\n};\n\nstruct file_data {\n    std::string basedir;\n    std::string basename;\n    std::string suffix;\n    std::string file_path;\n    std::string file_path_tmp;\n    bool dated_subdirectories;\n    bool continuous;\n    bool append;\n    bool split_on_transmission;\n    bool include_freq;\n    timeval open_time;\n    timeval last_write_time;\n    FILE* f;\n    enum output_type type;\n};\n\nstruct udp_stream_data {\n    float* stereo_buffer;\n    size_t stereo_buffer_len;\n\n    bool continuous;\n    const char* dest_address;\n    const char* dest_port;\n\n    int send_socket;\n    struct sockaddr dest_sockaddr;\n    socklen_t dest_sockaddr_len;\n};\n\n#ifdef WITH_PULSEAUDIO\nstruct pulse_data {\n    const char* server;\n    const char* name;\n    const char* sink;\n    const char* stream_name;\n    pa_context* context;\n    pa_stream *left, *right;\n    pa_channel_map lmap, rmap;\n    mix_modes mode;\n    bool continuous;\n};\n#endif /* WITH_PULSEAUDIO */\n\nstruct mixer_data {\n    struct mixer_t* mixer;\n    int input;\n};\n\nstruct output_t {\n    enum output_type type;\n    bool enabled;\n    bool active;\n    void* data;\n\n    // set to true in order to initialize `lame` and `lamebuf` after config parsing\n    // is complete\n    bool has_mp3_output;\n\n    // lame encoder and buffer for mp3 output. initialized after config parsing\n    // if `uses_mp3_output` is true\n    lame_t lame;\n    unsigned char* lamebuf;\n};\n\nstruct freq_tag {\n    int freq;\n    struct timeval tv;\n};\n\nenum modulations {\n    MOD_AM\n#ifdef NFM\n    ,\n    MOD_NFM\n#endif /* NFM */\n};\n\nclass Signal {\n   public:\n    Signal(void) {\n        pthread_cond_init(&cond_, NULL);\n        pthread_mutex_init(&mutex_, NULL);\n    }\n    void send(void) {\n        pthread_mutex_lock(&mutex_);\n        pthread_cond_signal(&cond_);\n        pthread_mutex_unlock(&mutex_);\n    }\n    void wait(void) {\n        pthread_mutex_lock(&mutex_);\n        pthread_cond_wait(&cond_, &mutex_);\n        pthread_mutex_unlock(&mutex_);\n    }\n\n   private:\n    pthread_cond_t cond_;\n    pthread_mutex_t mutex_;\n};\n\nstruct freq_t {\n    int frequency;     // scan frequency\n    char* label;       // frequency label\n    float agcavgfast;  // average power, for AGC\n    float ampfactor;   // multiplier to increase / decrease volume\n    Squelch squelch;\n    size_t active_counter;         // count of loops where channel has signal\n    NotchFilter notch_filter;      // notch filter - good to remove CTCSS tones\n    LowpassFilter lowpass_filter;  // lowpass filter, applied to I/Q after derotation, set at bandwidth/2 to remove out of band noise\n    enum modulations modulation;\n};\nstruct channel_t {\n    float wavein[WAVE_LEN];      // FFT output waveform\n    float waveout[WAVE_LEN];     // waveform after squelch + AGC (left/center channel mixer output)\n    float waveout_r[WAVE_LEN];   // right channel mixer output\n    float iq_in[2 * WAVE_LEN];   // raw input samples for I/Q outputs and NFM demod\n    float iq_out[2 * WAVE_LEN];  // raw output samples for I/Q outputs (FIXME: allocate only if required)\n#ifdef NFM\n    float pr;            // previous sample - real part\n    float pj;            // previous sample - imaginary part\n    float prev_waveout;  // previous sample - waveout before notch / ampfactor\n    float alpha;\n#endif                         /* NFM */\n    uint32_t dm_dphi, dm_phi;  // derotation frequency and current phase value\n    enum mix_modes mode;       // mono or stereo\n    status axcindicate;\n    unsigned char afc;  // 0 - AFC disabled; 1 - minimal AFC; 2 - more aggressive AFC and so on to 255\n    struct freq_t* freqlist;\n    int freq_count;\n    int freq_idx;\n    int needs_raw_iq;\n    int has_iq_outputs;\n    enum ch_states state;  // mixer channel state flag\n    int output_count;\n    output_t* outputs;\n    int highpass;  // highpass filter cutoff\n    int lowpass;   // lowpass filter cutoff\n};\n\nenum rec_modes { R_MULTICHANNEL, R_SCAN };\nstruct device_t {\n    input_t* input;\n#ifdef NFM\n    float alpha;\n#endif /* NFM */\n    int channel_count;\n    size_t *base_bins, *bins;\n    channel_t* channels;\n    // FIXME: size_t\n    int waveend;\n    int waveavail;\n    THREAD controller_thread;\n    struct freq_tag tag_queue[TAG_QUEUE_LEN];\n    int tq_head, tq_tail;\n    int last_frequency;\n    pthread_mutex_t tag_queue_lock;\n    int row;\n    int failed;\n    enum rec_modes mode;\n    size_t output_overrun_count;\n};\n\nstruct mixinput_t {\n    float* wavein;\n    float ampfactor;\n    float ampl, ampr;\n    bool ready;\n    bool has_signal;\n    pthread_mutex_t mutex;\n    size_t input_overrun_count;\n};\n\nstruct mixer_t {\n    const char* name;\n    bool enabled;\n    int interval;\n    size_t output_overrun_count;\n    int input_count;\n    mixinput_t* inputs;\n    bool* inputs_todo;\n    bool* input_mask;\n    channel_t channel;\n};\n\nstruct demod_params_t {\n    Signal* mp3_signal;\n    int device_start;\n    int device_end;\n\n#ifndef WITH_BCM_VC\n    fftwf_plan fft;\n    fftwf_complex* fftin;\n    fftwf_complex* fftout;\n#endif /* WITH_BCM_VC */\n};\n\nstruct output_params_t {\n    Signal* mp3_signal;\n    int device_start;\n    int device_end;\n    int mixer_start;\n    int mixer_end;\n};\n\n// version.cpp\nextern char const* RTL_AIRBAND_VERSION;\n\n// output.cpp\nlame_t airlame_init(mix_modes mixmode, int highpass, int lowpass);\nvoid shout_setup(icecast_data* icecast, mix_modes mixmode);\nvoid disable_device_outputs(device_t* dev);\nvoid disable_channel_outputs(channel_t* channel);\nvoid* output_check_thread(void* params);\nvoid* output_thread(void* params);\n\n// rtl_airband.cpp\nextern bool use_localtime;\nextern bool multiple_demod_threads;\nextern bool multiple_output_threads;\nextern char* stats_filepath;\nextern size_t fft_size, fft_size_log;\nextern int device_count, mixer_count;\nextern int shout_metadata_delay;\nextern volatile int do_exit, device_opened;\nextern float alpha;\nextern device_t* devices;\nextern mixer_t* mixers;\n\n// util.cpp\nint atomic_inc(volatile int* pv);\nint atomic_dec(volatile int* pv);\nint atomic_get(volatile int* pv);\ndouble atofs(char* s);\ndouble delta_sec(const timeval* start, const timeval* stop);\nvoid log(int priority, const char* format, ...);\nvoid tag_queue_put(device_t* dev, int freq, struct timeval tv);\nvoid tag_queue_get(device_t* dev, struct freq_tag* tag);\nvoid tag_queue_advance(device_t* dev);\nvoid sincosf_lut_init();\nvoid sincosf_lut(uint32_t phi, float* sine, float* cosine);\nvoid* xcalloc(size_t nmemb, size_t size, const char* file, const int line, const char* func);\nvoid* xrealloc(void* ptr, size_t size, const char* file, const int line, const char* func);\n#define XCALLOC(nmemb, size) xcalloc((nmemb), (size), __FILE__, __LINE__, __func__)\n#define XREALLOC(ptr, size) xrealloc((ptr), (size), __FILE__, __LINE__, __func__)\nfloat dBFS_to_level(const float& dBFS);\nfloat level_to_dBFS(const float& level);\n\n// mixer.cpp\nmixer_t* getmixerbyname(const char* name);\nint mixer_connect_input(mixer_t* mixer, float ampfactor, float balance);\nvoid mixer_disable_input(mixer_t* mixer, int input_idx);\nvoid mixer_put_samples(mixer_t* mixer, int input_idx, const float* samples, bool has_signal, unsigned int len);\nvoid* mixer_thread(void* params);\nconst char* mixer_get_error();\n\n// config.cpp\nint parse_devices(libconfig::Setting& devs);\nint parse_mixers(libconfig::Setting& mx);\n\n// udp_stream.cpp\nbool udp_stream_init(udp_stream_data* sdata, mix_modes mode, size_t len);\nvoid udp_stream_write(udp_stream_data* sdata, const float* data, size_t len);\nvoid udp_stream_write(udp_stream_data* sdata, const float* data_left, const float* data_right, size_t len);\nvoid udp_stream_shutdown(udp_stream_data* sdata);\n\n#ifdef WITH_PULSEAUDIO\n#define PULSE_STREAM_LATENCY_LIMIT 10000000UL\n// pulse.cpp\nvoid pulse_init();\nint pulse_setup(pulse_data* pdata, mix_modes mixmode);\nvoid pulse_start();\nvoid pulse_shutdown(pulse_data* pdata);\nvoid pulse_write_stream(pulse_data* pdata, mix_modes mode, const float* data_left, const float* data_right, size_t len);\n#endif /* WITH_PULSEAUDIO */\n\n#endif /* _RTL_AIRBAND_H */\n"
  },
  {
    "path": "src/rtl_airband_neon.s",
    "content": "#\n# RTLSDR AM demodulator and streaming\n#\n# Copyright (c) 2014 Wong Man Hang <microtony@gmail.com>\n#\n# Updates for NEON coprocessor by Tomasz Lemiech <szpajder@gmail.com>\n#\n# This program is free software; you can redistribute it and/or\n# modify it under the terms of the GNU General Public License\n# as published by the Free Software Foundation; either version 2\n# of the License, or (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <https://www.gnu.org/licenses/>.\n#\n\n.text\n.align  2\n.global samplefft\n.type samplefft, %function\n.fpu    neon\n\nsamplefft:\n\npush {r4-r12, lr}\nvpush {d4-d15}\n\n#r0 is sample_fft_arg\n#[r0, #0] is fft_size_by4\n#[r0, #4] is dest\nldr r4, [r0]\nldr r0, [r0, #4]\n\nldrb r5, [r1]\nldrb r6, [r1, #1]\nldrb r7, [r1, #2]\nldrb r8, [r1, #3]\nldrb r9, [r1, #4]\nldrb r10, [r1, #5]\nldrb r11, [r1, #6]\nldrb r12, [r1, #7]\n\n.a:\n\nldr r5, [r3, r5, LSL #2]\nldr r6, [r3, r6, LSL #2]\nldr r7, [r3, r7, LSL #2]\nldr r8, [r3, r8, LSL #2]\nldr r9, [r3, r9, LSL #2]\nldr r10, [r3, r10, LSL #2]\nldr r11, [r3, r11, LSL #2]\nldr r12, [r3, r12, LSL #2]\n# load window to NEON registers\nvldmia r2!,{d8-d11}\nadd r1, r1, #8\n# move level from ARM to NEON registers\nvmov d4, r5, r6\nvmov d5, r7, r8\nvmov d6, r9, r10\nvmov d7, r11, r12\npld [r1, #16]\nvmul.f32 q6, q2, q4\nvmul.f32 q7, q3, q5\npld [r2, #8]\nldrb r5, [r1]\nldrb r6, [r1, #1]\nldrb r7, [r1, #2]\nldrb r8, [r1, #3]\nldrb r9, [r1, #4]\nldrb r10, [r1, #5]\nldrb r11, [r1, #6]\nldrb r12, [r1, #7]\nvstmia r0!,{q6-q7}\nsubs r4, r4, #1\nbne .a\n\nvpop {d4-d15}\npop {r4-r12, pc}\n"
  },
  {
    "path": "src/squelch.cpp",
    "content": "/*\n * squelch.cpp\n *\n * Copyright (C) 2022-2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"squelch.h\"\n\n#ifdef DEBUG_SQUELCH\n#include <errno.h>   // errno\n#include <string.h>  // strerror()\n#endif               /* DEBUG_SQUELCH _*/\n\n#include <stdlib.h>   // calloc()\n#include <algorithm>  // min()\n#include <cassert>    // assert()\n#include <cmath>      // pow()\n\n#include \"logging.h\"  // debug_print()\n\nusing namespace std;\n\nSquelch::Squelch(void) {\n    noise_floor_ = 5.0f;\n    set_squelch_snr_threshold(9.54f);  // depends on noise_floor_, sets using_manual_level_, normal_signal_ratio_, flappy_signal_ratio_, and moving_avg_cap_\n    manual_signal_level_ = -1.0;\n\n    pre_filter_ = {0.001f, 0.001f};\n    post_filter_ = {0.001f, 0.001f};\n\n    squelch_level_ = 0.0f;\n\n    using_post_filter_ = false;\n    pre_vs_post_factor_ = 0.9f;\n\n    open_delay_ = 197;\n    close_delay_ = 197;\n    low_signal_abort_ = 88;\n\n    next_state_ = CLOSED;\n    current_state_ = CLOSED;\n\n    delay_ = 0;\n    open_count_ = 0;\n    sample_count_ = -1;\n    flappy_count_ = 0;\n    low_signal_count_ = 0;\n\n    recent_sample_size_ = 1000;\n    flap_opens_threshold_ = 3;\n    recent_open_count_ = 0;\n    closed_sample_count_ = 0;\n\n    buffer_size_ = 102;  // NOTE: this is specific to the 2nd order lowpass Bessel filter\n    buffer_head_ = 0;\n    buffer_tail_ = 1;\n    buffer_ = (float*)calloc(buffer_size_, sizeof(float));\n\n#ifdef DEBUG_SQUELCH\n    debug_file_ = NULL;\n    raw_input_ = 0.0;\n    filtered_input_ = 0.0;\n#endif /* DEBUG_SQUELCH */\n\n    assert(open_delay_ > buffer_size_);\n\n    debug_print(\"Created Squelch, open_delay_: %d, close_delay_: %d, low_signal_abort: %d, using_manual_level_: %s\\n\", open_delay_, close_delay_, low_signal_abort_,\n                using_manual_level_ ? \"true\" : \"false\");\n}\n\nvoid Squelch::set_squelch_level_threshold(const float& level) {\n    if (level > 0) {\n        using_manual_level_ = true;\n        manual_signal_level_ = level;\n    } else {\n        using_manual_level_ = false;\n    }\n\n    // Need to update moving_avg_cap_ - depends on using_manual_level_ and manual_signal_level_\n    calculate_moving_avg_cap();\n\n    debug_print(\"Set level threshold, using_manual_level_: %s, manual_signal_level_: %f, moving_avg_cap_: %f\\n\", using_manual_level_ ? \"true\" : \"false\", manual_signal_level_, moving_avg_cap_);\n}\n\nvoid Squelch::set_squelch_snr_threshold(const float& db) {\n    using_manual_level_ = false;\n    normal_signal_ratio_ = pow(10.0, db / 20.0);\n    flappy_signal_ratio_ = normal_signal_ratio_ * 0.9f;\n\n    // Need to update moving_avg_cap_ - depends on using_manual_level_ and normal_signal_ratio_\n    calculate_moving_avg_cap();\n\n    debug_print(\"SNR threshold updated, using_manual_level_: %s, normal_signal_ratio_: %f, flappy_signal_ratio_: %f, moving_avg_cap_: %f\\n\", using_manual_level_ ? \"true\" : \"false\",\n                normal_signal_ratio_, flappy_signal_ratio_, moving_avg_cap_);\n}\n\nvoid Squelch::set_ctcss_freq(const float& ctcss_freq, const float& sample_rate) {\n    // create two CTCSS detectors with different window sizes.  0.4 sec is required to tell between all the \"standard\"\n    // tones but 0.05 is enough to tell between tones ~20 Hz appart.  Will use ctcss_fast_ until there are enough samples\n    // for ctcss_slow_\n    ctcss_fast_ = CTCSS(ctcss_freq, sample_rate, sample_rate * 0.05);\n    ctcss_slow_ = CTCSS(ctcss_freq, sample_rate, sample_rate * 0.4);\n}\n\nbool Squelch::is_open(void) const {\n    // if current state is OPEN or CLOSING then decide based on CTCSS (if enabled)\n    if (current_state_ == OPEN || current_state_ == CLOSING) {\n        // if CTCSS is enabled then use slow (more accurate) if it has enough samples, otherwise\n        // use fast (will return false if also not enough samples)\n        if (ctcss_slow_.is_enabled()) {\n            if (ctcss_slow_.enough_samples()) {\n                return ctcss_slow_.has_tone();\n            }\n            return ctcss_fast_.has_tone();\n        }\n\n        return true;\n    }\n\n    return false;\n}\n\nbool Squelch::should_filter_sample(void) {\n    return ((has_pre_filter_signal() || current_state_ != CLOSED) && current_state_ != LOW_SIGNAL_ABORT);\n}\n\nbool Squelch::should_process_audio(void) {\n    return (current_state_ == OPEN || current_state_ == CLOSING);\n}\n\nbool Squelch::first_open_sample(void) const {\n    return (current_state_ != OPEN && next_state_ == OPEN);\n}\n\nbool Squelch::last_open_sample(void) const {\n    return (current_state_ == CLOSING && next_state_ == CLOSED) || (current_state_ != LOW_SIGNAL_ABORT && next_state_ == LOW_SIGNAL_ABORT);\n}\n\nbool Squelch::signal_outside_filter(void) {\n    return (using_post_filter_ && has_pre_filter_signal() && !has_post_filter_signal());\n}\n\nconst float& Squelch::noise_level(void) const {\n    return noise_floor_;\n}\n\nconst float& Squelch::signal_level(void) const {\n    return pre_filter_.full_;\n}\n\nconst float& Squelch::squelch_level(void) {\n    if (using_manual_level_) {\n        return manual_signal_level_;\n    }\n\n    if (squelch_level_ == 0.0f) {\n        if (currently_flapping() && flappy_signal_ratio_ < normal_signal_ratio_) {\n            squelch_level_ = flappy_signal_ratio_ * noise_floor_;\n        } else {\n            squelch_level_ = normal_signal_ratio_ * noise_floor_;\n        }\n    }\n    return squelch_level_;\n}\n\nconst size_t& Squelch::open_count(void) const {\n    return open_count_;\n}\n\nconst size_t& Squelch::flappy_count(void) const {\n    return flappy_count_;\n}\n\nconst size_t& Squelch::ctcss_count(void) const {\n    return ctcss_slow_.found_count();\n}\n\nconst size_t& Squelch::no_ctcss_count(void) const {\n    return ctcss_slow_.not_found_count();\n}\n\nvoid Squelch::process_raw_sample(const float& sample) {\n    // Update current state based on previous state from last iteration\n    update_current_state();\n\n#ifdef DEBUG_SQUELCH\n    raw_input_ = sample;\n#endif /* DEBUG_SQUELCH */\n\n    sample_count_++;\n\n    // Auto noise floor\n    //  - Doing this every 16 samples instead of every sample allows a gradual signal increase\n    //    to cross the squelch threshold (that is a function of the noise floor) sooner.\n    //  - Updating even when squelch is open and / or signal is outside filter means the noise\n    //    floor (and squelch threshold) will slowly increasing during a long signal.  This can lead\n    //    to flapping, but this keeps a sudden and sustained increase of noise from locking squelch\n    //    OPEN.\n    if (sample_count_ % 16 == 0) {\n        calculate_noise_floor();\n    }\n\n    update_moving_avg(pre_filter_, sample);\n\n    // Apply the comparison factor before adding to the buffer, will later be used as the threshold\n    // for the post_filter_\n    buffer_[buffer_head_] = pre_filter_.capped_ * pre_vs_post_factor_;\n\n    // Check signal against thresholds\n    if (current_state_ == OPEN && !has_signal()) {\n        debug_print(\"Closing at %zu: no signal after timeout (%f, %f, %f)\\n\", sample_count_, pre_filter_.capped_, post_filter_.capped_, squelch_level());\n        set_state(CLOSING);\n    }\n\n    if (current_state_ == CLOSED && has_signal()) {\n        debug_print(\"Opening at %zu: signal (%f, %f, %f)\\n\", sample_count_, pre_filter_.capped_, post_filter_.capped_, squelch_level());\n        set_state(OPENING);\n    }\n\n    // Override squelch and close if there are repeated samples under the squelch level\n    // NOTE: this can cause squelch to close, but it may immediately be re-opened if the signal level still hasn't fallen after the delays\n    if (current_state_ != CLOSED && current_state_ != LOW_SIGNAL_ABORT) {\n        if (sample >= squelch_level()) {\n            low_signal_count_ = 0;\n        } else {\n            low_signal_count_++;\n            if (low_signal_count_ >= low_signal_abort_) {\n                debug_print(\"Low signal abort at %zu: low signal count %d\\n\", sample_count_, low_signal_count_);\n                set_state(LOW_SIGNAL_ABORT);\n            }\n        }\n    }\n}\n\nvoid Squelch::process_filtered_sample(const float& sample) {\n#ifdef DEBUG_SQUELCH\n    filtered_input_ = sample;\n#endif /* DEBUG_SQUELCH */\n\n    if (!should_filter_sample()) {\n        return;\n    }\n\n    if (current_state_ == OPENING) {\n        // While OPENING, need to wait until the pre-filter value gets through the buffer\n        if (delay_ < buffer_size_) {\n            return;\n        }\n        // Buffer has been filled, initialize post-filter with the pre-filter value\n        if (delay_ == buffer_size_) {\n            post_filter_ = {buffer_[buffer_tail_], buffer_[buffer_tail_]};\n        }\n    }\n\n    using_post_filter_ = true;\n    update_moving_avg(post_filter_, sample);\n\n    // Always comparing the post-filter average to the buffered pre-filtered value\n    if (post_filter_.capped_ < buffer_[buffer_tail_]) {\n        debug_print(\"Closing at %zu: signal level post filter (%f < %f)\\n\", sample_count_, post_filter_.capped_, squelch_level());\n        set_state(CLOSED);\n    }\n}\n\nvoid Squelch::process_audio_sample(const float& sample) {\n#ifdef DEBUG_SQUELCH\n    audio_input_ = sample;\n#endif /* DEBUG_SQUELCH */\n\n    if (!ctcss_slow_.is_enabled()) {\n        return;\n    }\n\n    // ctcss_ is reset on transition to CLOSED and stays \"unused\" while CLOSED\n    if (current_state_ != CLOSED) {\n        // always send the sample to the slow (more accurate) detector, also send to the fast if there havent been enough yet\n        ctcss_slow_.process_audio_sample(sample);\n        if (!ctcss_slow_.enough_samples()) {\n            ctcss_fast_.process_audio_sample(sample);\n        }\n    }\n}\n\nvoid Squelch::set_state(State update) {\n    // Valid transitions (current_state_ -> next_state_) are:\n\n    //  - CLOSED -> CLOSED\n    //  - CLOSED -> OPENING\n    //    ---------------------------\n    //  - OPENING -> CLOSED\n    //  - OPENING -> OPENING\n    //  - OPENING -> CLOSING\n    //  - OPENING -> OPEN\n    //    ---------------------------\n    //  - CLOSING -> CLOSED\n    //  - CLOSING -> OPENING\n    //  - CLOSING -> CLOSING\n    //  - CLOSING -> LOW_SIGNAL_ABORT\n    //  - CLOSING -> OPEN\n    //    ---------------------------\n    //  - LOW_SIGNAL_ABORT -> CLOSED\n    //  - LOW_SIGNAL_ABORT -> LOW_SIGNAL_ABORT\n    //    ---------------------------\n    //  - OPEN -> CLOSING\n    //  - OPEN -> LOW_SIGNAL_ABORT\n    //  - OPEN -> OPEN\n\n    // Invalid transistions (current_state_ -> next_state_) are:\n\n    //  CLOSED -> CLOSING (if already CLOSED cant go backwards)\n    if (current_state_ == CLOSED && update == CLOSING) {\n        update = CLOSED;\n    }\n\n    //  CLOSED -> LOW_SIGNAL_ABORT (if already CLOSED cant go backwards)\n    else if (current_state_ == CLOSED && update == LOW_SIGNAL_ABORT) {\n        update = CLOSED;\n    }\n\n    //  CLOSED -> OPEN (must go through OPENING to get to OPEN)\n    else if (current_state_ == CLOSED && update == OPEN) {\n        update = OPENING;\n    }\n\n    //  OPENING -> LOW_SIGNAL_ABORT (just go to CLOSED instead)\n    else if (current_state_ == OPENING && update == LOW_SIGNAL_ABORT) {\n        update = CLOSED;\n    }\n\n    //  LOW_SIGNAL_ABORT -> OPENING (LOW_SIGNAL_ABORT can only go to CLOSED)\n    //  LOW_SIGNAL_ABORT -> OPEN (LOW_SIGNAL_ABORT can only go to CLOSED)\n    //  LOW_SIGNAL_ABORT -> CLOSING (LOW_SIGNAL_ABORT can only go to CLOSED)\n    else if (current_state_ == LOW_SIGNAL_ABORT && update != LOW_SIGNAL_ABORT && update != CLOSED) {\n        update = CLOSED;\n    }\n\n    //  OPEN -> CLOSED (must go through CLOSING to get to CLOSED)\n    else if (current_state_ == OPEN && update == CLOSED) {\n        update = CLOSING;\n    }\n\n    //  OPEN -> OPENING (if already OPEN cant go backwards)\n    else if (current_state_ == OPEN && update == OPENING) {\n        update = OPEN;\n    }\n\n    next_state_ = update;\n}\n\nvoid Squelch::update_current_state(void) {\n    if (next_state_ == OPENING) {\n        if (current_state_ != OPENING) {\n            debug_print(\"%zu: transitioning to OPENING\\n\", sample_count_);\n            delay_ = 0;\n            low_signal_count_ = 0;\n            using_post_filter_ = false;\n            current_state_ = next_state_;\n        } else {\n            // in OPENING delay\n            delay_++;\n            if (delay_ >= open_delay_) {\n                // After getting through OPENING delay, count this as an \"open\" for flap\n                // detection even if signal has gone.  NOTE - if process_filtered_sample() would\n                // have already sent state to CLOSED before the delay if post_filter_.capped_ was\n                // too low, so that wont count towards flapping\n                if (closed_sample_count_ < recent_sample_size_) {\n                    recent_open_count_++;\n                    if (currently_flapping()) {\n                        flappy_count_++;\n                    }\n\n                    // Force squelch_level_ recalculation at next call to squelch_level()\n                    squelch_level_ = 0.0f;\n                }\n\n                // Check signal level after delay to either go to OPEN or CLOSED\n                if (has_signal()) {\n                    next_state_ = OPEN;\n                } else {\n                    debug_print(\"%zu: no signal after OPENING delay, going to CLOSED\\n\", sample_count_);\n                    next_state_ = CLOSED;\n                }\n            }\n        }\n    } else if (next_state_ == CLOSING) {\n        if (current_state_ != CLOSING) {\n            debug_print(\"%zu: transitioning to CLOSING\\n\", sample_count_);\n            delay_ = 0;\n            current_state_ = next_state_;\n        } else {\n            // in CLOSING delay\n            delay_++;\n            if (delay_ >= close_delay_) {\n                if (!has_signal()) {\n                    next_state_ = CLOSED;\n                } else {\n                    debug_print(\"%zu: signal after CLOSING delay, reverting to OPEN\\n\", sample_count_);\n                    current_state_ = OPEN;  // set current_state_ to avoid incrementing open_count_\n                    next_state_ = OPEN;\n                }\n            }\n        }\n    } else if (next_state_ == LOW_SIGNAL_ABORT) {\n        if (current_state_ != LOW_SIGNAL_ABORT) {\n            debug_print(\"%zu: transitioning to LOW_SIGNAL_ABORT\\n\", sample_count_);\n            // If coming from CLOSING then keep the delay counter that has already started\n            if (current_state_ != CLOSING) {\n                delay_ = 0;\n            }\n            current_state_ = next_state_;\n        } else {\n            // in LOW_SIGNAL_ABORT delay\n            delay_++;\n            if (delay_ >= close_delay_) {\n                next_state_ = CLOSED;\n            }\n        }\n    } else if (next_state_ == OPEN && current_state_ != OPEN) {\n        debug_print(\"%zu: transitioning to OPEN\\n\", sample_count_);\n        open_count_++;\n        current_state_ = next_state_;\n    } else if (next_state_ == CLOSED && current_state_ != CLOSED) {\n        debug_print(\"%zu: transitioning to CLOSED\\n\", sample_count_);\n        using_post_filter_ = false;\n        closed_sample_count_ = 0;\n        current_state_ = next_state_;\n        ctcss_fast_.reset();\n        ctcss_slow_.reset();\n    } else if (next_state_ == CLOSED && current_state_ == CLOSED) {\n        // Count this as a closed sample towards flap detection (can stop counting at recent_sample_size_)\n        if (closed_sample_count_ < recent_sample_size_) {\n            closed_sample_count_++;\n        } else if (closed_sample_count_ == recent_sample_size_) {\n            recent_open_count_ = 0;\n            squelch_level_ = 0.0f;  // Force squelch_level_ recalculation\n        }\n    } else {\n        current_state_ = next_state_;\n    }\n\n    buffer_tail_ = (buffer_tail_ + 1) % buffer_size_;\n    buffer_head_ = (buffer_head_ + 1) % buffer_size_;\n\n#ifdef DEBUG_SQUELCH\n    debug_state();\n#endif /* DEBUG_SQUELCH */\n}\n\nbool Squelch::has_pre_filter_signal(void) {\n    return pre_filter_.capped_ >= squelch_level();\n}\n\nbool Squelch::has_post_filter_signal(void) {\n    return using_post_filter_ && post_filter_.capped_ >= buffer_[buffer_tail_];\n}\n\nbool Squelch::has_signal(void) {\n    if (using_post_filter_) {\n        return has_pre_filter_signal() && has_post_filter_signal();\n    }\n    return has_pre_filter_signal();\n}\n\nvoid Squelch::calculate_noise_floor(void) {\n    static const float decay_factor = 0.97f;\n    static const float new_factor = 1.0 - decay_factor;\n\n    noise_floor_ = noise_floor_ * decay_factor + std::min(pre_filter_.capped_, noise_floor_) * new_factor + 1e-6f;\n\n    debug_print(\"%zu: noise floor is now %f\\n\", sample_count_, noise_floor_);\n\n    // Need to update moving_avg_cap_ - depends on noise_floor_\n    calculate_moving_avg_cap();\n\n    // Force squelch_level_ recalculation at next call to squelch_level() - depends on noise_floor_\n    squelch_level_ = 0.0f;\n}\n\nvoid Squelch::calculate_moving_avg_cap(void) {\n    // set max value for MovingAverage's capped_ to 1.5 x the normal / manual squelch level.\n    if (using_manual_level_) {\n        moving_avg_cap_ = 1.5f * manual_signal_level_;\n    } else {\n        moving_avg_cap_ = 1.5f * normal_signal_ratio_ * noise_floor_;\n    }\n}\n\nvoid Squelch::update_moving_avg(MovingAverage& avg, const float& sample) {\n    static const float decay_factor = 0.99f;\n    static const float new_factor = 1.0 - decay_factor;\n\n    avg.full_ = avg.full_ * decay_factor + sample * new_factor;\n\n    // Cap average level, this lets the average drop after the signal goes away more quickly\n    // (if current value and update are both at/above the max then can avoid the float multiplications)\n    if (avg.capped_ >= moving_avg_cap_ && sample >= moving_avg_cap_) {\n        avg.capped_ = moving_avg_cap_;\n    } else {\n        avg.capped_ = min(moving_avg_cap_, avg.capped_ * decay_factor + sample * new_factor);\n    }\n}\n\nbool Squelch::currently_flapping(void) const {\n    return recent_open_count_ >= flap_opens_threshold_;\n}\n\n#ifdef DEBUG_SQUELCH\n/*\n Debug file methods\n ==================\n\n Values written to file are:\n         - (int16_t) process_raw_sample input\n         - (int16_t) process_filtered_sample input\n         - (int16_t) process_audio_sample input\n         - (int16_t) noise_floor_\n         - (int16_t) pre_filter_.capped_\n         - (int16_t) post_filter_.capped_\n         - (int) current_state_\n         - (int) delay_\n         - (int) low_signalcount_\n         - (int) ctcss_fast_.has_tone()\n         - (int) ctcss_slow_.has_tone()\n\n  The output file can be read / plotted in python as follows:\n\n        import matplotlib.pyplot as plt\n        import numpy as np\n\n        def plot_squelch_debug(filepath):\n\n                dt = np.dtype([('raw_input', np.single),\n                                           ('filtered_input', np.single),\n                                           ('audio_input', np.single),\n                                           ('noise_floor', np.single),\n                                           ('pre_filter_capped', np.single),\n                                           ('post_filter_capped', np.single),\n                                           ('current_state', np.intc),\n                                           ('delay', np.intc),\n                                           ('low_signalcount', np.intc),\n                                           ('ctcss_fast_has_tone', np.intc),\n                                           ('ctcss_slow_has_tone', np.intc)\n                                          ])\n\n                dat = np.fromfile(filepath, dtype=dt)\n\n                plt.figure()\n                plt.plot(dat['raw_input'], 'b')\n                plt.plot(dat['pre_filter_capped'], 'g')\n                plt.plot(dat['noise_floor'], 'r')\n                plt.show(block=False)\n\n                plt.figure()\n                plt.plot(dat['post_filter_capped'], 'k')\n                plt.show(block=False)\n\n                plt.figure()\n                axis = plt.subplot2grid((3, 1), (0, 0))\n                axis.plot(dat['current_state'], 'c')\n                axis = plt.subplot2grid((3, 1), (1, 0))\n                axis.plot(dat['delay'], 'm')\n                axis = plt.subplot2grid((3, 1), (2, 0))\n                axis.plot(dat['low_signalcount'], 'y')\n                plt.show(block=False)\n\n                return\n\n  */\n\nSquelch::~Squelch(void) {\n    if (debug_file_) {\n        fclose(debug_file_);\n    }\n}\n\nvoid Squelch::set_debug_file(const char* filepath) {\n    debug_file_ = fopen(filepath, \"wb\");\n}\n\nvoid Squelch::debug_value(const float& value) {\n    if (!debug_file_) {\n        return;\n    }\n\n    if (fwrite(&value, sizeof(value), 1, debug_file_) != 1) {\n        debug_print(\"Error writing to squelch debug file: %s\\n\", strerror(errno));\n    }\n}\n\nvoid Squelch::debug_value(const int& value) {\n    if (!debug_file_) {\n        return;\n    }\n\n    if (fwrite(&value, sizeof(value), 1, debug_file_) != 1) {\n        debug_print(\"Error writing to squelch debug file: %s\\n\", strerror(errno));\n    }\n}\n\nvoid Squelch::debug_state(void) {\n    if (!debug_file_) {\n        return;\n    }\n    debug_value(raw_input_);\n    debug_value(filtered_input_);\n    debug_value(audio_input_);\n\n    raw_input_ = 0.0;\n    filtered_input_ = 0.0;\n    audio_input_ = 0.0;\n\n    debug_value(noise_floor_);\n    debug_value(pre_filter_.capped_);\n    debug_value(post_filter_.capped_);\n    debug_value((int)current_state_);\n    debug_value(delay_);\n    debug_value(low_signal_count_);\n    debug_value((int)ctcss_fast_.has_tone());\n    debug_value((int)ctcss_slow_.has_tone());\n}\n\n#endif /* DEBUG_SQUELCH */\n"
  },
  {
    "path": "src/squelch.h",
    "content": "/*\n * squelch.h\n *\n * Copyright (C) 2022-2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#ifndef _SQUELCH_H\n#define _SQUELCH_H\n\n#include <cstddef>  // size_t\n\n#ifdef DEBUG_SQUELCH\n#include <stdio.h>  // needed for debug file output\n#endif              /* DEBUG_SQUELCH */\n\n#include \"ctcss.h\"\n\n/*\n Theory of operation:\n\n Squelch has 5 states, OPEN (has audio), CLOSED (no audio), OPENING (transitioning from CLOSED to OPEN),\n CLOSING (transitioning from OPEN to CLOSED), and LOW_SIGNAL_ABORT (same as CLOSING but because of a constant\n signal drop).\n\n Squelch is considered \"open\" when the state is OPEN or CLOSING and squelch is considered \"closed\" when the\n state is OPENING, LOW_SIGNAL_ABORT, or CLOSED.\n\n Noise floor is computed using a low pass filter and updated with the current sample or prior value, whatever\n is lower.  Noise floor is updated every 16 stamples, except when squelch is open.\n\n Low pass filters are also used to track the current signal levels.  One level is for the sample before\n filtering, the second for post signal filtering (if any).  The pre-filter signal level is updated for every\n sample.  The post-filter level is optional.  When used, the post-filter signal level is compared to a\n delayed pre-filter value.  The post-filter is set to a fraction of the pre-filtered value each time state\n transitions to OPENING, and is not updated while state is CLOSED.\n\n Squelch level can be set manually or is computed as a function of the noise floor.\n\n When the signal level exceeds the squelch level, the state transitions to OPENING and a delay counter starts,\n then once the counter is over the state moves to OPEN if there is signal, otherwise back to CLOSED. The same\n (but opposite) happens when the signal level drops below the squelch level.\n\n While the squelch is OPEN, a count of continuous samples that are below the squelch level is maintained.  If\n this count exceeds a threshold then the state moves to LOW_SIGNAL_ABORT.  This allows the squelch to close\n after a sharp drop off in signal before the signal level has caught up.\n\n A count of \"recent opens\" is maintained as a way to detect squelch flapping (ie rapidly opening and closing).\n When flapping is detected the squelch level is decreased in an attempt to keep squelch open longer.\n\n CTCSS tone detection can be enabled.  If used, two tone detectors are created at different window lengths.\n The “fast” detector has less resolution but needs fewer samples while the “slow” detector is more accurate.\n When CTCSS is enabled, squelch remains CLOSED for an additional 0.05 sec until a tone is detected by the “fast”\n detector.\n */\n\nclass Squelch {\n   public:\n    Squelch();\n\n    void set_squelch_level_threshold(const float& level);\n    void set_squelch_snr_threshold(const float& db);\n    void set_ctcss_freq(const float& ctcss_freq, const float& sample_rate);\n\n    void process_raw_sample(const float& sample);\n    void process_filtered_sample(const float& sample);\n    void process_audio_sample(const float& sample);\n\n    bool is_open(void) const;\n    bool should_filter_sample(void);\n    bool should_process_audio(void);\n\n    bool first_open_sample(void) const;\n    bool last_open_sample(void) const;\n    bool signal_outside_filter(void);\n\n    const float& noise_level(void) const;\n    const float& signal_level(void) const;\n    const float& squelch_level(void);\n\n    const size_t& open_count(void) const;\n    const size_t& flappy_count(void) const;\n    const size_t& ctcss_count(void) const;\n    const size_t& no_ctcss_count(void) const;\n\n#ifdef DEBUG_SQUELCH\n    ~Squelch(void);\n    void set_debug_file(const char* filepath);\n#endif /* DEBUG_SQUELCH */\n\n   private:\n    enum State {\n        CLOSED,            // Audio is suppressed\n        OPENING,           // Transitioning closed -> open\n        CLOSING,           // Transitioning open -> closed\n        LOW_SIGNAL_ABORT,  // Like CLOSING but is_open() is false\n        OPEN               // Audio not suppressed\n    };\n\n    struct MovingAverage {\n        float full_;\n        float capped_;\n    };\n\n    float noise_floor_;          // noise level\n    bool using_manual_level_;    // if using a manually set signal level threshold\n    float manual_signal_level_;  // manually configured squelch level, < 0 for disabled\n    float normal_signal_ratio_;  // signal-to-noise ratio for normal squelch - ratio, not in dB\n    float flappy_signal_ratio_;  // signal-to-noise ratio for flappy squelch - ratio, not in dB\n\n    float moving_avg_cap_;       // the max value for capped moving average\n    MovingAverage pre_filter_;   // average signal level for reference sample\n    MovingAverage post_filter_;  // average signal level for post-filter sample\n\n    float squelch_level_;  // cached calculation of the squelch_level() value\n\n    bool using_post_filter_;    // if the caller is providing filtered samples\n    float pre_vs_post_factor_;  // multiplier when doing pre vs post filter compaison\n\n    int open_delay_;        // how long to wait after signal level crosses squelch to open\n    int close_delay_;       // how long to wait after signal level crosses squelch to close\n    int low_signal_abort_;  // number of repeated samples below squelch to cause a close\n\n    State next_state_;\n    State current_state_;\n\n    int delay_;             // samples to wait before making next squelch decision\n    size_t open_count_;     // number of times squelch is opened\n    size_t sample_count_;   // number of samples processed (for logging)\n    size_t flappy_count_;   // number of times squelch was detected as flapping OPEN/CLOSED\n    int low_signal_count_;  // number of repeated samples below squelch\n\n    // Flap detection parameters\n    size_t recent_sample_size_;    // number of samples defined as \"recent\"\n    size_t flap_opens_threshold_;  // number of opens to count as flapping\n    size_t recent_open_count_;     // number of times squelch recently opened\n    size_t closed_sample_count_;   // number of continuous samples where squelch has been CLOSED\n\n    // Buffered pre-filtered values\n    int buffer_size_;  // size of buffer\n    int buffer_head_;  // index to add new values\n    int buffer_tail_;  // index to read buffered values\n    float* buffer_;    // buffer\n\n    CTCSS ctcss_fast_;  // ctcss tone detection\n    CTCSS ctcss_slow_;  // ctcss tone detection\n\n    void set_state(State update);\n    void update_current_state(void);\n    bool has_pre_filter_signal(void);\n    bool has_post_filter_signal(void);\n    bool has_signal(void);\n    void calculate_noise_floor(void);\n    void calculate_moving_avg_cap(void);\n    void update_moving_avg(MovingAverage& avg, const float& sample);\n    bool currently_flapping(void) const;\n\n#ifdef DEBUG_SQUELCH\n    FILE* debug_file_;\n    float raw_input_;\n    float filtered_input_;\n    float audio_input_;\n    void debug_value(const float& value);\n    void debug_value(const int& value);\n    void debug_state(void);\n#endif /* DEBUG_SQUELCH */\n};\n\n#endif /* _SQUELCH_H */\n"
  },
  {
    "path": "src/test_base_class.cpp",
    "content": "/*\n * test_base_class.cpp\n *\n * Copyright (C) 2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <dirent.h>\n\n#include \"logging.h\"\n\n#include \"test_base_class.h\"\n\nusing namespace std;\n\nvoid delete_directory(const string& root) {\n    DIR* dp = NULL;\n\n    dp = opendir(root.c_str());\n    if (dp == NULL) {\n        cerr << \"Error opening directory \" << root << endl;\n        return;\n    }\n\n    string current_dir = \".\";\n    string parent_dir = \"..\";\n\n    struct dirent* entry = NULL;\n    while ((entry = readdir(dp))) {\n        if (current_dir.compare(entry->d_name) == 0 || parent_dir.compare(entry->d_name) == 0) {\n            continue;\n        }\n\n        struct stat info;\n        string filepath = root + \"/\" + string(entry->d_name);\n\n        if (stat(filepath.c_str(), &info) != 0) {\n            cerr << \"Error getting info on \" << filepath.c_str() << \": \" << strerror(errno) << endl;\n            continue;\n        }\n\n        if (S_ISDIR(info.st_mode)) {\n            delete_directory(filepath);\n        } else {\n            unlink(filepath.c_str());\n        }\n    }\n\n    closedir(dp);\n    rmdir(root.c_str());\n}\n\nstring make_temp_dir(void) {\n    char temp_path_template[] = \"/tmp/temp_unittest_dir_XXXXXX\";\n    if (mkdtemp(temp_path_template) == NULL) {\n        cerr << \"Error making temp dir for test files: \" << strerror(errno) << endl;\n        return \"\";\n    }\n    return string(temp_path_template);\n}\n\nvoid TestBaseClass::SetUp(void) {\n    ::testing::Test::SetUp();\n\n    // setup debug log file for each test\n    temp_dir = make_temp_dir();\n    ASSERT_FALSE(temp_dir.empty());\n    string debug_filepath = temp_dir + \"/debug_file.log\";\n    init_debug(debug_filepath.c_str());\n\n    // point logging to stderr\n    log_destination = STDERR;\n}\n\nvoid TestBaseClass::TearDown(void) {\n    ::testing::Test::TearDown();\n    close_debug();\n    delete_directory(temp_dir);\n}\n\nTEST(TestHelpers, make_temp_dir) {\n    // make a temp dir\n    string temp_dir = make_temp_dir();\n\n    // path should not be empty string\n    ASSERT_FALSE(temp_dir.empty());\n\n    // a directory should exist at the path\n    struct stat info;\n    ASSERT_EQ(stat(temp_dir.c_str(), &info), 0);\n    EXPECT_TRUE(S_ISDIR(info.st_mode));\n\n    delete_directory(temp_dir);\n}\n\nTEST(TestHelpers, delete_directory) {\n    // make a temp dir\n    string temp_dir = make_temp_dir();\n    ASSERT_FALSE(temp_dir.empty());\n\n    // build a bunch of nested sub-dirs and files\n    string path = temp_dir;\n    for (int i = 0; i < 5; ++i) {\n        path = path + \"/sub_dir\";\n        mkdir(path.c_str(), 0777);\n\n        string filename = path + \"/some_file\";\n        fclose(fopen(filename.c_str(), \"w\"));\n    }\n\n    // last sub-dir should exist and be a directory\n    struct stat info;\n    ASSERT_EQ(stat(path.c_str(), &info), 0);\n    EXPECT_TRUE(S_ISDIR(info.st_mode));\n\n    // last sub-dir should have a file in it\n    string filename = path + \"/some_file\";\n    ASSERT_EQ(stat(filename.c_str(), &info), 0);\n    EXPECT_TRUE(S_ISREG(info.st_mode));\n\n    // delete the root temp dir\n    delete_directory(temp_dir);\n\n    // root temp dir should no longer exist\n    ASSERT_NE(stat(temp_dir.c_str(), &info), 0);\n}\n"
  },
  {
    "path": "src/test_base_class.h",
    "content": "/*\n * test_base_class.h\n *\n * Copyright (C) 2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#ifndef _TEST_BASE_CLASS_H\n#define _TEST_BASE_CLASS_H\n\n#include <gtest/gtest.h>\n\n#include <string>\n\nclass TestBaseClass : public ::testing::Test {\n   protected:\n    void SetUp(void);\n    void TearDown(void);\n\n    std::string temp_dir;\n};\n\n#endif /* _TEST_BASE_CLASS_H */\n"
  },
  {
    "path": "src/test_ctcss.cpp",
    "content": "/*\n * test_ctcss.cpp\n *\n * Copyright (C) 2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"generate_signal.h\"\n#include \"test_base_class.h\"\n\n#include \"ctcss.h\"\n\nusing namespace std;\n\nclass CTCSSTest : public TestBaseClass {\n   protected:\n    int sample_rate;\n    int fast_window_size;\n    int slow_window_size;\n\n    void SetUp(void) {\n        TestBaseClass::SetUp();\n        sample_rate = 8000;\n        fast_window_size = sample_rate * 0.05;\n        slow_window_size = sample_rate * 0.4;\n    }\n\n    void write_file(const vector<float>& samples, const string& filepath) {\n        cerr << \"writing file out to \" << filepath << endl;\n\n        FILE* fp = fopen(filepath.c_str(), \"wb\");\n\n        for (auto sample : samples) {\n            fwrite(&sample, sizeof(float), 1, fp);\n        }\n        fclose(fp);\n    }\n\n    void load_from_file(CTCSS& ctcss, const string& filepath) {\n        FILE* fp = fopen(filepath.c_str(), \"rb\");\n\n        while (!ctcss.enough_samples()) {\n            float sample;\n            if (fread(&sample, sizeof(float), 1, fp) != 1) {\n                break;\n            }\n            ctcss.process_audio_sample(sample);\n        }\n        fclose(fp);\n\n        ASSERT_TRUE(ctcss.enough_samples());\n    }\n\n    void test_all_tones(GenerateSignal& signal, const float& tone = 0) {\n        for (auto standard_tone : CTCSS::standard_tones) {\n            // skipping tones within +/- 5Hz\n            if (abs(standard_tone - tone) < 5) {\n                continue;\n            }\n\n            CTCSS ctcss(standard_tone, sample_rate, slow_window_size);\n            vector<float> samples;\n            run_signal(ctcss, signal, samples);\n\n            EXPECT_FALSE(ctcss.has_tone()) << \"Tone of \" << standard_tone << \" found, expected \" << tone;\n\n            // on failure write out a file for debugging\n            if (ctcss.has_tone()) {\n                // double the samples to write to the file for later testing\n                size_t initial_count = samples.size();\n                while (samples.size() < initial_count * 2) {\n                    samples.push_back(signal.get_sample());\n                }\n\n                string filepath = \"/tmp/found_\" + to_string(standard_tone) + \"_expected_\" + to_string(tone);\n                write_file(samples, filepath);\n            }\n        }\n        if (tone != 0) {\n            CTCSS ctcss(tone, sample_rate, slow_window_size);\n            vector<float> samples;\n            run_signal(ctcss, signal, samples);\n\n            EXPECT_TRUE(ctcss.has_tone()) << \"Expected tone of \" << tone << \" not found\";\n\n            // on failure write out a file for debugging\n            if (!ctcss.has_tone()) {\n                // double the samples to write to the file for later testing\n                size_t initial_count = samples.size();\n                while (samples.size() < initial_count * 2) {\n                    samples.push_back(signal.get_sample());\n                }\n\n                string filepath = \"/tmp/didnt_find_\" + to_string(tone);\n                write_file(samples, filepath);\n            }\n        }\n    }\n\n    void run_signal(CTCSS& ctcss, GenerateSignal& signal, vector<float>& samples) {\n        EXPECT_TRUE(ctcss.is_enabled()) << \"CTCSS not enabled\";\n        while (!ctcss.enough_samples()) {\n            float sample = signal.get_sample();\n            samples.push_back(sample);\n            ctcss.process_audio_sample(sample);\n        }\n    }\n};\n\nTEST_F(CTCSSTest, creation) {\n    CTCSS ctcss;\n    EXPECT_FALSE(ctcss.is_enabled());\n}\n\nTEST_F(CTCSSTest, no_signal) {\n    GenerateSignal signal(sample_rate);\n    test_all_tones(signal);\n}\n\nTEST_F(CTCSSTest, has_tone) {\n    float tone = CTCSS::standard_tones[0];\n    GenerateSignal signal(sample_rate);\n    signal.add_tone(tone, Tone::NORMAL);\n    signal.add_noise(Noise::NORMAL);\n    test_all_tones(signal, tone);\n}\n\nTEST_F(CTCSSTest, has_non_standard_tone) {\n    float tone = (CTCSS::standard_tones[0] + CTCSS::standard_tones[0]) / 2;\n    GenerateSignal signal(sample_rate);\n    signal.add_tone(tone, Tone::NORMAL);\n    signal.add_noise(Noise::NORMAL);\n    test_all_tones(signal, tone);\n}\n\nTEST_F(CTCSSTest, has_each_standard_tone) {\n    for (auto tone : CTCSS::standard_tones) {\n        GenerateSignal signal(sample_rate);\n        signal.add_tone(tone, Tone::NORMAL);\n        signal.add_noise(Noise::NORMAL);\n        test_all_tones(signal, tone);\n    }\n}\n"
  },
  {
    "path": "src/test_filters.cpp",
    "content": "/*\n * test_filters.cpp\n *\n * Copyright (C) 2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"test_base_class.h\"\n\n#include \"filters.h\"\n\nusing namespace std;\n\nclass FiltersTest : public TestBaseClass {\n   protected:\n    void SetUp(void) { TestBaseClass::SetUp(); }\n\n    void TearDown(void) { TestBaseClass::TearDown(); }\n};\n\nTEST_F(FiltersTest, default_notch) {\n    NotchFilter notch;\n    EXPECT_FALSE(notch.enabled());\n}\n\nTEST_F(FiltersTest, default_lowpass) {\n    LowpassFilter lowpass;\n    EXPECT_FALSE(lowpass.enabled());\n}\n"
  },
  {
    "path": "src/test_generate_signal.cpp",
    "content": "/*\n * test_generate_signal.cpp\n *\n * Copyright (C) 2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <algorithm>\n\n#include \"test_base_class.h\"\n\n#include \"generate_signal.h\"\n\nusing namespace std;\n\nclass ToneTest : public TestBaseClass {};\n\nTEST_F(ToneTest, simple_object) {\n    // simple case the sample rate is a multiple of the frequency so specific points can be measured\n    float tone_freq = 100;  // tone at 100 Hz\n    // set sample rate to 1000 times the tone so there will be 250 samples per quarter\n    float sample_rate = 1000 * tone_freq;\n    float amplitude = Tone::STRONG;\n\n    Tone tone(sample_rate, tone_freq, amplitude);\n\n    float last_sample = 0.0;\n    float this_sample = 0.0;\n\n    // loop through some number of cycles\n    for (int j = 0; j < 10; ++j) {\n        // first 249 samples will be positive and increasing\n        for (int i = 0; i < 249; ++i) {\n            this_sample = tone.get_sample();\n            ASSERT_GT(this_sample, 0.0);\n            ASSERT_GT(this_sample, last_sample);\n            last_sample = this_sample;\n        }\n\n        // sample 250 will be the amp\n        this_sample = tone.get_sample();\n        ASSERT_EQ(this_sample, amplitude);\n        ASSERT_GT(this_sample, last_sample);\n        last_sample = this_sample;\n\n        // next 249 samples will be positive and decreasing\n        for (int i = 0; i < 249; ++i) {\n            this_sample = tone.get_sample();\n            ASSERT_GT(this_sample, 0.0);\n            ASSERT_LT(this_sample, last_sample);\n            last_sample = this_sample;\n        }\n\n        // sample 500 will be zero-ish\n        this_sample = tone.get_sample();\n        ASSERT_LT(this_sample, 0.000001);\n        ASSERT_LT(this_sample, last_sample);\n        last_sample = this_sample;\n\n        // next 249 samples will be negative and decreasing\n        for (int i = 0; i < 249; ++i) {\n            this_sample = tone.get_sample();\n            ASSERT_LT(this_sample, 0.0);\n            ASSERT_LT(this_sample, last_sample);\n            last_sample = this_sample;\n        }\n\n        // sample 750 will be negative amp\n        this_sample = tone.get_sample();\n        ASSERT_EQ(this_sample, -1.0 * amplitude);\n        ASSERT_LT(this_sample, last_sample);\n        last_sample = this_sample;\n\n        // next 249 samples will be negative and increasing\n        for (int i = 0; i < 249; ++i) {\n            this_sample = tone.get_sample();\n            ASSERT_LT(this_sample, 0.0);\n            ASSERT_GT(this_sample, last_sample);\n            last_sample = this_sample;\n        }\n\n        // sample 1000 will be zero-ish\n        this_sample = tone.get_sample();\n        ASSERT_LT(this_sample, 0.000001);\n        ASSERT_GT(this_sample, last_sample);\n        last_sample = this_sample;\n    }\n}\n\nTEST_F(ToneTest, strengths) {\n    float tone_freq = 100;\n    float sample_rate = 8000;\n\n    Tone tone_weak(sample_rate, tone_freq, Tone::WEAK);\n    Tone tone_normal(sample_rate, tone_freq, Tone::NORMAL);\n    Tone tone_strong(sample_rate, tone_freq, Tone::STRONG);\n\n    for (int i = 0; i < 100 * sample_rate; ++i) {\n        float weak_sample = tone_weak.get_sample();\n        float normal_sample = tone_normal.get_sample();\n        float strong_sample = tone_strong.get_sample();\n\n        if (weak_sample > 0.0) {\n            ASSERT_LT(weak_sample, normal_sample);\n            ASSERT_LT(normal_sample, strong_sample);\n        } else if (weak_sample == 0.0) {\n            ASSERT_EQ(weak_sample, 0.0);\n            ASSERT_EQ(normal_sample, 0.0);\n            ASSERT_EQ(strong_sample, 0.0);\n        } else {\n            ASSERT_GT(weak_sample, normal_sample);\n            ASSERT_GT(normal_sample, strong_sample);\n        }\n    }\n}\n\nclass NoiseTest : public TestBaseClass {};\n\nTEST_F(NoiseTest, simple_object) {\n    Noise noise(Noise::STRONG);\n\n    int sample_count = 10000;\n    float sample_max = 0.0;\n    float sample_min = 0.0;\n    float sample_sum = 0.0;\n    for (int i = 0; i < sample_count; ++i) {\n        float sample = noise.get_sample();\n        sample_max = max(sample, sample_max);\n        sample_min = min(sample, sample_min);\n        sample_sum += sample;\n    }\n    float sample_avg = sample_sum / sample_count;\n\n    // average is near zero\n    EXPECT_LE(abs(sample_avg), 0.01);\n    // max and min are off of zero\n    EXPECT_LE(sample_min, Noise::STRONG * -0.3);\n    EXPECT_GT(sample_max, Noise::STRONG * 0.3);\n}\n\nTEST_F(NoiseTest, strengths) {\n    Noise noise_weak(Noise::WEAK);\n    Noise noise_normal(Noise::NORMAL);\n    Noise noise_strong(Noise::STRONG);\n\n    float weak_max = 0.0;\n    float normal_max = 0.0;\n    float strong_max = 0.0;\n    for (int i = 0; i < 10000; ++i) {\n        weak_max = max(weak_max, abs(noise_weak.get_sample()));\n        normal_max = max(normal_max, abs(noise_normal.get_sample()));\n        strong_max = max(strong_max, abs(noise_strong.get_sample()));\n    }\n\n    EXPECT_NE(weak_max, 0.0);\n    EXPECT_GT(normal_max, weak_max);\n    EXPECT_GT(strong_max, normal_max);\n}\n\nclass GenerateSignalTest : public TestBaseClass {\n   protected:\n    int sample_rate;\n    void SetUp(void) {\n        TestBaseClass::SetUp();\n        sample_rate = 8000;\n    }\n};\n\nTEST_F(GenerateSignalTest, default_object) {\n    GenerateSignal signal(8000);\n    EXPECT_EQ(signal.get_sample(), 0.0);\n}\n\nTEST_F(GenerateSignalTest, generate_file) {\n    float file_seconds = 10.5;\n    GenerateSignal signal(sample_rate);\n\n    string test_filepath = temp_dir + \"/10_sec_file.dat\";\n    signal.write_file(test_filepath, file_seconds);\n\n    // make sure the file exists and is the right size\n    struct stat info;\n    ASSERT_EQ(stat(test_filepath.c_str(), &info), 0);\n    EXPECT_TRUE(S_ISREG(info.st_mode));\n    EXPECT_EQ(info.st_size, sample_rate * file_seconds * sizeof(float));\n}\n\nTEST_F(GenerateSignalTest, get_sample_no_signals) {\n    GenerateSignal signal(sample_rate);\n    for (int i = 0; i < 60 * sample_rate; ++i) {\n        ASSERT_EQ(signal.get_sample(), 0.0);\n    }\n}\n\nTEST_F(GenerateSignalTest, get_sample_single_tone_only) {\n    float tone_freq = 123.34;\n    float tone_ampl = 0.32;\n\n    GenerateSignal signal(sample_rate);\n    signal.add_tone(tone_freq, tone_ampl);\n    Tone tone(sample_rate, tone_freq, tone_ampl);\n    for (int i = 0; i < 60 * sample_rate; ++i) {\n        ASSERT_FLOAT_EQ(signal.get_sample(), tone.get_sample());\n    }\n}\n\nTEST_F(GenerateSignalTest, get_sample_two_tones) {\n    float tone1_freq = 123.34;\n    float tone2_freq = 231.43;\n    float tone1_ampl = Tone::NORMAL;\n    float tone2_ampl = Tone::STRONG;\n\n    GenerateSignal signal(sample_rate);\n    signal.add_tone(tone1_freq, tone1_ampl);\n    signal.add_tone(tone2_freq, tone2_ampl);\n    Tone tone1(sample_rate, tone1_freq, tone1_ampl);\n    Tone tone2(sample_rate, tone2_freq, tone2_ampl);\n    for (int i = 0; i < 60 * sample_rate; ++i) {\n        ASSERT_NEAR(signal.get_sample(), tone1.get_sample() + tone2.get_sample(), 0.000001);\n    }\n}\n\nTEST_F(GenerateSignalTest, get_sample_only_noise) {\n    GenerateSignal signal(sample_rate);\n    signal.add_noise(Noise::NORMAL);\n\n    float max_value = 0;\n    float min_value = 0;\n    for (int i = 0; i < 600 * sample_rate; ++i) {\n        float sample = signal.get_sample();\n        min_value = min(sample, min_value);\n        max_value = max(sample, max_value);\n    }\n\n    EXPECT_GT(max_value, 0);\n    EXPECT_LT(max_value, Noise::NORMAL);\n\n    EXPECT_LT(min_value, 0);\n    EXPECT_GT(min_value, -1.0 * Noise::NORMAL);\n}\n\nTEST_F(GenerateSignalTest, get_sample_two_tones_and_noise) {\n    float tone1_freq = 123.34;\n    float tone2_freq = 231.43;\n    float tone1_ampl = Tone::NORMAL;\n    float tone2_ampl = Tone::WEAK;\n\n    GenerateSignal signal(sample_rate);\n    signal.add_tone(tone1_freq, tone1_ampl);\n    signal.add_tone(tone2_freq, tone2_ampl);\n    signal.add_noise(Noise::NORMAL);\n\n    Tone tone1(sample_rate, tone1_freq, tone1_ampl);\n    Tone tone2(sample_rate, tone2_freq, tone2_ampl);\n    float max_value = 0;\n    float min_value = 0;\n    for (int i = 0; i < 60 * sample_rate; ++i) {\n        float sample_noise = signal.get_sample() - tone1.get_sample() - tone2.get_sample();\n        min_value = min(sample_noise, min_value);\n        max_value = max(sample_noise, max_value);\n    }\n\n    EXPECT_GT(max_value, 0);\n    EXPECT_LT(max_value, Noise::NORMAL);\n\n    EXPECT_LT(min_value, 0);\n    EXPECT_GT(min_value, -1.0 * Noise::NORMAL);\n}\n"
  },
  {
    "path": "src/test_helper_functions.cpp",
    "content": "/*\n * test_output.cpp\n *\n * Copyright (C) 2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"test_base_class.h\"\n\n#include \"helper_functions.h\"\n\nusing namespace std;\n\nclass HelperFunctionsTest : public TestBaseClass {\n   protected:\n    void SetUp(void) { TestBaseClass::SetUp(); }\n\n    void create_file(const string& filepath) {\n        fclose(fopen(filepath.c_str(), \"wb\"));\n        EXPECT_TRUE(file_exists(filepath));\n    }\n};\n\nTEST_F(HelperFunctionsTest, dir_exists_true) {\n    EXPECT_TRUE(dir_exists(temp_dir));\n}\n\nTEST_F(HelperFunctionsTest, dir_exists_false) {\n    EXPECT_FALSE(dir_exists(\"/not/a/real/dir\"));\n}\n\nTEST_F(HelperFunctionsTest, dir_exists_not_dir) {\n    string file_in_dir = temp_dir + \"/some_file\";\n    create_file(file_in_dir);\n    EXPECT_FALSE(dir_exists(file_in_dir));\n}\n\nTEST_F(HelperFunctionsTest, file_exists_true) {\n    string file_in_dir = temp_dir + \"/some_file\";\n    create_file(file_in_dir);\n    EXPECT_TRUE(file_exists(file_in_dir));\n}\n\nTEST_F(HelperFunctionsTest, file_exists_false) {\n    EXPECT_FALSE(file_exists(temp_dir + \"/nothing\"));\n}\n\nTEST_F(HelperFunctionsTest, file_exists_not_file) {\n    EXPECT_FALSE(file_exists(temp_dir));\n    EXPECT_TRUE(dir_exists(temp_dir));\n}\n\nTEST_F(HelperFunctionsTest, make_dir_normal) {\n    const string dir_path = temp_dir + \"/a\";\n    EXPECT_FALSE(dir_exists(dir_path));\n    EXPECT_TRUE(make_dir(dir_path));\n    EXPECT_TRUE(dir_exists(dir_path));\n}\n\nTEST_F(HelperFunctionsTest, make_dir_exists) {\n    EXPECT_TRUE(dir_exists(temp_dir));\n    EXPECT_TRUE(make_dir(temp_dir));\n    EXPECT_TRUE(dir_exists(temp_dir));\n}\n\nTEST_F(HelperFunctionsTest, make_dir_empty) {\n    EXPECT_FALSE(make_dir(\"\"));\n}\n\nTEST_F(HelperFunctionsTest, make_dir_fail) {\n    EXPECT_FALSE(make_dir(\"/this/path/does/not/exist\"));\n}\n\nTEST_F(HelperFunctionsTest, make_dir_file_in_the_way) {\n    const string file_path = temp_dir + \"/some_file\";\n    create_file(file_path);\n    EXPECT_FALSE(make_dir(file_path));\n}\n\nTEST_F(HelperFunctionsTest, make_subdirs_exists) {\n    EXPECT_TRUE(dir_exists(temp_dir));\n    EXPECT_TRUE(make_subdirs(temp_dir, \"\"));\n    EXPECT_TRUE(dir_exists(temp_dir));\n}\n\nTEST_F(HelperFunctionsTest, make_subdirs_one_subdir) {\n    const string path = \"bob\";\n    EXPECT_FALSE(dir_exists(temp_dir + \"/\" + path));\n    EXPECT_TRUE(make_subdirs(temp_dir, path));\n    EXPECT_TRUE(dir_exists(temp_dir + \"/\" + path));\n}\n\nTEST_F(HelperFunctionsTest, make_subdirs_multiple_subdir) {\n    const string path = \"bob/joe/sam\";\n    EXPECT_FALSE(dir_exists(temp_dir + \"/\" + path));\n    EXPECT_TRUE(make_subdirs(temp_dir, path));\n    EXPECT_TRUE(dir_exists(temp_dir + \"/\" + path));\n}\n\nTEST_F(HelperFunctionsTest, make_subdirs_file_in_the_way) {\n    const string file_in_dir = temp_dir + \"/some_file\";\n    create_file(file_in_dir);\n    EXPECT_TRUE(file_exists(file_in_dir));\n    EXPECT_FALSE(make_subdirs(temp_dir, \"some_file/some_dir\"));\n    EXPECT_FALSE(dir_exists(file_in_dir));\n    EXPECT_TRUE(file_exists(file_in_dir));\n}\n\nTEST_F(HelperFunctionsTest, make_subdirs_create_base) {\n    EXPECT_FALSE(dir_exists(temp_dir + \"/base_dir/a\"));\n    EXPECT_TRUE(make_subdirs(temp_dir + \"/base_dir\", \"a\"));\n    EXPECT_TRUE(dir_exists(temp_dir + \"/base_dir/a\"));\n}\n\nTEST_F(HelperFunctionsTest, make_subdirs_extra_slashes) {\n    EXPECT_FALSE(dir_exists(temp_dir + \"/a/b/c/d\"));\n    EXPECT_TRUE(make_subdirs(temp_dir, \"///a/b////c///d\"));\n    EXPECT_TRUE(dir_exists(temp_dir + \"/a/b/c/d\"));\n}\n\nTEST_F(HelperFunctionsTest, make_dated_subdirs_normal) {\n    struct tm time_struct;\n\n    strptime(\"2010-3-7\", \"%Y-%m-%d\", &time_struct);\n\n    const string dir_path = temp_dir + \"/2010/03/07\";\n\n    EXPECT_FALSE(dir_exists(dir_path));\n    EXPECT_EQ(make_dated_subdirs(temp_dir, &time_struct), dir_path);\n    EXPECT_TRUE(dir_exists(dir_path));\n}\n\nTEST_F(HelperFunctionsTest, make_dated_subdirs_fail) {\n    struct tm time_struct;\n\n    strptime(\"2010-3-7\", \"%Y-%m-%d\", &time_struct);\n\n    EXPECT_EQ(make_dated_subdirs(\"/invalid/base/dir\", &time_struct), \"\");\n}\n\nTEST_F(HelperFunctionsTest, make_dated_subdirs_some_exist) {\n    struct tm time_struct;\n\n    const string dir_through_month = temp_dir + \"/2010/03/\";\n\n    strptime(\"2010-3-7\", \"%Y-%m-%d\", &time_struct);\n    EXPECT_EQ(make_dated_subdirs(temp_dir, &time_struct), dir_through_month + \"07\");\n\n    EXPECT_TRUE(dir_exists(dir_through_month));\n    EXPECT_FALSE(dir_exists(dir_through_month + \"08\"));\n\n    strptime(\"2010-3-8\", \"%Y-%m-%d\", &time_struct);\n    EXPECT_EQ(make_dated_subdirs(temp_dir, &time_struct), dir_through_month + \"08\");\n    EXPECT_TRUE(dir_exists(dir_through_month + \"08\"));\n}\n"
  },
  {
    "path": "src/test_squelch.cpp",
    "content": "/*\n * test_squelch.cpp\n *\n * Copyright (C) 2023 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include \"generate_signal.h\"\n#include \"test_base_class.h\"\n\n#include \"squelch.h\"\n\nusing namespace std;\n\nclass SquelchTest : public TestBaseClass {\n   protected:\n    void SetUp(void) {\n        TestBaseClass::SetUp();\n\n        raw_no_signal_sample = 0.05;\n        raw_signal_sample = 0.75;\n    }\n\n    void TearDown(void) { TestBaseClass::TearDown(); }\n\n    // send through \"no signal\" samples to get noise floor down\n    void send_samples_for_noise_floor(Squelch& squelch) {\n        while (squelch.noise_level() > 1.01 * raw_no_signal_sample) {\n            squelch.process_raw_sample(raw_no_signal_sample);\n        }\n        ASSERT_LE(squelch.noise_level(), 1.01 * raw_no_signal_sample);\n        ASSERT_GT(raw_signal_sample, squelch.squelch_level());\n    }\n\n    float raw_no_signal_sample;\n    float raw_signal_sample;\n};\n\nTEST_F(SquelchTest, default_object) {\n    Squelch squelch;\n    EXPECT_EQ(squelch.open_count(), 0);\n}\n\nTEST_F(SquelchTest, noise_floor) {\n    Squelch squelch;\n\n    // noise floor starts high\n    EXPECT_GT(squelch.noise_level(), 10.0 * raw_no_signal_sample);\n\n    // noise floor drifts down towards (but never at) the incoming raw sample level\n    float last_noise_level, this_noise_level;\n    this_noise_level = squelch.noise_level();\n    do {\n        last_noise_level = this_noise_level;\n\n        // not all samples update noise floor\n        for (int j = 0; j < 25; ++j) {\n            squelch.process_raw_sample(raw_no_signal_sample);\n        }\n\n        this_noise_level = squelch.noise_level();\n        ASSERT_LE(this_noise_level, last_noise_level);\n    } while (this_noise_level != last_noise_level);\n\n    // noise floor ends up close to the incoming level\n    EXPECT_LT(squelch.noise_level(), 1.01 * raw_no_signal_sample);\n}\n\nTEST_F(SquelchTest, normal_operation) {\n    Squelch squelch;\n\n    // send through \"no signal\" samples to get noise floor down\n    send_samples_for_noise_floor(squelch);\n    ASSERT_LE(squelch.noise_level(), 1.01 * raw_no_signal_sample);\n    ASSERT_GT(raw_signal_sample, squelch.squelch_level());\n\n    // send through \"signal\" samples and squelch should open shortly\n    for (int i = 0; i < 500 && !squelch.is_open(); ++i) {\n        squelch.process_raw_sample(raw_signal_sample);\n    }\n    ASSERT_TRUE(squelch.is_open());\n    ASSERT_TRUE(squelch.should_process_audio());\n\n    // send through a bunch more \"signal\" values and squelch stays open\n    for (int i = 0; i < 1000; ++i) {\n        squelch.process_raw_sample(raw_signal_sample);\n    }\n    ASSERT_TRUE(squelch.is_open());\n    ASSERT_TRUE(squelch.should_process_audio());\n\n    // send through \"no signal\" samples and squelch should close quickly\n    for (int i = 0; i < 100 && squelch.is_open(); ++i) {\n        squelch.process_raw_sample(raw_no_signal_sample);\n    }\n    ASSERT_FALSE(squelch.is_open());\n    ASSERT_FALSE(squelch.should_process_audio());\n}\n\nTEST_F(SquelchTest, dead_spot) {\n    Squelch squelch;\n\n    send_samples_for_noise_floor(squelch);\n\n    // send through \"signal\" samples and squelch should open shortly\n    for (int i = 0; i < 500 && !squelch.is_open(); ++i) {\n        squelch.process_raw_sample(raw_signal_sample);\n    }\n    ASSERT_TRUE(squelch.is_open());\n    ASSERT_TRUE(squelch.should_process_audio());\n\n    // send through a bunch more \"signal\" values and squelch stays open\n    for (int i = 0; i < 1000; ++i) {\n        squelch.process_raw_sample(raw_signal_sample);\n    }\n    ASSERT_TRUE(squelch.is_open());\n    ASSERT_TRUE(squelch.should_process_audio());\n\n    // send through a dead spot of \"no signal\" and squelch should stay open\n    for (int i = 0; i < 50; ++i) {\n        squelch.process_raw_sample(raw_no_signal_sample);\n        ASSERT_TRUE(squelch.is_open());\n        ASSERT_TRUE(squelch.should_process_audio());\n    }\n\n    // send go back to \"signal\" samples and squelch stays open\n    for (int i = 0; i < 1000; ++i) {\n        squelch.process_raw_sample(raw_signal_sample);\n        ASSERT_TRUE(squelch.is_open());\n        ASSERT_TRUE(squelch.should_process_audio());\n    }\n}\n\nTEST_F(SquelchTest, should_process_audio) {\n    Squelch squelch;\n\n    send_samples_for_noise_floor(squelch);\n\n    // should_process_audio is true as soon as squelch opens\n    for (int i = 0; i < 500 && !squelch.is_open(); ++i) {\n        ASSERT_FALSE(squelch.should_process_audio());\n        squelch.process_raw_sample(raw_signal_sample);\n    }\n    ASSERT_TRUE(squelch.is_open());\n    ASSERT_TRUE(squelch.should_process_audio());\n\n    // and stays true until fully closed\n    for (int i = 0; i < 100 && squelch.is_open(); ++i) {\n        ASSERT_TRUE(squelch.should_process_audio());\n        squelch.process_raw_sample(raw_no_signal_sample);\n    }\n    ASSERT_FALSE(squelch.is_open());\n    ASSERT_FALSE(squelch.should_process_audio());\n}\n\nTEST_F(SquelchTest, good_ctcss) {\n    float tone = CTCSS::standard_tones[5];\n    float sample_rate = 8000;\n\n    Squelch squelch;\n    squelch.set_ctcss_freq(tone, sample_rate);\n    send_samples_for_noise_floor(squelch);\n\n    GenerateSignal signal_with_tone(sample_rate);\n    signal_with_tone.add_tone(tone, Tone::NORMAL);\n\n    // send through \"signal\" samples until its time to process audio\n    for (int i = 0; i < 500 && !squelch.should_process_audio(); ++i) {\n        squelch.process_raw_sample(raw_signal_sample);\n    }\n    ASSERT_FALSE(squelch.is_open());\n    ASSERT_TRUE(squelch.should_process_audio());\n\n    // process audio samples and \"signal\" samples until squelch is open\n    for (int i = 0; i < 500 && !squelch.is_open(); ++i) {\n        squelch.process_audio_sample(signal_with_tone.get_sample());\n        squelch.process_raw_sample(raw_signal_sample);\n    }\n    ASSERT_TRUE(squelch.is_open());\n    ASSERT_TRUE(squelch.should_process_audio());\n\n    // run through a lot more to ensure squelch stays open\n    for (int i = 0; i < 100000; ++i) {\n        squelch.process_audio_sample(signal_with_tone.get_sample());\n        squelch.process_raw_sample(raw_signal_sample);\n        ASSERT_TRUE(squelch.is_open());\n        ASSERT_TRUE(squelch.should_process_audio());\n    }\n\n    EXPECT_GT(squelch.ctcss_count(), 0);\n    EXPECT_EQ(squelch.no_ctcss_count(), 0);\n}\n\nTEST_F(SquelchTest, wrong_ctcss) {\n    float actual_tone = CTCSS::standard_tones[0];\n    float expected_tone = CTCSS::standard_tones[7];\n    float sample_rate = 8000;\n\n    Squelch squelch;\n    squelch.set_ctcss_freq(expected_tone, sample_rate);\n    send_samples_for_noise_floor(squelch);\n\n    GenerateSignal signal_with_tone(sample_rate);\n    signal_with_tone.add_tone(actual_tone, Tone::NORMAL);\n\n    // send through \"signal\" samples until its time to process audio\n    for (int i = 0; i < 500 && !squelch.should_process_audio(); ++i) {\n        squelch.process_raw_sample(raw_signal_sample);\n    }\n    ASSERT_TRUE(squelch.should_process_audio());\n    ASSERT_FALSE(squelch.is_open());\n\n    // process lots of audio samples and \"signal\" samples and squelch never opens\n    for (int i = 0; i < 100000; ++i) {\n        squelch.process_audio_sample(signal_with_tone.get_sample());\n        squelch.process_raw_sample(raw_signal_sample);\n        ASSERT_TRUE(squelch.should_process_audio());\n        ASSERT_FALSE(squelch.is_open());\n    }\n\n    EXPECT_EQ(squelch.ctcss_count(), 0);\n    EXPECT_GT(squelch.no_ctcss_count(), 0);\n}\n\nTEST_F(SquelchTest, close_ctcss) {\n    float actual_tone = CTCSS::standard_tones[5];\n    float expected_tone = CTCSS::standard_tones[7];\n    float sample_rate = 8000;\n\n    Squelch squelch;\n    squelch.set_ctcss_freq(expected_tone, sample_rate);\n    send_samples_for_noise_floor(squelch);\n\n    GenerateSignal signal_with_tone(sample_rate);\n    signal_with_tone.add_tone(actual_tone, Tone::NORMAL);\n\n    // send through \"signal\" samples until its time to process audio\n    for (int i = 0; i < 500 && !squelch.should_process_audio(); ++i) {\n        squelch.process_raw_sample(raw_signal_sample);\n    }\n    ASSERT_TRUE(squelch.should_process_audio());\n    ASSERT_FALSE(squelch.is_open());\n\n    // process of audio samples and \"signal\" samples until squelch opens\n    for (int i = 0; i < 500 && !squelch.is_open(); ++i) {\n        squelch.process_audio_sample(signal_with_tone.get_sample());\n        squelch.process_raw_sample(raw_signal_sample);\n        ASSERT_TRUE(squelch.should_process_audio());\n    }\n    ASSERT_TRUE(squelch.is_open());\n\n    // keep processing samples until squelch closes again\n    for (int i = 0; i < 3000 && squelch.is_open(); ++i) {\n        squelch.process_audio_sample(signal_with_tone.get_sample());\n        squelch.process_raw_sample(raw_signal_sample);\n        ASSERT_TRUE(squelch.should_process_audio());\n    }\n    ASSERT_FALSE(squelch.is_open());\n\n    // process lots of audio samples and \"signal\" samples and squelch stays closed\n    for (int i = 0; i < 100000; ++i) {\n        squelch.process_audio_sample(signal_with_tone.get_sample());\n        squelch.process_raw_sample(raw_signal_sample);\n        ASSERT_TRUE(squelch.should_process_audio());\n        ASSERT_FALSE(squelch.is_open());\n    }\n\n    EXPECT_EQ(squelch.ctcss_count(), 0);\n    EXPECT_GT(squelch.no_ctcss_count(), 0);\n}\n"
  },
  {
    "path": "src/udp_stream.cpp",
    "content": "/*\n * udp_stream.cpp\n *\n * Copyright (C) 2024 charlie-foxtrot\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n#include <string.h>  // strerror()\n#include <syslog.h>  // LOG_INFO / LOG_ERR\n#include <unistd.h>  // close()\n#include <cassert>   // assert()\n\n#include <arpa/inet.h>  // inet_aton()\n#include <netdb.h>      // getaddrinfo()\n\n#include \"rtl_airband.h\"\n\nbool udp_stream_init(udp_stream_data* sdata, mix_modes mode, size_t len) {\n    // pre-allocate the stereo buffer\n    if (mode == MM_STEREO) {\n        sdata->stereo_buffer_len = len * 2;\n        sdata->stereo_buffer = (float*)XCALLOC(sdata->stereo_buffer_len, sizeof(float));\n    } else {\n        sdata->stereo_buffer_len = 0;\n        sdata->stereo_buffer = NULL;\n    }\n\n    sdata->send_socket = -1;\n    sdata->dest_sockaddr_len = 0;\n\n    // lookup address / port\n    struct addrinfo hints, *result, *rptr;\n    memset(&hints, 0, sizeof(struct addrinfo));\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = SOCK_DGRAM;\n    hints.ai_flags = 0;\n    hints.ai_protocol = 0;\n    int error = getaddrinfo(sdata->dest_address, sdata->dest_port, &hints, &result);\n    if (error) {\n        log(LOG_ERR, \"udp_stream: could not resolve %s:%s - %s\\n\", sdata->dest_address, sdata->dest_port, gai_strerror(error));\n        return false;\n    }\n\n    // check each result and try to create a connection\n    for (rptr = result; rptr != NULL; rptr = rptr->ai_next) {\n        sdata->send_socket = socket(rptr->ai_family, rptr->ai_socktype, rptr->ai_protocol);\n        if (sdata->send_socket == -1) {\n            log(LOG_ERR, \"udp_stream: socket failed: %s\\n\", strerror(errno));\n            continue;\n        }\n\n        if (connect(sdata->send_socket, rptr->ai_addr, rptr->ai_addrlen) == -1) {\n            log(LOG_INFO, \"udp_stream: connect to %s:%s failed: %s\\n\", sdata->dest_address, sdata->dest_port, strerror(errno));\n            close(sdata->send_socket);\n            sdata->send_socket = -1;\n            continue;\n        }\n\n        sdata->dest_sockaddr = *rptr->ai_addr;\n        sdata->dest_sockaddr_len = rptr->ai_addrlen;\n        break;\n    }\n    freeaddrinfo(result);\n\n    // error if no valid socket\n    if (sdata->send_socket == -1) {\n        log(LOG_ERR, \"udp_stream: could not set up UDP socket to %s:%s - all addresses failed\\n\", sdata->dest_address, sdata->dest_port);\n        return false;\n    }\n\n    log(LOG_INFO, \"udp_stream: sending %s 32-bit float at %d Hz to %s:%s\\n\", mode == MM_MONO ? \"Mono\" : \"Stereo\", WAVE_RATE, sdata->dest_address, sdata->dest_port);\n    return true;\n}\n\nvoid udp_stream_write(udp_stream_data* sdata, const float* data, size_t len) {\n    if (sdata->send_socket != -1) {\n        // Send without blocking or checking for success\n        sendto(sdata->send_socket, data, len, MSG_DONTWAIT | MSG_NOSIGNAL, &sdata->dest_sockaddr, sdata->dest_sockaddr_len);\n    }\n}\n\nvoid udp_stream_write(udp_stream_data* sdata, const float* data_left, const float* data_right, size_t len) {\n    if (sdata->send_socket != -1) {\n        assert(len * 2 <= sdata->stereo_buffer_len);\n        for (size_t i = 0; i < len; ++i) {\n            sdata->stereo_buffer[2 * i] = data_left[i];\n            sdata->stereo_buffer[2 * i + 1] = data_right[i];\n        }\n        udp_stream_write(sdata, sdata->stereo_buffer, len * 2);\n    }\n}\n\nvoid udp_stream_shutdown(udp_stream_data* sdata) {\n    if (sdata->send_socket != -1) {\n        close(sdata->send_socket);\n    }\n}\n"
  },
  {
    "path": "src/util.cpp",
    "content": "/*\n * util.cpp\n * Miscellaneous routines\n *\n * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, see <https://www.gnu.org/licenses/>.\n */\n\n#include <lame/lame.h>\n#include <shout/shout.h>\n#include <stdint.h>  // uint32_t\n#include <unistd.h>\n#include <cerrno>\n#include <cmath>\n#include <cstdarg>\n#include <cstdlib>\n#include <cstring>\n#include <iostream>\n#include \"config.h\"\n#include \"logging.h\"\n#include \"rtl_airband.h\"\n\nint atomic_inc(volatile int* pv) {\n    return __sync_fetch_and_add(pv, 1);\n}\n\nint atomic_dec(volatile int* pv) {\n    return __sync_fetch_and_sub(pv, 1);\n}\n\nint atomic_get(volatile int* pv) {\n    return __sync_fetch_and_add(pv, 0);\n}\n\nvoid tag_queue_put(device_t* dev, int freq, struct timeval tv) {\n    pthread_mutex_lock(&dev->tag_queue_lock);\n    dev->tq_head++;\n    dev->tq_head %= TAG_QUEUE_LEN;\n    if (dev->tq_head == dev->tq_tail) {\n        log(LOG_WARNING, \"tag_queue_put: queue overrun\\n\");\n        dev->tq_tail++;\n    }\n    dev->tag_queue[dev->tq_head].freq = freq;\n    memcpy(&dev->tag_queue[dev->tq_head].tv, &tv, sizeof(struct timeval));\n    pthread_mutex_unlock(&dev->tag_queue_lock);\n}\n\nvoid tag_queue_get(device_t* dev, struct freq_tag* tag) {\n    int i;\n\n    if (!tag)\n        return;\n    pthread_mutex_lock(&dev->tag_queue_lock);\n    if (dev->tq_head == dev->tq_tail) { /* empty queue */\n        tag->freq = -1;\n    } else {\n        // read queue entry at pos tq_tail+1 without dequeueing it\n        i = dev->tq_tail + 1;\n        i %= TAG_QUEUE_LEN;\n        tag->freq = dev->tag_queue[i].freq;\n        memcpy(&tag->tv, &dev->tag_queue[i].tv, sizeof(struct timeval));\n    }\n    pthread_mutex_unlock(&dev->tag_queue_lock);\n}\n\nvoid tag_queue_advance(device_t* dev) {\n    pthread_mutex_lock(&dev->tag_queue_lock);\n    dev->tq_tail++;\n    dev->tq_tail %= TAG_QUEUE_LEN;\n    pthread_mutex_unlock(&dev->tag_queue_lock);\n}\n\nvoid* xcalloc(size_t nmemb, size_t size, const char* file, const int line, const char* func) {\n    void* ptr = calloc(nmemb, size);\n    if (ptr == NULL) {\n        log(LOG_ERR, \"%s:%d: %s(): calloc(%zu, %zu) failed: %s\\n\", file, line, func, nmemb, size, strerror(errno));\n        error();\n    }\n    return ptr;\n}\n\nvoid* xrealloc(void* ptr, size_t size, const char* file, const int line, const char* func) {\n    ptr = realloc(ptr, size);\n    if (ptr == NULL) {\n        log(LOG_ERR, \"%s:%d: %s(): realloc(%zu) failed: %s\\n\", file, line, func, size, strerror(errno));\n        error();\n    }\n    return ptr;\n}\n\nstatic float sin_lut[257], cos_lut[257];\n\nvoid sincosf_lut_init() {\n    for (uint32_t i = 0; i < 256; i++)\n        SINCOSF(2.0F * M_PI * (float)i / 256.0f, sin_lut + i, cos_lut + i);\n    sin_lut[256] = sin_lut[0];\n    cos_lut[256] = cos_lut[0];\n}\n\n// phi range must be (0..1), rescaled to 0x0-0xFFFFFF\nvoid sincosf_lut(uint32_t phi, float* sine, float* cosine) {\n    float v1, v2, fract;\n    uint32_t idx;\n    // get LUT index\n    idx = phi >> 16;\n    // cast fixed point fraction to float\n    fract = (float)(phi & 0xffff) / 65536.0f;\n    // get two adjacent values from LUT and interpolate\n    v1 = sin_lut[idx];\n    v2 = sin_lut[idx + 1];\n    *sine = v1 + (v2 - v1) * fract;\n    v1 = cos_lut[idx];\n    v2 = cos_lut[idx + 1];\n    *cosine = v1 + (v2 - v1) * fract;\n}\n\n/* librtlsdr-keenerd, (c) Kyle Keen */\ndouble atofs(char* s) {\n    char last;\n    int len;\n    double suff = 1.0;\n    len = strlen(s);\n    last = s[len - 1];\n    s[len - 1] = '\\0';\n    switch (last) {\n        case 'g':\n        case 'G':\n            suff *= 1e3;\n            [[fallthrough]];\n        case 'm':\n        case 'M':\n            suff *= 1e3;\n            [[fallthrough]];\n        case 'k':\n        case 'K':\n            suff *= 1e3;\n            suff *= atof(s);\n            s[len - 1] = last;\n            return suff;\n    }\n    s[len - 1] = last;\n    return atof(s);\n}\n\ndouble delta_sec(const timeval* start, const timeval* stop) {\n    timeval delta;\n    timersub(stop, start, &delta);\n    return delta.tv_sec + delta.tv_usec / 1000000.0;\n}\n\n// level to/from dBFS conversion assumes level is nomalized to 1 and is based on:\n//    https://kluedo.ub.uni-kl.de/frontdoor/deliver/index/docId/4293/file/exact_fft_measurements.pdf\n//\n// expanded form:\n//    20.0f * log10f(level / fft_size) + 7.54f + 10.0f * log10f(fft_size/2) - 2.38f\n\nconst float& dBFS_offset(void) {\n    static const float offset = 7.54f + 10.0f * log10f(fft_size / 2) - 2.38f;\n    return offset;\n}\n\nfloat dBFS_to_level(const float& dBFS) {\n    return pow(10.0, (dBFS - dBFS_offset()) / 20.0f) * fft_size;\n}\n\nfloat level_to_dBFS(const float& level) {\n    return std::min(0.0f, 20.0f * log10f(level / fft_size) + dBFS_offset());\n}\n"
  }
]